asciify-engine 4.22.0 → 4.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +6 -0
  2. package/dist/{animation-presets-KnEWoJ_q.d.ts → animation-presets-CzM3jLT6.d.cts} +1 -1
  3. package/dist/{animation-presets-CEdD0FMM.d.cts → animation-presets-a8WDzKDj.d.ts} +1 -1
  4. package/dist/core.cjs +1 -1
  5. package/dist/core.d.cts +5 -4
  6. package/dist/core.d.ts +5 -4
  7. package/dist/core.js +1 -1
  8. package/dist/field.cjs +1 -1
  9. package/dist/field.d.cts +10 -1
  10. package/dist/field.d.ts +10 -1
  11. package/dist/field.js +1 -1
  12. package/dist/{hover-guide-CAfsLjFZ.d.cts → hover-catalog-CrmxlmUe.d.cts} +37 -10
  13. package/dist/{hover-guide-CAfsLjFZ.d.ts → hover-catalog-CrmxlmUe.d.ts} +37 -10
  14. package/dist/hover-guide-DdFnAnfU.d.cts +9 -0
  15. package/dist/hover-guide-DdFnAnfU.d.ts +9 -0
  16. package/dist/hover.cjs +1 -1
  17. package/dist/hover.d.cts +7 -5
  18. package/dist/hover.d.ts +7 -5
  19. package/dist/hover.js +1 -1
  20. package/dist/index.cjs +1 -1
  21. package/dist/index.d.cts +4 -3
  22. package/dist/index.d.ts +4 -3
  23. package/dist/index.js +1 -1
  24. package/dist/kit.cjs +1 -1
  25. package/dist/kit.d.cts +1 -0
  26. package/dist/kit.d.ts +1 -0
  27. package/dist/kit.js +1 -1
  28. package/dist/{model-BHIQYYk-.d.ts → model-C3TTmMXv.d.ts} +2 -1
  29. package/dist/{model-BzgEEqzP.d.cts → model-DAZNnqXr.d.cts} +2 -1
  30. package/dist/studio.cjs +1 -1
  31. package/dist/studio.d.cts +6 -4
  32. package/dist/studio.d.ts +6 -4
  33. package/dist/studio.js +1 -1
  34. package/dist/{types-C9lka3yC.d.ts → types-BnakIXAU.d.ts} +1 -1
  35. package/dist/{types-DOl5f2x3.d.cts → types-_8MohOZ1.d.cts} +1 -1
  36. package/package.json +1 -1
  37. package/skills/asciify-engine/SKILL.md +2 -2
  38. package/skills/asciify-engine/references/glyph-field.md +2 -1
  39. package/skills/asciify-engine/references/kit.md +1 -1
  40. package/skills/asciify-engine/references/studio-effects.md +12 -6
  41. package/skills/asciify-engine/references/studio-workspace.md +1 -1
  42. package/skills/asciify-engine/references/upgrading.md +1 -1
package/dist/hover.js CHANGED
@@ -1 +1 @@
1
- function t(t,e,i=()=>{}){const s=Array.isArray(e)?e:[e],a=document.createElement("canvas"),o=a.getContext("2d");let n,h=!0,r=!1,l=0;const c=()=>{r||(h=!0,i())},d=new ResizeObserver(c);d.observe(t),s.forEach(t=>d.observe(t));const u=new MutationObserver(c);return s.forEach(t=>u.observe(t,{subtree:!0,childList:!0,characterData:!0,attributes:!0})),document.fonts?.addEventListener("loadingdone",c),document.fonts?.ready.then(c),window.addEventListener("resize",c),{invalidate:c,read(){if(r)return;if(!h)return n;h=!1;const e=t.getBoundingClientRect(),i=Math.min(devicePixelRatio||1,1.5,Math.sqrt(4e6/Math.max(1,e.width*e.height)));a.width=Math.max(1,Math.round(e.width*i)),a.height=Math.max(1,Math.round(e.height*i)),o.setTransform(i,0,0,i,0,0),o.fillStyle="#fff",o.textBaseline="alphabetic";for(const t of s){const i=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(let t=i.nextNode();t;t=i.nextNode()){const i=t.parentElement;if(!i)continue;const s=getComputedStyle(i);if("hidden"===s.visibility||"none"===s.display)continue;o.font=`${s.fontStyle} ${s.fontWeight} ${s.fontSize} ${s.fontFamily}`;const a=o.measureText("Hg"),n=a.fontBoundingBoxAscent??.8*parseFloat(s.fontSize),h=a.fontBoundingBoxDescent??.2*parseFloat(s.fontSize),r=t.textContent??"",l=document.createRange();let c=0;for(const i of r){if(l.setStart(t,c),c+=i.length,l.setEnd(t,c),/\s/.test(i))continue;const s=l.getBoundingClientRect();s.width&&s.height&&o.fillText(i,s.left-e.left,s.top-e.top+(s.height-n-h)/2+n)}}}return n={canvas:a,revision:++l},n},destroy(){r=!0,d.disconnect(),u.disconnect(),document.fonts?.removeEventListener("loadingdone",c),window.removeEventListener("resize",c),a.width=a.height=1,n=void 0}}}var e={caustics:"sheen",grain:"shimmer",trace:"relight",tidal:"current",weave:"current",breeze:"current",reform:"develop",print:"develop",unfold:"develop"},i=[{value:"none",mode:"none",group:"Still",label:"Off",description:"Keep the image still. Hover stays available."},{value:"relight",mode:"relight",group:"Light",label:"Relight",description:"A key light circles the subject and models its own relief, like moving a lamp around a sculpture."},{value:"sheen",mode:"sheen",group:"Light",label:"Specular sweep",description:"One slow pass of light glances across the highlights and follows their form, then rests."},{value:"glow",mode:"glow",group:"Light",label:"Highlight bloom",description:"The brightest areas breathe a soft halo into their surroundings. Shadows stay deep."},{value:"shimmer",mode:"shimmer",group:"Light",label:"Glints",description:"Sparse glints on bright fine detail, like light on water, metal or an eye. Everything else holds still."},{value:"parallax",mode:"parallax",group:"Depth",label:"Parallax",description:"A slow camera drift: the subject moves against its background, read from the photo’s own depth cues."},{value:"push",mode:"push",group:"Depth",label:"Slow push",description:"A gentle push toward the subject and back, with nearer areas moving slightly more."},{value:"focus",mode:"focus",group:"Depth",label:"Focus pull",description:"Focus racks from the subject to the background and back; the characters soften out of focus."},{value:"mist",mode:"mist",group:"Atmosphere",label:"Mist",description:"Soft mist drifts through the distance and plain areas, leaving the subject clear."},{value:"current",mode:"current",group:"Atmosphere",label:"Drift",description:"Sky, water and smooth grounds flow slowly, like a cinemagraph; detailed areas hold still."},{value:"develop",mode:"develop",group:"Reveal",label:"Develop",description:"The image holds, fades, then develops back in from its highlights to its shadows, like a print in the tray."}];function s(t){const s=t&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:t;return i.find(t=>t.value===s||t.mode===s)?.mode??"none"}var a=t=>Math.max(0,Math.min(1,t)),o=(t,e,i)=>{const s=a((i-t)/(e-t));return s*s*(3-2*s)},n=(t,e)=>{const i=(.06711056*t+.00583715*e)%1*52.9829189;return i-Math.floor(i)},h=class{constructor(){this.last=null,this.mode="none",this.phase=0}update(t,e,i=1){const a=s(e);return Number.isFinite(t)?((a!==this.mode||null!==this.last&&t<this.last)&&(this.mode=a,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 r(t,e,i,s,h,r=.5,l,c=0){if(h[0]=h[1]=h[2]=0,h[3]=1,"none"===t)return h;r=a(r);const d=l?l[c]:r,u=l?l[c+1]:.5+.5*a(1-2*Math.hypot(e-.5,i-.55)),m=l?l[c+2]:o(.55,1,r)**2,f=l?l[c+3]:.5,g=l?l[c+4]:0,p=l?l[c+5]:0,M=s*Math.PI/6,v=(s%12+12)%12,x=o(0,.12,Math.min(e,1-e,i,1-i));if("relight"===t){const t=M+.6,s=Math.cos(t),a=Math.sin(t),n=Math.max(-1,Math.min(1,g*s+p*a))+.35*(s*(e-.5)+a*(i-.5));h[2]=.2*n*(.3+.7*o(.04,.3,d)*(1-.6*o(.82,1,r)))}else if("sheen"===t){const t=1.9*o(0,8,v)-.35,s=(.75*e+.45*i)/1.2+.05*(.75*g+.45*p),a=Math.exp(-(((s-t)/.12)**2));h[2]=a*o(.3,.8,d)*(1-.5*o(.9,1,r))*.45}else if("glow"===t){const t=.5-.5*Math.cos(M),e=1-.8*t;h[2]=.2*o(e-.3,e+.02,m)*Math.sqrt(m)*(1-.65*r)+.05*t*o(.6,.95,r)}else if("shimmer"===t){const t=n(Math.floor(160*e),Math.floor(100*i))*Math.PI*2,s=Math.pow(.5+.5*Math.cos(2*M+t),28);h[2]=s*o(.5,.88,r)*(.35+.65*o(.1,.55,f))*.42}else if("parallax"===t){const t=u-.45;h[0]=16*t*Math.sin(M)*x,h[1]=7*t*Math.sin(2*M)*x}else if("push"===t){const t=.045*(.5-.5*Math.cos(M))*(.7+.6*u)*960,s=l?l[c+6]:.5,a=l?l[c+7]:.5;h[0]=(e-s)*t,h[1]=(i-a)*t}else if("focus"===t){const t=Math.sin(M),e=t*t*o(.15,.6,t>=0?1-u:u);h[2]=(d-r)*e*.9}else if("mist"===t){const t=Math.pow(1-u,1.5)*(1-.6*f),s=.5*Math.sin(4.1*e-M+.9*Math.sin(3.3*i+M))+.3*Math.sin(7.3*e+2.1*i-2*M+1.1*Math.sin(2.7*e-5.1*i+M))+.2*Math.sin(5.7*i-1.9*e+M);h[2]=o(-.3,.9,s)*t*.16*(1-.55*r)}else if("current"===t){const t=(1-.4*f)*(1-.8*u)*x,s=t=>14*i-t+1.5*Math.sin(3*e+t);h[0]=7*(Math.sin(s(M))-Math.sin(s(0))+.43*(Math.sin(5*e-3*i+M)-Math.sin(5*e-3*i)))*t,h[1]=2*(Math.sin(11*e+M)-Math.sin(11*e))*t,h[2]=.03*(Math.cos(s(M))-Math.cos(s(0)))*t}else if("develop"===t){const t=o(7,8.5,v),s=a((v-8.5)/3.5),l=v<8.5?1-t:o(0,1,(1.45*s-(1-r)+.06*(n(Math.floor(160*e),Math.floor(100*i))-.5))/.3);h[2]=.3*-(1-l),h[3]=1-.9*(1-l)}return h}function l(t,e,i){const s=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)),a=Math.max(0,Math.min(1,(s-.035)/.105));return a*a*a*(a*(6*a-15)+10)}var c=class{constructor(t,e){this.edgeSafe=!1,this.rings=new Float64Array(40),this.slot=0,this.clock=0,this.lastRing=-1,this.previous=null,this.alive=!1,this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.values=new Float32Array(t*e),this.clear()}get active(){return this.alive}clear(){this.rings.fill(0),this.values.fill(0),this.pixels.fill(0);for(let t=0;t<this.pixels.length;t+=4)this.pixels[t]=128;this.previous=null,this.alive=!1,this.slot=0,this.lastRing=-1,this.clock=0}leave(){this.previous=null}move(t,e,i,s){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=Number.isFinite(s)?s/1e3:this.clock,o=this.previous;if(this.previous={x:t,y:e,time:a},!o)return;const n=this.width/this.height,h=Math.hypot((t-o.x)*Math.max(1,n),(e-o.y)*Math.max(1,1/n));if(h<1e-4||this.clock-this.lastRing<1/24)return;const r=h/Math.max(1/240,Math.min(.1,a-o.time||1/60)),l=5*this.slot;this.slot=(this.slot+1)%8,this.rings[l]=t,this.rings[l+1]=e,this.rings[l+2]=0,this.rings[l+3]=Math.min(.9,.26+.2*r),this.rings[l+4]=.035+.13*Math.max(.1,Math.min(1,i)),this.alive=!0,this.lastRing=this.clock}step(t){if(!Number.isFinite(t)||t<=0)return;const e=Math.min(.05,t);if(this.clock+=e,!this.alive)return;this.values.fill(0),this.alive=!1;const i=this.width/this.height,s=Math.max(1,i),a=Math.max(1,1/i);for(let t=0;t<this.rings.length;t+=5){if(!this.rings[t+3])continue;const i=this.rings[t+2]+=e;if(i>2.8){this.rings[t+3]=0;continue}this.alive=!0;const o=this.rings[t+4],n=.17*i,h=this.rings[t+3]*(1-Math.exp(20*-i))*Math.exp(2.5*-i),r=n+1.8*o,l=this.rings[t],c=this.rings[t+1],d=Math.max(0,Math.floor((l-r/s)*(this.width-1))),u=Math.min(this.width-1,Math.ceil((l+r/s)*(this.width-1))),m=Math.max(0,Math.floor((c-r/a)*(this.height-1))),f=Math.min(this.height-1,Math.ceil((c+r/a)*(this.height-1)));for(let t=m;t<=f;t++)for(let e=d;e<=u;e++){const i=(Math.hypot((e/(this.width-1)-l)*s,(t/(this.height-1)-c)*a)-n)/o;Math.abs(i)>1.8||(this.values[t*this.width+e]+=h*Math.cos(i*Math.PI*2)*Math.exp(-i*i*2.5))}}for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const s=t*this.width+e,a=this.values[s]=Math.max(-1,Math.min(1,this.values[s]))*(this.edgeSafe?l(e/(this.width-1),t/(this.height-1),i):1),o=Math.round(32767*a+32768);this.pixels[4*s]=o>>>8,this.pixels[4*s+1]=255&o}}sample(t,e,i){const s=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),a=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),o=Math.floor(s),n=Math.floor(a),h=s-o,r=a-n,l=n*this.width+o,c=l+this.width;i[0]=i[1]=0,i[2]=3*((this.values[l]*(1-h)+this.values[l+1]*h)*(1-r)+(this.values[c]*(1-h)+this.values[c+1]*h)*r)}},d=t=>["dissolve","silk","vortex","magnetic","scatter","etch","elastic","lens","smudge"].includes(t),u=t=>"elastic"===t||"scatter"===t,m={elastic:[150,4.2],scatter:[90,3.6]},f=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 s=0;s<t;s++)this.edge[i*t+s]=l(s/(t-1),i/(e-1),t/e);this.clear()}get active(){return this.peak>2e-4}setMode(t){if(u(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),e=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};for(let i=0;i<this.height;i++)for(let s=0;s<this.width;s++){const a=.09*s,o=.09*i,n=Math.floor(a),h=Math.floor(o),r=a-n,l=o-h,c=r*r*(3-2*r),d=l*l*(3-2*l),u=((e(n,h)*(1-c)+e(n+1,h)*c)*(1-d)+(e(n,h+1)*(1-c)+e(n+1,h+1)*c)*d)*Math.PI*4,m=2*(i*this.width+s);t[m]=.7*Math.cos(u),t[m+1]=.7*Math.sin(u)}}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 s=this.previous;this.previous={x:t,y:e};const a=this.width,o=this.height,n=Math.max(1,a/o),h=Math.max(1,o/a),r=s?(t-s.x)*n:0,l=s?(e-s.y)*h:0,c=Math.hypot(r,l);if(!s&&"dissolve"!==this.mode&&"etch"!==this.mode&&"lens"!==this.mode)return;if(s&&c<1e-4)return;const d=.035+.11*Math.max(.1,Math.min(1,i)),u=Math.min(128,Math.max(1,Math.ceil(c/(.45*d)))),m=c?r/c:1,f=c?l/c:0,g=s||"lens"!==this.mode?Math.min(1,c/(d*u)*2.2):.32;for(let i=0;i<u;i++){const r=(i+.5)/u,l=s?s.x+(t-s.x)*r:t,c=s?s.y+(e-s.y)*r:e,p=Math.max(0,Math.floor((l-2.5*d/n)*(a-1))),M=Math.min(a-1,Math.ceil((l+2.5*d/n)*(a-1))),v=Math.max(0,Math.floor((c-2.5*d/h)*(o-1))),x=Math.min(o-1,Math.ceil((c+2.5*d/h)*(o-1)));for(let t=v;t<=x;t++)for(let e=p;e<=M;e++){const i=(e/(a-1)-l)*n/d,s=(t/(o-1)-c)*h/d,r=Math.exp(1.5*-(i*i+s*s)),u=t*a+e;if("dissolve"===this.mode||"etch"===this.mode)this.ink[u]=Math.max(this.ink[u],r);else if("elastic"===this.mode)this.springX[u]=Math.max(-24,Math.min(24,this.springX[u]+m*r*g*12)),this.springY[u]=Math.max(-24,Math.min(24,this.springY[u]+f*r*g*12));else if("scatter"===this.mode){const t=this.scatterDirections;this.springX[u]=Math.max(-24,Math.min(24,this.springX[u]+(.6*i+t[2*u])*r*g*7)),this.springY[u]=Math.max(-24,Math.min(24,this.springY[u]+(.6*s+t[2*u+1])*r*g*7))}else if("lens"===this.mode)this.targetX[u]=Math.max(-.65,Math.min(.65,this.targetX[u]+i*r*g*1.6)),this.targetY[u]=Math.max(-.65,Math.min(.65,this.targetY[u]+s*r*g*1.6));else if("smudge"===this.mode)this.targetX[u]=Math.max(-1,Math.min(1,this.targetX[u]+m*r*g*1.3)),this.targetY[u]=Math.max(-1,Math.min(1,this.targetY[u]+f*r*g*1.3));else{const t=(-i*f+s*m)*r*2.8,e="magnetic"===this.mode?-i*r*2.5:"silk"===this.mode?m*t:-s*r*2.5,a="magnetic"===this.mode?-s*r*2.5:"silk"===this.mode?f*t:i*r*2.5;this.targetX[u]=Math.max(-1,Math.min(1,this.targetX[u]+e*g)),this.targetY[u]=Math.max(-1,Math.min(1,this.targetY[u]+a*g))}}}this.peak=1}step(t){if(!this.active||!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t)),i="dissolve"===this.mode?2.15:"smudge"===this.mode?2.4:3.2,s="lens"===this.mode?16:22,a=Math.exp(-i*e),o=1-Math.exp(-s*e);let n=0;const[h,r]="scatter"===this.mode?m.scatter:m.elastic,l=Math.sqrt(h-r*r),c=Math.exp(-r*e),d=Math.cos(l*e),f=Math.sin(l*e)/l;for(let t=0;t<this.ink.length;t++)if("etch"===this.mode)this.ink[t]*=a,n=Math.max(n,this.ink[t]);else if("dissolve"===this.mode){this.ink[t]*=a,n=Math.max(n,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(u(this.mode)){const e=this.offsetX[t],i=this.offsetY[t],s=this.springX[t],a=this.springY[t];this.offsetX[t]=Math.max(-1,Math.min(1,c*(e*d+(s+r*e)*f))),this.offsetY[t]=Math.max(-1,Math.min(1,c*(i*d+(a+r*i)*f))),this.springX[t]=c*(s*d-(r*s+h*e)*f),this.springY[t]=c*(a*d-(r*a+h*i)*f),n=Math.max(n,.05*Math.abs(this.springX[t]),.05*Math.abs(this.springY[t]))}else if("lens"===this.mode||"smudge"===this.mode){const e=1-o,n=s/(s-i)*(a-e);this.offsetX[t]=this.offsetX[t]*e+this.targetX[t]*n,this.offsetY[t]=this.offsetY[t]*e+this.targetY[t]*n,this.targetX[t]*=a,this.targetY[t]*=a}else this.targetX[t]*=a,this.targetY[t]*=a,this.offsetX[t]+=(this.targetX[t]-this.offsetX[t])*o,this.offsetY[t]+=(this.targetY[t]-this.offsetY[t])*o;n=Math.max(n,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),l=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]=l>>>8,this.pixels[4*t+3]=255&l}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,s=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,s))*(this.edgeSafe?this.edge[i]:1);const a=Math.round(32767*this.offsetX[i]+32768);this.pixels[4*i]=a>>>8,this.pixels[4*i+1]=255&a}this.peak=n,this.active||this.clear()}sample(t,e,i){const s=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),a=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),o=Math.floor(s),n=Math.floor(a),h=s-o,r=a-n,c=n*this.width+o,d=c+this.width,u=t=>(t[c]*(1-h)+t[c+1]*h)*(1-r)+(t[d]*(1-h)+t[d+1]*h)*r;if("etch"===this.mode)return i[0]=i[1]=0,void(i[2]=3*u(this.offsetX));i[0]=u(this.offsetX)*(this.edgeSafe?l(t,e,this.width/this.height):1)*.08,i[1]=u(this.offsetY)*(this.edgeSafe?l(t,e,this.width/this.height):1)*.08,i[2]="dissolve"===this.mode?6*-u(this.ink):0}},g=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 s=Math.max(1,this.width/this.height),a=Math.max(1,this.height/this.width);this.previous&&(Math.hypot((t-this.previous.x)*s,(e-this.previous.y)*a)<.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),s=Math.max(1,this.height/this.width);let a=0;for(const o of this.rings){const n=.015+o.age*(.15+.22*o.radius),h=.009+.014*o.radius,r=(Math.hypot((t-o.x)*i,(e-o.y)*s)-n)/h,l=Math.sin(Math.min(1,o.age/.07)*Math.PI/2)*Math.max(0,1-o.age/1.35)**2;a=Math.max(a,Math.exp(-r*r)*l)}return a}sample(t,e){const i=Math.max(0,Math.min(this.width-1,Math.round(t*(this.width-1)))),s=Math.max(0,Math.min(this.height-1,Math.round(e*(this.height-1))));return Math.max(this.ringSample(t,e),this.echo[s*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 s=0;for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const a=t*this.width+e;this.echo[a]=Math.max(this.ringSample(e/(this.width-1),t/(this.height-1)),this.echo[a]*i),s=Math.max(s,this.echo[a]);const o=Math.round(65535*this.echo[a]),n=4*a;this.pixels[n]=o>>>8,this.pixels[n+1]=255&o}this.echoPeak=s,this.active||(this.echo.fill(0),this.pixels.fill(0))}},p=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,s=performance.now()){if(!Number.isFinite(t+e+i+s))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 a=this.previous;if(this.previous={x:t,y:e,time:s},!a)return;const o=(t-a.x)*(this.width-1),n=(e-a.y)*(this.height-1),h=Math.hypot(o,n);if(h<.001)return;const r=Math.min(this.width,this.height),l=s>a.time?Math.max(1/240,(s-a.time)/1e3):1/60,c=Math.min(12,h/r/l),d=1-Math.exp(-c/2.2),u=r*(.022+.075*i)*(.65+.95*d),m=Math.min(128,Math.max(1,Math.ceil(h/(.4*u)))),f=h/u*(.32+.22*d)/m,g=o/h,p=n/h,M=-p,v=g,x=h*(2+18*d)/m;for(let i=0;i<m;i++){const s=(i+.5)/m,o=(a.x+(t-a.x)*s)*(this.width-1),n=(a.y+(e-a.y)*s)*(this.height-1),h=Math.max(1,Math.floor(o-3*u)),r=Math.min(this.width-2,Math.ceil(o+3*u)),l=Math.max(1,Math.floor(n-3*u)),c=Math.min(this.height-2,Math.ceil(n+3*u));for(let t=l;t<=c;t++)for(let e=h;e<=r;e++){const i=((e-o)*g+(t-n)*p)/u,s=((e-o)*M+(t-n)*v)/u,a=Math.exp(-i*i*.65-s*s*1.7),h=t*this.width+e;this.ink[h]=1-(1-this.ink[h])*Math.exp(-a*f);const r=1-s*s*.55,l=i*s*.7;this.u[h]=Math.max(-80,Math.min(80,this.u[h]+(g*r+M*l)*a*x)),this.v[h]=Math.max(-80,Math.min(80,this.v[h]+(p*r+v*l)*a*x))}}this.peak=1}read(t,e,i){const s=0|(e=Math.max(.5,Math.min(this.width-1.5,e))),a=0|(i=Math.max(.5,Math.min(this.height-1.5,i))),o=e-s,n=i-a,h=a*this.width+s;return(t[h]*(1-o)+t[h+1]*o)*(1-n)+(t[h+this.width]*(1-o)+t[h+this.width+1]*o)*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,s=this.height;for(;e>1e-7;){const t=Math.min(1/60,e);e-=t;const a=Math.exp(-1.9*t),o=Math.exp(-3.2*t);for(let e=1;e<s-1;e++)for(let n=1;n<i-1;n++){const h=e*i+n,r=Math.max(.5,Math.min(i-1.5,n-this.u[h]*t)),l=Math.max(.5,Math.min(s-1.5,e-this.v[h]*t)),c=0|r,d=0|l,u=r-c,m=l-d,f=d*i+c,g=(1-u)*(1-m),p=u*(1-m),M=(1-u)*m,v=u*m;this.a[h]=(this.u[f]*g+this.u[f+1]*p+this.u[f+i]*M+this.u[f+i+1]*v)*a,this.b[h]=(this.v[f]*g+this.v[f+1]*p+this.v[f+i]*M+this.v[f+i+1]*v)*a,this.c[h]=(this.ink[f]*g+this.ink[f+1]*p+this.ink[f+i]*M+this.ink[f+i+1]*v)*o}[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<s-1;t++)for(let e=1;e<i-1;e++){const s=t*i+e;this.curl[s]=.5*(this.v[s+1]-this.v[s-1]-this.u[s+i]+this.u[s-i])}for(let e=1;e<s-1;e++)for(let s=1;s<i-1;s++){const a=e*i+s,o=Math.abs(this.curl[a+1])-Math.abs(this.curl[a-1]),n=Math.abs(this.curl[a+i])-Math.abs(this.curl[a-i]),h=Math.hypot(o,n)+1e-4,r=this.curl[a]*t*10,l=Math.hypot(this.u[a],this.v[a]);this.u[a]+=n/h*r,this.v[a]-=o/h*r;const c=Math.min(1,l/(Math.hypot(this.u[a],this.v[a])+1e-6));this.u[a]*=c,this.v[a]*=c,this.divergence[a]=-.5*(this.u[a+1]-this.u[a-1]+this.v[a+i]-this.v[a-i])}this.pressure.fill(0);for(let t=0;t<4;t++){for(let t=1;t<s-1;t++)for(let e=1;e<i-1;e++){const s=t*i+e;this.pressureNext[s]=.25*(this.divergence[s]+this.pressure[s-1]+this.pressure[s+1]+this.pressure[s-i]+this.pressure[s+i])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let n=0;for(let e=1;e<s-1;e++)for(let s=1;s<i-1;s++){const a=e*i+s;this.u[a]=Math.max(-80,Math.min(80,this.u[a]-.5*(this.pressure[a+1]-this.pressure[a-1]))),this.v[a]=Math.max(-80,Math.min(80,this.v[a]-.5*(this.pressure[a+i]-this.pressure[a-i]))),this.driftX[a]+=(3.6*this.u[a]-58*this.offsetX[a]-12*this.driftX[a])*t,this.driftY[a]+=(3.6*this.v[a]-58*this.offsetY[a]-12*this.driftY[a])*t,this.offsetX[a]=Math.max(-2,Math.min(2,this.offsetX[a]+this.driftX[a]*t)),this.offsetY[a]=Math.max(-2,Math.min(2,this.offsetY[a]+this.driftY[a]*t)),this.signal[a]=1-Math.exp(.06*-Math.hypot(this.u[a],this.v[a])-.16*this.ink[a]),n=Math.max(n,this.signal[a])}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()}},M=t=>["trail","contour","dissolve","etch","ripple","bleed"].includes(t),v=t=>"etch"===t||"ripple"===t||"bleed"===t,x=t=>v(t)?3:"dissolve"===t?2:"contour"===t?1:0,y=(t,e,i,s)=>(v(i)?(256*t[e]+t[e+1]-32768)/32767:(256*t[e]+t[e+1])/65535)*s;function w(t,e,i){const s=Math.max(0,e-1),a=1-Math.exp(3.5*-Math.max(0,i));return Math.max(0,s-Math.abs(s-(t+a*s*2.1)))}function b(t,e,i,s,a,o,n,h,r,l,c,d=!1){const u=Math.min(a,o,i-1-a,s-1-o),m=Math.max(0,Math.min(1,(u-1)/4)),f=d?m*m*(3-2*m):1;n*=f;const g=1-Math.exp(3.5*-Math.max(0,n)),p=Math.max(0,Math.min(i-1,a-h*g*.026*i*f)),M=Math.max(0,Math.min(s-1,o-r*g*.026*s*f)),v=Math.floor(p),x=Math.floor(M),y=p-v,b=M-x;c.fill(0);for(let a=0;a<2;a++)for(let o=0;o<2;o++){const n=4*(Math.min(s-1,x+a)*i+Math.min(i-1,v+o)),h=(o?y:1-y)*(a?b:1-b);c[0]+=(t[n]+256*t[n+1])*h,c[1]+=t[n+2]/255*h;for(let t=0;t<4;t++)c[t+2]+=e[n+t]*h}const S=43758.5453*Math.sin(127.1*a+311.7*o),k=S-Math.floor(S);c[0]=Math.max(0,w(c[0],l,n)-g*(1-g)*k*3)}var S=[{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:"ripple",label:"Ripple rings",group:"Change characters",description:"Expanding light-and-shadow rings follow your stroke. Faster movement excites stronger rings; the grid stays still."},{value:"bleed",label:"Ink bleed",group:"Change characters",description:"Ink wells up where the cursor rests, spreads along the paper grain, then dries back."},{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:"Characters scatter in soft drifts from your stroke, then spring back into place."},{value:"elastic",label:"Elastic",group:"Move the image",description:"Push the image with your stroke; it recoils past its rest once, then settles."},{value:"lens",label:"Lens wake",group:"Move the image",description:"A soft magnifying wake brings details closer, then relaxes back into focus."},{value:"smudge",label:"Smudge",group:"Move the image",description:"Drag the image in the direction of your stroke; a smooth, lingering pull settles without a bounce."},{value:"loupe",label:"Loupe",group:"Follow the cursor",description:"A glass loupe glides after the cursor and magnifies what it covers, easing through a soft rim."},{value:"reveal",label:"Reveal",group:"Follow the cursor",description:"A soft spotlight shows the original photograph through the characters."},{value:"repel",label:"Repel",group:"Follow the cursor",description:"Characters part around the cursor and spring back with one soft rebound when it leaves."},{value:"tilt",label:"Tilt",group:"Follow the cursor",description:"The image leans toward the cursor; bright areas sit nearer and move more, like a parallax card."},{value:"haze",label:"Heat haze",group:"Follow the cursor",description:"A rising shimmer bends the characters above the cursor, livelier while you move."}],k={rake:"silk"};var E=[{value:"all",label:"Everywhere",description:"The hover acts on the whole artwork."},{value:"subject",label:"Subject",description:"The hover stays on the subject and fades softly at its edge."},{value:"outside",label:"Around",description:"The hover acts only on the ground around the subject."}];function A(t,e,i,s,a){if(!(a<1))for(let o=0;o<2;o++){for(let o=0;o<s;o++){let s=0;const n=o*i;for(let e=-a;e<=a;e++)s+=t[n+Math.max(0,Math.min(i-1,e))];for(let o=0;o<i;o++)e[n+o]=s/(2*a+1),s+=t[n+Math.min(i-1,o+a+1)]-t[n+Math.max(0,o-a)]}for(let o=0;o<i;o++){let n=0;for(let t=-a;t<=a;t++)n+=e[Math.max(0,Math.min(s-1,t))*i+o];for(let h=0;h<s;h++)t[h*i+o]=n/(2*a+1),n+=e[Math.min(s-1,h+a+1)*i+o]-e[Math.max(0,h-a)*i+o]}}}function T(t,e,i,s,a){const o=e*i,n=a&&a.width===e&&a.height===i?a:{width:e,height:i,subject:new Float32Array(o),depth:new Float32Array(o),key:"none"},{subject:h,depth:r}=n;let l=0;for(let e=0;e<o;e++)t[4*e+3]<250&&l++;const c=e=>(.2126*t[4*e]+.7152*t[4*e+1]+.0722*t[4*e+2])/255;let d="none",u=0;if(l>.01*o)d="alpha";else if(s)d="mask";else{let t=0,s=0,a=0;const o=Math.max(1,Math.round(.03*Math.min(e,i)));for(let n=0;n<i;n++)for(let h=0;h<e;h++){if(h>=o&&n>=o&&h<e-o&&n<i-o)continue;const r=c(n*e+h);t+=r,s+=r*r,a++}u=t/Math.max(1,a);Math.sqrt(Math.max(0,s/Math.max(1,a)-u*u))<.07&&(d="ground")}for(let e=0;e<o;e++){const i=t[4*e+3]/255,a=c(e);let o=1;if("alpha"===d)o=i;else if("ground"===d){const t=Math.max(0,Math.min(1,(Math.abs(a-u)-.035)/.12));o=t*t*(3-2*t)}h[e]=o*(s?Math.max(0,Math.min(1,s[e])):1),r[e]=a*i}n.key=d;const m=new Float32Array(o);return A(h,m,e,i,Math.max(1,Math.round(.02*Math.min(e,i)))),A(r,m,e,i,Math.max(1,Math.round(.035*Math.min(e,i)))),n}var D=["loupe","repel","tilt","reveal","haze","bleed"],R=t=>D.includes(t),z=class{constructor(){this.value=0,this.velocity=0}step(t,e,i,s){const a=2*Math.sqrt(i)*s;for(let s=e;s>1e-6;s-=1/480){const e=Math.min(1/480,s);this.velocity+=((t-this.value)*i-this.velocity*a)*e,this.value+=this.velocity*e}}resting(t){return Math.abs(this.value-t)<.0015&&Math.abs(this.velocity)<.01}set(t){this.value=t,this.velocity=0}},F=t=>t*t*(3-2*t),C=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};function X(t,e){const i=Math.floor(t),s=Math.floor(e),a=F(t-i),o=F(e-s),n=C(i,s),h=C(i+1,s),r=C(i,s+1);return(n+(h-n)*a)*(1-o)+(r+(C(i+1,s+1)-r)*a)*o}var I=class{constructor(t,e){this.edgeSafe=!1,this.settle=1,this.focus=[.5,.5,0,.2],this.guide=null,this.mode="loupe",this.radius=.35,this.x=new z,this.y=new z,this.tx=new z,this.ty=new z,this.presence=new z,this.target=null,this.speed=0,this.clock=0,this.inkPeak=0,this.ink=null,this.next=null,this.fiber=null,this.sampled=[0,0,0],this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.sx=Math.max(1,t/e),this.sy=Math.max(1,e/t),this.clear()}setMode(t){if(t!==this.mode&&(this.mode=t,this.clear(),"bleed"===t&&!this.ink)){const t=this.width*this.height;this.ink=new Float32Array(t),this.next=new Float32Array(t),this.fiber=new Float32Array(t);for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++)this.fiber[t*this.width+e]=.35+.5*X(.09*e,.045*t)+.15*C(e,t)}}setRadius(t){this.radius=Math.max(.1,Math.min(1,t))}get reach(){return(.05+.25*this.radius)*("loupe"===this.mode?1-.14*this.speed:1)}get engaged(){return this.presence.value>.002||this.inkPeak>.002||Math.abs(this.tx.value)+Math.abs(this.ty.value)>4e-4}get active(){const t=this.target?1:0;return!this.presence.resting(t)||!!this.target&&(!this.x.resting(this.target.x)||!this.y.resting(this.target.y))||!this.tx.resting(this.tiltGoal(0))||!this.ty.resting(this.tiltGoal(1))||this.speed>.01||"haze"===this.mode&&this.presence.value>.002||this.inkPeak>.002}tiltGoal(t){return this.target&&"tilt"===this.mode?2*((t?this.target.y:this.target.x)-.5):0}clear(){for(const t of[this.x,this.y,this.tx,this.ty,this.presence])t.set(0);this.x.set(.5),this.y.set(.5),this.target=null,this.speed=0,this.inkPeak=0,this.ink?.fill(0),this.next?.fill(0),this.encode()}move(t,e,i){if(!Number.isFinite(t+e))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e));const s=Number.isFinite(i)?i/1e3:this.clock,a=this.target;if(!a&&this.presence.value<.05&&(this.x.set(t),this.y.set(e)),a){const i=Math.hypot((t-a.x)*this.sx,(e-a.y)*this.sy),o=i/Math.max(1/240,Math.min(.1,s-a.time||1/60));this.speed=Math.max(this.speed,Math.min(1,o/1.6)),"bleed"===this.mode&&this.deposit(a.x,a.y,t,e,Math.min(1,9*i))}else"bleed"===this.mode&&this.deposit(t,e,t,e,.5);this.target={x:t,y:e,time:s}}leave(){this.target=null}deposit(t,e,i,s,a){const o=this.ink,n=this.width,h=this.height,r=.55*this.reach,l=Math.hypot((i-t)*this.sx,(s-e)*this.sy),c=Math.min(48,Math.max(1,Math.ceil(l/(.5*r))));for(let l=0;l<c;l++){const d=(l+.5)/c,u=t+(i-t)*d,m=e+(s-e)*d,f=Math.max(0,Math.floor((u-2*r/this.sx)*(n-1))),g=Math.min(n-1,Math.ceil((u+2*r/this.sx)*(n-1))),p=Math.max(0,Math.floor((m-2*r/this.sy)*(h-1))),M=Math.min(h-1,Math.ceil((m+2*r/this.sy)*(h-1)));for(let t=p;t<=M;t++)for(let e=f;e<=g;e++){const i=(e/(n-1)-u)*this.sx/r,s=(t/(h-1)-m)*this.sy/r,l=t*n+e;o[l]=Math.min(1.4,o[l]+Math.exp(1.8*-(i*i+s*s))*a/c*1.6)}}this.inkPeak=Math.max(this.inkPeak,.01)}step(t){if(!Number.isFinite(t)||t<=0)return;const e=Math.min(.05,t),i=e*this.settle;this.clock+=e;const s=this.target,a=this.mode;if(s?this.presence.step(1,e,190,1):this.presence.step(0,i,"repel"===a?120:70,"repel"===a?.42:1),s){const t="tilt"===a?60:"haze"===a?90:240,i="loupe"===a||"repel"===a?.72:.9;this.x.step(s.x,e,t,i),this.y.step(s.y,e,t,i)}this.tx.step(this.tiltGoal(0),s?e:i,45,.78),this.ty.step(this.tiltGoal(1),s?e:i,45,.78),this.speed*=Math.exp(7*-e),"bleed"===a&&this.spread(e,i,!!s),this.engaged||this.active||(this.presence.set(0),this.tx.set(0),this.ty.set(0)),this.focus[0]=this.x.value,this.focus[1]=this.y.value,this.focus[2]=Math.max(0,Math.min(1,this.presence.value)),this.focus[3]=this.reach,this.encode()}spread(t,e,i){const s=this.ink,a=this.next,o=this.fiber,n=this.width,h=this.height;i&&this.target&&this.deposit(this.x.value,this.y.value,this.x.value,this.y.value,.9*t);const r=Math.max(1,Math.ceil(t/(1/240))),l=t/r,c=26*(.4+this.radius),d=(i?.02:.1)*e/t,u=Math.exp(-(i?.15:.9)*e/r);let m=0;for(let t=0;t<r;t++){m=0;for(let t=1;t<h-1;t++)for(let e=1;e<n-1;e++){const i=t*n+e,h=s[i],r=o[i],f=Math.min(r,o[i-1])*(s[i-1]-h)+Math.min(r,o[i+1])*(s[i+1]-h)+Math.min(r,o[i-n])*(s[i-n]-h)+Math.min(r,o[i+n])*(s[i+n]-h),g=Math.max(0,(h+f*Math.min(.24,c*l))*u-d*l);a[i]=g,g>m&&(m=g)}s.set(a)}this.inkPeak=m}sample(t,e,i){i[0]=i[1]=i[2]=0;const s=this.presence.value,a=this.mode;if("bleed"===a){if(this.inkPeak<=.002)return;const s=this.width,a=this.height,o=this.ink,n=Math.max(0,Math.min(s-1.001,t*(s-1))),h=Math.max(0,Math.min(a-1.001,e*(a-1))),r=Math.floor(n),l=Math.floor(h),c=n-r,d=h-l,u=l*s+r,m=u+s,f=(o[u]*(1-c)+o[u+1]*c)*(1-d)+(o[m]*(1-c)+o[m+1]*c)*d;return void(i[2]=1-Math.exp(2.4*-f))}if("tilt"===a){const s=this.guide?function(t,e,i,s){const a=t[e],o=t.width,n=t.height,h=Math.max(0,Math.min(o-1.001,i*(o-1))),r=Math.max(0,Math.min(n-1.001,s*(n-1))),l=Math.floor(h),c=Math.floor(r),d=h-l,u=r-c,m=c*o+l,f=Math.min(n-1,c+1)*o+l,g=l+1<o?1:0;return(a[m]*(1-d)+a[m+g]*d)*(1-u)+(a[f]*(1-d)+a[f+g]*d)*u}(this.guide,"depth",t,e):.6,a=.2+.8*s,o=this.edgeSafe?l(t,e,this.sx/this.sy):1;return i[0]=.024*this.tx.value*a*o/this.sx,void(i[1]=.024*this.ty.value*a*o/this.sy)}if(s<=.001)return;const o=this.reach,n=(t-this.x.value)*this.sx,h=(e-this.y.value)*this.sy,r=(n*n+h*h)/(o*o);if("reveal"===a)return void(i[2]=Math.exp(2.4*-r)*s);if(r>9)return;const c=this.edgeSafe?l(t,e,this.sx/this.sy):1;let d=0,u=0;if("loupe"===a){const t=Math.exp(-r*r)*s*.5;d=n*t,u=h*t;const e=Math.sqrt(r)-1;i[2]=Math.exp(-e*e/.018)*s*.55}else if("repel"===a){const t=Math.sqrt(r),e=.5*o*Math.exp(-r/1.7)*s,a=Math.max(1e-6,Math.sqrt(n*n+h*h));d=n/a*Math.min(e,a+.5*o*s),u=h/a*Math.min(e,a+.5*o*s);const l=Math.max(0,Math.min(1,(t-.3)/.32));i[2]=-(1-l*l*(3-2*l))*s}else if("haze"===a){const a=h/o+.45,r=Math.exp(-n*n/(o*o)-a*a/2.6)*s*(.35+.65*Math.min(1,1.4*this.speed+.25));if(r<.002)return;const l=this.clock,c=t*this.sx*9,m=e*this.sy*9+2.3*l;d=.06*(X(c,m)-.5)*r,u=.026*(X(c+17.3,1.3*m+.7*l)-.5)*r,i[2]=.35*(X(1.7*c+5,1.7*m)-.5)*r}i[0]=d*c/this.sx,i[1]=u*c/this.sy}encode(){const t=this.width,e=this.height,i=this.pixels,s=this.sampled,a=this.engaged;for(let o=0;o<e;o++)for(let n=0;n<t;n++){const h=4*(o*t+n);if(a?this.sample(n/(t-1),o/(e-1),s):s[0]=s[1]=s[2]=0,"bleed"===this.mode){const t=Math.round(32767*Math.max(-1,Math.min(1,s[2]))+32768);i[h]=t>>>8,i[h+1]=255&t,i[h+2]=128,i[h+3]=0}else{"repel"===this.mode&&(s[0]*=.3,s[1]*=.3);const t=Math.round(32767*Math.max(-1,Math.min(1,s[0]/.16))+32768),e=Math.round(32767*Math.max(-1,Math.min(1,s[1]/.16))+32768);i[h]=t>>>8,i[h+1]=255&t,i[h+2]=e>>>8,i[h+3]=255&e}}}},_=(t,e)=>"water"===t?30*e/.55:"silk"===t?28*e:"vortex"===t?38*e:["magnetic","scatter","elastic","lens","smudge"].includes(t)?32*e:["loupe","repel","tilt","haze"].includes(t)?.16*e/.55:0,P=class{constructor(t=1){this.ripple=null,this.cursor=null,this.settle=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,this.guide=null,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]=l(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 p(this.columns,this.rows),this.contour=new g(this.columns,this.rows),this.afterimage=new f(this.columns,this.rows),this.clear()}get invertsDensity(){return"trail"===this.mode}get densityTrail(){return["trail","contour","dissolve","etch","ripple","bleed"].includes(this.mode)}get hasRefraction(){return this.active||this.lensStrength>15e-5}get effect(){return this.mode}get engaged(){return R(this.mode)?this.cursor.engaged:this.active}get spotlight(){return"reveal"===this.mode&&this.cursor?this.cursor.focus:null}get signature(){return R(this.mode)&&this.cursor.engaged?this.cursor.focus.map(t=>t.toFixed(4)).join(","):""}setGuide(t){this.cursor&&(this.cursor.guide=t),this.guide=t}get active(){return R(this.mode)?this.cursor.active:"ripple"===this.mode?this.ripple?.active??!1:d(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){const e="light"===t||"scan"===t?t:function(t){if("string"==typeof t)return t in k?k[t]:S.some(e=>e.value===t)?t:void 0}(t)??"none";e!==this.mode&&(this.clear(),this.mode=e,this.refraction.mode=e,d(e)&&this.afterimage.setMode(e),"ripple"!==e||this.ripple||(this.ripple=new c(this.columns,this.rows)),R(e)&&(this.cursor??(this.cursor=new I(this.columns,this.rows)),this.cursor.guide=this.guide,this.cursor.setMode(e)),this.refraction.pixels=R(e)?this.cursor.pixels:"ripple"===e?this.ripple.pixels:"trail"===e?this.trail.pixels:"contour"===e?this.contour.pixels:d(e)?this.afterimage.pixels:this.waterPixels,this.refraction.strength=_(e,this.amount),this.refraction.relative=R(e))}configure(t,e=.55,i=.2,s=!1,a=.5){this.setMode(t),this.settle=((t=.5)=>Math.pow(2,2.4*(.5-(Number.isFinite(t)?Math.max(0,Math.min(1,t)):.5))))(a),this.refraction.edgeSafe=s,this.afterimage.edgeSafe=s,this.ripple&&(this.ripple.edgeSafe=s),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.cursor&&(this.cursor.edgeSafe=s,this.cursor.settle=this.settle,this.cursor.setRadius(this.radius)),this.refraction.strength=_(this.mode,this.amount),this.refraction.focus[2]=this.densityTrail?this.amount:this.lensStrength*this.amount,this.refraction.focus[3]=this.radius,"reveal"!==this.mode&&"repel"!==this.mode||this.syncSpot()}syncSpot(){const t=this.cursor.focus;this.refraction.focus=[t[0],t[1],t[2]*("repel"===this.mode?Math.min(1,this.amount/.55):this.amount),t[3]]}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)),R(this.mode))return void this.cursor.move(t,e,i);if("ripple"===this.mode)return void this.ripple.move(t,e,this.radius,i);if(d(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 s=this.previous;this.previous={x:t,y:e};const a=(t-s.x)*this.xScale,o=(e-s.y)*this.yScale,n=Math.hypot(a,o);if(n<1e-5)return;const h=.035+.1*this.radius,r=3*h,l=Math.min(192,Math.max(1,Math.ceil(n/(.5*h)))),c=95*Math.min(n,1)/l;for(let i=0;i<l;i++){const a=(i+.5)/l,o=s.x+(t-s.x)*a,n=s.y+(e-s.y)*a,d=Math.max(1,Math.floor((o-r/this.xScale)*(this.columns-1))),u=Math.min(this.columns-2,Math.ceil((o+r/this.xScale)*(this.columns-1))),m=Math.max(1,Math.floor((n-r/this.yScale)*(this.rows-1))),f=Math.min(this.rows-2,Math.ceil((n+r/this.yScale)*(this.rows-1)));for(let t=m;t<=f;t++)for(let e=d;e<=u;e++){const i=(e/(this.columns-1)-o)*this.xScale,s=(t/(this.rows-1)-n)*this.yScale,a=Math.exp(-(i*i+s*s)/(h*h))*c,r=t*this.columns+e;this.velocity[r]=Math.max(-12,this.velocity[r]-a)}}this.pending=!0}leave(){this.cursor?.leave(),this.ripple?.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.ripple?.clear(),this.cursor?.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(R(this.mode))return this.cursor.step(t),void("reveal"!==this.mode&&"repel"!==this.mode||this.syncSpot());if(t*=this.settle,"ripple"===this.mode)return void this.ripple.step(t);if(d(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),s=.3*Math.min(this.columns,this.rows);for(;this.remainder+1e-8>=e;){this.remainder-=e;let t=0;for(let a=1;a<this.rows-1;a++)for(let o=1;o<this.columns-1;o++){const n=a*this.columns+o,h=this.heights[n],r=this.heights[n-1]+this.heights[n+1]+this.heights[n-this.columns]+this.heights[n+this.columns]-4*h,l=Math.min(o,a,this.columns-1-o,this.rows-1-a),c=l<5?.88+.024*l:1,d=(this.velocity[n]+(r*s*s-8*h)*e)*i*c;this.velocity[n]=d,this.next[n]=(h+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 a=.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,s=(this.heights[t*this.columns+Math.max(0,e-1)]-this.heights[t*this.columns+Math.min(this.columns-1,e+1)])*a,o=(this.heights[Math.max(0,t-1)*this.columns+e]-this.heights[Math.min(this.rows-1,t+1)*this.columns+e])*a,n=Math.tanh(s)*(this.refraction.edgeSafe?this.edgeMask[i]:1),h=Math.tanh(o)*(this.refraction.edgeSafe?this.edgeMask[i]:1);this.normals[2*i]=n,this.normals[2*i+1]=h;const r=Math.round(32767*n+32768),l=Math.round(32767*h+32768);this.refraction.pixels[4*i]=r>>>8,this.refraction.pixels[4*i+1]=255&r,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),s=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)*s,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(R(this.mode))return this.cursor.sample(t,e,i),i[0]*=this.amount/.55,i[1]*=this.amount/.55,void(i[2]*="reveal"===this.mode||"repel"===this.mode?Math.min(1,this.amount/.55):3*this.amount);if("ripple"===this.mode)return this.ripple.sample(t,e,i),void(i[2]*=this.amount);if(d(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 s=Math.max(0,Math.min(this.columns-1.001,t*(this.columns-1))),a=Math.max(0,Math.min(this.rows-1.001,e*(this.rows-1))),o=Math.floor(s),n=Math.floor(a),h=s-o,r=a-n,l=2*(n*this.columns+o),c=l+2*this.columns;for(let t=0;t<2;t++)i[t]=.08*((this.normals[l+t]*(1-h)+this.normals[l+2+t]*h)*(1-r)+(this.normals[c+t]*(1-h)+this.normals[c+2+t]*h)*r);i[0]*=this.amount/.55,i[1]*=this.amount/.55,i[2]="light"===this.mode||"scan"===this.mode?function(t,e,i,s){const[a,o,n,h]=i.focus,r=(t-a)*Math.max(1,s)/h,l=(e-o)*Math.max(1,1/s)/h;return"light"===i.mode?Math.exp(-3*(r*r+l*l))*n:"scan"===i.mode?(1.3*Math.exp(-r*r*110)-.3*Math.exp(-r*r*12))*Math.exp(-l*l*1.8)*n:0}(t,e,this.refraction,this.xScale/this.yScale):0}};var U=[{value:"clean",label:"Clean",description:"Crisp characters with no optical texture."},{value:"signal",label:"Signal",description:"Broken scanlines at the edges, with a clear center."},{value:"prism",label:"Prism",description:"Soft red/cyan separation at the edges, with a crisp center."},{value:"etch",label:"Etch",description:"A fine engraved texture, keeping the ink monochrome."}];var G=(t,e,i)=>{const s=Math.max(0,Math.min(1,(i-t)/(e-t)));return s*s*(3-2*s)};function L(t,e,i=256){let s=0;for(let e=0;e<t.length;e++)t[e]>s&&(s=t[e]);if(s<=0)return 0;const a=new Uint32Array(i);for(let e=0;e<t.length;e++)a[Math.min(i-1,Math.floor(t[e]/s*i))]++;let o=0;const n=t.length*e;for(let t=0;t<i;t++)if(o+=a[t],o>=n)return(t+1)/i*s;return s}function N(t){const e=Intl.Segmenter;return e?Array.from(new e(void 0,{granularity:"grapheme"}).segment(t),t=>t.segment):Array.from(t)}function Y(){const t=document.createElement("canvas"),e=document.createElement("canvas"),i=t.getContext("2d"),s=e.getContext("2d",{willReadFrequently:!0}),a=function(){const t=new WeakMap;return(e,i,s="")=>{if(!e)return i;let a=t.get(e);if(!a){const i=new Set;for(const t of e)for(const e of t)e.char&&i.add(e.char);a=[...i].sort(),t.set(e,a)}const o=i+s;return i+a.filter(t=>!o.includes(t)).join("")}}();let o,n=null;return{update(h,r,l,c,d,u,m,f){const g=m?.[0]?.length??Math.max(1,Math.round(r/c)),p=m?.length??Math.max(1,Math.round(l/d)),M=f??{charset:" .:-=+*#%@",customText:"",colorMode:"fullcolor"},v=a(m,M.charset+(M.charsetFrames?.join("")??""),M.customText),x=function(t,e,i,s,a,o,n,h=4096,r=0,l=1){if(![i,s,a,o,n,h].every(t=>Number.isFinite(t)&&t>0))throw new Error("Glyph atlas dimensions must be positive and finite.");const c=JSON.stringify([e.charset,e.customText,i,s,a,o,n,h,r,l]);if(t?.key===c)return t;const d=[...new Set([" ",...N(e.charset),...N(e.customText??"")])];if(d.length>65536)throw new Error("This character set exceeds the glyph texture capacity.");const u=i/o,m=s/n,f=.9*Math.min(u/.55,m)*l,g=Math.ceil(u*a)+6,p=Math.ceil(m*a)+6,M=Math.min(d.length,Math.floor(h/g));if(M<1||Math.ceil(d.length/M)*p>h)throw new Error("The glyph atlas exceeds the available GPU texture size.");return{key:c,glyphs:d,indices:new Map(d.map((t,e)=>[t,e])),cellWidth:u,cellHeight:m,fontSize:f,padding:3,tileWidth:g,tileHeight:p,atlasColumns:M,atlasWidth:M*g,atlasHeight:Math.ceil(d.length/M)*p}}(n,{...M,charset:v},r,l,u,g,p);if(x!==n&&(t.width=x.atlasWidth,t.height=x.atlasHeight,i.font=x.fontSize*u+'px "JetBrains Mono", monospace',i.textAlign="center",i.textBaseline="middle",i.fillStyle="#fff",x.glyphs.forEach((t,e)=>i.fillText(t,e%x.atlasColumns*x.tileWidth+x.padding+x.cellWidth*u*.5,Math.floor(e/x.atlasColumns)*x.tileHeight+x.padding+x.cellHeight*u*.5))),n=x,m)o=function(t,e,i,s,a=!1){const o=t.length,n=t[0]?.length??0,h=s?.cols===n&&s.rows===o?s:{cols:n,rows:o,indices:new Uint8Array(n*o*4),colors:new Uint8ClampedArray(n*o*4)};h.indices.fill(0),h.colors.fill(0);const r="accent"===i.colorMode?[1,3,5].map(t=>parseInt(i.accentColor.slice(t,t+2),16)):null;for(let s=0;s<o;s++){if(t[s].length!==n)throw new Error("Glyph frames must have a rectangular cell grid.");for(let o=0;o<n;o++){const l=t[s][o];if(!l.char||!a&&" "===l.char||l.a<10)continue;const c=e.get(l.char);if(void 0===c)throw new Error(`Glyph is absent from the configured character set: ${l.char}`);const d=4*(s*n+o);let u=l.r,m=l.g,f=l.b;if(r)[u,m,f]=r;else if("fullcolor"!==i.colorMode){const t=.299*u+.587*m+.114*f|0;u="matrix"===i.colorMode?0:t,m=t,f=u}(a||0!==u||0!==m||0!==f)&&(h.indices[d]=255&c,h.indices[d+1]=c>>>8,h.indices[d+2]=Math.round(.299*l.r+.587*l.g+.114*l.b),h.colors[d]=u,h.colors[d+1]=m,h.colors[d+2]=f,h.colors[d+3]=l.a)}}return h}(m,n.indices,M,o,!0);else{e.width=g,e.height=p,s.drawImage(h,0,0,g,p);const t=s.getImageData(0,0,g,p).data;o={cols:g,rows:p,indices:new Uint8Array(g*p*4),colors:new Uint8ClampedArray(t)};for(let e=0;e<t.length;e+=4){const i=Math.min(1,(.299*t[e]+.587*t[e+1]+.114*t[e+2])/255*(t[e+3]/255)*3);o.indices[e+2]=Math.round(255*i),o.indices[e]=Math.min(n.glyphs.length-1,Math.floor(i*n.glyphs.length))}}return{plan:n,packed:o,atlas:t,dots:"dots"===M.renderMode,dotSize:M.dotSizeRatio??.72}},reset(){n=null},destroy(){t.width=t.height=e.width=e.height=1,o=void 0,n=null}}}function B(t){return!!t&&"ascii"===t.renderMode&&!/\p{Extended_Pictographic}/u.test(t.customText||t.charset)&&!t.charsetFrames?.length&&["fullcolor","grayscale","matrix","accent"].includes(t.colorMode)&&("accent"!==t.colorMode||/^#[\da-f]{6}$/i.test(t.accentColor))}function O(t){for(let e=t;e;e=e.parentElement){const t=getComputedStyle(e).backgroundColor.match(/[\d.]+/g)?.map(Number);if(t&&t.length>=3&&(t[3]??1)>.5)return(.299*t[0]+.587*t[1]+.114*t[2])/255<.4?[10/255,10/255,10/255,1]:[250/255,249/255,247/255,1]}const e=document.documentElement.dataset.theme;if("dark"!==e&&"light"!==e&&!t.isConnected&&document.body)return O(document.body);return"dark"===e||"light"!==e&&(document.documentElement.classList.contains("dark")||matchMedia("(prefers-color-scheme: dark)").matches)?[10/255,10/255,10/255,1]:[250/255,249/255,247/255,1]}function H(t,e,a){const o=e.style.visibility;let l=document.createElement("canvas"),c=null,d=null,u=null,m=null;const f=[],g=[];let p=!1,v=!1,S=4096,k=null,E=0,D=0,R=0,z=0,F=!1;const C=function(){const t=document.createElement("canvas"),e=t.getContext("2d");return{paint(i,s,a,o){s&&(t.width===i.canvas.width&&t.height===i.canvas.height||(t.width=i.canvas.width,t.height=i.canvas.height),e.globalCompositeOperation="copy",e.drawImage(i.canvas,0,0),e.globalCompositeOperation="destination-in",e.drawImage(s.canvas,0,0,t.width,t.height),e.globalCompositeOperation="source-in",e.fillStyle="#090909",e.fillRect(0,0,t.width,t.height),e.globalCompositeOperation="source-over",i.drawImage(t,0,0,a,o))},destroy(){t.width=t.height=1}}}();let X,I;const _=document.createElement("canvas"),P=document.createElement("canvas"),N=_.getContext("2d"),H=P.getContext("2d");let W=!1;const j=new h,K=Y();let q=null,$=null,V=null,J=new Uint8Array(0),Z=new Uint8Array(0),Q={};const tt=()=>{l.className="ascii-hover-surface",l.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none",l.setAttribute("role","img"),l.setAttribute("aria-label","ASCII artwork preview"),l.dataset.renderer=c?"surface-gpu":"surface-canvas",t.prepend(l),e.style.visibility="hidden"},et=()=>{c&&(f.forEach(t=>c.deleteTexture(t)),g.forEach(t=>c.deleteShader(t)),u&&c.deleteProgram(u),m&&c.deleteBuffer(m))},it=()=>{p||d||(l.removeEventListener("webglcontextlost",it),et(),l.remove(),c=null,l=document.createElement("canvas"),d=l.getContext("2d"),tt(),a())};try{if(c=l.getContext("webgl",{alpha:!0,antialias:!1,depth:!1,stencil:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!0}),!c)throw new Error("WebGL unavailable");S=c.getParameter(c.MAX_TEXTURE_SIZE);const t=(t,e)=>{const i=c.createShader(t);if(g.push(i),c.shaderSource(i,e),c.compileShader(i),!c.getShaderParameter(i,c.COMPILE_STATUS))throw new Error(c.getShaderInfoLog(i)||"Shader compilation failed");return i};if(u=c.createProgram(),c.attachShader(u,t(c.VERTEX_SHADER,"attribute vec2 position; void main(){gl_Position=vec4(position,0.,1.);}")),c.attachShader(u,t(c.FRAGMENT_SHADER,"\n precision highp float;\n uniform sampler2D artwork; uniform sampler2D surface;\n uniform vec2 resolution; uniform vec2 sceneSize; uniform vec2 cellSize;\n uniform vec2 surfaceSize; uniform float strength; uniform float relativeStrength;\n \nuniform float hoverMode;\nuniform vec4 hoverFocus;\nfloat surfaceLight(vec2 uv, vec2 size) {\n vec2 delta = (uv - hoverFocus.xy) * size / min(size.x, size.y) / hoverFocus.w;\n float light = exp(-3.0 * dot(delta, delta));\n if (hoverMode > 2.5) light = -smoothstep(.85, .35, length(delta));\n else if (hoverMode > 1.5) light = (exp(-delta.x * delta.x * 110.0) * 1.3 - exp(-delta.x * delta.x * 12.0) * .3) * exp(-delta.y * delta.y * 1.8);\n return hoverMode > .5 ? light * hoverFocus.z : 0.0;\n}\nvec3 illuminate(vec3 ink, float light) {\n return mix(ink, vec3(1.0), max(0.0, light) * .82) * (1.0 + min(0.0, light));\n}\n\n uniform sampler2D codes; uniform sampler2D cellColors; uniform sampler2D glyphAtlas;\n uniform vec2 gridSize; uniform vec2 atlasSize; uniform vec2 tileSize;\n uniform float atlasColumns; uniform float padding; uniform float glyphCount;\n uniform float dots; uniform float dotSize; uniform float directGlyphs; uniform vec4 backdrop;\n uniform float edgeEffect; uniform sampler2D textMask; uniform float hasTextMask; uniform sampler2D cueMap;\n \nuniform float finishMode;\nuniform float finishPixelRatio;\nuniform float finishSoftness;\nvec3 edgeCoverage(sampler2D sheet, vec2 uv, vec2 atlas, vec2 pixel, vec2 viewport, float amount) {\n float a=texture2D(sheet,uv).a;\n if(amount<=0.0 || finishMode<.5) return vec3(a);\n vec2 radial=(pixel/viewport-.5)*2.0;\n float edge=smoothstep(.3,1.05,length(radial));\n float strength=clamp(amount,0.0,1.0)*edge;\n if(strength<=0.0) return vec3(a);\n vec2 cssPixel=pixel/max(1.0,finishPixelRatio);\n // Etch is a single texture sample: linework, not an opacity wash.\n if(finishMode>1.5 && finishMode<2.5) {\n float hatch=step(.68,fract((cssPixel.y+cssPixel.x*.22)*.5));\n return vec3(a*(1.0-hatch*strength*.64));\n }\n // Samples remain inside the current atlas tile's three-pixel padding.\n if(finishMode>2.5) {\n float band=floor(cssPixel.y/3.0);\n float phase=fract(sin(band*12.9898)*43758.5453);\n float tear=(phase-.5)*3.6*strength;\n float displaced=texture2D(sheet,uv+vec2(tear,0.0)/atlas).a;\n float cut=step(.72,fract(cssPixel.y*.5));\n return vec3(mix(a,displaced,strength)*(1.0-cut*.55*strength));\n }\n // A five-tap lens: opposed red/cyan edges with a short soft shoulder.\n // The center remains untouched; all offsets stay within three atlas texels.\n vec2 direction=normalize(vec2(radial.x-radial.y*.3,radial.y+radial.x*.3)+vec2(.00001));\n vec2 shift=direction*(2.35+.45*finishSoftness)*strength/atlas;\n float left=texture2D(sheet,uv-shift).a,right=texture2D(sheet,uv+shift).a;\n float softLeft=texture2D(sheet,uv-shift*.45).a,softRight=texture2D(sheet,uv+shift*.45).a;\n float red=left*.7+softLeft*.22+a*.08;\n float cyan=right*.7+softRight*.22+a*.08;\n // Reuse the same taps for a short optical blur and peripheral fade.\n // No whole-canvas blur, extra pass or softened HTML controls.\n float soft=a*.4+(left+right+softLeft+softRight)*.15;\n vec3 fringe=mix(vec3(red,cyan,cyan),vec3(soft),finishSoftness*.45);\n return mix(vec3(a),fringe,strength)*(1.-finishSoftness*strength*.32);\n\n}\n\n \nuniform float edgeSafe;\nuniform float trailAmount;\nuniform float trailKind;\nuniform sampler2D scopeMap;\nuniform float scopeMode;\n// Hover scope: 0 everywhere, 1 on the subject, 2 around it. The map holds soft subject coverage in alpha.\nfloat hoverScope(vec2 uv) {\n if (scopeMode < .5) return 1.;\n float s=texture2D(scopeMap,uv).a;\n return scopeMode < 1.5 ? s : 1.-s;\n}\nvec4 trailField(vec2 address) {\n return texture2D(surface,(address*(surfaceSize-1.0)+.5)/surfaceSize);\n}\nfloat trailFieldDensity(vec4 field) {\n float raw=field.r*65280.0+field.g*255.0;\n return (trailKind>2.5?(raw-32768.)/32767.:raw/65535.)*trailAmount;\n}\nfloat trailDensity(vec2 address) { return trailFieldDensity(trailField(address))*hoverScope(address); }\nfloat trailPin(vec2 cell, vec2 grid) {\n vec2 edge=min(cell,grid-1.0-cell);\n return mix(1.,smoothstep(1.0,5.0,min(edge.x,edge.y)),edgeSafe);\n}\nvec2 trailSource(vec2 cell, vec2 grid, vec4 field) {\n vec2 home=(cell+.5)/grid;\n if(trailKind>.5 || trailAmount<=0.) return home;\n float pin=trailPin(cell,grid);\n float response=1.-exp(-trailFieldDensity(field)*hoverScope(home)*pin*3.5);\n vec2 drift=(field.ba*255.-128.)/127.;\n return clamp(home-drift*response*.026*pin,.5/grid,1.-.5/grid);\n}\nvec2 decodedGlyph(vec4 code) {\n return vec2(floor(code.r*255.+.5)+floor(code.g*255.+.5)*256.,code.b);\n}\n// Bilinear interpolation happens before glyph selection, never between bitmap\n// letters. Four small metadata reads replace the old four full-glyph gathers.\nvec2 flowGlyph(sampler2D codes,vec2 uv,vec2 grid) {\n vec2 p=uv*grid-.5,b=floor(p),f=fract(p);\n return mix(mix(decodedGlyph(texture2D(codes,(b+.5)/grid)),decodedGlyph(texture2D(codes,(b+vec2(1.5,.5))/grid)),f.x),\n mix(decodedGlyph(texture2D(codes,(b+vec2(.5,1.5))/grid)),decodedGlyph(texture2D(codes,(b+1.5)/grid)),f.x),f.y);\n}\nvec3 trailInk(vec3 ink, float density) {\n if (trailKind < .5) return ink;\n float peak=max(ink.r,max(ink.g,ink.b));\n float raised=trailKind>1.5?peak:max(peak,min(.44,density*.75));\n return peak>.001 ? ink*(raised/peak) : vec3(raised);\n}\nfloat flowIndex(float index,float count,float density) {\n float last=max(0.,count-1.);\n float response=1.-exp(-max(0.,density)*3.5);\n return max(0.,last-abs(last-(index+response*last*2.1)));\n}\nfloat trailTone(float tone, float density) {\n if (trailKind > 2.5) return clamp(tone+density*.35,0.,1.);\n if (trailKind < .5) return flowIndex(tone,2.,density);\n return clamp(tone + (trailKind > 1.5 ? -density : density) * .65, 0.0, 1.0);\n}\nfloat trailIndex(float index, float count, float density, vec2 cell) {\n float grain=fract((cell.x*cell.x*17.0+cell.y*cell.y*23.0+cell.x*cell.y*19.0)*.0137);\n if(trailKind>2.5) return clamp(floor(index+density*(count-1.)*.35+.5),0.,count-1.);\n if(trailKind>1.5) return max(0.0,index-floor(density*count*(1.35+grain*.9)));\n if(trailKind<.5) {\n float seed=fract(sin(dot(cell,vec2(127.1,311.7)))*43758.5453);\n float response=1.-exp(-max(0.,density)*3.5);\n return floor(max(0.,flowIndex(index,count,density)-response*(1.-response)*seed*3.)+.5);\n }\n return min(count-1.0,index+floor(density*count*.85));\n}\n\n \n uniform float motionMode; uniform float motionTime; uniform float fineDither; uniform float ditherAmount; uniform vec2 motionFocus;\n float printGrain(vec2 p) { return fract(52.9829189*fract(dot(p,vec2(.06711056,.00583715)))); }\n // cue: light, depth, glow, detail; normal: relief normal.\n vec4 ambientAt(vec2 uv, float tone, vec4 cue, vec2 normal) {\n if(motionMode<.5) return vec4(0.,0.,0.,1.);\n float p=motionTime*.5235987756, cycle=mod(motionTime,12.);\n float edge=smoothstep(0.,.12,min(min(uv.x,1.-uv.x),min(uv.y,1.-uv.y)));\n tone=clamp(tone,0.,1.);\n if(motionMode<1.5) {\n float a=p+.6; vec2 l=vec2(cos(a),sin(a));\n float form=clamp(dot(normal,l),-1.,1.)+dot(uv-.5,l)*.35;\n return vec4(0.,0.,form*.2*(.3+.7*smoothstep(.04,.3,cue.x)*(1.-.6*smoothstep(.82,1.,tone))),1.);\n }\n if(motionMode<2.5) {\n float position=-.35+1.9*smoothstep(0.,8.,cycle);\n float d=(uv.x*.75+uv.y*.45)/1.2+(normal.x*.75+normal.y*.45)*.05;\n float band=exp(-pow((d-position)/.12,2.));\n return vec4(0.,0.,band*smoothstep(.3,.8,cue.x)*(1.-.5*smoothstep(.9,1.,tone))*.45,1.);\n }\n if(motionMode<3.5) {\n float k=.5-.5*cos(p), threshold=1.-.8*k;\n return vec4(0.,0.,.2*smoothstep(threshold-.3,threshold+.02,cue.z)*sqrt(cue.z)*(1.-.65*tone)+.05*k*smoothstep(.6,.95,tone),1.);\n }\n if(motionMode<4.5) {\n float phase=printGrain(floor(uv*vec2(160.,100.)))*6.28318530718;\n float glint=pow(.5+.5*cos(p*2.+phase),28.);\n return vec4(0.,0.,glint*smoothstep(.5,.88,tone)*(.35+.65*smoothstep(.1,.55,cue.w))*.42,1.);\n }\n if(motionMode<5.5) { float near=cue.y-.45; return vec4(near*16.*sin(p)*edge,near*7.*sin(p*2.)*edge,0.,1.); }\n if(motionMode<6.5) return vec4((uv-motionFocus)*.045*(.5-.5*cos(p))*(.7+.6*cue.y)*960.,0.,1.);\n if(motionMode<7.5) {\n float s=sin(p), defocus=s*s*smoothstep(.15,.6,s>=0.?1.-cue.y:cue.y);\n return vec4(0.,0.,(cue.x-tone)*defocus*.9,1.);\n }\n if(motionMode<8.5) {\n float far=pow(1.-cue.y,1.5)*(1.-.6*cue.w);\n float veil=sin(uv.x*4.1-p+sin(uv.y*3.3+p)*.9)*.5+sin(uv.x*7.3+uv.y*2.1-p*2.+sin(uv.x*2.7-uv.y*5.1+p)*1.1)*.3+sin(uv.y*5.7-uv.x*1.9+p)*.2;\n return vec4(0.,0.,smoothstep(-.3,.9,veil)*far*.16*(1.-.55*tone),1.);\n }\n if(motionMode<9.5) {\n float fluid=(1.-.4*cue.w)*(1.-.8*cue.y)*edge, wave=uv.y*14.-p+sin(uv.x*3.+p)*1.5, still=uv.y*14.+sin(uv.x*3.)*1.5;\n return vec4((sin(wave)-sin(still)+(sin(uv.x*5.-uv.y*3.+p)-sin(uv.x*5.-uv.y*3.))*.43)*7.*fluid,(sin(uv.x*11.+p)-sin(uv.x*11.))*2.*fluid,(cos(wave)-cos(still))*.03*fluid,1.);\n }\n float fade=smoothstep(7.,8.5,cycle), k=clamp((cycle-8.5)/3.5,0.,1.);\n float shown=cycle<8.5?1.-fade:smoothstep(0.,1.,(k*1.45-(1.-tone)+(printGrain(floor(uv*vec2(160.,100.)))-.5)*.06)/.3);\n return vec4(0.,0.,-(1.-shown)*.3,1.-(1.-shown)*.9);\n }\n\n float toneAt(vec2 uv) {\n vec2 p=uv*gridSize-.5, b=floor(p), f=fract(p);\n return mix(mix(texture2D(codes,(b+.5)/gridSize).b,texture2D(codes,(b+vec2(1.5,.5))/gridSize).b,f.x),mix(texture2D(codes,(b+vec2(.5,1.5))/gridSize).b,texture2D(codes,(b+1.5)/gridSize).b,f.x),f.y);\n }\n vec4 flowingCharacter(vec2 pixel, vec2 cell, vec4 ambient) {\n if(cell.x<0. || cell.y<0. || cell.x>=gridSize.x || cell.y>=gridSize.y) return vec4(0.);\n vec2 address=(cell+.5)/gridSize;\n vec4 field=trailField(address);\n vec2 local=pixel-cell*cellSize;\n if(local.x<0. || local.y<0. || local.x>=cellSize.x || local.y>=cellSize.y) return vec4(0.);\n vec2 source=trailSource(cell,gridSize,field);\n vec2 encoded=flowGlyph(codes,source,gridSize);\n vec4 color=texture2D(cellColors,source);\n float original=encoded.x;\n float density=trailFieldDensity(field)*hoverScope(address)*trailPin(cell,gridSize),index=trailIndex(original,glyphCount,density,cell);\n if(original>.5) index=clamp(floor(index+ambient.z*(glyphCount-1.)+printGrain(cell)),0.,glyphCount-1.);\n if(index<.5 || color.a<.01) return vec4(0.);\n vec2 slot=vec2(mod(index,atlasColumns),floor(index/atlasColumns));\n float alpha=texture2D(glyphAtlas,(slot*tileSize+padding+local*resolution/sceneSize)/atlasSize).a;\n if(dots>.5) {\n vec2 d=(local-cellSize*.5)/min(cellSize.x,cellSize.y);\n float r=min(.48,(index/(glyphCount-1.))*.5*dotSize);\n alpha=1.-smoothstep(r-.06,r+.02,length(d));\n }\n vec3 coverage=dots>.5?vec3(alpha):edgeCoverage(glyphAtlas,(slot*tileSize+padding+local*resolution/sceneSize)/atlasSize,atlasSize,pixel,sceneSize,edgeEffect);\n coverage*=color.a;alpha=max(coverage.r,max(coverage.g,coverage.b));\n return vec4(trailInk(color.rgb,density)*coverage,alpha);\n }\n void main(){\n vec2 uv = vec2(gl_FragCoord.x, resolution.y - gl_FragCoord.y) / resolution;\n vec2 pixel = uv * sceneSize;\n if (strength > 0.) {\n vec4 normal = texture2D(surface, (uv * (surfaceSize - 1.) + .5) / surfaceSize) * 255.;\n vec2 slope = (vec2(normal.r * 256. + normal.g, normal.b * 256. + normal.a) - 32768.) / 32767.;\n vec2 edge = min(pixel, sceneSize - pixel) / cellSize;\n // Cursor hovers store a fraction of the scene, so they scale with it; stroke hovers store CSS pixels.\n vec2 unit = relativeStrength > .5 ? vec2(1.) : 1. / sceneSize;\n uv -= slope * strength * mix(1.,smoothstep(2.,8.,min(edge.x,edge.y)),edgeSafe) * hoverScope(uv) * unit;\n }\n vec4 ambient=vec4(0.,0.,0.,1.);\n if(motionMode>.5) {\n vec4 cue=texture2D(cueMap,uv);\n vec2 step=1./gridSize;\n vec2 slope=vec2(texture2D(cueMap,uv+vec2(step.x,0.)).x-texture2D(cueMap,uv-vec2(step.x,0.)).x,texture2D(cueMap,uv+vec2(0.,step.y)).x-texture2D(cueMap,uv-vec2(0.,step.y)).x);\n // Bright reads as raised; normals lean away from the brighter side.\n ambient=ambientAt(uv,toneAt(uv),cue,-slope/max(length(slope),1e-4)*smoothstep(0.,.06,length(slope)));\n }\n uv -= ambient.xy/sceneSize;\n pixel=uv*sceneSize;\n vec4 ink = vec4(0.);\n if (directGlyphs > .5) {\n vec2 cell=floor(pixel/cellSize), address=(cell+.5)/gridSize;\n vec4 encoded=texture2D(codes,address), color=texture2D(cellColors,address);\n float index=floor(encoded.r*255.+.5)+floor(encoded.g*255.+.5)*256.;\n if(index>.5 && color.a>.01) {\n vec2 local=(pixel-cell*cellSize)*resolution/sceneSize;\n vec2 slot=vec2(mod(index,atlasColumns),floor(index/atlasColumns));\n float alpha=texture2D(glyphAtlas,(slot*tileSize+padding+local)/atlasSize).a*color.a;\n vec3 coverage=edgeCoverage(glyphAtlas,(slot*tileSize+padding+local)/atlasSize,atlasSize,pixel,sceneSize,edgeEffect)*color.a;\n ink=vec4(color.rgb*coverage,max(coverage.r,max(coverage.g,coverage.b)));\n }\n } else ink = texture2D(artwork, uv);\n if (fineDither > .5) {\n vec2 cell=floor(pixel/cellSize),address=(cell+.5)/gridSize;\n vec4 color=texture2D(cellColors,address);\n float density=trailAmount>0.?trailDensity(address):0.;\n vec2 source=trailAmount>0. && trailKind<.5?trailSource(cell,gridSize,trailField(address)):uv;\n float tone=trailTone(clamp(toneAt(source)+ambient.z,0.,1.),density*(trailKind<.5?trailPin(cell,gridSize):1.));\n float pitch=max(1.,min(cellSize.x,cellSize.y)*.32);\n float grain=.5+(printGrain(floor(pixel/pitch))-.5)*ditherAmount;\n float alpha=(tone<.001?0.:tone>.999?1.:smoothstep(grain-.035,grain+.035,tone))*color.a*ambient.w;\n // Preserve hue; tone is carried by mark coverage rather than muddy ink.\n vec3 hue=color.rgb/max(.001,max(color.r,max(color.g,color.b)));\n if(hasTextMask>.5) hue=mix(hue,vec3(.035),texture2D(textMask,vec2(gl_FragCoord.x,resolution.y-gl_FragCoord.y)/resolution).a);\n gl_FragColor=vec4(hue*alpha,alpha); return;\n }\n if ((trailAmount > 0. && trailKind > .5) || motionMode > .5) {\n vec2 cell=floor(pixel/cellSize), address=(cell+.5)/gridSize;\n float density=trailAmount>0.?trailDensity(address):0.;\n vec4 encoded=texture2D(codes,address);\n float original=floor(encoded.r*255.+.5)+floor(encoded.g*255.+.5)*256.;\n float index=trailIndex(original,glyphCount,density,cell);\n if(original>.5) index=clamp(floor(index+ambient.z*(glyphCount-1.)+printGrain(cell)),0.,glyphCount-1.);\n vec4 color=texture2D(cellColors,address);\n if((index!=original || motionMode>.5) && color.a>.01) {\n vec2 local=(pixel-cell*cellSize)*resolution/sceneSize;\n vec2 slot=vec2(mod(index,atlasColumns),floor(index/atlasColumns));\n float alpha=texture2D(glyphAtlas,(slot*tileSize+padding+local)/atlasSize).a;\n if(dots>.5) {\n vec2 d=(pixel-(cell+.5)*cellSize)/min(cellSize.x,cellSize.y);\n float r=min(.48,(index/(glyphCount-1.))*.5*dotSize);\n alpha=1.-smoothstep(r-.06,r+.02,length(d));\n }\n // Replace the cell, rather than blending two glyphs into a ghost.\n vec3 rgb=trailInk(color.rgb,density);\n ink=vec4(rgb*alpha*color.a,alpha*color.a);\n }\n }\n if(trailAmount>0. && trailKind<.5 && trailDensity((floor(pixel/cellSize)+.5)/gridSize)>.001) {\n ink=flowingCharacter(pixel,floor(pixel/cellSize),ambient);\n }\n vec3 straightInk = ink.a > .0 ? ink.rgb / ink.a : vec3(.0);\n float value = max(straightInk.r, max(straightInk.g, straightInk.b));\n // Lighting belongs to character ink; black/transparent gaps stay empty.\n float light = surfaceLight((floor(pixel / cellSize) + .5) * cellSize / sceneSize, sceneSize) * hoverScope(pixel / sceneSize);\n vec3 lit = illuminate(straightInk, light * smoothstep(0., .22, value)) * ink.a;\n if(hasTextMask>.5) lit=mix(lit,vec3(.035)*ink.a,texture2D(textMask,vec2(gl_FragCoord.x,resolution.y-gl_FragCoord.y)/resolution).a);\n vec4 result = vec4(lit, ink.a)*ambient.w;\n gl_FragColor = directGlyphs > .5 ? result + backdrop*(1.-result.a) : result;\n }")),c.linkProgram(u),!c.getProgramParameter(u,c.LINK_STATUS))throw new Error("Surface shader link failed");c.useProgram(u),m=c.createBuffer(),c.bindBuffer(c.ARRAY_BUFFER,m),c.bufferData(c.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),c.STATIC_DRAW);const e=c.getAttribLocation(u,"position");c.enableVertexAttribArray(e),c.vertexAttribPointer(e,2,c.FLOAT,!1,0,0),Q=Object.fromEntries(["finishSoftness","finishMode","finishPixelRatio","edgeEffect","textMask","hasTextMask","artwork","surface","resolution","sceneSize","cellSize","surfaceSize","strength","hoverMode","hoverFocus","codes","cellColors","glyphAtlas","gridSize","atlasSize","tileSize","atlasColumns","padding","glyphCount","dots","dotSize","directGlyphs","backdrop","trailKind","edgeSafe","relativeStrength","scopeMap","scopeMode","trailAmount","motionMode","motionTime","fineDither","ditherAmount","cueMap","motionFocus"].map(t=>[t,c.getUniformLocation(u,t)]));for(let t=0;t<8;t++){const e=c.createTexture();f.push(e),c.activeTexture(c.TEXTURE0+t),c.bindTexture(c.TEXTURE_2D,e),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,1,1,0,c.RGBA,c.UNSIGNED_BYTE,new Uint8Array(4)),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE)}c.uniform1i(Q.textMask,5),c.uniform1i(Q.scopeMap,6),c.uniform1i(Q.cueMap,7),c.uniform1i(Q.codes,2),c.uniform1i(Q.cellColors,3),c.uniform1i(Q.glyphAtlas,4),c.uniform1i(Q.artwork,0),c.uniform1i(Q.surface,1),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),c.disable(c.BLEND),c.disable(c.DEPTH_TEST),l.addEventListener("webglcontextlost",it),tt()}catch{it()}const st=()=>{p||(K.reset(),q=null,v=!1,a())};return document.fonts?.addEventListener("loadingdone",st),document.fonts?.ready.then(st),{get canvas(){return l},canRenderGlyphs:t=>!!c&&!p&&B(t),render(t,a,o,h,u,m,g,Y,tt=0,et={}){const st=s(Y?.animationStyle),at=j.update(tt,st,Y?.animationSpeed),ot=(t=>!0===t?.fineDither&&!t.customText&&!t.charsetFrames?.length&&!/[A-Za-z]/.test(t.charset??""))(Y),nt=!!c&&!!g&&B(Y);if(nt!==F&&(v=!1,F=nt),p||!o||!h||!e.width||!e.height)return;const ht=Math.min(e.width/o,1.5,Math.sqrt(4e6/(o*h))),rt=Math.max(1,Math.round(o*ht)),lt=Math.max(1,Math.round(h*ht));if(l.width===rt&&l.height===lt||(l.width=rt,l.height=lt,v=!1),c&&(e.width>S||e.height>S)&&it(),(nt||M(a.mode)||"none"!==st||ot)&&(t||!v||!q)&&(q=K.update(e,o,h,u,m,ht,g,Y),c)){const{plan:t,packed:e,atlas:i}=q;for(const[t,i]of[[2,e.indices],[3,e.colors]])c.activeTexture(c.TEXTURE0+t),c.bindTexture(c.TEXTURE_2D,f[t]),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,3===t?c.LINEAR:c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,3===t?c.LINEAR:c.NEAREST),E!==e.cols||D!==e.rows?c.texImage2D(c.TEXTURE_2D,0,c.RGBA,e.cols,e.rows,0,c.RGBA,c.UNSIGNED_BYTE,i):c.texSubImage2D(c.TEXTURE_2D,0,0,0,e.cols,e.rows,c.RGBA,c.UNSIGNED_BYTE,i);E=e.cols,D=e.rows,k!==t&&(c.activeTexture(c.TEXTURE4),c.bindTexture(c.TEXTURE_2D,f[4]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,i),k=t),c.uniform2f(Q.gridSize,e.cols,e.rows),c.uniform2f(Q.atlasSize,t.atlasWidth,t.atlasHeight),c.uniform2f(Q.tileSize,t.tileWidth,t.tileHeight),c.uniform1f(Q.atlasColumns,t.atlasColumns),c.uniform1f(Q.padding,t.padding),c.uniform1f(Q.glyphCount,t.glyphs.length),c.uniform1f(Q.dots,q.dots?1:0),c.uniform1f(Q.dotSize,q.dotSize)}if("none"!==st&&q&&V!==q){const{packed:t}=q,e=t.cols*t.rows;J.length!==4*e&&(J=new Uint8Array(4*e));for(let i=0;i<e;i++){const e=t.indices[4*i+2];J[4*i]=J[4*i+1]=J[4*i+2]=e,J[4*i+3]=t.colors[4*i+3]}$=function(t,e,i,s){const a=e*i,o=s?.length===8*a?s:new Float32Array(8*a);if(!a)return o;const n=Math.min(e,i),h=new Float32Array(a),r=new Float32Array(a),l=new Float32Array(a),c=new Float32Array(a),d=new Float32Array(a),u=new Float32Array(a),m=new Float32Array(a);for(let e=0;e<a;e++){const i=t[4*e+3]/255;h[e]=(.299*t[4*e]+.587*t[4*e+1]+.114*t[4*e+2])/255*i}r.set(h),A(r,m,e,i,Math.max(1,Math.round(.012*n))),l.set(h),A(l,m,e,i,Math.max(1,Math.round(.03*n)));for(let t=0;t<a;t++){c[t]=Math.abs(h[t]-r[t]);const e=Math.max(0,h[t]-.55)/.45;d[t]=e*e}A(c,m,e,i,Math.max(1,Math.round(.02*n)));const f=1/Math.max(.02,L(c,.95));A(d,m,e,i,Math.max(1,Math.round(.05*n)));const g=1/Math.max(.03,L(d,.98)),p=T(t,e,i);let M=0,v=0,x=0;for(let t=0;t<i;t++)for(let s=0;s<e;s++){const a=t*e+s,o=(s+.5)/e,n=(t+.5)/i,r=.55*Math.min(1,c[a]*f)+.3*(1-Math.min(1,1.6*Math.hypot(1.3*(o-.5),n-.55)))+.15*G(.2,1,n);u[a]="none"===p.key?r:.75*p.subject[a]+.25*r;const l=u[a]*u[a]*(.25+h[a]);M+=o*l,v+=n*l,x+=l}A(u,m,e,i,Math.max(1,Math.round(.06*n)));const y=L(u,.05),w=L(u,.95),b=Math.max(.05,w-y);M=x>0?Math.max(.3,Math.min(.7,M/x)):.5,v=x>0?Math.max(.3,Math.min(.7,v/x)):.5;const S=1/Math.max(.004,L((()=>{const t=new Float32Array(a);for(let s=0;s<i;s++)for(let a=0;a<e;a++)t[s*e+a]=Math.hypot(l[s*e+Math.min(e-1,a+1)]-l[s*e+Math.max(0,a-1)],l[Math.min(i-1,s+1)*e+a]-l[Math.max(0,s-1)*e+a]);return t})(),.97));for(let t=0;t<i;t++)for(let s=0;s<e;s++){const a=t*e+s,n=8*a,h=(l[t*e+Math.min(e-1,s+1)]-l[t*e+Math.max(0,s-1)])*S,r=(l[Math.min(i-1,t+1)*e+s]-l[Math.max(0,t-1)*e+s])*S;o[n]=l[a],o[n+1]=Math.max(0,Math.min(1,(u[a]-y)/b)),o[n+2]=Math.min(1,d[a]*g),o[n+3]=Math.min(1,c[a]*f),o[n+4]=Math.max(-1,Math.min(1,-h)),o[n+5]=Math.max(-1,Math.min(1,-r)),o[n+6]=M,o[n+7]=v}return o}(J,t.cols,t.rows,$),V=q,c&&(Z=function(t,e){const i=t.length/8,s=e?.length===4*i?e:new Uint8Array(4*i);for(let e=0;e<i;e++)for(let i=0;i<4;i++)s[4*e+i]=Math.round(255*t[8*e+i]);return s}($,Z),c.activeTexture(c.TEXTURE7),c.bindTexture(c.TEXTURE_2D,f[7]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,t.cols,t.rows,0,c.RGBA,c.UNSIGNED_BYTE,Z),c.uniform2f(Q.motionFocus,$[6]??.5,$[7]??.5))}if(c){c.uniform1f(Q.motionMode,(t=>i.findIndex(e=>e.mode===t))(st)),c.uniform1f(Q.motionTime,at),c.uniform1f(Q.fineDither,ot?1:0),c.uniform1f(Q.ditherAmount,Math.max(0,Math.min(2,Y?.ditherStrength??1))),c.uniform1f(Q.trailKind,x(a.mode)),c.uniform1f(Q.edgeSafe,a.edgeSafe?1:0),c.uniform1f(Q.trailAmount,M(a.mode)?a.focus[2]:0),c.viewport(0,0,rt,lt),nt||!t&&v||(c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,f[0]),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,e),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1)),c.uniform1f(Q.directGlyphs,nt?1:0),!nt||!t&&v||c.uniform4fv(Q.backdrop,et.textMask||function(t){const e=t.length,i=t[0]?.length??0;for(let s=0;s<e;s+=Math.max(1,e>>2))for(let e=0;e<i;e+=Math.max(1,i>>2))if(t[s][e].a<200)return!0;return!1}(g)?[0,0,0,0]:O(e)),v=!0,c.activeTexture(c.TEXTURE1),c.bindTexture(c.TEXTURE_2D,f[1]),R!==a.width||z!==a.height?(c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a.width,a.height,0,c.RGBA,c.UNSIGNED_BYTE,a.pixels),R=a.width,z=a.height):c.texSubImage2D(c.TEXTURE_2D,0,0,0,a.width,a.height,c.RGBA,c.UNSIGNED_BYTE,a.pixels),c.uniform2f(Q.resolution,rt,lt),c.uniform2f(Q.sceneSize,o,h),c.uniform2f(Q.cellSize,u,m),c.uniform2f(Q.surfaceSize,a.width,a.height),c.uniform1f(Q.strength,a.strength),c.uniform1f(Q.relativeStrength,a.relative?1:0);const s=et.scope;c.uniform1f(Q.scopeMode,s&&"all"!==s.mode?"subject"===s.mode?1:2:0),s&&"all"!==s.mode&&s.pixels!==I&&(c.activeTexture(c.TEXTURE6),c.bindTexture(c.TEXTURE_2D,f[6]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,s.width,s.height,0,c.RGBA,c.UNSIGNED_BYTE,s.pixels),I=s.pixels),c.uniform1f(Q.hoverMode,"light"===a.mode||"reveal"===a.mode?1:"scan"===a.mode?2:"repel"===a.mode?3:0),c.uniform4fv(Q.hoverFocus,a.focus),et.textMask&&et.textMask!==X&&(c.activeTexture(c.TEXTURE5),c.bindTexture(c.TEXTURE_2D,f[5]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,et.textMask.canvas),X=et.textMask),c.uniform1f(Q.hasTextMask,et.textMask?1:0);const n=function(t={}){const e=U.some(e=>e.value===t.filter)?t.filter:"prism",i=Number.isFinite(t.edgeEffect)?Math.max(0,Math.min(1,t.edgeEffect)):t.filter?1:0,s=Number.isFinite(t.edgeSoftness)?Math.max(0,Math.min(1,t.edgeSoftness)):0;return{mode:["clean","prism","etch","signal"].indexOf(e),amount:"clean"===e?0:i,softness:"prism"===e?s:0}}(et);c.uniform1f(Q.edgeEffect,n.amount),c.uniform1f(Q.finishMode,n.mode),c.uniform1f(Q.finishSoftness,n.softness),c.uniform1f(Q.finishPixelRatio,1),c.drawArrays(c.TRIANGLE_STRIP,0,4)}else if(d){if(d.setTransform(ht,0,0,ht,0,0),d.clearRect(0,0,o,h),d.drawImage(e,0,0,o,h),("none"!==st||ot)&&q){d.clearRect(0,0,o,h);const{plan:t,packed:e,atlas:i}=q,s=[0,0,0,1],l=[0,0,0,0,0,0],c=Math.max(1,.32*Math.min(u,m));for(let o=0;o<e.rows;o++)for(let h=0;h<e.cols;h++){const f=(h+.5)/e.cols,g=(o+.5)/e.rows,p=4*(o*e.cols+h);if(e.colors[p+3]<10)continue;r(st,f,g,at,s,e.indices[p+2]/255,$??void 0,8*(o*e.cols+h));const v=4*(Math.min(a.height-1,Math.round(g*(a.height-1)))*a.width+Math.min(a.width-1,Math.round(f*(a.width-1)))),S=M(a.mode)?y(a.pixels,v,a.mode,a.focus[2]):0,k=e.indices[p]+256*e.indices[p+1];"trail"===a.mode&&b(e.indices,e.colors,e.cols,e.rows,h,o,S,(a.pixels[v+2]-128)/127,(a.pixels[v+3]-128)/127,t.glyphs.length,l,a.edgeSafe);let E="trail"===a.mode?l[0]:3===x(a.mode)?Math.round(k+S*(t.glyphs.length-1)*.35):"dissolve"===a.mode?k-Math.floor(S*t.glyphs.length*1.8):k+Math.floor(S*t.glyphs.length*.85);k>0&&(E+=s[2]*(t.glyphs.length-1)),E=Math.max(0,Math.min(t.glyphs.length-1,Math.floor(E+n(h,o))));let A=s[0],T=s[1];a.strength>0&&(A+=(256*a.pixels[v]+a.pixels[v+1]-32768)/32767*a.strength,T+=(256*a.pixels[v+2]+a.pixels[v+3]-32768)/32767*a.strength);const D=h*u+A,R=o*m+T,z=("trail"===a.mode?l[5]:e.colors[p+3])/255*s[3],F="trail"===a.mode?l[2]:e.colors[p],C="trail"===a.mode?l[3]:e.colors[p+1],X="trail"===a.mode?l[4]:e.colors[p+2],I=ot?Math.max(1,F,C,X):255,_=`rgb(${F/I*255},${C/I*255},${X/I*255})`;if(d.fillStyle=_,ot){const t="trail"===a.mode?w(Math.max(0,Math.min(1,l[1]+s[2])),2,S):Math.max(0,Math.min(1,e.indices[p+2]/255+s[2]+(3===x(a.mode)?.35*S:.65*("dissolve"===a.mode?-S:S))));d.globalAlpha=z;for(let e=0;e<m;e+=c)for(let i=0;i<u;i+=c)t>.5+(n(Math.floor((D+i)/c),Math.floor((R+e)/c))-.5)*Math.max(0,Math.min(2,Y?.ditherStrength??1))&&d.fillRect(D+i,R+e,Math.min(c,u-i),Math.min(c,m-e))}else if(E>0)if(d.globalAlpha=z,q.dots){const e=Math.min(.48,E/(t.glyphs.length-1)*.5*q.dotSize)*Math.min(u,m);d.beginPath(),d.arc(D+.5*u,R+.5*m,e,0,2*Math.PI),d.fill()}else d.drawImage(i,E%t.atlasColumns*t.tileWidth+t.padding,Math.floor(E/t.atlasColumns)*t.tileHeight+t.padding,t.cellWidth*ht,t.cellHeight*ht,D,R,u,m),d.globalAlpha=1,d.globalCompositeOperation="source-atop",d.fillRect(D,R,u,m),d.globalCompositeOperation="source-over"}d.globalAlpha=1}else if(M(a.mode)&&q){const{plan:t,packed:e,atlas:i}=q,s=[0,0,0,0,0,0];for(let o=0;o<e.rows;o++)for(let n=0;n<e.cols;n++){const h=4*(Math.min(a.height-1,Math.round((o+.5)/e.rows*(a.height-1)))*a.width+Math.min(a.width-1,Math.round((n+.5)/e.cols*(a.width-1)))),r=y(a.pixels,h,a.mode,a.focus[2]),l=4*(o*e.cols+n),c=.0137*(n*n*17+o*o*23+n*o*19),f=c-Math.floor(c);"trail"===a.mode&&b(e.indices,e.colors,e.cols,e.rows,n,o,r,(a.pixels[h+2]-128)/127,(a.pixels[h+3]-128)/127,t.glyphs.length,s,a.edgeSafe);const g=e.indices[l]+256*e.indices[l+1],p="trail"===a.mode?Math.round(s[0]):3===x(a.mode)?Math.max(0,Math.min(t.glyphs.length-1,Math.round(g+r*(t.glyphs.length-1)*.35))):"dissolve"===a.mode?Math.max(0,g-Math.floor(r*t.glyphs.length*(1.35+.9*f))):Math.min(t.glyphs.length-1,g+Math.floor(r*t.glyphs.length*.85));if(p===g&&("trail"!==a.mode||r<1e-4)||e.colors[l+3]<10)continue;const M=n*u,v=o*m;if(d.clearRect(M,v,u,m),d.globalAlpha=("trail"===a.mode?s[5]:e.colors[l+3])/255,q.dots){const e=Math.min(.48,p/(t.glyphs.length-1)*.5*q.dotSize)*Math.min(u,m);d.fillStyle="#fff",d.beginPath(),d.arc(M+.5*u,v+.5*m,e,0,2*Math.PI),d.fill()}else d.drawImage(i,p%t.atlasColumns*t.tileWidth+t.padding,Math.floor(p/t.atlasColumns)*t.tileHeight+t.padding,t.cellWidth*ht,t.cellHeight*ht,M,v,u,m);d.globalAlpha=1,d.globalCompositeOperation="source-atop";const w="trail"===a.mode?s[2]:e.colors[l],S="trail"===a.mode?s[3]:e.colors[l+1],k="trail"===a.mode?s[4]:e.colors[l+2],E=Math.max(w,S,k),A="dissolve"===a.mode||"trail"===a.mode||3===x(a.mode)?E:Math.max(E,Math.min(112,191*r)),T=E?A/E:0;d.fillStyle=`rgb(${E?w*T:A},${E?S*T:A},${E?k*T:A})`,d.fillRect(M,v,u,m),d.globalCompositeOperation="source-over"}}else if("light"===a.mode||"scan"===a.mode||"reveal"===a.mode){!t&&W&&_.width===rt&&_.height===lt||(_.width=rt,_.height=lt,P.width=rt,P.height=lt,N.filter="brightness(3)",N.drawImage(e,0,0,rt,lt),N.filter="none",W=!0);const[i,s,n,r]=a.focus;if(n>.001){H.setTransform(1,0,0,1,0,0),H.clearRect(0,0,rt,lt),H.drawImage(_,0,0),H.globalCompositeOperation="destination-in",H.save(),H.translate(i*rt,s*lt),H.scale("scan"===a.mode?.13:1,1);const t=r*Math.min(rt,lt),e=H.createRadialGradient(0,0,0,0,0,t);e.addColorStop(0,`rgba(255,255,255,${n})`),e.addColorStop(.5,`rgba(255,255,255,${.4*n})`),e.addColorStop(1,"rgba(255,255,255,0)"),H.fillStyle=e,H.fillRect(10*-rt,10*-lt,20*rt,20*lt),H.restore(),H.globalCompositeOperation="source-over",d.globalCompositeOperation="source-atop",d.drawImage(P,0,0,o,h),d.globalCompositeOperation="source-over"}}else if(a.strength>0){const t=32,i=18,s=o/t,n=h/i;for(let r=0;r<i;r++)for(let l=0;l<t;l++){const c=(l+.5)/t,f=(r+.5)/i,g=Math.min(a.width-1,Math.round(c*(a.width-1))),p=4*(Math.min(a.height-1,Math.round(f*(a.height-1)))*a.width+g),M=a.pixels,v=Math.min(l*s/u,(o-(l+1)*s)/u,r*n/m,(h-(r+1)*n)/m),x=Math.max(0,Math.min(1,(v-2)/6)),y=a.edgeSafe?x*x*(3-2*x):1,w=et.scope&&"all"!==et.scope.mode?et.scope.pixels[4*(Math.min(et.scope.height-1,Math.floor(f*et.scope.height))*et.scope.width+Math.min(et.scope.width-1,Math.floor(c*et.scope.width)))+3]/255:1,b=("outside"===et.scope?.mode?1-w:w)*y,S=(256*M[p]+M[p+1]-32768)/32767*a.strength*b*(a.relative?o:1),k=(256*M[p+2]+M[p+3]-32768)/32767*a.strength*b*(a.relative?h:1);Math.abs(S)+Math.abs(k)<.02||(d.clearRect(l*s,r*n,s,n),d.drawImage(e,Math.max(0,Math.min(o-s,l*s-S))*e.width/o,Math.max(0,Math.min(h-n,r*n-k))*e.height/h,s*e.width/o,n*e.height/h,l*s,r*n,s,n))}}C.paint(d,et.textMask,o,h)}},destroy(){p=!0,C.destroy(),document.fonts?.removeEventListener("loadingdone",st),K.destroy(),l.removeEventListener("webglcontextlost",it),et(),l.remove(),_.width=_.height=P.width=P.height=1,e.style.visibility=o,c?.getExtension("WEBGL_lose_context")?.loseContext()}}}function W(e,i,a={}){let o,n,h,r={effect:"trail",scope:"all",decay:.5,touch:!0,strength:.55,radius:a.effect&&"trail"!==a.effect?.2:.45,animated:!1,fps:30,fontSize:7,charAspect:.58,charSpacing:1,paused:!1,charset:" .:-=+*#%@",customText:"",renderMode:"ascii",dotSizeRatio:.72,...a},l=new P(i.clientWidth/Math.max(1,i.clientHeight)),c=!1,d=!1,u=!0,m=0,f=0,g=-1/0,p=0,M=null,v=!1,x=[],y=null,w=!0;const b=document.createElement("canvas"),S=b.getContext("2d",{willReadFrequently:!0}),k=matchMedia("(prefers-reduced-motion: reduce)"),E=()=>{c||!d||document.hidden||m||(m=requestAnimationFrame(D))},A=H(e,i,()=>queueMicrotask(()=>{u=!0,E()}));function D(t){if(m=0,c||!d||document.hidden)return;const e=i.clientWidth,a=i.clientHeight;if(!e||!a)return;const D=k.matches||r.paused;l.configure(r.effect,r.strength,r.radius,r.edgeSafe,r.decay),w&&(()=>{if(w=!1,"all"===r.scope&&"tilt"!==r.effect)return h=void 0,y=null,void l.setGuide(null);if(!S||!i.width||!i.height)return;b.width=l.columns,b.height=l.rows,S.clearRect(0,0,b.width,b.height),S.drawImage(i,0,0,b.width,b.height);try{y=T(S.getImageData(0,0,b.width,b.height).data,b.width,b.height,null,y)}catch{y=null}if(l.setGuide(y),!y||"all"===r.scope||"none"===y.key)return void(h=void 0);const t=new Uint8Array(y.width*y.height*4);for(let e=0;e<y.subject.length;e++)t[4*e+3]=255*y.subject[e];h={pixels:t,width:y.width,height:y.height,mode:r.scope}})();const R=l.active;if(!D){if(p+=f?Math.min(.1,(t-f)/1e3):0,v){const t=i.getBoundingClientRect();if(t.width&&t.height)for(const e of x)l.move((e.x-t.left)/t.width,(e.y-t.top)/t.height,e.time);x=[],M||l.leave(),v=!1}l.step(f?(t-f)/1e3:1/60)}const z=u||r.animated&&!D&&t-g>=1e3/Math.max(1,Math.min(60,r.fps))-.5;(z||R||l.active||!D&&"none"!==s(r.motion))&&(z&&(o=r.getFrame?.()),A.render(z,l.refraction,e,a,r.fontSize*r.charSpacing,r.fontSize/r.charAspect*r.charSpacing,o,{charset:r.charset,customText:r.customText,renderMode:r.renderMode,dotSizeRatio:r.dotSizeRatio,colorMode:r.colorMode??"fullcolor",accentColor:r.accentColor??"#888888",animationStyle:r.motion,animationSpeed:r.motionSpeed??1,artStyle:"classic",fineDither:r.fineDither,ditherStrength:r.ditherStrength??1},p,{filter:r.filter,edgeEffect:r.edgeEffect,edgeSoftness:r.edgeSoftness,textMask:n?.read(),scope:h}),z&&(g=t),u=!1),f=t,D||!r.animated&&!l.active&&"none"===s(r.motion)||E()}r.textMask&&(n=t(e,r.textMask,()=>{u=!0,E()}));const R=()=>{l.clear(),M=null,x=[],v=!1,f=0,u=!0,cancelAnimationFrame(m),m=0,E()},z=t=>{if("touch"===t.pointerType&&!r.touch||r.paused||k.matches)return;if(t.target instanceof Element&&t.target.closest("button,a,input,summary,select"))return void F();const e=i.getBoundingClientRect();t.clientX<e.left||t.clientX>e.right||t.clientY<e.top||t.clientY>e.bottom?F():(M={x:t.clientX,y:t.clientY,time:t.timeStamp},x.push(M),x.length>6&&x.shift(),v=!0,E())},F=()=>{M=null,v=!0,E()},C=t=>{"touch"===t.pointerType&&F()},X=new IntersectionObserver(([t])=>{d=t.isIntersecting,R()});X.observe(e);const I=new ResizeObserver(()=>{l=new P(i.clientWidth/Math.max(1,i.clientHeight)),w=!0,R()});return I.observe(i),e.addEventListener("pointerdown",z),e.addEventListener("pointerup",C),e.addEventListener("pointermove",z),e.addEventListener("pointerleave",F),e.addEventListener("pointercancel",F),document.addEventListener("visibilitychange",R),k.addEventListener("change",R),{get canvas(){return A.canvas},invalidate(){n?.invalidate(),u=!0,w=!0,E()},update(i){"textMask"in i&&(n?.destroy(),n=i.textMask?t(e,i.textMask,()=>{u=!0,E()}):void 0),r={...r,...i},w=!0,R()},destroy(){c||(c=!0,cancelAnimationFrame(m),X.disconnect(),I.disconnect(),A.destroy(),n?.destroy(),e.removeEventListener("pointerdown",z),e.removeEventListener("pointerup",C),e.removeEventListener("pointermove",z),e.removeEventListener("pointerleave",F),e.removeEventListener("pointercancel",F),document.removeEventListener("visibilitychange",R),k.removeEventListener("change",R))}}}var j=[{id:"quiet-light",label:"Quiet light",description:"A key light circles the subject’s own relief, with a soft magnifying wake.",motion:{type:"relight",speed:.6,amount:.8},hover:{effect:"lens",radius:.45,strength:.5}},{id:"living-paper",label:"Memory",description:"A slow push toward the subject; the image leans toward your cursor.",motion:{type:"push",speed:.5,amount:.8},hover:{effect:"tilt",radius:.5,strength:.45}},{id:"silver-grain",label:"Silver light",description:"Sparse glints on bright detail, with a fluid character trail.",motion:{type:"shimmer",speed:.6,amount:.9},hover:{effect:"trail",radius:.35,strength:.55}},{id:"ripple-study",label:"Still water",description:"Smooth water and sky drift like a cinemagraph; your stroke sends out rings.",motion:{type:"current",speed:.6,amount:.8},hover:{effect:"ripple",radius:.45,strength:.7}},{id:"unfolding-print",label:"Darkroom",description:"The print develops from its highlights; your cursor dissolves a soft path.",motion:{type:"develop",speed:.7,amount:1},hover:{effect:"dissolve",radius:.35,strength:.55}},{id:"silk-flow",label:"Morning mist",description:"Mist drifts through the distance; directional folds follow your hand.",motion:{type:"mist",speed:.6,amount:1},hover:{effect:"silk",radius:.4,strength:.5}},{id:"depth-study",label:"Depth study",description:"A slow parallax drift from the photo’s own depth, with a loupe under your cursor.",motion:{type:"parallax",speed:.6,amount:.9},hover:{effect:"loupe",radius:.35,strength:.55}}];export{k as DEPRECATED_STUDIO_HOVERS,e as DEPRECATED_STUDIO_MOTIONS,E as HOVER_SCOPES,j as STUDIO_ANIMATION_PRESETS,S as STUDIO_HOVERS,i as STUDIO_MOTIONS,t as createTextMask,W as mountHover,W as mountStudioHover};//# sourceMappingURL=hover.js.map
1
+ function t(t,e,i=()=>{}){const s=Array.isArray(e)?e:[e],a=document.createElement("canvas"),o=a.getContext("2d");let n,h=!0,r=!1,l=0;const c=()=>{r||(h=!0,i())},d=new ResizeObserver(c);d.observe(t),s.forEach(t=>d.observe(t));const m=new MutationObserver(c);return s.forEach(t=>m.observe(t,{subtree:!0,childList:!0,characterData:!0,attributes:!0})),document.fonts?.addEventListener("loadingdone",c),document.fonts?.ready.then(c),window.addEventListener("resize",c),{invalidate:c,read(){if(r)return;if(!h)return n;h=!1;const e=t.getBoundingClientRect(),i=Math.min(devicePixelRatio||1,1.5,Math.sqrt(4e6/Math.max(1,e.width*e.height)));a.width=Math.max(1,Math.round(e.width*i)),a.height=Math.max(1,Math.round(e.height*i)),o.setTransform(i,0,0,i,0,0),o.fillStyle="#fff",o.textBaseline="alphabetic";for(const t of s){const i=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(let t=i.nextNode();t;t=i.nextNode()){const i=t.parentElement;if(!i)continue;const s=getComputedStyle(i);if("hidden"===s.visibility||"none"===s.display)continue;o.font=`${s.fontStyle} ${s.fontWeight} ${s.fontSize} ${s.fontFamily}`;const a=o.measureText("Hg"),n=a.fontBoundingBoxAscent??.8*parseFloat(s.fontSize),h=a.fontBoundingBoxDescent??.2*parseFloat(s.fontSize),r=t.textContent??"",l=document.createRange();let c=0;for(const i of r){if(l.setStart(t,c),c+=i.length,l.setEnd(t,c),/\s/.test(i))continue;const s=l.getBoundingClientRect();s.width&&s.height&&o.fillText(i,s.left-e.left,s.top-e.top+(s.height-n-h)/2+n)}}}return n={canvas:a,revision:++l},n},destroy(){r=!0,d.disconnect(),m.disconnect(),document.fonts?.removeEventListener("loadingdone",c),window.removeEventListener("resize",c),a.width=a.height=1,n=void 0}}}var e={caustics:"sheen",grain:"shimmer",trace:"relight",tidal:"current",weave:"current",breeze:"current",reform:"develop",print:"develop",unfold:"develop"},i=[{value:"none",mode:"none",group:"Still",label:"Off",description:"Keep the image still. Hover stays available."},{value:"relight",mode:"relight",group:"Light",label:"Relight",description:"A key light circles the subject and models its own relief, like moving a lamp around a sculpture."},{value:"sheen",mode:"sheen",group:"Light",label:"Specular sweep",description:"One slow pass of light glances across the highlights and follows their form, then rests."},{value:"glow",mode:"glow",group:"Light",label:"Highlight bloom",description:"The brightest areas breathe a soft halo into their surroundings. Shadows stay deep."},{value:"shimmer",mode:"shimmer",group:"Light",label:"Glints",description:"Sparse glints on bright fine detail, like light on water, metal or an eye. Everything else holds still."},{value:"parallax",mode:"parallax",group:"Depth",label:"Parallax",description:"A slow camera drift: the subject moves against its background, read from the photo’s own depth cues."},{value:"push",mode:"push",group:"Depth",label:"Slow push",description:"A gentle push toward the subject and back, with nearer areas moving slightly more."},{value:"focus",mode:"focus",group:"Depth",label:"Focus pull",description:"Focus racks from the subject to the background and back; the characters soften out of focus."},{value:"mist",mode:"mist",group:"Atmosphere",label:"Mist",description:"Soft mist drifts through the distance and plain areas, leaving the subject clear."},{value:"current",mode:"current",group:"Atmosphere",label:"Drift",description:"Water swells and glints, falls stream down, sky and clouds drift slowly, like a cinemagraph. Subjects and buildings hold still."},{value:"develop",mode:"develop",group:"Reveal",label:"Develop",description:"The image holds, fades, then develops back in from its highlights to its shadows, like a print in the tray."}];function s(t){const s=t&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:t;return i.find(t=>t.value===s||t.mode===s)?.mode??"none"}var a=t=>Math.max(0,Math.min(1,t)),o=(t,e,i)=>{const s=a((i-t)/(e-t));return s*s*(3-2*s)},n=(t,e)=>{const i=(.06711056*t+.00583715*e)%1*52.9829189;return i-Math.floor(i)},h=class{constructor(){this.last=null,this.mode="none",this.phase=0}update(t,e,i=1){const a=s(e);return Number.isFinite(t)?((a!==this.mode||null!==this.last&&t<this.last)&&(this.mode=a,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 r(t,e,i,s,h,r=.5,l,c=0){if(h[0]=h[1]=h[2]=0,h[3]=1,"none"===t)return h;r=a(r);const d=l?l[c]:r,m=l?l[c+1]:.5+.5*a(1-2*Math.hypot(e-.5,i-.55)),u=l?l[c+2]:o(.55,1,r)**2,f=l?l[c+3]:.5,g=l?l[c+4]:0,p=l?l[c+5]:0,M=s*Math.PI/6,x=(s%12+12)%12,v=o(0,.12,Math.min(e,1-e,i,1-i));if("relight"===t){const t=M+.6,s=Math.cos(t),a=Math.sin(t),n=Math.max(-1,Math.min(1,g*s+p*a))+.35*(s*(e-.5)+a*(i-.5));h[2]=.2*n*(.3+.7*o(.04,.3,d)*(1-.6*o(.82,1,r)))}else if("sheen"===t){const t=1.9*o(0,8,x)-.35,s=(.75*e+.45*i)/1.2+.05*(.75*g+.45*p),a=Math.exp(-(((s-t)/.12)**2));h[2]=a*o(.3,.8,d)*(1-.5*o(.9,1,r))*.45}else if("glow"===t){const t=.5-.5*Math.cos(M),e=1-.8*t;h[2]=.2*o(e-.3,e+.02,u)*Math.sqrt(u)*(1-.65*r)+.05*t*o(.6,.95,r)}else if("shimmer"===t){const t=n(Math.floor(160*e),Math.floor(100*i))*Math.PI*2,s=Math.pow(.5+.5*Math.cos(2*M+t),28);h[2]=s*o(.5,.88,r)*(.35+.65*o(.1,.55,f))*.42}else if("parallax"===t){const t=m-.45;h[0]=16*t*Math.sin(M)*v,h[1]=7*t*Math.sin(2*M)*v}else if("push"===t){const t=.045*(.5-.5*Math.cos(M))*(.7+.6*m)*960,s=l?l[c+6]:.5,a=l?l[c+7]:.5;h[0]=(e-s)*t,h[1]=(i-a)*t}else if("focus"===t){const t=Math.sin(M),e=t*t*o(.35,.85,t>=0?1-m:m);h[2]=(d-r)*e*.75}else if("mist"===t){const t=Math.pow(1-m,1.5)*(1-.6*f),s=.5*Math.sin(4.1*e-M+.9*Math.sin(3.3*i+M))+.3*Math.sin(7.3*e+2.1*i-2*M+1.1*Math.sin(2.7*e-5.1*i+M))+.2*Math.sin(5.7*i-1.9*e+M);h[2]=o(-.3,.9,s)*t*.16*(1-.55*r)}else if("current"===t){const t=l?.[c+8]??0,s=l?.[c+9]??0,a=l?.[c+10]??0,d=o(0,.06,Math.min(e,1-e,i,1-i)),u=l?0:(1-.4*f)*(1-.8*m)*v,g=t=>14*i-t+1.5*Math.sin(3*e+t),p=t=>16*i+2*e-t,x=t=>29*i-3*e-2*t,y=t=>1.7*e+2.3*i-t,w=t=>26*i+1.5*Math.sin(40*e)-2*t;h[0]=7*(Math.sin(g(M))-Math.sin(g(0))+.43*(Math.sin(5*e-3*i+M)-Math.sin(5*e-3*i)))*u+(3.5*(Math.sin(p(M))-Math.sin(p(0)))+1.5*(Math.sin(x(M))-Math.sin(x(0))))*t*d+5*(Math.sin(y(M))-Math.sin(y(0)))*s*d,h[1]=2*(Math.sin(11*e+M)-Math.sin(11*e))*u+.8*(Math.cos(p(M))-Math.cos(p(0)))*t*d+12*(Math.sin(w(M))-Math.sin(w(0)))*a*d;const b=Math.pow(.5+.5*Math.cos(2*M+9*e-4*i+6.2831853*n(Math.floor(160*e),Math.floor(100*i))),24)-Math.pow(.5+.5*Math.cos(9*e-4*i+6.2831853*n(Math.floor(160*e),Math.floor(100*i))),24);h[2]=.03*(Math.cos(g(M))-Math.cos(g(0)))*u+(b*o(.5,.85,r)*.3+.025*(Math.cos(p(M))-Math.cos(p(0))))*t*d+.08*(Math.cos(w(M))-Math.cos(w(0)))*a*d}else if("develop"===t){const t=o(7,8.5,x),s=a((x-8.5)/3.5),l=x<8.5?1-t:o(0,1,(1.45*s-(1-r)+.06*(n(Math.floor(160*e),Math.floor(100*i))-.5))/.3);h[2]=.3*-(1-l),h[3]=1-.9*(1-l)}return h}function l(t,e,i){const s=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)),a=Math.max(0,Math.min(1,(s-.035)/.105));return a*a*a*(a*(6*a-15)+10)}var c=class{constructor(t,e){this.edgeSafe=!1,this.rings=new Float64Array(40),this.slot=0,this.clock=0,this.lastRing=-1,this.previous=null,this.alive=!1,this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.values=new Float32Array(t*e),this.clear()}get active(){return this.alive}clear(){this.rings.fill(0),this.values.fill(0),this.pixels.fill(0);for(let t=0;t<this.pixels.length;t+=4)this.pixels[t]=128;this.previous=null,this.alive=!1,this.slot=0,this.lastRing=-1,this.clock=0}leave(){this.previous=null}move(t,e,i,s){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=Number.isFinite(s)?s/1e3:this.clock,o=this.previous;if(this.previous={x:t,y:e,time:a},!o)return;const n=this.width/this.height,h=Math.hypot((t-o.x)*Math.max(1,n),(e-o.y)*Math.max(1,1/n));if(h<1e-4||this.clock-this.lastRing<1/24)return;const r=h/Math.max(1/240,Math.min(.1,a-o.time||1/60)),l=5*this.slot;this.slot=(this.slot+1)%8,this.rings[l]=t,this.rings[l+1]=e,this.rings[l+2]=0,this.rings[l+3]=Math.min(.9,.26+.2*r),this.rings[l+4]=.035+.13*Math.max(.1,Math.min(1,i)),this.alive=!0,this.lastRing=this.clock}step(t){if(!Number.isFinite(t)||t<=0)return;const e=Math.min(.05,t);if(this.clock+=e,!this.alive)return;this.values.fill(0),this.alive=!1;const i=this.width/this.height,s=Math.max(1,i),a=Math.max(1,1/i);for(let t=0;t<this.rings.length;t+=5){if(!this.rings[t+3])continue;const i=this.rings[t+2]+=e;if(i>2.8){this.rings[t+3]=0;continue}this.alive=!0;const o=this.rings[t+4],n=.17*i,h=this.rings[t+3]*(1-Math.exp(20*-i))*Math.exp(2.5*-i),r=n+1.8*o,l=this.rings[t],c=this.rings[t+1],d=Math.max(0,Math.floor((l-r/s)*(this.width-1))),m=Math.min(this.width-1,Math.ceil((l+r/s)*(this.width-1))),u=Math.max(0,Math.floor((c-r/a)*(this.height-1))),f=Math.min(this.height-1,Math.ceil((c+r/a)*(this.height-1)));for(let t=u;t<=f;t++)for(let e=d;e<=m;e++){const i=(Math.hypot((e/(this.width-1)-l)*s,(t/(this.height-1)-c)*a)-n)/o;Math.abs(i)>1.8||(this.values[t*this.width+e]+=h*Math.cos(i*Math.PI*2)*Math.exp(-i*i*2.5))}}for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const s=t*this.width+e,a=this.values[s]=Math.max(-1,Math.min(1,this.values[s]))*(this.edgeSafe?l(e/(this.width-1),t/(this.height-1),i):1),o=Math.round(32767*a+32768);this.pixels[4*s]=o>>>8,this.pixels[4*s+1]=255&o}}sample(t,e,i){const s=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),a=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),o=Math.floor(s),n=Math.floor(a),h=s-o,r=a-n,l=n*this.width+o,c=l+this.width;i[0]=i[1]=0,i[2]=3*((this.values[l]*(1-h)+this.values[l+1]*h)*(1-r)+(this.values[c]*(1-h)+this.values[c+1]*h)*r)}},d=t=>["dissolve","silk","vortex","magnetic","scatter","etch","elastic","lens","smudge"].includes(t),m=t=>"elastic"===t||"scatter"===t,u={elastic:[150,4.2],scatter:[90,3.6]},f=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 s=0;s<t;s++)this.edge[i*t+s]=l(s/(t-1),i/(e-1),t/e);this.clear()}get active(){return this.peak>2e-4}setMode(t){if(m(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),e=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};for(let i=0;i<this.height;i++)for(let s=0;s<this.width;s++){const a=.09*s,o=.09*i,n=Math.floor(a),h=Math.floor(o),r=a-n,l=o-h,c=r*r*(3-2*r),d=l*l*(3-2*l),m=((e(n,h)*(1-c)+e(n+1,h)*c)*(1-d)+(e(n,h+1)*(1-c)+e(n+1,h+1)*c)*d)*Math.PI*4,u=2*(i*this.width+s);t[u]=.7*Math.cos(m),t[u+1]=.7*Math.sin(m)}}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 s=this.previous;this.previous={x:t,y:e};const a=this.width,o=this.height,n=Math.max(1,a/o),h=Math.max(1,o/a),r=s?(t-s.x)*n:0,l=s?(e-s.y)*h:0,c=Math.hypot(r,l);if(!s&&"dissolve"!==this.mode&&"etch"!==this.mode&&"lens"!==this.mode)return;if(s&&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)))),u=c?r/c:1,f=c?l/c:0,g=s||"lens"!==this.mode?Math.min(1,c/(d*m)*2.2):.32;for(let i=0;i<m;i++){const r=(i+.5)/m,l=s?s.x+(t-s.x)*r:t,c=s?s.y+(e-s.y)*r:e,p=Math.max(0,Math.floor((l-2.5*d/n)*(a-1))),M=Math.min(a-1,Math.ceil((l+2.5*d/n)*(a-1))),x=Math.max(0,Math.floor((c-2.5*d/h)*(o-1))),v=Math.min(o-1,Math.ceil((c+2.5*d/h)*(o-1)));for(let t=x;t<=v;t++)for(let e=p;e<=M;e++){const i=(e/(a-1)-l)*n/d,s=(t/(o-1)-c)*h/d,r=Math.exp(1.5*-(i*i+s*s)),m=t*a+e;if("dissolve"===this.mode||"etch"===this.mode)this.ink[m]=Math.max(this.ink[m],r);else if("elastic"===this.mode)this.springX[m]=Math.max(-24,Math.min(24,this.springX[m]+u*r*g*12)),this.springY[m]=Math.max(-24,Math.min(24,this.springY[m]+f*r*g*12));else if("scatter"===this.mode){const t=this.scatterDirections;this.springX[m]=Math.max(-24,Math.min(24,this.springX[m]+(.6*i+t[2*m])*r*g*7)),this.springY[m]=Math.max(-24,Math.min(24,this.springY[m]+(.6*s+t[2*m+1])*r*g*7))}else if("lens"===this.mode)this.targetX[m]=Math.max(-.65,Math.min(.65,this.targetX[m]+i*r*g*1.6)),this.targetY[m]=Math.max(-.65,Math.min(.65,this.targetY[m]+s*r*g*1.6));else if("smudge"===this.mode)this.targetX[m]=Math.max(-1,Math.min(1,this.targetX[m]+u*r*g*1.3)),this.targetY[m]=Math.max(-1,Math.min(1,this.targetY[m]+f*r*g*1.3));else{const t=(-i*f+s*u)*r*2.8,e="magnetic"===this.mode?-i*r*2.5:"silk"===this.mode?u*t:-s*r*2.5,a="magnetic"===this.mode?-s*r*2.5:"silk"===this.mode?f*t:i*r*2.5;this.targetX[m]=Math.max(-1,Math.min(1,this.targetX[m]+e*g)),this.targetY[m]=Math.max(-1,Math.min(1,this.targetY[m]+a*g))}}}this.peak=1}step(t){if(!this.active||!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t)),i="dissolve"===this.mode?2.15:"smudge"===this.mode?2.4:3.2,s="lens"===this.mode?16:22,a=Math.exp(-i*e),o=1-Math.exp(-s*e);let n=0;const[h,r]="scatter"===this.mode?u.scatter:u.elastic,l=Math.sqrt(h-r*r),c=Math.exp(-r*e),d=Math.cos(l*e),f=Math.sin(l*e)/l;for(let t=0;t<this.ink.length;t++)if("etch"===this.mode)this.ink[t]*=a,n=Math.max(n,this.ink[t]);else if("dissolve"===this.mode){this.ink[t]*=a,n=Math.max(n,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(m(this.mode)){const e=this.offsetX[t],i=this.offsetY[t],s=this.springX[t],a=this.springY[t];this.offsetX[t]=Math.max(-1,Math.min(1,c*(e*d+(s+r*e)*f))),this.offsetY[t]=Math.max(-1,Math.min(1,c*(i*d+(a+r*i)*f))),this.springX[t]=c*(s*d-(r*s+h*e)*f),this.springY[t]=c*(a*d-(r*a+h*i)*f),n=Math.max(n,.05*Math.abs(this.springX[t]),.05*Math.abs(this.springY[t]))}else if("lens"===this.mode||"smudge"===this.mode){const e=1-o,n=s/(s-i)*(a-e);this.offsetX[t]=this.offsetX[t]*e+this.targetX[t]*n,this.offsetY[t]=this.offsetY[t]*e+this.targetY[t]*n,this.targetX[t]*=a,this.targetY[t]*=a}else this.targetX[t]*=a,this.targetY[t]*=a,this.offsetX[t]+=(this.targetX[t]-this.offsetX[t])*o,this.offsetY[t]+=(this.targetY[t]-this.offsetY[t])*o;n=Math.max(n,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),l=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]=l>>>8,this.pixels[4*t+3]=255&l}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,s=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,s))*(this.edgeSafe?this.edge[i]:1);const a=Math.round(32767*this.offsetX[i]+32768);this.pixels[4*i]=a>>>8,this.pixels[4*i+1]=255&a}this.peak=n,this.active||this.clear()}sample(t,e,i){const s=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),a=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),o=Math.floor(s),n=Math.floor(a),h=s-o,r=a-n,c=n*this.width+o,d=c+this.width,m=t=>(t[c]*(1-h)+t[c+1]*h)*(1-r)+(t[d]*(1-h)+t[d+1]*h)*r;if("etch"===this.mode)return i[0]=i[1]=0,void(i[2]=3*m(this.offsetX));i[0]=m(this.offsetX)*(this.edgeSafe?l(t,e,this.width/this.height):1)*.08,i[1]=m(this.offsetY)*(this.edgeSafe?l(t,e,this.width/this.height):1)*.08,i[2]="dissolve"===this.mode?6*-m(this.ink):0}},g=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 s=Math.max(1,this.width/this.height),a=Math.max(1,this.height/this.width);this.previous&&(Math.hypot((t-this.previous.x)*s,(e-this.previous.y)*a)<.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),s=Math.max(1,this.height/this.width);let a=0;for(const o of this.rings){const n=.015+o.age*(.15+.22*o.radius),h=.009+.014*o.radius,r=(Math.hypot((t-o.x)*i,(e-o.y)*s)-n)/h,l=Math.sin(Math.min(1,o.age/.07)*Math.PI/2)*Math.max(0,1-o.age/1.35)**2;a=Math.max(a,Math.exp(-r*r)*l)}return a}sample(t,e){const i=Math.max(0,Math.min(this.width-1,Math.round(t*(this.width-1)))),s=Math.max(0,Math.min(this.height-1,Math.round(e*(this.height-1))));return Math.max(this.ringSample(t,e),this.echo[s*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 s=0;for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const a=t*this.width+e;this.echo[a]=Math.max(this.ringSample(e/(this.width-1),t/(this.height-1)),this.echo[a]*i),s=Math.max(s,this.echo[a]);const o=Math.round(65535*this.echo[a]),n=4*a;this.pixels[n]=o>>>8,this.pixels[n+1]=255&o}this.echoPeak=s,this.active||(this.echo.fill(0),this.pixels.fill(0))}},p=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,s=performance.now()){if(!Number.isFinite(t+e+i+s))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 a=this.previous;if(this.previous={x:t,y:e,time:s},!a)return;const o=(t-a.x)*(this.width-1),n=(e-a.y)*(this.height-1),h=Math.hypot(o,n);if(h<.001)return;const r=Math.min(this.width,this.height),l=s>a.time?Math.max(1/240,(s-a.time)/1e3):1/60,c=Math.min(12,h/r/l),d=1-Math.exp(-c/2.2),m=r*(.022+.075*i)*(.65+.95*d),u=Math.min(128,Math.max(1,Math.ceil(h/(.4*m)))),f=h/m*(.32+.22*d)/u,g=o/h,p=n/h,M=-p,x=g,v=h*(2+18*d)/u;for(let i=0;i<u;i++){const s=(i+.5)/u,o=(a.x+(t-a.x)*s)*(this.width-1),n=(a.y+(e-a.y)*s)*(this.height-1),h=Math.max(1,Math.floor(o-3*m)),r=Math.min(this.width-2,Math.ceil(o+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=h;e<=r;e++){const i=((e-o)*g+(t-n)*p)/m,s=((e-o)*M+(t-n)*x)/m,a=Math.exp(-i*i*.65-s*s*1.7),h=t*this.width+e;this.ink[h]=1-(1-this.ink[h])*Math.exp(-a*f);const r=1-s*s*.55,l=i*s*.7;this.u[h]=Math.max(-80,Math.min(80,this.u[h]+(g*r+M*l)*a*v)),this.v[h]=Math.max(-80,Math.min(80,this.v[h]+(p*r+x*l)*a*v))}}this.peak=1}read(t,e,i){const s=0|(e=Math.max(.5,Math.min(this.width-1.5,e))),a=0|(i=Math.max(.5,Math.min(this.height-1.5,i))),o=e-s,n=i-a,h=a*this.width+s;return(t[h]*(1-o)+t[h+1]*o)*(1-n)+(t[h+this.width]*(1-o)+t[h+this.width+1]*o)*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,s=this.height;for(;e>1e-7;){const t=Math.min(1/60,e);e-=t;const a=Math.exp(-1.9*t),o=Math.exp(-3.2*t);for(let e=1;e<s-1;e++)for(let n=1;n<i-1;n++){const h=e*i+n,r=Math.max(.5,Math.min(i-1.5,n-this.u[h]*t)),l=Math.max(.5,Math.min(s-1.5,e-this.v[h]*t)),c=0|r,d=0|l,m=r-c,u=l-d,f=d*i+c,g=(1-m)*(1-u),p=m*(1-u),M=(1-m)*u,x=m*u;this.a[h]=(this.u[f]*g+this.u[f+1]*p+this.u[f+i]*M+this.u[f+i+1]*x)*a,this.b[h]=(this.v[f]*g+this.v[f+1]*p+this.v[f+i]*M+this.v[f+i+1]*x)*a,this.c[h]=(this.ink[f]*g+this.ink[f+1]*p+this.ink[f+i]*M+this.ink[f+i+1]*x)*o}[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<s-1;t++)for(let e=1;e<i-1;e++){const s=t*i+e;this.curl[s]=.5*(this.v[s+1]-this.v[s-1]-this.u[s+i]+this.u[s-i])}for(let e=1;e<s-1;e++)for(let s=1;s<i-1;s++){const a=e*i+s,o=Math.abs(this.curl[a+1])-Math.abs(this.curl[a-1]),n=Math.abs(this.curl[a+i])-Math.abs(this.curl[a-i]),h=Math.hypot(o,n)+1e-4,r=this.curl[a]*t*10,l=Math.hypot(this.u[a],this.v[a]);this.u[a]+=n/h*r,this.v[a]-=o/h*r;const c=Math.min(1,l/(Math.hypot(this.u[a],this.v[a])+1e-6));this.u[a]*=c,this.v[a]*=c,this.divergence[a]=-.5*(this.u[a+1]-this.u[a-1]+this.v[a+i]-this.v[a-i])}this.pressure.fill(0);for(let t=0;t<4;t++){for(let t=1;t<s-1;t++)for(let e=1;e<i-1;e++){const s=t*i+e;this.pressureNext[s]=.25*(this.divergence[s]+this.pressure[s-1]+this.pressure[s+1]+this.pressure[s-i]+this.pressure[s+i])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let n=0;for(let e=1;e<s-1;e++)for(let s=1;s<i-1;s++){const a=e*i+s;this.u[a]=Math.max(-80,Math.min(80,this.u[a]-.5*(this.pressure[a+1]-this.pressure[a-1]))),this.v[a]=Math.max(-80,Math.min(80,this.v[a]-.5*(this.pressure[a+i]-this.pressure[a-i]))),this.driftX[a]+=(3.6*this.u[a]-58*this.offsetX[a]-12*this.driftX[a])*t,this.driftY[a]+=(3.6*this.v[a]-58*this.offsetY[a]-12*this.driftY[a])*t,this.offsetX[a]=Math.max(-2,Math.min(2,this.offsetX[a]+this.driftX[a]*t)),this.offsetY[a]=Math.max(-2,Math.min(2,this.offsetY[a]+this.driftY[a]*t)),this.signal[a]=1-Math.exp(.06*-Math.hypot(this.u[a],this.v[a])-.16*this.ink[a]),n=Math.max(n,this.signal[a])}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()}},M=t=>["trail","contour","dissolve","etch","ripple","bleed"].includes(t),x=t=>"etch"===t||"ripple"===t||"bleed"===t,v=t=>x(t)?3:"dissolve"===t?2:"contour"===t?1:0,y=(t,e,i,s)=>(x(i)?(256*t[e]+t[e+1]-32768)/32767:(256*t[e]+t[e+1])/65535)*s;function w(t,e,i){const s=Math.max(0,e-1),a=1-Math.exp(3.5*-Math.max(0,i));return Math.max(0,s-Math.abs(s-(t+a*s*2.1)))}function b(t,e,i,s,a,o,n,h,r,l,c,d=!1){const m=Math.min(a,o,i-1-a,s-1-o),u=Math.max(0,Math.min(1,(m-1)/4)),f=d?u*u*(3-2*u):1;n*=f;const g=1-Math.exp(3.5*-Math.max(0,n)),p=Math.max(0,Math.min(i-1,a-h*g*.026*i*f)),M=Math.max(0,Math.min(s-1,o-r*g*.026*s*f)),x=Math.floor(p),v=Math.floor(M),y=p-x,b=M-v;c.fill(0);for(let a=0;a<2;a++)for(let o=0;o<2;o++){const n=4*(Math.min(s-1,v+a)*i+Math.min(i-1,x+o)),h=(o?y:1-y)*(a?b:1-b);c[0]+=(t[n]+256*t[n+1])*h,c[1]+=t[n+2]/255*h;for(let t=0;t<4;t++)c[t+2]+=e[n+t]*h}const S=43758.5453*Math.sin(127.1*a+311.7*o),k=S-Math.floor(S);c[0]=Math.max(0,w(c[0],l,n)-g*(1-g)*k*3)}var S=[{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:"ripple",label:"Ripple rings",group:"Change characters",description:"Expanding light-and-shadow rings follow your stroke. Faster movement excites stronger rings; the grid stays still."},{value:"bleed",label:"Ink bleed",group:"Change characters",description:"Ink wells up where the cursor rests, spreads along the paper grain, then dries back."},{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:"Characters scatter in soft drifts from your stroke, then spring back into place."},{value:"elastic",label:"Elastic",group:"Move the image",description:"Push the image with your stroke; it recoils past its rest once, then settles."},{value:"lens",label:"Lens wake",group:"Move the image",description:"A soft magnifying wake brings details closer, then relaxes back into focus."},{value:"smudge",label:"Smudge",group:"Move the image",description:"Drag the image in the direction of your stroke; a smooth, lingering pull settles without a bounce."},{value:"loupe",label:"Loupe",group:"Follow the cursor",description:"A glass loupe glides after the cursor and magnifies what it covers, easing through a soft rim."},{value:"reveal",label:"Reveal",group:"Follow the cursor",description:"A soft spotlight shows the original photograph through the characters."},{value:"repel",label:"Repel",group:"Follow the cursor",description:"Characters part around the cursor and spring back with one soft rebound when it leaves."},{value:"tilt",label:"Tilt",group:"Follow the cursor",description:"The image leans toward the cursor; bright areas sit nearer and move more, like a parallax card."},{value:"haze",label:"Heat haze",group:"Follow the cursor",description:"A rising shimmer bends the characters above the cursor, livelier while you move."}],k={rake:"silk"},E={radius:{label:"Hover size",min:.1,max:1,step:.05,default:.2},strength:{label:"Hover strength",min:0,max:1,step:.05,default:.55},decay:{label:"Linger",min:0,max:1,step:.05,default:.5}},A={effect:"trail",strength:.55,radius:.2,decay:.5,scope:"all",edgeSafe:!1};function T(t){if("string"==typeof t)return t in k?k[t]:S.some(e=>e.value===t)?t:void 0}var z=[{value:"all",label:"Everywhere",description:"The hover acts on the whole artwork."},{value:"subject",label:"Subject",description:"The hover stays on the subject and fades softly at its edge."},{value:"outside",label:"Around",description:"The hover acts only on the ground around the subject."}];function D(t,e,i,s,a){if(!(a<1))for(let o=0;o<2;o++){for(let o=0;o<s;o++){let s=0;const n=o*i;for(let e=-a;e<=a;e++)s+=t[n+Math.max(0,Math.min(i-1,e))];for(let o=0;o<i;o++)e[n+o]=s/(2*a+1),s+=t[n+Math.min(i-1,o+a+1)]-t[n+Math.max(0,o-a)]}for(let o=0;o<i;o++){let n=0;for(let t=-a;t<=a;t++)n+=e[Math.max(0,Math.min(s-1,t))*i+o];for(let h=0;h<s;h++)t[h*i+o]=n/(2*a+1),n+=e[Math.min(s-1,h+a+1)*i+o]-e[Math.max(0,h-a)*i+o]}}}var R=new Float32Array(0);function F(t,e,i,s,a){const o=e*i,n=a&&a.width===e&&a.height===i?a:{width:e,height:i,subject:new Float32Array(o),depth:new Float32Array(o),key:"none"},{subject:h,depth:r}=n;let l=0;for(let e=0;e<o;e++)t[4*e+3]<250&&l++;const c=e=>(.2126*t[4*e]+.7152*t[4*e+1]+.0722*t[4*e+2])/255;let d="none",m=0;if(l>.01*o)d="alpha";else if(s)d="mask";else{let t=0,s=0,a=0;const o=Math.max(1,Math.round(.03*Math.min(e,i)));for(let n=0;n<i;n++)for(let h=0;h<e;h++){if(h>=o&&n>=o&&h<e-o&&n<i-o)continue;const r=c(n*e+h);t+=r,s+=r*r,a++}m=t/Math.max(1,a);Math.sqrt(Math.max(0,s/Math.max(1,a)-m*m))<.07&&(d="ground")}for(let e=0;e<o;e++){const i=t[4*e+3]/255,a=c(e);let o=1;if("alpha"===d)o=i;else if("ground"===d){const t=Math.max(0,Math.min(1,(Math.abs(a-m)-.035)/.12));o=t*t*(3-2*t)}h[e]=o*(s?Math.max(0,Math.min(1,s[e])):1),r[e]=a*i}n.key=d,R.length<o&&(R=new Float32Array(o));const u=R;return D(h,u,e,i,Math.max(1,Math.round(.02*Math.min(e,i)))),D(r,u,e,i,Math.max(1,Math.round(.035*Math.min(e,i)))),n}var C=["loupe","repel","tilt","reveal","haze","bleed"],X=t=>C.includes(t),I=class{constructor(){this.value=0,this.velocity=0}step(t,e,i,s){const a=2*Math.sqrt(i)*s;for(let s=e;s>1e-6;s-=1/480){const e=Math.min(1/480,s);this.velocity+=((t-this.value)*i-this.velocity*a)*e,this.value+=this.velocity*e}}resting(t){return Math.abs(this.value-t)<.0015&&Math.abs(this.velocity)<.01}set(t){this.value=t,this.velocity=0}},P=t=>t*t*(3-2*t),_=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};function U(t,e){const i=Math.floor(t),s=Math.floor(e),a=P(t-i),o=P(e-s),n=_(i,s),h=_(i+1,s),r=_(i,s+1);return(n+(h-n)*a)*(1-o)+(r+(_(i+1,s+1)-r)*a)*o}var G=class{constructor(t,e){this.edgeSafe=!1,this.settle=1,this.focus=[.5,.5,0,.2],this.guide=null,this.mode="loupe",this.radius=.35,this.x=new I,this.y=new I,this.tx=new I,this.ty=new I,this.presence=new I,this.target=null,this.speed=0,this.clock=0,this.inkPeak=0,this.ink=null,this.next=null,this.fiber=null,this.sampled=[0,0,0],this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.sx=Math.max(1,t/e),this.sy=Math.max(1,e/t),this.clear()}setMode(t){if(t!==this.mode&&(this.mode=t,this.clear(),"bleed"===t&&!this.ink)){const t=this.width*this.height;this.ink=new Float32Array(t),this.next=new Float32Array(t),this.fiber=new Float32Array(t);for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++)this.fiber[t*this.width+e]=.35+.5*U(.09*e,.045*t)+.15*_(e,t)}}setRadius(t){this.radius=Math.max(.1,Math.min(1,t))}get reach(){return(.05+.25*this.radius)*("loupe"===this.mode?1-.14*this.speed:1)}get engaged(){return this.presence.value>.002||this.inkPeak>.002||Math.abs(this.tx.value)+Math.abs(this.ty.value)>4e-4}get active(){const t=this.target?1:0;return!this.presence.resting(t)||!!this.target&&(!this.x.resting(this.target.x)||!this.y.resting(this.target.y))||!this.tx.resting(this.tiltGoal(0))||!this.ty.resting(this.tiltGoal(1))||this.speed>.01||"haze"===this.mode&&this.presence.value>.002||this.inkPeak>.002}tiltGoal(t){return this.target&&"tilt"===this.mode?2*((t?this.target.y:this.target.x)-.5):0}clear(){for(const t of[this.x,this.y,this.tx,this.ty,this.presence])t.set(0);this.x.set(.5),this.y.set(.5),this.target=null,this.speed=0,this.inkPeak=0,this.ink?.fill(0),this.next?.fill(0),this.encode()}move(t,e,i){if(!Number.isFinite(t+e))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e));const s=Number.isFinite(i)?i/1e3:this.clock,a=this.target;if(!a&&this.presence.value<.05&&(this.x.set(t),this.y.set(e)),a){const i=Math.hypot((t-a.x)*this.sx,(e-a.y)*this.sy),o=i/Math.max(1/240,Math.min(.1,s-a.time||1/60));this.speed=Math.max(this.speed,Math.min(1,o/1.6)),"bleed"===this.mode&&this.deposit(a.x,a.y,t,e,Math.min(1,9*i))}else"bleed"===this.mode&&this.deposit(t,e,t,e,.5);this.target={x:t,y:e,time:s}}leave(){this.target=null}deposit(t,e,i,s,a){const o=this.ink,n=this.width,h=this.height,r=.55*this.reach,l=Math.hypot((i-t)*this.sx,(s-e)*this.sy),c=Math.min(48,Math.max(1,Math.ceil(l/(.5*r))));for(let l=0;l<c;l++){const d=(l+.5)/c,m=t+(i-t)*d,u=e+(s-e)*d,f=Math.max(0,Math.floor((m-2*r/this.sx)*(n-1))),g=Math.min(n-1,Math.ceil((m+2*r/this.sx)*(n-1))),p=Math.max(0,Math.floor((u-2*r/this.sy)*(h-1))),M=Math.min(h-1,Math.ceil((u+2*r/this.sy)*(h-1)));for(let t=p;t<=M;t++)for(let e=f;e<=g;e++){const i=(e/(n-1)-m)*this.sx/r,s=(t/(h-1)-u)*this.sy/r,l=t*n+e;o[l]=Math.min(1.4,o[l]+Math.exp(1.8*-(i*i+s*s))*a/c*1.6)}}this.inkPeak=Math.max(this.inkPeak,.01)}step(t){if(!Number.isFinite(t)||t<=0)return;const e=Math.min(.05,t),i=e*this.settle;this.clock+=e;const s=this.target,a=this.mode;if(s?this.presence.step(1,e,190,1):this.presence.step(0,i,"repel"===a?120:70,"repel"===a?.42:1),s){const t="tilt"===a?60:"haze"===a?90:240,i="loupe"===a||"repel"===a?.72:.9;this.x.step(s.x,e,t,i),this.y.step(s.y,e,t,i)}this.tx.step(this.tiltGoal(0),s?e:i,45,.78),this.ty.step(this.tiltGoal(1),s?e:i,45,.78),this.speed*=Math.exp(7*-e),"bleed"===a&&this.spread(e,i,!!s),this.engaged||this.active||(this.presence.set(0),this.tx.set(0),this.ty.set(0)),this.focus[0]=this.x.value,this.focus[1]=this.y.value,this.focus[2]=Math.max(0,Math.min(1,this.presence.value)),this.focus[3]=this.reach,this.encode()}spread(t,e,i){const s=this.ink,a=this.next,o=this.fiber,n=this.width,h=this.height;i&&this.target&&this.deposit(this.x.value,this.y.value,this.x.value,this.y.value,.9*t);const r=Math.max(1,Math.ceil(t/(1/240))),l=t/r,c=26*(.4+this.radius),d=(i?.02:.1)*e/t,m=Math.exp(-(i?.15:.9)*e/r);let u=0;for(let t=0;t<r;t++){u=0;for(let t=1;t<h-1;t++)for(let e=1;e<n-1;e++){const i=t*n+e,h=s[i],r=o[i],f=Math.min(r,o[i-1])*(s[i-1]-h)+Math.min(r,o[i+1])*(s[i+1]-h)+Math.min(r,o[i-n])*(s[i-n]-h)+Math.min(r,o[i+n])*(s[i+n]-h),g=Math.max(0,(h+f*Math.min(.24,c*l))*m-d*l);a[i]=g,g>u&&(u=g)}s.set(a)}this.inkPeak=u}sample(t,e,i){i[0]=i[1]=i[2]=0;const s=this.presence.value,a=this.mode;if("bleed"===a){if(this.inkPeak<=.002)return;const s=this.width,a=this.height,o=this.ink,n=Math.max(0,Math.min(s-1.001,t*(s-1))),h=Math.max(0,Math.min(a-1.001,e*(a-1))),r=Math.floor(n),l=Math.floor(h),c=n-r,d=h-l,m=l*s+r,u=m+s,f=(o[m]*(1-c)+o[m+1]*c)*(1-d)+(o[u]*(1-c)+o[u+1]*c)*d;return void(i[2]=1-Math.exp(2.4*-f))}if("tilt"===a){const s=this.guide?function(t,e,i,s){const a=t[e],o=t.width,n=t.height,h=Math.max(0,Math.min(o-1.001,i*(o-1))),r=Math.max(0,Math.min(n-1.001,s*(n-1))),l=Math.floor(h),c=Math.floor(r),d=h-l,m=r-c,u=c*o+l,f=Math.min(n-1,c+1)*o+l,g=l+1<o?1:0;return(a[u]*(1-d)+a[u+g]*d)*(1-m)+(a[f]*(1-d)+a[f+g]*d)*m}(this.guide,"depth",t,e):.6,a=.2+.8*s,o=this.edgeSafe?l(t,e,this.sx/this.sy):1;return i[0]=.024*this.tx.value*a*o/this.sx,void(i[1]=.024*this.ty.value*a*o/this.sy)}if(s<=.001)return;const o=this.reach,n=(t-this.x.value)*this.sx,h=(e-this.y.value)*this.sy,r=(n*n+h*h)/(o*o);if("reveal"===a)return void(i[2]=Math.exp(2.4*-r)*s);if(r>9)return;const c=this.edgeSafe?l(t,e,this.sx/this.sy):1;let d=0,m=0;if("loupe"===a){const t=Math.exp(-r*r)*s*.5;d=n*t,m=h*t;const e=Math.sqrt(r)-1;i[2]=Math.exp(-e*e/.018)*s*.55}else if("repel"===a){const t=Math.sqrt(r),e=.5*o*Math.exp(-r/1.7)*s,a=Math.max(1e-6,Math.sqrt(n*n+h*h));d=n/a*Math.min(e,a+.5*o*s),m=h/a*Math.min(e,a+.5*o*s);const l=Math.max(0,Math.min(1,(t-.3)/.32));i[2]=-(1-l*l*(3-2*l))*s}else if("haze"===a){const a=h/o+.45,r=Math.exp(-n*n/(o*o)-a*a/2.6)*s*(.35+.65*Math.min(1,1.4*this.speed+.25));if(r<.002)return;const l=this.clock,c=t*this.sx*9,u=e*this.sy*9+2.3*l;d=.06*(U(c,u)-.5)*r,m=.026*(U(c+17.3,1.3*u+.7*l)-.5)*r,i[2]=.35*(U(1.7*c+5,1.7*u)-.5)*r}i[0]=d*c/this.sx,i[1]=m*c/this.sy}encode(){const t=this.width,e=this.height,i=this.pixels,s=this.sampled,a=this.engaged;for(let o=0;o<e;o++)for(let n=0;n<t;n++){const h=4*(o*t+n);if(a?this.sample(n/(t-1),o/(e-1),s):s[0]=s[1]=s[2]=0,"bleed"===this.mode){const t=Math.round(32767*Math.max(-1,Math.min(1,s[2]))+32768);i[h]=t>>>8,i[h+1]=255&t,i[h+2]=128,i[h+3]=0}else{"repel"===this.mode&&(s[0]*=.3,s[1]*=.3);const t=Math.round(32767*Math.max(-1,Math.min(1,s[0]/.16))+32768),e=Math.round(32767*Math.max(-1,Math.min(1,s[1]/.16))+32768);i[h]=t>>>8,i[h+1]=255&t,i[h+2]=e>>>8,i[h+3]=255&e}}}},L=(t,e)=>"water"===t?30*e/.55:"silk"===t?28*e:"vortex"===t?38*e:["magnetic","scatter","elastic","lens","smudge"].includes(t)?32*e:["loupe","repel","tilt","haze"].includes(t)?.16*e/.55:0,N=class{constructor(t=1){this.ripple=null,this.cursor=null,this.settle=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,this.quiet=0,this.guide=null,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]=l(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 p(this.columns,this.rows),this.contour=new g(this.columns,this.rows),this.afterimage=new f(this.columns,this.rows),this.clear()}get invertsDensity(){return"trail"===this.mode}get densityTrail(){return["trail","contour","dissolve","etch","ripple","bleed"].includes(this.mode)}get hasRefraction(){return this.active||this.lensStrength>15e-5}get effect(){return this.mode}get engaged(){return X(this.mode)?this.cursor.engaged:this.active}get spotlight(){return"reveal"===this.mode&&this.cursor?this.cursor.focus:null}get signature(){return X(this.mode)&&this.cursor.engaged?this.cursor.focus.map(t=>t.toFixed(4)).join(","):""}setGuide(t){this.cursor&&(this.cursor.guide=t),this.guide=t}get active(){return X(this.mode)?this.cursor.active:"ripple"===this.mode?this.ripple?.active??!1:d(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){const e="light"===t||"scan"===t?t:T(t)??"none";e!==this.mode&&(this.clear(),this.mode=e,this.refraction.mode=e,d(e)&&this.afterimage.setMode(e),"ripple"!==e||this.ripple||(this.ripple=new c(this.columns,this.rows)),X(e)&&(this.cursor??(this.cursor=new G(this.columns,this.rows)),this.cursor.guide=this.guide,this.cursor.setMode(e)),this.refraction.pixels=X(e)?this.cursor.pixels:"ripple"===e?this.ripple.pixels:"trail"===e?this.trail.pixels:"contour"===e?this.contour.pixels:d(e)?this.afterimage.pixels:this.waterPixels,this.refraction.strength=L(e,this.amount),this.refraction.relative=X(e))}configure(t,e=.55,i=.2,s=!1,a=.5){this.setMode(t),this.settle=((t=.5)=>Math.pow(2,2.4*(.5-(Number.isFinite(t)?Math.max(0,Math.min(1,t)):.5))))(a),this.refraction.edgeSafe=s,this.afterimage.edgeSafe=s,this.ripple&&(this.ripple.edgeSafe=s),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.cursor&&(this.cursor.edgeSafe=s,this.cursor.settle=this.settle,this.cursor.setRadius(this.radius)),this.refraction.strength=L(this.mode,this.amount),this.refraction.focus[2]=this.densityTrail?this.amount:this.lensStrength*this.amount,this.refraction.focus[3]=this.radius,"reveal"!==this.mode&&"repel"!==this.mode||this.syncSpot()}syncSpot(){const t=this.cursor.focus;this.refraction.focus=[t[0],t[1],t[2]*("repel"===this.mode?Math.min(1,this.amount/.55):this.amount),t[3]]}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)),X(this.mode))return void this.cursor.move(t,e,i);if("ripple"===this.mode)return void this.ripple.move(t,e,this.radius,i);if(d(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 s=this.previous;this.previous={x:t,y:e};const a=(t-s.x)*this.xScale,o=(e-s.y)*this.yScale,n=Math.hypot(a,o);if(n<1e-5)return;const h=.035+.1*this.radius,r=3*h,l=Math.min(192,Math.max(1,Math.ceil(n/(.5*h)))),c=95*Math.min(n,1)/l;for(let i=0;i<l;i++){const a=(i+.5)/l,o=s.x+(t-s.x)*a,n=s.y+(e-s.y)*a,d=Math.max(1,Math.floor((o-r/this.xScale)*(this.columns-1))),m=Math.min(this.columns-2,Math.ceil((o+r/this.xScale)*(this.columns-1))),u=Math.max(1,Math.floor((n-r/this.yScale)*(this.rows-1))),f=Math.min(this.rows-2,Math.ceil((n+r/this.yScale)*(this.rows-1)));for(let t=u;t<=f;t++)for(let e=d;e<=m;e++){const i=(e/(this.columns-1)-o)*this.xScale,s=(t/(this.rows-1)-n)*this.yScale,a=Math.exp(-(i*i+s*s)/(h*h))*c,r=t*this.columns+e;this.velocity[r]=Math.max(-12,this.velocity[r]-a)}}this.pending=!0,this.quiet=0}leave(){this.cursor?.leave(),this.ripple?.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.ripple?.clear(),this.cursor?.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,this.quiet=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(X(this.mode))return this.cursor.step(t),void("reveal"!==this.mode&&"repel"!==this.mode||this.syncSpot());if(t*=this.settle,"ripple"===this.mode)return void this.ripple.step(t);if(d(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=.3*Math.min(this.columns,this.rows);for(;this.remainder+1e-8>=e;){this.remainder-=e,this.quiet+=e;const t=Math.max(0,Math.min(1,(this.quiet-.2)/.6)),s=t*t*(3-2*t),a=Math.exp(-(3.8+3*s)*e),o=Math.exp(7*-s*e);let n=0;for(let t=1;t<this.rows-1;t++)for(let s=1;s<this.columns-1;s++){const h=t*this.columns+s,r=this.heights[h],l=this.heights[h-1]+this.heights[h+1]+this.heights[h-this.columns]+this.heights[h+this.columns]-4*r,c=Math.min(s,t,this.columns-1-s,this.rows-1-t),d=c<5?.88+.024*c:1,m=(this.velocity[h]+(l*i*i-8*r)*e)*a*d;this.velocity[h]=m,this.next[h]=(r+m*e)*d*o,n=Math.max(n,Math.abs(this.next[h]),.1*Math.abs(m))}this.heights.set(this.next),this.energy=n,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,o=(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),h=Math.tanh(o)*(this.refraction.edgeSafe?this.edgeMask[i]:1);this.normals[2*i]=n,this.normals[2*i+1]=h;const r=Math.round(32767*n+32768),l=Math.round(32767*h+32768);this.refraction.pixels[4*i]=r>>>8,this.refraction.pixels[4*i+1]=255&r,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),s=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)*s,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(X(this.mode))return this.cursor.sample(t,e,i),i[0]*=this.amount/.55,i[1]*=this.amount/.55,void(i[2]*="reveal"===this.mode||"repel"===this.mode?Math.min(1,this.amount/.55):3*this.amount);if("ripple"===this.mode)return this.ripple.sample(t,e,i),void(i[2]*=this.amount);if(d(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 s=Math.max(0,Math.min(this.columns-1.001,t*(this.columns-1))),a=Math.max(0,Math.min(this.rows-1.001,e*(this.rows-1))),o=Math.floor(s),n=Math.floor(a),h=s-o,r=a-n,l=2*(n*this.columns+o),c=l+2*this.columns;for(let t=0;t<2;t++)i[t]=.08*((this.normals[l+t]*(1-h)+this.normals[l+2+t]*h)*(1-r)+(this.normals[c+t]*(1-h)+this.normals[c+2+t]*h)*r);i[0]*=this.amount/.55,i[1]*=this.amount/.55,i[2]="light"===this.mode||"scan"===this.mode?function(t,e,i,s){const[a,o,n,h]=i.focus,r=(t-a)*Math.max(1,s)/h,l=(e-o)*Math.max(1,1/s)/h;return"light"===i.mode?Math.exp(-3*(r*r+l*l))*n:"scan"===i.mode?(1.3*Math.exp(-r*r*110)-.3*Math.exp(-r*r*12))*Math.exp(-l*l*1.8)*n:0}(t,e,this.refraction,this.xScale/this.yScale):0}};var Y=[{value:"clean",label:"Clean",description:"Crisp characters with no optical texture."},{value:"signal",label:"Signal",description:"Broken scanlines at the edges, with a clear center."},{value:"prism",label:"Prism",description:"Soft red/cyan separation at the edges, with a crisp center."},{value:"etch",label:"Etch",description:"A fine engraved texture, keeping the ink monochrome."}];var B=11,O=t=>Math.max(0,Math.min(1,t)),H=(t,e,i)=>{const s=O((i-t)/(e-t));return s*s*(3-2*s)};function W(t,e,i=256){let s=0;for(let e=0;e<t.length;e++)t[e]>s&&(s=t[e]);if(s<=0)return 0;const a=new Uint32Array(i);for(let e=0;e<t.length;e++)a[Math.min(i-1,Math.floor(Math.max(0,t[e])/s*i))]++;let o=0;const n=t.length*e;for(let t=0;t<i;t++)if(o+=a[t],o>=n)return(t+1)/i*s;return s}var j=class{constructor(t){this.n=t,this.arrays=[],this.next=0}take(t){this.next===this.arrays.length&&this.arrays.push(new Float32Array(this.n));const e=this.arrays[this.next++];return t?e.set(t):e.fill(0),e}reset(){this.next=0}},K=null;function q(t,e,i,s,a){const o=2*a+1;for(let n=0;n<s;n++){const s=n*i;let h=0;for(let e=-a;e<=a;e++)h+=t[s+Math.max(0,Math.min(i-1,e))];for(let n=0;n<i;n++)e[s+n]=h/o,h+=t[s+Math.min(i-1,n+a+1)]-t[s+Math.max(0,n-a)]}for(let n=0;n<i;n++){let h=0;for(let t=-a;t<=a;t++)h+=e[Math.max(0,Math.min(s-1,t))*i+n];for(let r=0;r<s;r++)t[r*i+n]=h/o,h+=e[Math.min(s-1,r+a+1)*i+n]-e[Math.max(0,r-a)*i+n]}}function $(t,e,i,s,a,o,n){const h=i*s,r=n.take(),l=n.take(e),c=n.take(t),d=n.take(),m=n.take();for(let i=0;i<h;i++)d[i]=e[i]*e[i],m[i]=e[i]*t[i];q(l,r,i,s,a),q(c,r,i,s,a),q(d,r,i,s,a),q(m,r,i,s,a);for(let t=0;t<h;t++){const e=(m[t]-l[t]*c[t])/(d[t]-l[t]*l[t]+o);d[t]=e,m[t]=c[t]-e*l[t]}q(d,r,i,s,a),q(m,r,i,s,a);for(let i=0;i<h;i++)t[i]=d[i]*e[i]+m[i]}function V(t,e,i,s,a,o=2){for(let n=0;n<o;n++){for(let o=0;o<s;o++)for(let s=0;s<i;s++){const n=o*i+s;let h=t[n];s>0&&(h=Math.max(h,Math.min(e[n],t[n-1]*a))),o>0&&(h=Math.max(h,Math.min(e[n],t[n-i]*a),s>0?Math.min(e[n],t[n-i-1]*a):0,s<i-1?Math.min(e[n],t[n-i+1]*a):0)),t[n]=h}for(let o=s-1;o>=0;o--)for(let n=i-1;n>=0;n--){const h=o*i+n;let r=t[h];n<i-1&&(r=Math.max(r,Math.min(e[h],t[h+1]*a))),o<s-1&&(r=Math.max(r,Math.min(e[h],t[h+i]*a),n>0?Math.min(e[h],t[h+i-1]*a):0,n<i-1?Math.min(e[h],t[h+i+1]*a):0)),t[h]=r}}}function J(t,e,i,s,a){for(let o=0;o<s;o++)for(let s=0;s<i;s++){let n=1;for(let e=Math.max(0,s-a);e<=Math.min(i-1,s+a);e++)n=Math.min(n,t[o*i+e]);e[o*i+s]=n}for(let o=0;o<s;o++)for(let n=0;n<i;n++){let h=1;for(let t=Math.max(0,o-a);t<=Math.min(s-1,o+a);t++)h=Math.min(h,e[t*i+n]);t[o*i+n]=h}}function Z(t,e,i,s,a){const o=i*s,n=Math.min(i,s),h=a.take(),r=a.take(),l=a.take(),c=a.take(),d=a.take();for(let i=0;i<o;i++){const s=t[4*i+3]/255;d[i]=s,h[i]=e[4*i]/255*s,r[i]=e[4*i+1]/255*s,l[i]=e[4*i+2]/255*s,c[i]=(.299*t[4*i]+.587*t[4*i+1]+.114*t[4*i+2])/255*s}const m=a.take(),u=(t,e)=>{const o=a.take(t);return D(o,m,i,s,e),o},f=Math.max(2,Math.round(.04*n)),g=Math.max(f+2,Math.round(.12*n)),p=Math.max(2,Math.round(.05*n)),M=u(c,1),x=u(c,f),v=u(c,g),y=a.take(),w=a.take(),b=a.take(),S=a.take(),k=a.take();for(let t=0;t<s;t++)for(let e=0;e<i;e++){const a=t*i+e;y[a]=Math.abs(c[a]-M[a]),w[a]=Math.abs(M[a]-x[a]),b[a]=Math.abs(x[a]-v[a]),S[a]=Math.abs(c[t*i+Math.min(i-1,e+1)]-c[t*i+Math.max(0,e-1)]),k[a]=Math.abs(c[Math.min(s-1,t+1)*i+e]-c[Math.max(0,t-1)*i+e])}D(y,m,i,s,p),D(w,m,i,s,p),D(b,m,i,s,p),D(S,m,i,s,2),D(k,m,i,s,2);const E=Math.max(.01,W(y,.9)+W(w,.9)),A=u(h,1),T=u(r,1),z=u(l,1),R=a.take(),C=a.take(),X=a.take();let I=0;for(let t=0;t<o;t++){const e=A[t],i=T[t],s=z[t],a=Math.max(e,i,s),o=a-Math.min(e,i,s);X[t]=a,C[t]=a>.001?o/a:0,I+=o;let n=0;o>1e-4&&(n=a===e?((i-s)/o+6)%6:a===i?(s-e)/o+2:(e-i)/o+4),R[t]=60*n}const P=H(.02,.07,I/o),_=Math.max(2,Math.round(.06*s)),U=new Float32Array(s);for(let t=0;t<s;t++){let e=0;for(let s=0;s<i;s++)e+=y[t*i+s]+w[t*i+s];U[t]=e/i}let G=.5,L=0;for(let t=Math.max(_,Math.round(.12*s));t<=Math.min(s-_,Math.round(.88*s));t++){let e=0,a=0,o=0,n=0;for(let s=0;s<i;s++){let o=0,n=0,h=0,r=0,l=0,c=0;for(let e=1;e<=_;e++){const a=(t-e)*i+s,d=(t+e-1)*i+s;o+=A[a],n+=T[a],h+=z[a],r+=A[d],l+=T[d],c+=z[d]}const d=(Math.abs(o-r)+Math.abs(n-l)+Math.abs(h-c))/_;e+=d,a+=d>.12?1:0}const h=Math.max(2,Math.round(.15*s)),r=Math.max(0,t-h),l=Math.min(s,t+h);for(let e=r;e<t;e++)o+=U[e];for(let e=t;e<l;e++)n+=U[e];o/=t-r,n/=l-t;const c=H(-.05,.3,(n-o)/(n+o+1e-4)),d=H(.08,.35,e/i)*(a/i)*c;d>L&&(L=d,G=t/s)}const N=H(.15,.45,L),Y=a.take(),B=a.take(),j=a.take();for(let t=0;t<o;t++)Y[t]=Math.min(h[t],r[t],l[t]);J(Y,m,i,s,1),D(Y,m,i,s,f);for(let t=0;t<o;t++)B[t]=w[t]+b[t];let K=0,Z=0,Q=0;for(let t=0;t<o;t++)K+=A[t],Z+=T[t],Q+=z[t];K/=o,Z/=o,Q/=o;const tt=u(A,f),et=u(T,f),it=u(z,f),st=u(A,g),at=u(T,g),ot=u(z,g);for(let t=0;t<o;t++){const e=Math.hypot(tt[t]-K,et[t]-Z,it[t]-Q),i=Math.hypot(tt[t]-st[t],et[t]-at[t],it[t]-ot[t]);j[t]=(e+1.5*i)*(.4+.6*C[t]*P+.4*(1-P))}const nt=a.take(),ht=a.take(),rt=a.take(),lt=a.take(),ct=a.take(),dt=a.take(),mt=a.take(),ut=a.take(),ft=a.take(),gt=a.take();for(let t=0;t<s;t++)for(let e=0;e<i;e++)gt[t*i+e]=Math.abs(c[Math.min(s-1,t+1)*i+e]-c[Math.max(0,t-1)*i+e]);D(gt,m,i,s,1);for(let t=0;t<s;t++)for(let e=0;e<i;e++){const a=t*i+e,o=(t+.5)/s,n=R[a],h=C[a]*P,r=X[a],l=y[a]+w[a],c=H(175,200,n)*(1-H(250,275,n))*H(.08,.25,h),d=(1-H(45,65,n)+H(290,330,n))*H(.2,.45,h)*H(.3,.55,r),m=(1-H(.15,.35,h))*H(.45,.7,r)*N,u=(1-H(.08,.2,r))*N,f=N>.3?1-H(G,G+.1,o):1-H(.4,.8,o),g=1-H(.02,.06,l),p=1-H(.03,.09,l);ht[a]=Math.max(c*g,.7*u*(1-H(.008,.025,l)),d*p*.9)*f,rt[a]=Math.max(ht[a],m*g*f),nt[a]=0===t?ht[a]:0,lt[a]=H(150,172,n)*(1-H(232,250,n))*H(.25,.45,h),mt[a]=H(1.3,2.2,(S[a]+.004)/(k[a]+.004))*H(.35,.55,M[a])*(1-H(.1,.18,C[a]*P))*H(.025,.07,l)*H(.025,.045,gt[a]);const x=1-H(.18,.4,h),v=H(.55,.8,r)*H(.05,.12,l);ct[a]=Math.max(lt[a],.85*x,.8*v)}V(nt,ht,i,s,.995,1),V(nt,rt,i,s,.8,1);let pt=0;for(let t=0;t<o;t++)pt+=nt[t];const Mt=pt>.04*o&&N>.3;if(Mt)for(let t=0;t<s;t++)for(let e=0;e<i;e++)lt[t*i+e]*=H(G,G+.05,(t+.5)/s);if(Mt){const t=a.take(),e=a.take(),n=a.take();for(let e=0;e<o;e++)t[e]=.299*tt[e]+.587*et[e]+.114*it[e];for(let t=0;t<s;t++)for(let a=0;a<i;a++)e[t*i+a]=M[Math.min(s-1,t+1)*i+a]-M[Math.max(0,t-1)*i+a];const h=new Uint8Array(o);for(let t=1;t<s-1;t++)for(let a=0;a<i;a++){const o=Math.abs(e[t*i+a]);let n=o>.03;for(let h=-3;h<=3&&n;h++)h&&t+h>=0&&t+h<s&&Math.abs(e[(t+h)*i+a])>o&&(n=!1);h[t*i+a]=n?1:0}const r=(e,i,s,a=!0)=>{const o=tt[i]+et[i]+it[i]+.05,n=tt[s]+et[s]+it[s]+.05,h=Math.abs(tt[i]/o-tt[s]/n)+Math.abs(et[i]/o-et[s]/n)+Math.abs(it[i]/o-it[s]/n),r=Math.min(Math.abs(R[i]-R[s]),360-Math.abs(R[i]-R[s])),l=Math.max(1-H(.1,.25,h),(1-H(15,35,r))*H(.15,.3,Math.min(C[i],C[s]))),c=Math.max(H(2,3,(k[i]+.004)/(S[i]+.004))*H(.015,.04,y[i]+w[i])*H(.4,.55,y[i]/(y[i]+w[i]+1e-4)),1-H(.12,.25,t[i]));return l*(a?c:1)*(1-H(.82*t[s]+.02,1.02*t[s]+.05,t[i]))};let l=0,c=0;for(let t=Math.max(3,Math.round(s*Math.max(.25,G)));t<Math.round(.88*s);t++){let e=0;for(let s=0;s<i;s++)(h[(t-1)*i+s]||h[t*i+s]||h[(t+1)*i+s])&&e++;if(e<.5*i)continue;let a=0;for(let e=t+1;e<Math.min(s,2*t);e++)for(let s=0;s<i;s++)a+=r(t,e*i+s,(2*t-e)*i+s);a>c&&(c=a,l=t)}const d=H(.05,.1,c/o);if(d>0)for(let t=l+1;t<Math.min(s,2*l);t++)for(let e=0;e<i;e++){const s=t*i+e;ut[s]=r(l,s,(2*l-t)*i+e)*d,ft[s]=r(l,s,(2*l-t)*i+e,!1)*d,n[s]=ut[s]}D(n,m,i,s,1);for(let t=0;t<o;t++)ut[t]=Math.max(ut[t],n[t]),lt[t]=Math.max(lt[t],ut[t])}const xt=u(lt,g);for(let t=0;t<o;t++)lt[t]*=H(.15,.35,xt[t]);const vt=u(lt,f);for(let t=0;t<o;t++){lt[t]*=1-.8*ht[t];const e=Math.min(Math.abs(R[t]-200),360-Math.abs(R[t]-200));dt[t]=H(.28,.45,C[t]*P)*H(55,80,e)*(1-H(.3,.6,ft[t]))}const yt=u(dt,f);for(let t=0;t<o;t++)dt[t]=Math.max(dt[t]*(1-(1-H(.15,.3,yt[t]))*H(.55,.7,X[t])*H(.5,.65,C[t])),1-d[t]),ct[t]=Math.min(Math.max(ct[t],.9*ft[t]),Math.max(lt[t],H(.25,.6,vt[t])))*(1-nt[t])*(1-dt[t]);V(lt,ct,i,s,.97);const wt=a.take(mt),bt=Math.max(2,Math.round(.12*s));for(let t=0;t<i;t++){let e=0;for(let a=-bt;a<=bt;a++)e+=mt[Math.max(0,Math.min(s-1,a))*i+t];for(let a=0;a<s;a++)wt[a*i+t]=e/(2*bt+1),e+=mt[Math.min(s-1,a+bt+1)*i+t]-mt[Math.max(0,a-bt)*i+t]}D(wt,m,i,s,1);for(let t=0;t<o;t++)mt[t]=H(.2,.45,wt[t])*H(.2,.5,mt[t]+.5*wt[t])*(1-nt[t]);$(nt,c,i,s,Math.max(2,Math.round(.04*n)),.002,a),$(lt,c,i,s,Math.max(2,Math.round(.04*n)),.002,a),$(mt,c,i,s,Math.max(2,Math.round(.03*n)),.002,a),D(dt,m,i,s,1);for(let t=0;t<o;t++)nt[t]=H(.3,.7,nt[t])*d[t],mt[t]=H(.3,.7,mt[t])*d[t]*(1-nt[t]),lt[t]=H(.3,.7,lt[t])*(1-nt[t])*(1-mt[t])*(1-H(.15,.4,dt[t]));J(nt,m,i,s,2),J(lt,m,i,s,2),J(mt,m,i,s,1),D(nt,m,i,s,1),D(lt,m,i,s,1),D(mt,m,i,s,1);const St=1/Math.max(.02,W(j,.97)),kt=1/Math.max(.01,W(B,.9)),Et=W(Y,.97),At=W(Y,.1),Tt=H(.06,.25,Et-At),zt=a.take();for(let t=0;t<s;t++)for(let e=0;e<i;e++){const a=t*i+e,o=(e+.5)/i,n=(t+.5)/s,h=Math.max(nt[a],lt[a]),r=y[a]+w[a]+b[a],l=.6*O(((y[a]+.6*w[a])/(r+.004)-.25)/.55)+.4*O((y[a]+w[a])/E),c=H(.04,.35,r/E)*(1-h),d=.55*O((Y[a]-At)/Math.max(.05,Et-At))+.25*(1-O(B[a]*kt))+.2*O(2*(z[a]-A[a])+.3)*P,m=Tt*H(.12,.35,x[a])*(.4+.6*N),u=N*(n<G?.45:.45+.55*H(0,1,(n-G)/Math.max(.15,1-G)))+(1-N)*(.5+.4*(n-.5)),f=y[a]/(y[a]+w[a]+1e-4),g=H(.2,.7,(y[a]+w[a])/E)*(.35+.65*N)*(1-h),p=1-O(1.5*Math.hypot(1.2*(o-.5),n-.52)),M=O(j[a]*St)*(.55+.45*p),v=.3*c,S=.25*m,k=.12+.45*N,T=.12*g,D=.35*(1-.4*N)*(1-h);zt[a]=(v*l+S*(1-d)+k*u+T*O(1.6-1.6*f)+D*M+.04)/(v+S+k+T+D+.08)*(1-.85*nt[a])*(1-.45*lt[a]*(1-N))}const Dt=F(t,i,s);if("none"!==Dt.key)for(let t=0;t<o;t++)zt[t]=.7*Dt.subject[t]+.3*zt[t];return D(zt,m,i,s,Math.max(1,Math.round(.03*n))),function(t,e,i,s,a,o,n,h,r){const l=a*o,c=r.take(),d=t=>(q(t,c,a,o,n),t),m=(t,e)=>{const i=r.take();for(let s=0;s<l;s++)i[s]=t[s]*e[s];return d(i)},u=d(r.take(e)),f=d(r.take(i)),g=d(r.take(s)),p=d(r.take(t)),M=m(e,e),x=m(e,i),v=m(e,s),y=m(i,i),w=m(i,s),b=m(s,s),S=m(e,t),k=m(i,t),E=m(s,t),A=r.take(),T=r.take(),z=r.take(),D=r.take();for(let t=0;t<l;t++){const e=S[t]-u[t]*p[t],i=k[t]-f[t]*p[t],s=E[t]-g[t]*p[t],a=M[t]-u[t]*u[t]+h,o=x[t]-u[t]*f[t],n=v[t]-u[t]*g[t],r=y[t]-f[t]*f[t]+h,l=w[t]-f[t]*g[t],c=b[t]-g[t]*g[t]+h,d=r*c-l*l,m=n*l-o*c,R=o*l-n*r,F=a*c-n*n,C=o*n-a*l,X=a*r-o*o,I=a*d+o*m+n*R,P=Math.abs(I)>1e-12?1/I:0;A[t]=(d*e+m*i+R*s)*P,T[t]=(m*e+F*i+C*s)*P,z[t]=(R*e+C*i+X*s)*P,D[t]=p[t]-A[t]*u[t]-T[t]*f[t]-z[t]*g[t]}d(A),d(T),d(z),d(D);for(let a=0;a<l;a++)t[a]=A[a]*e[a]+T[a]*i[a]+z[a]*s[a]+D[a]}(zt,A,T,z,i,s,Math.max(2,Math.round(.07*n)),.004,a),{depth:zt,water:lt,sky:nt,falls:mt}}function Q(t,e,i,s,a,o,n){if(e===o&&i===n)return t[a*o+s];const h=Math.max(0,Math.min(e-1,(s+.5)*e/o-.5)),r=Math.max(0,Math.min(i-1,(a+.5)*i/n-.5)),l=Math.min(e-2,Math.floor(h)),c=Math.min(i-2,Math.floor(r)),d=h-l,m=r-c;if(l<0||c<0)return t[Math.round(r)*e+Math.round(h)];const u=c*e+l,f=u+e;return(t[u]*(1-d)+t[u+1]*d)*(1-m)+(t[f]*(1-d)+t[f+1]*d)*m}function tt(t){const e=Intl.Segmenter;return e?Array.from(new e(void 0,{granularity:"grapheme"}).segment(t),t=>t.segment):Array.from(t)}function et(){const t=document.createElement("canvas"),e=document.createElement("canvas"),i=t.getContext("2d"),s=e.getContext("2d",{willReadFrequently:!0}),a=function(){const t=new WeakMap;return(e,i,s="")=>{if(!e)return i;let a=t.get(e);if(!a){const i=new Set;for(const t of e)for(const e of t)e.char&&i.add(e.char);a=[...i].sort(),t.set(e,a)}const o=i+s;return i+a.filter(t=>!o.includes(t)).join("")}}();let o,n=null;return{update(h,r,l,c,d,m,u,f){const g=u?.[0]?.length??Math.max(1,Math.round(r/c)),p=u?.length??Math.max(1,Math.round(l/d)),M=f??{charset:" .:-=+*#%@",customText:"",colorMode:"fullcolor"},x=a(u,M.charset+(M.charsetFrames?.join("")??""),M.customText),v=function(t,e,i,s,a,o,n,h=4096,r=0,l=1){if(![i,s,a,o,n,h].every(t=>Number.isFinite(t)&&t>0))throw new Error("Glyph atlas dimensions must be positive and finite.");const c=JSON.stringify([e.charset,e.customText,i,s,a,o,n,h,r,l]);if(t?.key===c)return t;const d=[...new Set([" ",...tt(e.charset),...tt(e.customText??"")])];if(d.length>65536)throw new Error("This character set exceeds the glyph texture capacity.");const m=i/o,u=s/n,f=.9*Math.min(m/.55,u)*l,g=Math.ceil(m*a)+6,p=Math.ceil(u*a)+6,M=Math.min(d.length,Math.floor(h/g));if(M<1||Math.ceil(d.length/M)*p>h)throw new Error("The glyph atlas exceeds the available GPU texture size.");return{key:c,glyphs:d,indices:new Map(d.map((t,e)=>[t,e])),cellWidth:m,cellHeight:u,fontSize:f,padding:3,tileWidth:g,tileHeight:p,atlasColumns:M,atlasWidth:M*g,atlasHeight:Math.ceil(d.length/M)*p}}(n,{...M,charset:x},r,l,m,g,p);if(v!==n&&(t.width=v.atlasWidth,t.height=v.atlasHeight,i.font=v.fontSize*m+'px "JetBrains Mono", monospace',i.textAlign="center",i.textBaseline="middle",i.fillStyle="#fff",v.glyphs.forEach((t,e)=>i.fillText(t,e%v.atlasColumns*v.tileWidth+v.padding+v.cellWidth*m*.5,Math.floor(e/v.atlasColumns)*v.tileHeight+v.padding+v.cellHeight*m*.5))),n=v,u)o=function(t,e,i,s,a=!1){const o=t.length,n=t[0]?.length??0,h=s?.cols===n&&s.rows===o?s:{cols:n,rows:o,indices:new Uint8Array(n*o*4),colors:new Uint8ClampedArray(n*o*4)};h.indices.fill(0),h.colors.fill(0);const r="accent"===i.colorMode?[1,3,5].map(t=>parseInt(i.accentColor.slice(t,t+2),16)):null;for(let s=0;s<o;s++){if(t[s].length!==n)throw new Error("Glyph frames must have a rectangular cell grid.");for(let o=0;o<n;o++){const l=t[s][o];if(!l.char||!a&&" "===l.char||l.a<10)continue;const c=e.get(l.char);if(void 0===c)throw new Error(`Glyph is absent from the configured character set: ${l.char}`);const d=4*(s*n+o);let m=l.r,u=l.g,f=l.b;if(r)[m,u,f]=r;else if("fullcolor"!==i.colorMode){const t=.299*m+.587*u+.114*f|0;m="matrix"===i.colorMode?0:t,u=t,f=m}(a||0!==m||0!==u||0!==f)&&(h.indices[d]=255&c,h.indices[d+1]=c>>>8,h.indices[d+2]=Math.round(.299*l.r+.587*l.g+.114*l.b),h.colors[d]=m,h.colors[d+1]=u,h.colors[d+2]=f,h.colors[d+3]=l.a)}}return h}(u,n.indices,M,o,!0);else{e.width=g,e.height=p,s.drawImage(h,0,0,g,p);const t=s.getImageData(0,0,g,p).data;o={cols:g,rows:p,indices:new Uint8Array(g*p*4),colors:new Uint8ClampedArray(t)};for(let e=0;e<t.length;e+=4){const i=Math.min(1,(.299*t[e]+.587*t[e+1]+.114*t[e+2])/255*(t[e+3]/255)*3);o.indices[e+2]=Math.round(255*i),o.indices[e]=Math.min(n.glyphs.length-1,Math.floor(i*n.glyphs.length))}}return{plan:n,packed:o,atlas:t,dots:"dots"===M.renderMode,dotSize:M.dotSizeRatio??.72}},reset(){n=null},destroy(){t.width=t.height=e.width=e.height=1,o=void 0,n=null}}}function it(t){return!!t&&"ascii"===t.renderMode&&!/\p{Extended_Pictographic}/u.test(t.customText||t.charset)&&!t.charsetFrames?.length&&["fullcolor","grayscale","matrix","accent"].includes(t.colorMode)&&("accent"!==t.colorMode||/^#[\da-f]{6}$/i.test(t.accentColor))}function st(t){for(let e=t;e;e=e.parentElement){const t=getComputedStyle(e).backgroundColor.match(/[\d.]+/g)?.map(Number);if(t&&t.length>=3&&(t[3]??1)>.5)return(.299*t[0]+.587*t[1]+.114*t[2])/255<.4?[10/255,10/255,10/255,1]:[250/255,249/255,247/255,1]}const e=document.documentElement.dataset.theme;if("dark"!==e&&"light"!==e&&!t.isConnected&&document.body)return st(document.body);return"dark"===e||"light"!==e&&(document.documentElement.classList.contains("dark")||matchMedia("(prefers-color-scheme: dark)").matches)?[10/255,10/255,10/255,1]:[250/255,249/255,247/255,1]}function at(t,e,a){const o=e.style.visibility;let l=document.createElement("canvas"),c=null,d=null,m=null,u=null;const f=[],g=[];let p=!1,x=!1,S=4096,k=null,E=0,A=0,T=0,z=0,R=!1;const F=function(){const t=document.createElement("canvas"),e=t.getContext("2d");return{paint(i,s,a,o){s&&(t.width===i.canvas.width&&t.height===i.canvas.height||(t.width=i.canvas.width,t.height=i.canvas.height),e.globalCompositeOperation="copy",e.drawImage(i.canvas,0,0),e.globalCompositeOperation="destination-in",e.drawImage(s.canvas,0,0,t.width,t.height),e.globalCompositeOperation="source-in",e.fillStyle="#090909",e.fillRect(0,0,t.width,t.height),e.globalCompositeOperation="source-over",i.drawImage(t,0,0,a,o))},destroy(){t.width=t.height=1}}}();let C,X;const I=document.createElement("canvas"),P=document.createElement("canvas"),_=I.getContext("2d"),U=P.getContext("2d");let G=!1;const L=new h,N=et();let H=null,q=null,$=null,V=!1,J=new Uint8Array(0),tt=new Uint8Array(0),at={};const ot=document.createElement("canvas"),nt=ot.getContext("2d",{willReadFrequently:!0});ot.width=8,ot.height=1;const ht=()=>{l.className="ascii-hover-surface",l.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none",l.setAttribute("role","img"),l.setAttribute("aria-label","ASCII artwork preview"),l.dataset.renderer=c?"surface-gpu":"surface-canvas",t.prepend(l),e.style.visibility="hidden"},rt=()=>{c&&(f.forEach(t=>c.deleteTexture(t)),g.forEach(t=>c.deleteShader(t)),m&&c.deleteProgram(m),u&&c.deleteBuffer(u))},lt=()=>{p||d||(l.removeEventListener("webglcontextlost",lt),rt(),l.remove(),c=null,l=document.createElement("canvas"),d=l.getContext("2d"),ht(),a())};try{if(c=l.getContext("webgl",{alpha:!0,antialias:!1,depth:!1,stencil:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!0}),!c)throw new Error("WebGL unavailable");S=c.getParameter(c.MAX_TEXTURE_SIZE);const t=(t,e)=>{const i=c.createShader(t);if(g.push(i),c.shaderSource(i,e),c.compileShader(i),!c.getShaderParameter(i,c.COMPILE_STATUS))throw new Error(c.getShaderInfoLog(i)||"Shader compilation failed");return i};if(m=c.createProgram(),c.attachShader(m,t(c.VERTEX_SHADER,"attribute vec2 position; void main(){gl_Position=vec4(position,0.,1.);}")),c.attachShader(m,t(c.FRAGMENT_SHADER,"\n precision highp float;\n uniform sampler2D artwork; uniform sampler2D surface;\n uniform vec2 resolution; uniform vec2 sceneSize; uniform vec2 cellSize;\n uniform vec2 surfaceSize; uniform float strength; uniform float relativeStrength;\n \nuniform float hoverMode;\nuniform vec4 hoverFocus;\nfloat surfaceLight(vec2 uv, vec2 size) {\n vec2 delta = (uv - hoverFocus.xy) * size / min(size.x, size.y) / hoverFocus.w;\n float light = exp(-3.0 * dot(delta, delta));\n if (hoverMode > 2.5) light = -smoothstep(.85, .35, length(delta));\n else if (hoverMode > 1.5) light = (exp(-delta.x * delta.x * 110.0) * 1.3 - exp(-delta.x * delta.x * 12.0) * .3) * exp(-delta.y * delta.y * 1.8);\n return hoverMode > .5 ? light * hoverFocus.z : 0.0;\n}\nvec3 illuminate(vec3 ink, float light) {\n return mix(ink, vec3(1.0), max(0.0, light) * .82) * (1.0 + min(0.0, light));\n}\n\n uniform sampler2D codes; uniform sampler2D cellColors; uniform sampler2D glyphAtlas;\n uniform vec2 gridSize; uniform vec2 atlasSize; uniform vec2 tileSize;\n uniform float atlasColumns; uniform float padding; uniform float glyphCount;\n uniform float dots; uniform float dotSize; uniform float directGlyphs; uniform vec4 backdrop; uniform vec4 cellGround;\n uniform float edgeEffect; uniform sampler2D textMask; uniform float hasTextMask; uniform sampler2D cueMap;\n \nuniform float finishMode;\nuniform float finishPixelRatio;\nuniform float finishSoftness;\nvec3 edgeCoverage(sampler2D sheet, vec2 uv, vec2 atlas, vec2 pixel, vec2 viewport, float amount) {\n float a=texture2D(sheet,uv).a;\n if(amount<=0.0 || finishMode<.5) return vec3(a);\n vec2 radial=(pixel/viewport-.5)*2.0;\n float edge=smoothstep(.3,1.05,length(radial));\n float strength=clamp(amount,0.0,1.0)*edge;\n if(strength<=0.0) return vec3(a);\n vec2 cssPixel=pixel/max(1.0,finishPixelRatio);\n // Etch is a single texture sample: linework, not an opacity wash.\n if(finishMode>1.5 && finishMode<2.5) {\n float hatch=step(.68,fract((cssPixel.y+cssPixel.x*.22)*.5));\n return vec3(a*(1.0-hatch*strength*.64));\n }\n // Samples remain inside the current atlas tile's three-pixel padding.\n if(finishMode>2.5) {\n float band=floor(cssPixel.y/3.0);\n float phase=fract(sin(band*12.9898)*43758.5453);\n float tear=(phase-.5)*3.6*strength;\n float displaced=texture2D(sheet,uv+vec2(tear,0.0)/atlas).a;\n float cut=step(.72,fract(cssPixel.y*.5));\n return vec3(mix(a,displaced,strength)*(1.0-cut*.55*strength));\n }\n // A five-tap lens: opposed red/cyan edges with a short soft shoulder.\n // The center remains untouched; all offsets stay within three atlas texels.\n vec2 direction=normalize(vec2(radial.x-radial.y*.3,radial.y+radial.x*.3)+vec2(.00001));\n vec2 shift=direction*(2.35+.45*finishSoftness)*strength/atlas;\n float left=texture2D(sheet,uv-shift).a,right=texture2D(sheet,uv+shift).a;\n float softLeft=texture2D(sheet,uv-shift*.45).a,softRight=texture2D(sheet,uv+shift*.45).a;\n float red=left*.7+softLeft*.22+a*.08;\n float cyan=right*.7+softRight*.22+a*.08;\n // Reuse the same taps for a short optical blur and peripheral fade.\n // No whole-canvas blur, extra pass or softened HTML controls.\n float soft=a*.4+(left+right+softLeft+softRight)*.15;\n vec3 fringe=mix(vec3(red,cyan,cyan),vec3(soft),finishSoftness*.45);\n return mix(vec3(a),fringe,strength)*(1.-finishSoftness*strength*.32);\n\n}\n\n \nuniform float edgeSafe;\nuniform float trailAmount;\nuniform float trailKind;\nuniform sampler2D scopeMap;\nuniform float scopeMode;\n// Hover scope: 0 everywhere, 1 on the subject, 2 around it. The map holds soft subject coverage in alpha.\nfloat hoverScope(vec2 uv) {\n if (scopeMode < .5) return 1.;\n float s=texture2D(scopeMap,uv).a;\n return scopeMode < 1.5 ? s : 1.-s;\n}\nvec4 trailField(vec2 address) {\n return texture2D(surface,(address*(surfaceSize-1.0)+.5)/surfaceSize);\n}\nfloat trailFieldDensity(vec4 field) {\n float raw=field.r*65280.0+field.g*255.0;\n return (trailKind>2.5?(raw-32768.)/32767.:raw/65535.)*trailAmount;\n}\nfloat trailDensity(vec2 address) { return trailFieldDensity(trailField(address))*hoverScope(address); }\nfloat trailPin(vec2 cell, vec2 grid) {\n vec2 edge=min(cell,grid-1.0-cell);\n return mix(1.,smoothstep(1.0,5.0,min(edge.x,edge.y)),edgeSafe);\n}\nvec2 trailSource(vec2 cell, vec2 grid, vec4 field) {\n vec2 home=(cell+.5)/grid;\n if(trailKind>.5 || trailAmount<=0.) return home;\n float pin=trailPin(cell,grid);\n float response=1.-exp(-trailFieldDensity(field)*hoverScope(home)*pin*3.5);\n vec2 drift=(field.ba*255.-128.)/127.;\n return clamp(home-drift*response*.026*pin,.5/grid,1.-.5/grid);\n}\nvec2 decodedGlyph(vec4 code) {\n return vec2(floor(code.r*255.+.5)+floor(code.g*255.+.5)*256.,code.b);\n}\n// Bilinear interpolation happens before glyph selection, never between bitmap\n// letters. Four small metadata reads replace the old four full-glyph gathers.\nvec2 flowGlyph(sampler2D codes,vec2 uv,vec2 grid) {\n vec2 p=uv*grid-.5,b=floor(p),f=fract(p);\n return mix(mix(decodedGlyph(texture2D(codes,(b+.5)/grid)),decodedGlyph(texture2D(codes,(b+vec2(1.5,.5))/grid)),f.x),\n mix(decodedGlyph(texture2D(codes,(b+vec2(.5,1.5))/grid)),decodedGlyph(texture2D(codes,(b+1.5)/grid)),f.x),f.y);\n}\nvec3 trailInk(vec3 ink, float density) {\n if (trailKind < .5) return ink;\n float peak=max(ink.r,max(ink.g,ink.b));\n float raised=trailKind>1.5?peak:max(peak,min(.44,density*.75));\n return peak>.001 ? ink*(raised/peak) : vec3(raised);\n}\nfloat flowIndex(float index,float count,float density) {\n float last=max(0.,count-1.);\n float response=1.-exp(-max(0.,density)*3.5);\n return max(0.,last-abs(last-(index+response*last*2.1)));\n}\nfloat trailTone(float tone, float density) {\n if (trailKind > 2.5) return clamp(tone+density*.35,0.,1.);\n if (trailKind < .5) return flowIndex(tone,2.,density);\n return clamp(tone + (trailKind > 1.5 ? -density : density) * .65, 0.0, 1.0);\n}\nfloat trailIndex(float index, float count, float density, vec2 cell) {\n float grain=fract((cell.x*cell.x*17.0+cell.y*cell.y*23.0+cell.x*cell.y*19.0)*.0137);\n if(trailKind>2.5) return clamp(floor(index+density*(count-1.)*.35+.5),0.,count-1.);\n if(trailKind>1.5) return max(0.0,index-floor(density*count*(1.35+grain*.9)));\n if(trailKind<.5) {\n float seed=fract(sin(dot(cell,vec2(127.1,311.7)))*43758.5453);\n float response=1.-exp(-max(0.,density)*3.5);\n return floor(max(0.,flowIndex(index,count,density)-response*(1.-response)*seed*3.)+.5);\n }\n return min(count-1.0,index+floor(density*count*.85));\n}\n\n \n uniform float motionMode; uniform float motionTime; uniform float fineDither; uniform float ditherAmount; uniform vec2 motionFocus;\n float printGrain(vec2 p) { return fract(52.9829189*fract(dot(p,vec2(.06711056,.00583715)))); }\n // cue: light, depth, glow, detail; normal: relief normal.\n vec4 ambientAt(vec2 uv, float tone, vec4 cue, vec2 normal) {\n if(motionMode<.5) return vec4(0.,0.,0.,1.);\n float p=motionTime*.5235987756, cycle=mod(motionTime,12.);\n float edge=smoothstep(0.,.12,min(min(uv.x,1.-uv.x),min(uv.y,1.-uv.y)));\n tone=clamp(tone,0.,1.);\n if(motionMode<1.5) {\n float a=p+.6; vec2 l=vec2(cos(a),sin(a));\n float form=clamp(dot(normal,l),-1.,1.)+dot(uv-.5,l)*.35;\n return vec4(0.,0.,form*.2*(.3+.7*smoothstep(.04,.3,cue.x)*(1.-.6*smoothstep(.82,1.,tone))),1.);\n }\n if(motionMode<2.5) {\n float position=-.35+1.9*smoothstep(0.,8.,cycle);\n float d=(uv.x*.75+uv.y*.45)/1.2+(normal.x*.75+normal.y*.45)*.05;\n float band=exp(-pow((d-position)/.12,2.));\n return vec4(0.,0.,band*smoothstep(.3,.8,cue.x)*(1.-.5*smoothstep(.9,1.,tone))*.45,1.);\n }\n if(motionMode<3.5) {\n float k=.5-.5*cos(p), threshold=1.-.8*k;\n return vec4(0.,0.,.2*smoothstep(threshold-.3,threshold+.02,cue.z)*sqrt(cue.z)*(1.-.65*tone)+.05*k*smoothstep(.6,.95,tone),1.);\n }\n if(motionMode<4.5) {\n float phase=printGrain(floor(uv*vec2(160.,100.)))*6.28318530718;\n float glint=pow(.5+.5*cos(p*2.+phase),28.);\n return vec4(0.,0.,glint*smoothstep(.5,.88,tone)*(.35+.65*smoothstep(.1,.55,cue.w))*.42,1.);\n }\n if(motionMode<5.5) { float near=cue.y-.45; return vec4(near*16.*sin(p)*edge,near*7.*sin(p*2.)*edge,0.,1.); }\n if(motionMode<6.5) return vec4((uv-motionFocus)*.045*(.5-.5*cos(p))*(.7+.6*cue.y)*960.,0.,1.);\n if(motionMode<7.5) {\n float s=sin(p), defocus=s*s*smoothstep(.35,.85,s>=0.?1.-cue.y:cue.y);\n return vec4(0.,0.,(cue.x-tone)*defocus*.75,1.);\n }\n if(motionMode<8.5) {\n float far=pow(1.-cue.y,1.5)*(1.-.6*cue.w);\n float veil=sin(uv.x*4.1-p+sin(uv.y*3.3+p)*.9)*.5+sin(uv.x*7.3+uv.y*2.1-p*2.+sin(uv.x*2.7-uv.y*5.1+p)*1.1)*.3+sin(uv.y*5.7-uv.x*1.9+p)*.2;\n return vec4(0.,0.,smoothstep(-.3,.9,veil)*far*.16*(1.-.55*tone),1.);\n }\n if(motionMode<9.5) {\n // Drift is packed with water in z and sky in w (see packPhotoCues): only they move.\n // w holds sky below one half and falling water above it.\n float water=cue.z, sky=min(1.,cue.w*2.), falls=max(0.,cue.w*2.-1.), rim=smoothstep(0.,.06,min(min(uv.x,1.-uv.x),min(uv.y,1.-uv.y)));\n sky*=1.-step(.5,cue.w);\n float swell=uv.y*16.+uv.x*2., chop=uv.y*29.-uv.x*3., sheet=uv.x*1.7+uv.y*2.3, fall=uv.y*26.+sin(uv.x*40.)*1.5;\n float seed=printGrain(floor(uv*vec2(160.,100.)))*6.2831853+uv.x*9.-uv.y*4.;\n float glint=pow(.5+.5*cos(p*2.+seed),24.)-pow(.5+.5*cos(seed),24.);\n return vec4(\n ((sin(swell-p)-sin(swell))*3.5+(sin(chop-p*2.)-sin(chop))*1.5)*water*rim+(sin(sheet-p)-sin(sheet))*5.*sky*rim,\n (cos(swell-p)-cos(swell))*.8*water*rim+(sin(fall-p*2.)-sin(fall))*12.*falls*rim,\n (glint*smoothstep(.5,.85,tone)*.3+(cos(swell-p)-cos(swell))*.025)*water*rim+(cos(fall-p*2.)-cos(fall))*.08*falls*rim,1.);\n }\n float fade=smoothstep(7.,8.5,cycle), k=clamp((cycle-8.5)/3.5,0.,1.);\n float shown=cycle<8.5?1.-fade:smoothstep(0.,1.,(k*1.45-(1.-tone)+(printGrain(floor(uv*vec2(160.,100.)))-.5)*.06)/.3);\n return vec4(0.,0.,-(1.-shown)*.3,1.-(1.-shown)*.9);\n }\n\n float toneAt(vec2 uv) {\n vec2 p=uv*gridSize-.5, b=floor(p), f=fract(p);\n return mix(mix(texture2D(codes,(b+.5)/gridSize).b,texture2D(codes,(b+vec2(1.5,.5))/gridSize).b,f.x),mix(texture2D(codes,(b+vec2(.5,1.5))/gridSize).b,texture2D(codes,(b+1.5)/gridSize).b,f.x),f.y);\n }\n vec4 flowingCharacter(vec2 pixel, vec2 cell, vec4 ambient) {\n if(cell.x<0. || cell.y<0. || cell.x>=gridSize.x || cell.y>=gridSize.y) return vec4(0.);\n vec2 address=(cell+.5)/gridSize;\n vec4 field=trailField(address);\n vec2 local=pixel-cell*cellSize;\n if(local.x<0. || local.y<0. || local.x>=cellSize.x || local.y>=cellSize.y) return vec4(0.);\n vec2 source=trailSource(cell,gridSize,field);\n vec2 encoded=flowGlyph(codes,source,gridSize);\n vec4 color=texture2D(cellColors,source);\n float original=encoded.x;\n float density=trailFieldDensity(field)*hoverScope(address)*trailPin(cell,gridSize),index=trailIndex(original,glyphCount,density,cell);\n if(original>.5) index=clamp(floor(index+ambient.z*(glyphCount-1.)+printGrain(cell)),0.,glyphCount-1.);\n if(index<.5 || color.a<.01) return vec4(0.);\n vec2 slot=vec2(mod(index,atlasColumns),floor(index/atlasColumns));\n float alpha=texture2D(glyphAtlas,(slot*tileSize+padding+local*resolution/sceneSize)/atlasSize).a;\n if(dots>.5) {\n vec2 d=(local-cellSize*.5)/min(cellSize.x,cellSize.y);\n float r=min(.48,(index/(glyphCount-1.))*.5*dotSize);\n alpha=1.-smoothstep(r-.06,r+.02,length(d));\n }\n vec3 coverage=dots>.5?vec3(alpha):edgeCoverage(glyphAtlas,(slot*tileSize+padding+local*resolution/sceneSize)/atlasSize,atlasSize,pixel,sceneSize,edgeEffect);\n coverage*=color.a;alpha=max(coverage.r,max(coverage.g,coverage.b));\n return vec4(trailInk(color.rgb,density)*coverage,alpha);\n }\n void main(){\n vec2 uv = vec2(gl_FragCoord.x, resolution.y - gl_FragCoord.y) / resolution;\n vec2 pixel = uv * sceneSize;\n if (strength > 0.) {\n // Whole cells move, read at the cell centre, so characters are carried intact rather than smeared through.\n vec2 home = (floor(pixel / cellSize) + .5) * cellSize / sceneSize;\n vec4 normal = texture2D(surface, (home * (surfaceSize - 1.) + .5) / surfaceSize) * 255.;\n vec2 slope = (vec2(normal.r * 256. + normal.g, normal.b * 256. + normal.a) - 32768.) / 32767.;\n vec2 edge = min(home * sceneSize, sceneSize - home * sceneSize) / cellSize;\n // Cursor hovers store a fraction of the scene, so they scale with it; stroke hovers store CSS pixels.\n vec2 unit = relativeStrength > .5 ? vec2(1.) : 1. / sceneSize;\n vec2 shift = slope * strength * mix(1.,smoothstep(2.,8.,min(edge.x,edge.y)),edgeSafe) * hoverScope(home) * unit * sceneSize / cellSize;\n uv -= floor(shift + .5) * cellSize / sceneSize;\n }\n vec4 ambient=vec4(0.,0.,0.,1.);\n if(motionMode>.5) {\n vec4 cue=texture2D(cueMap,uv);\n vec2 step=1./gridSize;\n vec2 slope=vec2(texture2D(cueMap,uv+vec2(step.x,0.)).x-texture2D(cueMap,uv-vec2(step.x,0.)).x,texture2D(cueMap,uv+vec2(0.,step.y)).x-texture2D(cueMap,uv-vec2(0.,step.y)).x);\n // Bright reads as raised; normals lean away from the brighter side.\n ambient=ambientAt(uv,toneAt(uv),cue,-slope/max(length(slope),1e-4)*smoothstep(0.,.06,length(slope)));\n }\n uv -= ambient.xy/sceneSize;\n pixel=uv*sceneSize;\n vec4 ink = vec4(0.);\n if (directGlyphs > .5) {\n vec2 cell=floor(pixel/cellSize), address=(cell+.5)/gridSize;\n vec4 encoded=texture2D(codes,address), color=texture2D(cellColors,address);\n float index=floor(encoded.r*255.+.5)+floor(encoded.g*255.+.5)*256.;\n if(index>.5 && color.a>.01) {\n vec2 local=(pixel-cell*cellSize)*resolution/sceneSize;\n vec2 slot=vec2(mod(index,atlasColumns),floor(index/atlasColumns));\n float alpha=texture2D(glyphAtlas,(slot*tileSize+padding+local)/atlasSize).a*color.a;\n vec3 coverage=edgeCoverage(glyphAtlas,(slot*tileSize+padding+local)/atlasSize,atlasSize,pixel,sceneSize,edgeEffect)*color.a;\n ink=vec4(color.rgb*coverage,max(coverage.r,max(coverage.g,coverage.b)));\n }\n } else ink = texture2D(artwork, uv);\n if (fineDither > .5) {\n vec2 cell=floor(pixel/cellSize),address=(cell+.5)/gridSize;\n vec4 color=texture2D(cellColors,address);\n float density=trailAmount>0.?trailDensity(address):0.;\n vec2 source=trailAmount>0. && trailKind<.5?trailSource(cell,gridSize,trailField(address)):uv;\n float tone=trailTone(clamp(toneAt(source)+ambient.z,0.,1.),density*(trailKind<.5?trailPin(cell,gridSize):1.));\n float pitch=max(1.,min(cellSize.x,cellSize.y)*.32);\n float grain=.5+(printGrain(floor(pixel/pitch))-.5)*ditherAmount;\n float alpha=(tone<.001?0.:tone>.999?1.:smoothstep(grain-.035,grain+.035,tone))*color.a*ambient.w;\n // Preserve hue; tone is carried by mark coverage rather than muddy ink.\n vec3 hue=color.rgb/max(.001,max(color.r,max(color.g,color.b)));\n if(hasTextMask>.5) hue=mix(hue,vec3(.035),texture2D(textMask,vec2(gl_FragCoord.x,resolution.y-gl_FragCoord.y)/resolution).a);\n gl_FragColor=vec4(hue*alpha,alpha); return;\n }\n if ((trailAmount > 0. && trailKind > .5) || motionMode > .5) {\n vec2 cell=floor(pixel/cellSize), address=(cell+.5)/gridSize;\n float density=trailAmount>0.?trailDensity(address):0.;\n vec4 encoded=texture2D(codes,address);\n float original=floor(encoded.r*255.+.5)+floor(encoded.g*255.+.5)*256.;\n float index=trailIndex(original,glyphCount,density,cell);\n if(original>.5) index=clamp(floor(index+ambient.z*(glyphCount-1.)+printGrain(cell)),0.,glyphCount-1.);\n vec4 color=texture2D(cellColors,address);\n // Ripple and Emboss draw their own faint rings on an empty or near-black ground, where a tone lift barely shows.\n if(trailKind>2.5 && density>.012 && (color.a<.01 ? scopeMode>1.5 : max(color.r,max(color.g,color.b))<.12)) {\n float ring=smoothstep(.012,.132,density);\n index=max(index,floor((.1+ring*.45)*(glyphCount-1.)+.5));\n color=vec4(vec3(.84),.3+ring*.45);\n }\n if((index!=original || motionMode>.5) && color.a>.01) {\n vec2 local=(pixel-cell*cellSize)*resolution/sceneSize;\n vec2 slot=vec2(mod(index,atlasColumns),floor(index/atlasColumns));\n float alpha=texture2D(glyphAtlas,(slot*tileSize+padding+local)/atlasSize).a;\n if(dots>.5) {\n vec2 d=(pixel-(cell+.5)*cellSize)/min(cellSize.x,cellSize.y);\n float r=min(.48,(index/(glyphCount-1.))*.5*dotSize);\n alpha=1.-smoothstep(r-.06,r+.02,length(d));\n }\n // Replace the cell, rather than blending two glyphs into a ghost.\n vec3 rgb=trailInk(color.rgb,density);\n ink=vec4(rgb*alpha*color.a,alpha*color.a);\n ink+=cellGround*(1.-ink.a);\n }\n }\n if(trailAmount>0. && trailKind<.5 && trailDensity((floor(pixel/cellSize)+.5)/gridSize)>.001) {\n ink=flowingCharacter(pixel,floor(pixel/cellSize),ambient);\n ink+=cellGround*(1.-ink.a);\n }\n vec3 straightInk = ink.a > .0 ? ink.rgb / ink.a : vec3(.0);\n float value = max(straightInk.r, max(straightInk.g, straightInk.b));\n // Lighting belongs to character ink; black/transparent gaps stay empty.\n float light = surfaceLight((floor(pixel / cellSize) + .5) * cellSize / sceneSize, sceneSize) * hoverScope(pixel / sceneSize);\n vec3 lit = illuminate(straightInk, light * smoothstep(0., .22, value)) * ink.a;\n if(hasTextMask>.5) lit=mix(lit,vec3(.035)*ink.a,texture2D(textMask,vec2(gl_FragCoord.x,resolution.y-gl_FragCoord.y)/resolution).a);\n vec4 result = vec4(lit, ink.a)*ambient.w;\n gl_FragColor = directGlyphs > .5 ? result + backdrop*(1.-result.a) : result;\n }")),c.linkProgram(m),!c.getProgramParameter(m,c.LINK_STATUS))throw new Error("Surface shader link failed");c.useProgram(m),u=c.createBuffer(),c.bindBuffer(c.ARRAY_BUFFER,u),c.bufferData(c.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),c.STATIC_DRAW);const e=c.getAttribLocation(m,"position");c.enableVertexAttribArray(e),c.vertexAttribPointer(e,2,c.FLOAT,!1,0,0),at=Object.fromEntries(["finishSoftness","finishMode","finishPixelRatio","edgeEffect","textMask","hasTextMask","artwork","surface","resolution","sceneSize","cellSize","surfaceSize","strength","hoverMode","hoverFocus","codes","cellColors","glyphAtlas","gridSize","atlasSize","tileSize","atlasColumns","padding","glyphCount","dots","dotSize","directGlyphs","backdrop","cellGround","trailKind","edgeSafe","relativeStrength","scopeMap","scopeMode","trailAmount","motionMode","motionTime","fineDither","ditherAmount","cueMap","motionFocus"].map(t=>[t,c.getUniformLocation(m,t)]));for(let t=0;t<8;t++){const e=c.createTexture();f.push(e),c.activeTexture(c.TEXTURE0+t),c.bindTexture(c.TEXTURE_2D,e),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,1,1,0,c.RGBA,c.UNSIGNED_BYTE,new Uint8Array(4)),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE)}c.uniform1i(at.textMask,5),c.uniform1i(at.scopeMap,6),c.uniform1i(at.cueMap,7),c.uniform1i(at.codes,2),c.uniform1i(at.cellColors,3),c.uniform1i(at.glyphAtlas,4),c.uniform1i(at.artwork,0),c.uniform1i(at.surface,1),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),c.disable(c.BLEND),c.disable(c.DEPTH_TEST),l.addEventListener("webglcontextlost",lt),ht()}catch{lt()}const ct=()=>{p||(N.reset(),H=null,x=!1,a())};return document.fonts?.addEventListener("loadingdone",ct),document.fonts?.ready.then(ct),{get canvas(){return l},canRenderGlyphs:t=>!!c&&!p&&it(t),render(t,a,o,h,m,u,g,et,ot=0,ht={}){const rt=s(et?.animationStyle),ct=L.update(ot,rt,et?.animationSpeed),dt=(t=>!0===t?.fineDither&&!t.customText&&!t.charsetFrames?.length&&!/[A-Za-z]/.test(t.charset??""))(et),mt=!!c&&!!g&&it(et);if(mt!==R&&(x=!1,R=mt),p||!o||!h||!e.width||!e.height)return;const ut=Math.min(e.width/o,1.5,Math.sqrt(4e6/(o*h))),ft=Math.max(1,Math.round(o*ut)),gt=Math.max(1,Math.round(h*ut));if(l.width===ft&&l.height===gt||(l.width=ft,l.height=gt,x=!1),c&&(e.width>S||e.height>S)&&lt(),(mt||M(a.mode)||"none"!==rt||dt)&&(t||!x||!H)&&(H=N.update(e,o,h,m,u,ut,g,et),c)){const{plan:t,packed:e,atlas:i}=H;for(const[t,i]of[[2,e.indices],[3,e.colors]])c.activeTexture(c.TEXTURE0+t),c.bindTexture(c.TEXTURE_2D,f[t]),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,3===t?c.LINEAR:c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,3===t?c.LINEAR:c.NEAREST),E!==e.cols||A!==e.rows?c.texImage2D(c.TEXTURE_2D,0,c.RGBA,e.cols,e.rows,0,c.RGBA,c.UNSIGNED_BYTE,i):c.texSubImage2D(c.TEXTURE_2D,0,0,0,e.cols,e.rows,c.RGBA,c.UNSIGNED_BYTE,i);E=e.cols,A=e.rows,k!==t&&(c.activeTexture(c.TEXTURE4),c.bindTexture(c.TEXTURE_2D,f[4]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,i),k=t),c.uniform2f(at.gridSize,e.cols,e.rows),c.uniform2f(at.atlasSize,t.atlasWidth,t.atlasHeight),c.uniform2f(at.tileSize,t.tileWidth,t.tileHeight),c.uniform1f(at.atlasColumns,t.atlasColumns),c.uniform1f(at.padding,t.padding),c.uniform1f(at.glyphCount,t.glyphs.length),c.uniform1f(at.dots,H.dots?1:0),c.uniform1f(at.dotSize,H.dotSize)}if("none"!==rt&&H&&($!==H||V!==("current"===rt))){const{packed:t}=H,e=t.cols*t.rows;J.length!==4*e&&(J=new Uint8Array(4*e));for(let i=0;i<e;i++){const e=t.indices[4*i+2];J[4*i]=J[4*i+1]=J[4*i+2]=e,J[4*i+3]=t.colors[4*i+3]}$!==H&&(q=function(t,e,i,s,a=t){const o=e*i,n=s?.length===o*B?s:new Float32Array(o*B);if(!o)return n;const h=Math.min(e,i),r=new Float32Array(o),l=new Float32Array(o),c=new Float32Array(o),d=new Float32Array(o),m=new Float32Array(o),u=new Float32Array(o);for(let e=0;e<o;e++){const i=t[4*e+3]/255;r[e]=(.299*t[4*e]+.587*t[4*e+1]+.114*t[4*e+2])/255*i}l.set(r),D(l,u,e,i,Math.max(1,Math.round(.012*h))),c.set(r),D(c,u,e,i,Math.max(1,Math.round(.03*h)));for(let t=0;t<o;t++){d[t]=Math.abs(r[t]-l[t]);const e=Math.max(0,r[t]-.55)/.45;m[t]=e*e}D(d,u,e,i,Math.max(1,Math.round(.02*h)));const f=1/Math.max(.02,W(d,.95));D(m,u,e,i,Math.max(1,Math.round(.05*h)));const g=1/Math.max(.03,W(m,.98)),p=Math.max(1,Math.ceil(Math.sqrt(o/12e3))),M=Math.max(1,Math.floor(e/p)),x=Math.max(1,Math.floor(i/p)),v=M*x;let y=t,w=a;if(p>1){const i=new Uint8ClampedArray(4*v),s=a===t?i:new Uint8ClampedArray(4*v);for(let o=0;o<x;o++)for(let n=0;n<M;n++){const h=[0,0,0,0,0,0,0];for(let r=o*p;r<(o+1)*p;r++)for(let o=n*p;o<(n+1)*p;o++){const n=4*(r*e+o);for(let e=0;e<4;e++)h[e]+=t[n+e];if(s!==i)for(let t=0;t<3;t++)h[4+t]+=a[n+t]}const r=4*(o*M+n),l=p*p;for(let t=0;t<4;t++)i[r+t]=h[t]/l;if(s!==i){for(let t=0;t<3;t++)s[r+t]=h[4+t]/l;s[r+3]=i[r+3]}}y=i,w=s}K?.n!==v&&(K=new j(v)),K.reset();const{depth:b,water:S,sky:k,falls:E}=Z(y,w,M,x,K),A=W(b,.03),T=W(b,.97),z=Math.max(.05,T-A);let R=0,F=0,C=0;const X=new Float32Array(o);for(let t=0;t<i;t++)for(let s=0;s<e;s++){const a=t*e+s,o=a*B,h=O((Q(b,M,x,s,t,e,i)-A)/z);n[o+1]=h,n[o+8]=O(Q(S,M,x,s,t,e,i)),n[o+9]=O(Q(k,M,x,s,t,e,i)),n[o+10]=O(Q(E,M,x,s,t,e,i));const l=h*h*h*(.25+r[a]);R+=(s+.5)/e*l,F+=(t+.5)/i*l,C+=l,X[a]=Math.hypot(c[t*e+Math.min(e-1,s+1)]-c[t*e+Math.max(0,s-1)],c[Math.min(i-1,t+1)*e+s]-c[Math.max(0,t-1)*e+s])}R=C>0?Math.max(.3,Math.min(.7,R/C)):.5,F=C>0?Math.max(.3,Math.min(.7,F/C)):.5;const I=1/Math.max(.004,W(X,.97));for(let t=0;t<i;t++)for(let s=0;s<e;s++){const a=t*e+s,o=a*B,h=(c[t*e+Math.min(e-1,s+1)]-c[t*e+Math.max(0,s-1)])*I,r=(c[Math.min(i-1,t+1)*e+s]-c[Math.max(0,t-1)*e+s])*I;n[o]=c[a],n[o+2]=Math.min(1,m[a]*g),n[o+3]=Math.min(1,d[a]*f),n[o+4]=Math.max(-1,Math.min(1,-h)),n[o+5]=Math.max(-1,Math.min(1,-r)),n[o+6]=R,n[o+7]=F}return n}(J,t.cols,t.rows,q,t.colors)),$=H,V="current"===rt,c&&(tt=function(t,e,i=!1){const s=t.length/B,a=e?.length===4*s?e:new Uint8Array(4*s);for(let e=0;e<s;e++){const s=e*B;a[4*e]=Math.round(255*t[s]),a[4*e+1]=Math.round(255*t[s+1]),a[4*e+2]=Math.round(255*t[s+(i?8:2)]),a[4*e+3]=Math.round(255*(i?t[s+10]>t[s+9]?.5+.5*t[s+10]:.5*t[s+9]:t[s+3]))}return a}(q,tt,V),c.activeTexture(c.TEXTURE7),c.bindTexture(c.TEXTURE_2D,f[7]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,t.cols,t.rows,0,c.RGBA,c.UNSIGNED_BYTE,tt),c.uniform2f(at.motionFocus,q?.[6]??.5,q?.[7]??.5))}if(c){c.uniform1f(at.motionMode,(t=>i.findIndex(e=>e.mode===t))(rt)),c.uniform1f(at.motionTime,ct),c.uniform1f(at.fineDither,dt?1:0),c.uniform1f(at.ditherAmount,Math.max(0,Math.min(2,et?.ditherStrength??1))),c.uniform1f(at.trailKind,v(a.mode)),c.uniform1f(at.edgeSafe,a.edgeSafe?1:0),c.uniform1f(at.trailAmount,M(a.mode)?a.focus[2]:0),c.viewport(0,0,ft,gt),mt||!t&&x||(c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,f[0]),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,e),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),c.uniform4fv(at.cellGround,(()=>{if(!nt)return[0,0,0,0];const t=e.width,i=e.height;let s;nt.clearRect(0,0,8,1),[[1,1],[t-2,1],[1,i-2],[t-2,i-2],[t>>1,1],[t>>1,i-2],[1,i>>1],[t-2,i>>1]].forEach(([t,i],s)=>nt.drawImage(e,t,i,1,1,s,0,1,1));try{s=nt.getImageData(0,0,8,1).data}catch{return[0,0,0,0]}for(let t=0;t<32;t+=4){if(s[t+3]<250)continue;let e=0;for(let i=0;i<32;i+=4)s[i+3]>=250&&Math.abs(s[i]-s[t])+Math.abs(s[i+1]-s[t+1])+Math.abs(s[i+2]-s[t+2])<=18&&e++;if(e>=5)return[s[t]/255,s[t+1]/255,s[t+2]/255,1]}return[0,0,0,0]})())),mt&&c.uniform4fv(at.cellGround,[0,0,0,0]),c.uniform1f(at.directGlyphs,mt?1:0),!mt||!t&&x||c.uniform4fv(at.backdrop,ht.textMask||function(t){const e=t.length,i=t[0]?.length??0;for(let s=0;s<e;s+=Math.max(1,e>>2))for(let e=0;e<i;e+=Math.max(1,i>>2))if(t[s][e].a<200)return!0;return!1}(g)?[0,0,0,0]:st(e)),x=!0,c.activeTexture(c.TEXTURE1),c.bindTexture(c.TEXTURE_2D,f[1]),T!==a.width||z!==a.height?(c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a.width,a.height,0,c.RGBA,c.UNSIGNED_BYTE,a.pixels),T=a.width,z=a.height):c.texSubImage2D(c.TEXTURE_2D,0,0,0,a.width,a.height,c.RGBA,c.UNSIGNED_BYTE,a.pixels),c.uniform2f(at.resolution,ft,gt),c.uniform2f(at.sceneSize,o,h),c.uniform2f(at.cellSize,m,u),c.uniform2f(at.surfaceSize,a.width,a.height),c.uniform1f(at.strength,a.strength),c.uniform1f(at.relativeStrength,a.relative?1:0);const s=ht.scope;c.uniform1f(at.scopeMode,s&&"all"!==s.mode?"subject"===s.mode?1:2:0),s&&"all"!==s.mode&&s.pixels!==X&&(c.activeTexture(c.TEXTURE6),c.bindTexture(c.TEXTURE_2D,f[6]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,s.width,s.height,0,c.RGBA,c.UNSIGNED_BYTE,s.pixels),X=s.pixels),c.uniform1f(at.hoverMode,"light"===a.mode||"reveal"===a.mode?1:"scan"===a.mode?2:"repel"===a.mode?3:0),c.uniform4fv(at.hoverFocus,a.focus),ht.textMask&&ht.textMask!==C&&(c.activeTexture(c.TEXTURE5),c.bindTexture(c.TEXTURE_2D,f[5]),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,ht.textMask.canvas),C=ht.textMask),c.uniform1f(at.hasTextMask,ht.textMask?1:0);const n=function(t={}){const e=Y.some(e=>e.value===t.filter)?t.filter:"prism",i=Number.isFinite(t.edgeEffect)?Math.max(0,Math.min(1,t.edgeEffect)):t.filter?1:0,s=Number.isFinite(t.edgeSoftness)?Math.max(0,Math.min(1,t.edgeSoftness)):0;return{mode:["clean","prism","etch","signal"].indexOf(e),amount:"clean"===e?0:i,softness:"prism"===e?s:0}}(ht);c.uniform1f(at.edgeEffect,n.amount),c.uniform1f(at.finishMode,n.mode),c.uniform1f(at.finishSoftness,n.softness),c.uniform1f(at.finishPixelRatio,1),c.drawArrays(c.TRIANGLE_STRIP,0,4)}else if(d){if(d.setTransform(ut,0,0,ut,0,0),d.clearRect(0,0,o,h),d.drawImage(e,0,0,o,h),("none"!==rt||dt)&&H){d.clearRect(0,0,o,h);const{plan:t,packed:e,atlas:i}=H,s=[0,0,0,1],l=[0,0,0,0,0,0],c=Math.max(1,.32*Math.min(m,u));for(let o=0;o<e.rows;o++)for(let h=0;h<e.cols;h++){const f=(h+.5)/e.cols,g=(o+.5)/e.rows,p=4*(o*e.cols+h);if(e.colors[p+3]<10)continue;r(rt,f,g,ct,s,e.indices[p+2]/255,q??void 0,(o*e.cols+h)*B);const x=4*(Math.min(a.height-1,Math.round(g*(a.height-1)))*a.width+Math.min(a.width-1,Math.round(f*(a.width-1)))),S=M(a.mode)?y(a.pixels,x,a.mode,a.focus[2]):0,k=e.indices[p]+256*e.indices[p+1];"trail"===a.mode&&b(e.indices,e.colors,e.cols,e.rows,h,o,S,(a.pixels[x+2]-128)/127,(a.pixels[x+3]-128)/127,t.glyphs.length,l,a.edgeSafe);let E="trail"===a.mode?l[0]:3===v(a.mode)?Math.round(k+S*(t.glyphs.length-1)*.35):"dissolve"===a.mode?k-Math.floor(S*t.glyphs.length*1.8):k+Math.floor(S*t.glyphs.length*.85);k>0&&(E+=s[2]*(t.glyphs.length-1)),E=Math.max(0,Math.min(t.glyphs.length-1,Math.floor(E+n(h,o))));let A=s[0],T=s[1];a.strength>0&&(A+=(256*a.pixels[x]+a.pixels[x+1]-32768)/32767*a.strength,T+=(256*a.pixels[x+2]+a.pixels[x+3]-32768)/32767*a.strength);const z=h*m+A,D=o*u+T,R=("trail"===a.mode?l[5]:e.colors[p+3])/255*s[3],F="trail"===a.mode?l[2]:e.colors[p],C="trail"===a.mode?l[3]:e.colors[p+1],X="trail"===a.mode?l[4]:e.colors[p+2],I=dt?Math.max(1,F,C,X):255,P=`rgb(${F/I*255},${C/I*255},${X/I*255})`;if(d.fillStyle=P,dt){const t="trail"===a.mode?w(Math.max(0,Math.min(1,l[1]+s[2])),2,S):Math.max(0,Math.min(1,e.indices[p+2]/255+s[2]+(3===v(a.mode)?.35*S:.65*("dissolve"===a.mode?-S:S))));d.globalAlpha=R;for(let e=0;e<u;e+=c)for(let i=0;i<m;i+=c)t>.5+(n(Math.floor((z+i)/c),Math.floor((D+e)/c))-.5)*Math.max(0,Math.min(2,et?.ditherStrength??1))&&d.fillRect(z+i,D+e,Math.min(c,m-i),Math.min(c,u-e))}else if(E>0)if(d.globalAlpha=R,H.dots){const e=Math.min(.48,E/(t.glyphs.length-1)*.5*H.dotSize)*Math.min(m,u);d.beginPath(),d.arc(z+.5*m,D+.5*u,e,0,2*Math.PI),d.fill()}else d.drawImage(i,E%t.atlasColumns*t.tileWidth+t.padding,Math.floor(E/t.atlasColumns)*t.tileHeight+t.padding,t.cellWidth*ut,t.cellHeight*ut,z,D,m,u),d.globalAlpha=1,d.globalCompositeOperation="source-atop",d.fillRect(z,D,m,u),d.globalCompositeOperation="source-over"}d.globalAlpha=1}else if(M(a.mode)&&H){const{plan:t,packed:e,atlas:i}=H,s=[0,0,0,0,0,0];for(let o=0;o<e.rows;o++)for(let n=0;n<e.cols;n++){const h=4*(Math.min(a.height-1,Math.round((o+.5)/e.rows*(a.height-1)))*a.width+Math.min(a.width-1,Math.round((n+.5)/e.cols*(a.width-1)))),r=y(a.pixels,h,a.mode,a.focus[2]),l=4*(o*e.cols+n),c=.0137*(n*n*17+o*o*23+n*o*19),f=c-Math.floor(c);"trail"===a.mode&&b(e.indices,e.colors,e.cols,e.rows,n,o,r,(a.pixels[h+2]-128)/127,(a.pixels[h+3]-128)/127,t.glyphs.length,s,a.edgeSafe);const g=e.indices[l]+256*e.indices[l+1],p="trail"===a.mode?Math.round(s[0]):3===v(a.mode)?Math.max(0,Math.min(t.glyphs.length-1,Math.round(g+r*(t.glyphs.length-1)*.35))):"dissolve"===a.mode?Math.max(0,g-Math.floor(r*t.glyphs.length*(1.35+.9*f))):Math.min(t.glyphs.length-1,g+Math.floor(r*t.glyphs.length*.85));if(p===g&&("trail"!==a.mode||r<1e-4)||e.colors[l+3]<10)continue;const M=n*m,x=o*u;if(d.clearRect(M,x,m,u),d.globalAlpha=("trail"===a.mode?s[5]:e.colors[l+3])/255,H.dots){const e=Math.min(.48,p/(t.glyphs.length-1)*.5*H.dotSize)*Math.min(m,u);d.fillStyle="#fff",d.beginPath(),d.arc(M+.5*m,x+.5*u,e,0,2*Math.PI),d.fill()}else d.drawImage(i,p%t.atlasColumns*t.tileWidth+t.padding,Math.floor(p/t.atlasColumns)*t.tileHeight+t.padding,t.cellWidth*ut,t.cellHeight*ut,M,x,m,u);d.globalAlpha=1,d.globalCompositeOperation="source-atop";const w="trail"===a.mode?s[2]:e.colors[l],S="trail"===a.mode?s[3]:e.colors[l+1],k="trail"===a.mode?s[4]:e.colors[l+2],E=Math.max(w,S,k),A="dissolve"===a.mode||"trail"===a.mode||3===v(a.mode)?E:Math.max(E,Math.min(112,191*r)),T=E?A/E:0;d.fillStyle=`rgb(${E?w*T:A},${E?S*T:A},${E?k*T:A})`,d.fillRect(M,x,m,u),d.globalCompositeOperation="source-over"}}else if("light"===a.mode||"scan"===a.mode||"reveal"===a.mode){!t&&G&&I.width===ft&&I.height===gt||(I.width=ft,I.height=gt,P.width=ft,P.height=gt,_.filter="brightness(3)",_.drawImage(e,0,0,ft,gt),_.filter="none",G=!0);const[i,s,n,r]=a.focus;if(n>.001){U.setTransform(1,0,0,1,0,0),U.clearRect(0,0,ft,gt),U.drawImage(I,0,0),U.globalCompositeOperation="destination-in",U.save(),U.translate(i*ft,s*gt),U.scale("scan"===a.mode?.13:1,1);const t=r*Math.min(ft,gt),e=U.createRadialGradient(0,0,0,0,0,t);e.addColorStop(0,`rgba(255,255,255,${n})`),e.addColorStop(.5,`rgba(255,255,255,${.4*n})`),e.addColorStop(1,"rgba(255,255,255,0)"),U.fillStyle=e,U.fillRect(10*-ft,10*-gt,20*ft,20*gt),U.restore(),U.globalCompositeOperation="source-over",d.globalCompositeOperation="source-atop",d.drawImage(P,0,0,o,h),d.globalCompositeOperation="source-over"}}else if(a.strength>0){const t=32,i=18,s=o/t,n=h/i;for(let r=0;r<i;r++)for(let l=0;l<t;l++){const c=(l+.5)/t,f=(r+.5)/i,g=Math.min(a.width-1,Math.round(c*(a.width-1))),p=4*(Math.min(a.height-1,Math.round(f*(a.height-1)))*a.width+g),M=a.pixels,x=Math.min(l*s/m,(o-(l+1)*s)/m,r*n/u,(h-(r+1)*n)/u),v=Math.max(0,Math.min(1,(x-2)/6)),y=a.edgeSafe?v*v*(3-2*v):1,w=ht.scope&&"all"!==ht.scope.mode?ht.scope.pixels[4*(Math.min(ht.scope.height-1,Math.floor(f*ht.scope.height))*ht.scope.width+Math.min(ht.scope.width-1,Math.floor(c*ht.scope.width)))+3]/255:1,b=("outside"===ht.scope?.mode?1-w:w)*y,S=(256*M[p]+M[p+1]-32768)/32767*a.strength*b*(a.relative?o:1),k=(256*M[p+2]+M[p+3]-32768)/32767*a.strength*b*(a.relative?h:1);Math.abs(S)+Math.abs(k)<.02||(d.clearRect(l*s,r*n,s,n),d.drawImage(e,Math.max(0,Math.min(o-s,l*s-S))*e.width/o,Math.max(0,Math.min(h-n,r*n-k))*e.height/h,s*e.width/o,n*e.height/h,l*s,r*n,s,n))}}F.paint(d,ht.textMask,o,h)}},destroy(){p=!0,F.destroy(),document.fonts?.removeEventListener("loadingdone",ct),N.destroy(),l.removeEventListener("webglcontextlost",lt),rt(),l.remove(),I.width=I.height=P.width=P.height=1,e.style.visibility=o,c?.getExtension("WEBGL_lose_context")?.loseContext()}}}function ot(e,i,a={}){let o,n,h,r={effect:"trail",scope:"all",decay:.5,touch:!0,strength:.55,radius:a.effect&&"trail"!==a.effect?.2:.45,animated:!1,fps:30,fontSize:7,charAspect:.58,charSpacing:1,paused:!1,charset:" .:-=+*#%@",customText:"",renderMode:"ascii",dotSizeRatio:.72,...a},l=new N(i.clientWidth/Math.max(1,i.clientHeight)),c=!1,d=!1,m=!0,u=0,f=0,g=-1/0,p=0,M=null,x=!1,v=[],y=null,w=!0,b=-1/0;const S=[new Uint8Array(0),new Uint8Array(0)];let k=0;const E=document.createElement("canvas"),A=E.getContext("2d",{willReadFrequently:!0}),T=()=>{if(w=!1,"all"===r.scope&&"tilt"!==r.effect)return h=void 0,y=null,void l.setGuide(null);if(!A||!i.width||!i.height)return;E.width===l.columns&&E.height===l.rows||(E.width=l.columns,E.height=l.rows),A.clearRect(0,0,E.width,E.height),A.drawImage(i,0,0,E.width,E.height);try{y=F(A.getImageData(0,0,E.width,E.height).data,E.width,E.height,null,y)}catch{y=null}if(l.setGuide(y),!y||"all"===r.scope||"none"===y.key)return void(h=void 0);k^=1,S[k].length!==y.width*y.height*4&&(S[k]=new Uint8Array(y.width*y.height*4));const t=S[k];for(let e=0;e<y.subject.length;e++)t[4*e+3]=255*y.subject[e];h={pixels:t,width:y.width,height:y.height,mode:r.scope}},z=matchMedia("(prefers-reduced-motion: reduce)"),D=()=>{c||!d||document.hidden||u||(u=requestAnimationFrame(C))},R=at(e,i,()=>queueMicrotask(()=>{m=!0,D()}));function C(t){if(u=0,c||!d||document.hidden)return;const e=i.clientWidth,a=i.clientHeight;if(!e||!a)return;const S=z.matches||r.paused;l.configure(r.effect,r.strength,r.radius,r.edgeSafe,r.decay),w&&(T(),b=t);const k=l.active;if(!S){if(p+=f?Math.min(.1,(t-f)/1e3):0,x){const t=i.getBoundingClientRect();if(t.width&&t.height)for(const e of v)l.move((e.x-t.left)/t.width,(e.y-t.top)/t.height,e.time);v=[],M||l.leave(),x=!1}l.step(f?(t-f)/1e3:1/60)}const E=m||r.animated&&!S&&t-g>=1e3/Math.max(1,Math.min(60,r.fps))-.5;(E||k||l.active||!S&&"none"!==s(r.motion))&&(E&&(o=r.getFrame?.()),E&&r.animated&&y&&t-b>=160&&(T(),b=t),R.render(E,l.refraction,e,a,r.fontSize*r.charSpacing,r.fontSize/r.charAspect*r.charSpacing,o,{charset:r.charset,customText:r.customText,renderMode:r.renderMode,dotSizeRatio:r.dotSizeRatio,colorMode:r.colorMode??"fullcolor",accentColor:r.accentColor??"#888888",animationStyle:r.motion,animationSpeed:r.motionSpeed??1,artStyle:"classic",fineDither:r.fineDither,ditherStrength:r.ditherStrength??1},p,{filter:r.filter,edgeEffect:r.edgeEffect,edgeSoftness:r.edgeSoftness,textMask:n?.read(),scope:h}),E&&(g=t),m=!1),f=t,S||!r.animated&&!l.active&&"none"===s(r.motion)||D()}r.textMask&&(n=t(e,r.textMask,()=>{m=!0,D()}));const X=()=>{l.clear(),M=null,v=[],x=!1,f=0,m=!0,cancelAnimationFrame(u),u=0,D()},I=t=>{if("touch"===t.pointerType&&!r.touch||r.paused||z.matches)return;if(t.target instanceof Element&&t.target.closest("button,a,input,summary,select"))return void P();const e=i.getBoundingClientRect();t.clientX<e.left||t.clientX>e.right||t.clientY<e.top||t.clientY>e.bottom?P():(M={x:t.clientX,y:t.clientY,time:t.timeStamp},v.push(M),v.length>6&&v.shift(),x=!0,D())},P=()=>{M=null,x=!0,D()},_=t=>{"touch"===t.pointerType&&P()},U=new IntersectionObserver(([t])=>{d=t.isIntersecting,X()});U.observe(e);const G=new ResizeObserver(()=>{l=new N(i.clientWidth/Math.max(1,i.clientHeight)),w=!0,X()});return G.observe(i),e.addEventListener("pointerdown",I),e.addEventListener("pointerup",_),e.addEventListener("pointermove",I),e.addEventListener("pointerleave",P),e.addEventListener("pointercancel",P),document.addEventListener("visibilitychange",X),z.addEventListener("change",X),{get canvas(){return R.canvas},invalidate(){n?.invalidate(),m=!0,w=!0,D()},update(i){"textMask"in i&&(n?.destroy(),n=i.textMask?t(e,i.textMask,()=>{m=!0,D()}):void 0),r={...r,...i},w=!0,X()},destroy(){c||(c=!0,cancelAnimationFrame(u),U.disconnect(),G.disconnect(),R.destroy(),n?.destroy(),e.removeEventListener("pointerdown",I),e.removeEventListener("pointerup",_),e.removeEventListener("pointermove",I),e.removeEventListener("pointerleave",P),e.removeEventListener("pointercancel",P),document.removeEventListener("visibilitychange",X),z.removeEventListener("change",X))}}}var nt=[{id:"quiet-light",label:"Quiet light",description:"A key light circles the subject’s own relief, with a soft magnifying wake.",motion:{type:"relight",speed:.6,amount:.8},hover:{effect:"lens",radius:.45,strength:.5}},{id:"living-paper",label:"Memory",description:"A slow push toward the subject; the image leans toward your cursor.",motion:{type:"push",speed:.5,amount:.8},hover:{effect:"tilt",radius:.5,strength:.45}},{id:"silver-grain",label:"Silver light",description:"Sparse glints on bright detail, with a fluid character trail.",motion:{type:"shimmer",speed:.6,amount:.9},hover:{effect:"trail",radius:.35,strength:.55}},{id:"ripple-study",label:"Still water",description:"Smooth water and sky drift like a cinemagraph; your stroke sends out rings.",motion:{type:"current",speed:.6,amount:.8},hover:{effect:"ripple",radius:.45,strength:.7}},{id:"unfolding-print",label:"Darkroom",description:"The print develops from its highlights; your cursor dissolves a soft path.",motion:{type:"develop",speed:.7,amount:1},hover:{effect:"dissolve",radius:.35,strength:.55}},{id:"silk-flow",label:"Morning mist",description:"Mist drifts through the distance; directional folds follow your hand.",motion:{type:"mist",speed:.6,amount:1},hover:{effect:"silk",radius:.4,strength:.5}},{id:"depth-study",label:"Depth study",description:"A slow parallax drift from the photo’s own depth, with a loupe under your cursor.",motion:{type:"parallax",speed:.6,amount:.9},hover:{effect:"loupe",radius:.35,strength:.55}}];export{A as DEFAULT_HOVER,k as DEPRECATED_STUDIO_HOVERS,e as DEPRECATED_STUDIO_MOTIONS,E as HOVER_CONTROLS,z as HOVER_SCOPES,nt as STUDIO_ANIMATION_PRESETS,S as STUDIO_HOVERS,i as STUDIO_MOTIONS,t as createTextMask,ot as mountHover,ot as mountStudioHover,T as resolveHover};//# sourceMappingURL=hover.js.map