asciify-engine 4.25.0 → 4.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/field.cjs +1 -1
- package/dist/field.d.cts +132 -275
- package/dist/field.d.ts +132 -275
- package/dist/field.js +1 -1
- package/dist/glyph-field-C2fQIlnq.d.cts +292 -0
- package/dist/glyph-field-DRC-7uVf.d.ts +292 -0
- package/dist/kit/{chunk-KS3TL3S2.js → chunk-2FH6GGV6.js} +1 -1
- package/dist/kit/chunk-2GAV4OAK.js +1 -0
- package/dist/kit/{chunk-3F6FTBMN.js → chunk-2LBQ7QJT.js} +1 -1
- package/dist/kit/chunk-3LJ5C3U3.js +1 -0
- package/dist/kit/{chunk-SQGJ263V.js → chunk-3MHEDZLZ.js} +1 -1
- package/dist/kit/{chunk-KTYCGGRO.js → chunk-3OD5BMF5.js} +1 -1
- package/dist/kit/{chunk-OVCIHOOS.js → chunk-3VEMKDBW.js} +1 -1
- package/dist/kit/{chunk-H4DBJULW.js → chunk-42KMN727.js} +1 -1
- package/dist/kit/{chunk-PND73YEV.js → chunk-6G5MPND3.js} +1 -1
- package/dist/kit/{chunk-CA5J25SV.js → chunk-6WU247CB.js} +1 -1
- package/dist/kit/{chunk-6L2GAV5C.js → chunk-776H2BJ7.js} +1 -1
- package/dist/kit/{chunk-4SHQA3CO.js → chunk-7DXSG526.js} +1 -1
- package/dist/kit/{chunk-L3P7ZDSK.js → chunk-7M2FFUZ3.js} +1 -1
- package/dist/kit/{chunk-XYLLL2PQ.js → chunk-7NVKRDKE.js} +1 -1
- package/dist/kit/chunk-AIGAJMNN.js +1 -0
- package/dist/kit/{chunk-XXPDXJMQ.js → chunk-B3TY6UXJ.js} +1 -1
- package/dist/kit/chunk-BFBG3VHI.js +1 -0
- package/dist/kit/{chunk-6XNIZ52V.js → chunk-CG6SGQMY.js} +1 -1
- package/dist/kit/{chunk-KBXVIAWS.js → chunk-CGSWUO67.js} +1 -1
- package/dist/kit/{chunk-YDP6566E.js → chunk-DAJSBX6H.js} +1 -1
- package/dist/kit/{chunk-PFNFW4ZI.js → chunk-DCLJHSWM.js} +1 -1
- package/dist/kit/{chunk-QTVMD62E.js → chunk-DMRPBFLW.js} +1 -1
- package/dist/kit/{chunk-CR7QS3B3.js → chunk-E3FPFANJ.js} +1 -1
- package/dist/kit/{chunk-LUOIH2EM.js → chunk-EKYEA7Z4.js} +1 -1
- package/dist/kit/{chunk-QKZYCROD.js → chunk-F6F2C3RH.js} +1 -1
- package/dist/kit/chunk-FEAFQY7O.js +1 -0
- package/dist/kit/{chunk-A6EDU3UT.js → chunk-FHN3PPSI.js} +1 -1
- package/dist/kit/{chunk-FIWIUXNV.js → chunk-FPCCX4FM.js} +1 -1
- package/dist/kit/{chunk-EHYFSX5K.js → chunk-FWODCYYJ.js} +1 -1
- package/dist/kit/{chunk-PZAQLUAS.js → chunk-GBNV3GXG.js} +1 -1
- package/dist/kit/chunk-GF72XM4C.js +1 -0
- package/dist/kit/{chunk-MRDEO5HZ.js → chunk-GKR3ROYR.js} +1 -1
- package/dist/kit/{chunk-D4KCZSIP.js → chunk-H5KHXZWR.js} +1 -1
- package/dist/kit/{chunk-EJ3W4FN6.js → chunk-I5R2347P.js} +1 -1
- package/dist/kit/{chunk-ZYYLWSPY.js → chunk-IBNDCKEX.js} +1 -1
- package/dist/kit/{chunk-A73S2BCE.js → chunk-ILXVBO7M.js} +1 -1
- package/dist/kit/{chunk-QZHZWO7N.js → chunk-JELJEEJO.js} +1 -1
- package/dist/kit/{chunk-XDNCXCR7.js → chunk-K6JX64AS.js} +1 -1
- package/dist/kit/{chunk-2D2SG6FW.js → chunk-KCEYRIU4.js} +1 -1
- package/dist/kit/{chunk-SE6MQQLB.js → chunk-KDROJANO.js} +1 -1
- package/dist/kit/{chunk-ODMQERGZ.js → chunk-KEE55QSD.js} +1 -1
- package/dist/kit/{chunk-YBBYCUFP.js → chunk-KFXMLIVF.js} +1 -1
- package/dist/kit/{chunk-P6S6HSN3.js → chunk-KLRF3S7O.js} +1 -1
- package/dist/kit/{chunk-ANLBW5RI.js → chunk-KXI3T72F.js} +1 -1
- package/dist/kit/{chunk-PDNKLLBI.js → chunk-KY5KCIZE.js} +1 -1
- package/dist/kit/{chunk-PCGRRX5P.js → chunk-LE53AVKR.js} +1 -1
- package/dist/kit/{chunk-MIA6TUQC.js → chunk-LVCGC3SO.js} +1 -1
- package/dist/kit/chunk-M5VVLYI2.js +1 -0
- package/dist/kit/{chunk-KJJJORN6.js → chunk-MJJSZS23.js} +1 -1
- package/dist/kit/{chunk-EPVZIGEZ.js → chunk-MZFK765W.js} +1 -1
- package/dist/kit/{chunk-G4BQYQJ6.js → chunk-NF4WVWAC.js} +1 -1
- package/dist/kit/{chunk-JRSCTMFM.js → chunk-NW4U2YRE.js} +1 -1
- package/dist/kit/chunk-ORSI57T2.js +1 -0
- package/dist/kit/{chunk-GCIZKMJL.js → chunk-QSTDYL35.js} +1 -1
- package/dist/kit/{chunk-B6GZ645M.js → chunk-QVICL57J.js} +1 -1
- package/dist/kit/{chunk-JAM46FF6.js → chunk-RXOPJJC4.js} +1 -1
- package/dist/kit/{chunk-YL2AXWRA.js → chunk-SDSW7422.js} +1 -1
- package/dist/kit/{chunk-WT3XOWAI.js → chunk-TRDA73HN.js} +1 -1
- package/dist/kit/{chunk-VFV7HZ3G.js → chunk-UOYBFLGJ.js} +1 -1
- package/dist/kit/{chunk-EWPT56TR.js → chunk-UVLKCAKH.js} +1 -1
- package/dist/kit/{chunk-EHXSXMBE.js → chunk-VBWG7HQA.js} +1 -1
- package/dist/kit/{chunk-2TQW2PIG.js → chunk-VIUEAEBX.js} +1 -1
- package/dist/kit/{chunk-BBOSHBZK.js → chunk-VV2KP7ZW.js} +1 -1
- package/dist/kit/{chunk-4XT5IKM3.js → chunk-VX2AD3M7.js} +1 -1
- package/dist/kit/{chunk-2KFBIOVS.js → chunk-W4U5CK6L.js} +1 -1
- package/dist/kit/{chunk-6YVZZ3DO.js → chunk-WI2AF2KE.js} +1 -1
- package/dist/kit/{chunk-HMW5NRUV.js → chunk-XUCYFWC3.js} +1 -1
- package/dist/kit/{chunk-V6GEQ5Y5.js → chunk-Z2FRNFMB.js} +1 -1
- package/dist/kit/{chunk-NPJ77LDC.js → chunk-Z3KD6CLE.js} +1 -1
- package/dist/kit/{chunk-ONVONNUH.js → chunk-ZCXNGJGB.js} +1 -1
- package/dist/kit/{chunk-IUX46UDR.js → chunk-ZWZZMU5P.js} +1 -1
- package/dist/kit.cjs +1 -1
- package/dist/kit.d.cts +1 -1
- package/dist/kit.d.ts +1 -1
- package/dist/kit.js +1 -1
- package/dist/studio-worker.js +1 -0
- package/dist/studio.cjs +1 -1
- package/dist/studio.js +1 -1
- package/package.json +2 -1
- package/skills/asciify-engine/SKILL.md +2 -2
- package/skills/asciify-engine/references/performance.md +1 -1
- package/dist/kit/chunk-2JQ4MRIP.js +0 -1
- package/dist/kit/chunk-BJRPY7UB.js +0 -1
- package/dist/kit/chunk-EK4GIXIO.js +0 -1
- package/dist/kit/chunk-PFQBEWCF.js +0 -1
- package/dist/kit/chunk-SAQJAH2I.js +0 -1
- package/dist/kit/chunk-SVXRMHUJ.js +0 -1
- package/dist/kit/chunk-UO4U32P7.js +0 -1
- package/dist/kit/chunk-XVB3B3FV.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to `asciify-engine`, newest first. Releases are published to [npm](https://www.npmjs.com/package/asciify-engine) from version tags.
|
|
4
4
|
|
|
5
|
+
## 4.26: Studio off the main thread, live while scrolling
|
|
6
|
+
|
|
7
|
+
- Kit fields mount while the page scrolls instead of waiting for it to rest: within two viewports ahead, scroll direction first, at most two mounts per frame inside a 4 ms budget, with glyph atlases prewarmed at idle. A poster swaps for its canvas in the same frame the first frame is drawn, so a host is never blank, and paused fields keep their last frame.
|
|
8
|
+
- Fixed: the kit bundled its own copy of the field's shared context, so kit fields ran a second context and frame loop and were still held to the old 12-context cap. The build now fails if a kit chunk carries its own copy.
|
|
9
|
+
|
|
10
|
+
- `mountStudio` and `mountStudioMedia` draw in workers on `OffscreenCanvas`. The page keeps the pointer and posts only input; frames come back as `ImageBitmap`s and are shown without a copy, one per display frame. No first frame or hover is a long task on the page any more (a /looks card's first live frame was a 100 ms task).
|
|
11
|
+
- Hover draws at the display's rate (120 Hz on ProMotion) for every look: workers take turns drawing frames (as many as the first frames' cost needs, up to three, within 6 megapixels of frames in all), each applying the same input so their hover state is identical; and Pointillism fills its dots on the GPU the way Chrome's canvas does (same polygons, same 4x multisampling). Pointillism hover: about 110 ms → 6 ms a frame. If the browser's own frames slow down under the raster load (CMYK's multiplied dots in a large frame), hover backs off to every second frame or less, so the page stays at the display's rate.
|
|
12
|
+
- Output is unchanged: `tests/studio-parity-browser.mjs` compares every look, at rest and along a hover path, in light and dark, against the previous release; Pointillism matches within rounding.
|
|
13
|
+
- The worker's script is its own chunk (`studio-worker.js`, about 47 KB gzip), fetched with the first mount's media. Without `OffscreenCanvas` 2D, or if the worker cannot start, the Studio draws on the page as before. `createStudioRenderer` is unchanged and still draws on the calling thread. Public API unchanged.
|
|
14
|
+
|
|
5
15
|
## 4.25: one shared context, bounded memory
|
|
6
16
|
|
|
7
17
|
- Every glyph field and kit surface on a page now draws through one shared WebGL2 context and one frame loop. Programs compile once, atlases are shared per glyphs/font/size, and one set of page listeners and observers serves every field. Output is pixel-identical.
|
package/dist/field.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e={none:3,flow:1,orb:2,drift:4,swell:5,caustics:6,contour:7,aurora:8,ripple:9,halo:10,interference:11,mesh:12,cascade:13,constellation:14},t=e=>e?"\nconst float VSCALE=6.;\nvec4 decodeFluid(vec4 t){return vec4((t.xy*2.-1.)*VSCALE,t.z,t.w);}\nvec4 encodeFluid(vec4 v){return vec4(clamp(v.xy/VSCALE*.5+.5,0.,1.),clamp(v.z,0.,1.),1.);}":"\nvec4 decodeFluid(vec4 t){return t;}\nvec4 encodeFluid(vec4 v){return vec4(v.xyz,1.);}",n=e=>`#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform sampler2D uSource, uFluid;\nuniform vec2 uResolution, uCell;\nuniform float uCount, uBlend;\nconst float BAYER[16]=float[16](0.,8.,2.,10.,12.,4.,14.,6.,3.,11.,1.,9.,15.,7.,13.,5.);\nuniform vec4 uSourceMap;\nuniform int uScene;\nuniform vec3 uInk, uHighlight;\nuniform vec4 uBackground;\nuniform float uBrightness, uContrast, uGamma, uInvert, uVignette, uSourceColor;\nuniform float uRefraction, uGlow, uTime, uDrift, uFluidOn, uLod, uSaturation, uBackdrop, uShade, uHighlightAuto, uFluidMode;\nuniform vec2 uFluidTexel;\nuniform int uHoverMode;\nuniform vec3 uLight;\nuniform vec3 uTrail[12];\nuniform float uLightRadius, uLightGain, uClock, uFlicker, uTrailAmount;\nuniform sampler2D uTrailMap, uScope;\nuniform float uScopeMode;\nuniform vec2 uLevels;\nuniform int uMark;\nuniform float uScale, uClearFeather, uClearShape;\nuniform vec4 uClear;\nuniform vec4 uPulse[4];\nlayout(location=0) out vec4 outInk;\nlayout(location=1) out vec4 outUnder;\n${t(e)}\nfloat hash(vec2 p){p=fract(p*vec2(123.34,456.21));p+=dot(p,p+45.32);return fract(p.x*p.y);}\nfloat noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.-2.*f);\n return mix(mix(hash(i),hash(i+vec2(1,0)),u.x),mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),u.x),u.y);}\nfloat fbm(vec2 p){float v=0.,a=.5;for(int i=0;i<5;i++){v+=a*noise(p);p=p*2.03+vec2(1.7,9.2);a*=.5;}return v;}\nvec3 generated(vec2 uv,float aspect){\n vec2 p=(uv-.5)*vec2(aspect,1.)*uScale;\n if(uScene==1){\n float t=uTime*.08;\n vec2 q=vec2(fbm(p*1.6+t),fbm(p*1.6-t+3.1));\n return vec3(smoothstep(.28,.86,fbm(p*1.8+q*1.6+vec2(t*.6,-t*.4))));\n }\n if(uScene==2){\n float r=.36,d=length(p),a=uTime*.25;\n vec3 l=normalize(vec3(cos(a)*.8,.55,sin(a)*.6+.6));\n if(d<r){\n vec3 n=normalize(vec3(p.x,-p.y,sqrt(r*r-d*d)));\n float diffuse=max(dot(n,l),0.),rim=pow(1.-n.z,2.5);\n float lon=atan(n.x,n.z)+uTime*.35,lat=asin(clamp(n.y,-1.,1.));\n float bands=.5+.25*sin(lat*14.)+.25*sin(lon*6.);\n return vec3(clamp(diffuse*.85+rim*.5+bands*.12,0.,1.));\n }\n return vec3(exp(-pow((d-r)*9.,2.))*.35);\n }\n if(uScene==4){\n // Drift: a few broad lobes that wander slowly. Built for halftone, where large soft shapes read best.\n float t=uTime*.045;\n vec2 q=p*1.15;\n vec2 w=vec2(fbm(q*.7+vec2(t,-t*.7)),fbm(q*.7+vec2(4.3-t*.8,t+1.7)));\n float n=fbm(q+w*1.3+vec2(t*.4,t*.25));\n return vec3(smoothstep(.36,.74,n));\n }\n if(uScene==5){\n // Swell: three crossing swells, the second bent by the first, so crests roll diagonally instead of pooling.\n float t=uTime;\n float s=sin((dot(p,vec2(.94,.33))/.95-t/9.)*6.2831853);\n float c=sin((dot(p,vec2(.6,-.8))/.58-t/13.)*6.2831853+s*.9);\n float k=sin((dot(p,vec2(-.29,.96))/.36+t/17.)*6.2831853);\n return vec3(smoothstep(.3,.9,.5+.5*(s*.5+c*.35+k*.15)));\n }\n // The kit's background scenes. Each starts a little way in, so a reduced-motion still is already composed.\n float t=uTime+40.,px=uCell.y/uResolution.y*uScale;\n if(uScene==6){\n // Caustics: light focused by a moving water surface. Two layers of warped sine waves drift against each other; each draws\n // smooth filaments along its zero line, about a character wide. Where they cross the light lifts a little, never to a blot.\n float tt=t*.12,a=0.,b=0.;\n for(int l=0;l<2;l++){\n float f=float(l),sc=5.4+f*2.4;\n vec2 q=(l==0?p:mat2(.8,-.6,.6,.8)*p)*sc;\n q+=vec2(sin(q.y*.45+tt*(1.+f*.3)),cos(q.x*.4-tt*(.8+f*.4)))*1.3;\n float v=sin(q.x+1.4*sin(q.y*.7+tt))+sin(q.y*1.1+1.2*sin(q.x*.8-tt*1.3))*.9;\n float wv=max(fwidth(v),1e-4);\n float line=(1.-smoothstep(.2,1.5,abs(v)/wv))*(l==0?.78:.62)+exp(-abs(v)/(wv*5.))*.16;\n if(l==0)a=line;else b=line;\n }\n float pulse=.85+.15*sin(tt*3.+p.x*1.7-p.y*1.1);\n float light=max(a,b)+.3*min(a,b);\n return vec3(clamp(light*light*pulse,0.,.78));\n }\n if(uScene==7){\n // Contour: a slow terrain read as survey lines about a character wide at any size; every fifth is an index line.\n float tt=t*.02;\n vec2 q=p*1.15+vec2(tt,-tt*.6);\n float h=noise(q)*.62+noise(q*2.07+3.1)*.27+noise(q*4.3-tt+7.)*.11;\n h+=.08*sin(tt*2.+p.x*.8);\n float k=h*13.,w=max(fwidth(k),1e-4),d=abs(fract(k+.5)-.5)/w;\n float major=mod(floor(k+.5),5.)<.5?1.:0.;\n return vec3((1.-smoothstep(.35,1.25-major*.25,d))*mix(.55,1.,major));\n }\n if(uScene==8){\n // Aurora: three curtains at different distances hang from the top. Far ones sit higher and dimmer; the nearest is tallest\n // and brightest. Each folds slowly and is brightest along its lower hem, fading upward. The rays are set per character\n // column, so the curtains read as vertical strokes at any stage size, from a small card to a phone.\n float tt=t*.05,a=0.,cw=uCell.x/uResolution.x;\n float col=floor(uv.x/cw+.5);\n for(int n=0;n<3;n++){\n float f=float(n),near=f/2.;\n float x=p.x*(1.3-near*.4)+f*3.7;\n float hem=-.28+near*.3+.16*sin(x*1.3+tt*(.9+f*.25)+f*2.)+.045*sin(x*3.4-tt*1.5+f);\n float d=hem-p.y;\n float body=d>0.?exp(-d/(.14+near*.26))*(.45+.55*exp(-d/.03)):exp(-d*d/.0002);\n float fold=.5+.5*sin(x*2.1+tt*.9+f*1.7+.7*sin(x*.8-tt*.6));\n float ray=mix(hash(vec2(col,f*7.1)),noise(vec2(col*.18+f*9.,tt*.7+f)),.55);\n float layer=clamp(body*(.1+.9*fold*fold)*(.2+.8*ray)*(.4+near*.6)*4.2,0.,1.);\n a=1.-(1.-a)*(1.-layer);\n }\n return vec3(smoothstep(.12,.9,a));\n }\n if(uScene==9){\n // Ripple: still water. Drops land here and there, each a few rings that widen and fade; the pointer drops its own.\n float tone=0.,g=.72;\n vec2 q=p/g,id=floor(q);\n for(int j=-1;j<=1;j++)for(int i=-1;i<=1;i++){\n vec2 c=id+vec2(i,j),h=vec2(hash(c),hash(c+7.3));\n float period=5.+h.x*5.,age=fract(t*.3/period*4.+h.y);\n vec2 at=(c+.2+.6*h)*g;\n float d=length(p-at),r=age*.62;\n float rings=max(0.,cos((d-r)*34.))*exp(-pow((d-r)/.11,2.));\n tone+=rings*pow(1.-age,1.8)*smoothstep(0.,.06,age)*(.7+.3*h.x);\n }\n return vec3(clamp(tone*1.25,0.,1.));\n }\n if(uScene==10){\n // Halo: a slow breathing corona that frames the content, its rays turning. The ring fits the stage: wide on a desktop\n // hero, tall on a phone, so the whole halo stays on screen; the middle stays empty for a headline.\n vec2 r=vec2(min(.46,aspect*.4),min(.34,.36/max(aspect,.01)*.5+.2));\n vec2 e=p/r;\n float d=length(e),a=atan(e.y,e.x),tt=t*.07,k=min(r.x,r.y);\n float breathe=1.+.04*sin(tt*3.1);\n float rays=.5+.5*noise(vec2(a*3.2+tt,tt*.5))*(.6+.4*noise(vec2(a*7.-tt*1.2,3.+tt*.4)));\n float s=(d-breathe)*k;\n float rim=exp(-pow(s/.03,2.));\n float corona=exp(-max(0.,s)/(.1+.08*rays))*smoothstep(-.04,.015,s)*rays*smoothstep(.36,.12,s);\n return vec3(clamp(rim*(.55+.45*rays)+corona*.85,0.,1.));\n }\n if(uScene==11){\n // Interference: two ring grids from slowly orbiting centres. Where they cross, broad moire bands open and close.\n float tt=t*.05;\n vec2 a=vec2(-.3+.12*sin(tt),.07*cos(tt*1.3)),b=vec2(.3+.1*cos(tt*.8),-.06*sin(tt*1.1));\n float f=6.2831853/max(px*4.6,.004);\n float m=cos(length(p-a)*f)+cos(length(p-b)*f);\n return vec3(smoothstep(.7,2.,m));\n }\n if(uScene==12){\n // Mesh: four soft lights on slow Lissajous paths, a gradient mesh written in characters.\n float tt=t*.07,m=0.;\n for(int n=0;n<4;n++){\n float f=float(n)*1.7;\n vec2 c=vec2(.66*sin(tt*(.7+f*.13)+f),.34*cos(tt*(.9-f*.07)+f*1.3));\n float s=.3+.07*sin(tt+f);\n m+=exp(-dot(p-c,p-c)/(s*s))*(.8-float(n)*.1);\n }\n return vec3(smoothstep(.06,1.1,m));\n }\n if(uScene==13){\n // Cascade: streaks fall in three depths. Far ones are frequent, faint, short and slow; near ones rare, long, bright and\n // quick. Each has a bright head and a tail that fades behind it, and a column can carry two streaks at once.\n float tone=0.,cw=uCell.x/uResolution.x,ch=uCell.y/uResolution.y;\n float col=floor(uv.x/cw+.5);\n for(int n=0;n<3;n++){\n float f=float(n);\n for(int k=0;k<2;k++){\n float seed=f*13.1+float(k)*41.7,h=hash(vec2(col,seed));\n if(h<1.-(.5-f*.15))continue;\n float speed=(.045+f*.07)*(.75+.5*hash(vec2(col,seed+2.)));\n float tail=.12+f*.16,y=fract(t*speed+hash(vec2(col,seed+5.)))*(1.+tail*2.)-tail;\n float d=y-uv.y;\n if(d<0.||d>tail)continue;\n float head=d<ch*1.2?1.:0.;\n tone=max(tone,max(head*(.55+f*.22),pow(1.-d/tail,1.7)*(.28+f*.3)));\n }\n }\n return vec3(clamp(tone,0.,1.));\n }\n if(uScene==14){\n // Constellation: points wander in their own cells; neighbours close enough are linked by fine lines. Each point is a\n // bright core in a soft halo, so it reads at card size as well as full width.\n float g=.23,tt=t*.18;\n vec2 q=p/g,id=floor(q);\n vec2 pts[9];\n for(int j=-1;j<=1;j++)for(int i=-1;i<=1;i++){\n vec2 c=id+vec2(i,j);\n float h=hash(c),k=hash(c+3.7);\n pts[(j+1)*3+i+1]=c+.5+.36*vec2(sin(tt*(.6+h)+h*6.28),cos(tt*(.5+k)+k*6.28));\n }\n float line=0.,star=0.,lw=max(px/g,.02);\n for(int n=0;n<9;n++){\n vec2 e=q-pts[n];\n float d2=dot(e,e),tw=.8+.2*sin(tt*3.+float(n)*1.7);\n star=max(star,max(exp(-d2/(lw*lw*1.6)),.38*exp(-d2/(lw*lw*7.)))*tw);\n for(int m=n+1;m<9;m++){\n vec2 a=pts[n],ba=pts[m]-a;\n float len=length(ba);\n if(len>1.35)continue;\n float hh=clamp(dot(q-a,ba)/dot(ba,ba),0.,1.);\n float d=length(q-a-ba*hh);\n line=max(line,(1.-smoothstep(lw*.3,lw*.75,d))*smoothstep(1.35,.6,len)*.72);\n }\n }\n return vec3(clamp(max(line,star),0.,1.));\n }\n return vec3(0.);\n}\n// Hover scope: 1 where the pointer response may act. The map holds the source's soft subject coverage in alpha.\nfloat hoverScope(vec2 uv){\n if(uScopeMode<.5||uScene!=0)return 1.;\n vec2 s=uv*uSourceMap.xy+uSourceMap.zw;\n float c=(s.x<0.||s.y<0.||s.x>1.||s.y>1.)?0.:texture(uScope,s).a;\n return uScopeMode<1.5?c:1.-c;\n}\nvoid main(){\n vec2 cell=floor(gl_FragCoord.xy);\n vec2 uv=(cell+.5)*uCell/uResolution;\n float aspect=uResolution.x/uResolution.y;\n float hs=hoverScope(uv);\n vec4 fluid=vec4(0.);\n // lift: signed tone change. The solver's flow brightens one side of each eddy and opens the other into gaps.\n float lift=0.,wake=0.,bend=1.,swirl=0.,speed=0.;\n if(uFluidOn>.5){\n vec4 raw=texture(uFluid,vec2(uv.x,1.-uv.y));\n if(uFluidMode>.5){\n vec2 v=raw.xy*uFluidTexel*vec2(aspect,1.)*hs;\n fluid=vec4(v,0.,1.);\n swirl=clamp(dot(v,vec2(.4,.65))*uGlow*.32,-.65,.65);\n speed=clamp(length(v)*uGlow*.055,0.,.38);\n bend=.4;\n } else {\n fluid=decodeFluid(raw);\n fluid.xyz*=hs;\n wake=clamp(fluid.z*uGlow,0.,1.);\n lift=wake*.55;\n }\n }\n vec2 drift=uDrift*.006*vec2(sin(uv.y*5.3+uTime*.6),cos(uv.x*4.1-uTime*.5));\n vec2 sampleAt=uv-vec2(fluid.x/aspect,-fluid.y)*uRefraction*bend+drift;\n float spot=0.;\n if(uHoverMode==4||uHoverMode==5){\n vec2 d=(uv-uLight.xy)*vec2(aspect,1.);\n float q2=dot(d,d)/(uLightRadius*uLightRadius*2.2);\n // Loupe: flat-topped zoom with a soft rim. Reveal: a soft spot in the source's colours.\n if(uHoverMode==4) sampleAt-=(uv-uLight.xy)*exp(-q2*q2)*.45*uLight.z*min(1.,uLightGain*1.6)*hs;\n else spot=exp(-q2*1.6)*uLight.z*min(1.,uLightGain*1.6)*hs;\n }\n vec3 rgb,glow=vec3(0.);\n if(uScene==0){\n vec2 s=sampleAt*uSourceMap.xy+uSourceMap.zw;\n bool inside=!(s.x<0.||s.y<0.||s.x>1.||s.y>1.);\n rgb=inside?textureLod(uSource,s,uLod).rgb:vec3(0.);\n if(uBackdrop>0.){\n vec2 b=(uv-vec2(fluid.x/aspect,-fluid.y)*uRefraction*bend*.5)*uSourceMap.xy+uSourceMap.zw;\n glow=(b.x<0.||b.y<0.||b.x>1.||b.y>1.)?vec3(0.):textureLod(uSource,b,uLod+3.).rgb*uBackdrop;\n }\n } else rgb=generated(sampleAt,aspect);\n float tone=dot(rgb,vec3(.2126,.7152,.0722));\n tone=clamp((tone-uLevels.x)/max(uLevels.y-uLevels.x,.01),0.,1.);\n tone=clamp((tone-.5)*uContrast+.5+uBrightness,0.,1.);\n tone=pow(tone,1./uGamma);\n if(uInvert>.5)tone=1.-tone;\n float flick=0.,trailFold=0.;\n // Reveal: under the spot the characters take the source's own colour and a little more ink.\n if(spot>0.)lift=spot*.22;\n if(uHoverMode==2){\n // Lantern: a soft light and its fading tail lift the characters they pass. Nothing moves the image.\n vec2 ap=vec2(aspect,1.),d=(uv-uLight.xy)*ap;\n float r2=uLightRadius*uLightRadius,glowL=uLight.z*exp(-dot(d,d)/r2);\n for(int i=0;i<12;i++){vec2 e=(uv-uTrail[i].xy)*ap;glowL+=uTrail[i].z*exp(-dot(e,e)/(r2*.55));}\n glowL=min(glowL,1.)*hs;\n float grain=fract(sin(dot(cell,vec2(12.9898,78.233)))*43758.5453);\n lift=glowL*uLightGain*(.7+.6*grain);\n wake=glowL*.4;\n // A few letters at the light's rim step up the ramp and back, as if being retyped.\n flick=uFlicker*step(.9,fract(grain*13.7+floor(uClock*7.+grain*5.)*.37))*glowL*(1.-glowL)*4.;\n }\n if(uHoverMode==3){\n // Trail: the studio's ink field, as a 16-bit density. Sparse marks fill in, dense marks open up.\n vec4 ink=texture(uTrailMap,uv);\n float density=(ink.r*65280.+ink.g*255.)/65535.*uTrailAmount;\n float t=clamp(density/.38,0.,1.);\n trailFold=t*t*(3.-2.*t)*hs;\n }\n if(uFluidMode>.5&&uHoverMode==1){\n // Dark ground: any motion lights the characters. Lit ground: the flow lights one side of each eddy and opens the other.\n // A little cell-to-cell grain keeps the lit area a shimmer of letters rather than a solid block.\n float grain=fract(sin(dot(cell,vec2(12.9898,78.233)))*43758.5453);\n lift=mix(abs(swirl)*.5+speed,swirl+speed*.35,smoothstep(.12,.55,tone))*(.65+.7*grain);\n wake=clamp(lift*1.6,0.,1.);\n }\n tone=clamp(tone+lift,0.,1.);\n tone+=(1.-2.*tone)*trailFold;\n // Pulses: rings sent by the interface (field.pulse()), e.g. on a save or a notification.\n for(int i=0;i<4;i++){\n if(uPulse[i].w<=0.)continue;\n float dist=length((uv-uPulse[i].xy)*vec2(aspect,1.)),front=uPulse[i].z*.95;\n float ring=exp(-pow((dist-front)/.1,2.))*uPulse[i].w*exp(-uPulse[i].z*.85);\n tone=clamp(tone+ring*.85,0.,1.);\n }\n tone*=1.-uVignette*smoothstep(.35,1.05,length((uv-.5)*vec2(min(aspect,1.8),1.)*2.));\n if(uClear.z>0.){\n // Clear zone: the field fades out around content so text above it stays readable.\n vec2 half_=uClear.zw*.5*vec2(aspect,1.),q=(uv-uClear.xy-uClear.zw*.5)*vec2(aspect,1.);\n float dz;\n if(uClearShape>.5){vec2 e=abs(q)-half_;dz=length(max(e,0.))+min(max(e.x,e.y),0.);}\n else dz=(length(q/max(half_,vec2(1e-4)))-1.)*min(half_.x,half_.y);\n tone*=smoothstep(0.,uClearFeather,dz);\n }\n // Blend: a shade between two characters takes the upper one in the share of cells a 4x4 Bayer pattern gives it.\n float level=tone*(uCount-1.),upper=fract(level)>=.5?1.:0.;\n if(uBlend>.5&&tone>.02&&tone<.98){\n ivec2 q=ivec2(mod(gl_FragCoord.xy,4.));\n upper=fract(level)>(BAYER[q.y*4+q.x]+.5)/16.?1.:0.;\n }\n float index=min(uCount-1.,floor(level)+upper+(flick>.5&&tone>.02?1.:0.));\n vec3 hue=rgb/max(max(rgb.r,rgb.g),max(rgb.b,.03));\n hue=mix(vec3(dot(hue,vec3(.2126,.7152,.0722))),hue,uSaturation);\n vec3 ink=mix(uInk*mix(1.,.3+.7*tone,uShade),clamp(hue*(.38+.62*tone),0.,1.),uSourceColor);\n vec3 lifted=uHighlightAuto>.5?ink/max(max(ink.r,ink.g),max(ink.b,.06)):uHighlight;\n ink=mix(ink,lifted,wake*.7);\n if(spot>0.)ink=mix(ink,clamp(rgb/max(max(rgb.r,rgb.g),max(rgb.b,.08))*(.45+.55*tone),0.,1.),spot);\n float underAlpha=max(uBackground.a,min(1.,max(glow.r,max(glow.g,glow.b))));\n vec3 under=min(uBackground.rgb*uBackground.a+glow,vec3(underAlpha));\n // Glyphs keep their atlas index, exact in 8 bits; the other marks keep the tone, and empty where the charset is blank.\n outInk=vec4(ink,uMark==0?index/255.:uMark==1?(tone>.003?tone:0.):index>0.?max(tone,1./255.):0.);\n outUnder=vec4(under,underAlpha);\n}`,r="#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform sampler2D uAtlas, uCells, uUnder;\nuniform vec2 uResolution, uCell, uPitch;\nuniform float uColumns, uDotScale, uSourceColor;\nuniform int uMark;\nout vec4 outColor;\nconst float BAYER[16]=float[16](0.,8.,2.,10.,12.,4.,14.,6.,3.,11.,1.,9.,15.,7.,13.,5.);\n// The Studio's print defaults: screen angle -35deg, roughness .35, seed 7, registration .2 and its coral second ink.\nconst vec2 DIR=vec2(.81915,-.57358);\nconst float ROUGH=.35,SEED=7.;\nconst vec3 SECOND=vec3(.925,.404,.322);\nfloat hash(vec2 p){p=fract(p*vec2(123.34,456.21));p+=dot(p,p+45.32);return fract(p.x*p.y);}\n// Coverage of a signed distance given in device pixels.\nfloat cover(float d){return clamp(.5-d,0.,1.);}\nfloat box(vec2 p,vec2 lo,vec2 hi){vec2 a=clamp(p-lo,0.,1.)*clamp(hi-p,0.,1.);return a.x*a.y;}\nfloat disc(vec2 p,vec2 c,float r){return r>.05?cover(length(p-c)-r):0.;}\nfloat ellipse(vec2 p,vec2 c,vec2 r,float a){vec2 d=p-c;d=vec2(cos(a)*d.x+sin(a)*d.y,-sin(a)*d.x+cos(a)*d.y);float k=length(d/r);return cover((k-1.)*min(r.x,r.y));}\n// World-anchored parallel cuts across direction d: period and width in cell heights, so lines run on from cell to cell.\nfloat cuts(vec2 w,vec2 d,float period,float width,float px){\n if(width<=0.)return 0.;\n float proj=dot(vec2(-d.y,d.x),w);\n return cover((abs(fract(proj/period+.5)-.5)*period-width*.5)*px);\n}\n// Lays an ink over what is already down, multiplying where they overlap, as transparent inks do on paper.\nvoid lay(inout vec3 rgb,inout float a,vec3 c,float k){\n float next=a+k*(1.-a);\n rgb=next>0.?(rgb*a*(1.-k)+mix(c,rgb*c,a)*k)/next:c;\n a=next;\n}\nvoid main(){\n vec2 frag=vec2(gl_FragCoord.x,uResolution.y-gl_FragCoord.y);\n // The pitch is the atlas cell, or a fractional one under cellFit 'fill', where each glyph sits centred in its stretched cell.\n vec2 cell=floor(frag/uPitch);\n vec4 ink=texelFetch(uCells,ivec2(cell),0),under=texelFetch(uUnder,ivec2(cell),0);\n vec2 local=frag-cell*uPitch;\n float coverage;\n vec3 rgb=ink.rgb;\n if(uMark==0){\n float index=floor(ink.a*255.+.5);\n ivec2 tile=ivec2(int(mod(index,uColumns)),int(floor(index/uColumns)));\n vec2 texel=floor(local-floor((uPitch-uCell)*.5));\n coverage=all(greaterThanEqual(texel,vec2(0.)))&&all(lessThan(texel,uCell))?texelFetch(uAtlas,tile*ivec2(uCell)+ivec2(texel),0).a:0.;\n } else if(uMark==1){\n // Halftone: dot area follows tone, so midtones read true; edges are antialiased to one device pixel.\n float r=sqrt(ink.a)*min(uPitch.x,uPitch.y)*.5*uDotScale;\n coverage=ink.a>.003?clamp(r-length(local-uPitch*.5)+.5,0.,1.):0.;\n } else if(ink.a<=0.){\n coverage=0.;\n } else {\n float tone=ink.a,side=min(uPitch.x,uPitch.y);\n vec2 q=local/uPitch,c=uPitch*.5,p=local+.5;\n // Tiles fade with the tone in one ink, as the Studio's do; in source colour the colour already carries it.\n float fade=uSourceColor>.5?1.:tone,gap=max(.5,uPitch.x*.06),grain=hash(cell+SEED);\n vec2 w=(cell+q)*uPitch/uPitch.y;\n if(uMark==2)coverage=fade;\n else if(uMark==3)coverage=box(p,vec2(0.),uPitch-gap)*fade;\n else if(uMark==4){\n // Lego: a gapped brick, lit from above, with a raised stud ringed by its shadow.\n coverage=box(p,vec2(0.),uPitch-gap)*fade;\n rgb*=1.06-.14*q.y;\n float r=side*.28,d=length(local-c)-r,lit=clamp(dot(c-local,vec2(.6,.8))/r,-1.,1.);\n rgb=mix(rgb,mix(rgb,vec3(1.),.2+.12*lit),cover(d));\n rgb=mix(rgb,rgb*.72,cover(abs(d)-max(.5,side*.04)));\n } else if(uMark==5){\n // Voxel: an isometric cube; top, left and right faces at full, .72 and .42 strength.\n float h=.5*abs(q.x-.5);\n coverage=cover(-min(q.y-h,1.-h-q.y)*uPitch.y)*cover(-min(q.x,1.-q.x)*uPitch.x);\n coverage*=mix(q.x<.5?.72:.42,1.,cover((q.y-(.5-h))*uPitch.y))*fade;\n } else if(uMark==6){\n // Disco: a gapped mirror tile, its upper facet catching light and its lower in shade.\n coverage=box(p,vec2(0.),uPitch-gap)*fade;\n rgb=q.y<.35?mix(rgb,vec3(1.),.1+grain*.25):q.y>.65?rgb*.75:rgb;\n } else if(uMark==7){\n // Dither: an ordered 4x4 Bayer screen at about five dots a cell, lit where the cell's tone passes the threshold.\n ivec2 b=ivec2(mod(floor(frag/max(1.,floor(side/5.))),4.));\n coverage=tone>(BAYER[b.y*4+b.x]+.5)/16.?1.:0.;\n } else if(uMark==8){\n // Hex: a flat-topped hexagon filling the cell.\n vec2 h=abs((local-c)/(uPitch*.49));\n coverage=cover(max(h.y-.866,h.x*.866+h.y*.5-.866)*side*.49)*fade;\n } else if(uMark==9){\n // LED: a round lamp with a soft halo and a specular glint, separated by an unlit matrix.\n float r=side*.39,d=length(local-c);\n coverage=max(cover(d-r),.3*exp(-pow(max(0.,d-r)/(side*.12),2.)))*fade;\n rgb=mix(rgb,vec3(1.),.35*disc(local,uPitch*vec2(.43,.4),side*.11));\n } else if(uMark==10){\n // CMYK: the cell's hue separated into offset cyan, magenta and yellow dots, each sized by its share of the tone. The\n // key screen carries the neutral share in the ink's own lightness, since a light ink on a dark page has no black.\n float top=max(rgb.r,max(rgb.g,rgb.b)),low=min(rgb.r,min(rgb.g,rgb.b));\n vec3 cmy=(top-rgb)/max(top,.001);\n float a=0.;vec3 col=vec3(1.);\n lay(col,a,vec3(top),disc(local,c,side*.48*sqrt(tone*low/max(top,.001))));\n lay(col,a,vec3(0.,1.,1.),disc(local,uPitch*vec2(.36,.36),side*.48*sqrt(tone*cmy.x)));\n lay(col,a,vec3(1.,0.,1.),disc(local,uPitch*vec2(.64,.36),side*.48*sqrt(tone*cmy.y)));\n lay(col,a,vec3(1.,1.,0.),disc(local,uPitch*vec2(.5,.66),side*.48*sqrt(tone*cmy.z)));\n rgb=col;coverage=a;\n } else if(uMark==11||uMark==16){\n // Stipple and pointillism: four jittered marks a cell, their size following the tone.\n coverage=0.;vec3 col=rgb;\n for(int m=0;m<4;m++){\n vec2 o=vec2(float(m%2),float(m/2));\n float j=hash(cell*2.+o+SEED),jy=hash(cell+o*11.+SEED+1.);\n vec2 at=((o+.5)/2.+(vec2(j,jy)-.5)*ROUGH*.28)*uPitch;\n float r=min(min(min(at.x,uPitch.x-at.x),min(at.y,uPitch.y-at.y)),side*min(.245,.21*sqrt(tone)*(1.-ROUGH*j*.35)));\n float k=uMark==11?disc(local,at,r):ellipse(local,at,vec2(r,r*.64),j*3.14159);\n if(uMark==16&&k>coverage)col=uSourceColor>.5?clamp(rgb+(j-.5)*ROUGH*.25*vec3(1.,-.4,-1.),0.,1.):rgb*(1.+(j-.5)*ROUGH*.5);\n coverage=max(coverage,k);\n }\n rgb=col;\n } else if(uMark==12||uMark==13){\n // Engraving and crosshatch: parallel cuts whose weight follows the tone; crossings join only in the darker tones.\n float cv=tone*(1.-ROUGH*grain*.3),px=uPitch.y;\n coverage=cuts(w,DIR,.5,min(.47,.36*cv),px);\n if(uMark==13){\n coverage=max(coverage,cuts(w,vec2(-DIR.y,DIR.x),.5,min(.47,.36*max(0.,cv*1.5-.3)),px)*step(.2,cv));\n coverage=max(coverage,cuts(w,normalize(DIR+vec2(-DIR.y,DIR.x)),.5,min(.47,.36*max(0.,cv*2.-1.2)),px)*step(.6,cv));\n }\n } else if(uMark==14){\n // Woodblock: broad carved bands in five stepped weights, their edges wavering along the grain.\n float cv=ceil(tone*(1.-ROUGH*grain*.3)*5.)/5.,width=min(.94,.72*cv);\n float proj=dot(vec2(-DIR.y,DIR.x),w),line=floor(proj+.5),along=dot(DIR,w);\n float cut=sin(along*5.3+line*1.9+SEED)*.5+sin(along*13.1+line)*.25;\n coverage=cover((abs(proj-line)-width*.5*(1.+ROUGH*cut*.5))*uPitch.y);\n } else if(uMark==15){\n // Risograph: two offset screens, the main ink and the coral second ink, misregistered along the screen angle.\n float split=uSourceColor>.5?clamp(.5+(rgb.r-rgb.b)*.5,0.,1.):.5,r=side*min(.48,.44*sqrt(tone));\n float a=0.;vec3 col=rgb;\n lay(col,a,rgb,disc(local,c,r*sqrt(.35+(1.-split)*.65)));\n lay(col,a,SECOND,disc(local,c+DIR*.2*.38*side,r*sqrt(.3+split*.7)*(1.-ROUGH*hash(cell+SEED+13.)*.3)));\n rgb=col;coverage=a;\n } else coverage=0.;\n }\n outColor=vec4(rgb*coverage+under.rgb*(1.-coverage),coverage+under.a*(1.-coverage));\n}",i="#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform vec2 uTexel;\nout vec4 outColor;\nvec2 here(){return gl_FragCoord.xy*uTexel;}\n",o=i+"\nuniform sampler2D uVelocity;\nuniform vec2 uFrom, uTo, uForce;\nuniform float uAspect, uRadius;\nfloat segment(vec2 p,vec2 a,vec2 b){vec2 pa=p-a,ba=b-a;float h=clamp(dot(pa,ba)/max(dot(ba,ba),1e-8),0.,1.);return length(pa-ba*h);}\nvoid main(){\n vec2 uv=here(),scale=vec2(uAspect,1.);\n float d=segment(uv*scale,uFrom*scale,uTo*scale);\n outColor=vec4(texture(uVelocity,uv).xy+uForce*exp(-d*d/(uRadius*uRadius)),0.,1.);\n}",a=i+"\nuniform sampler2D uVelocity;\nvoid main(){\n vec2 uv=here();\n float l=texture(uVelocity,uv-vec2(uTexel.x,0.)).y,r=texture(uVelocity,uv+vec2(uTexel.x,0.)).y;\n float t=texture(uVelocity,uv+vec2(0.,uTexel.y)).x,b=texture(uVelocity,uv-vec2(0.,uTexel.y)).x;\n outColor=vec4(.5*(r-l-t+b),0.,0.,1.);\n}",l=i+"\nuniform sampler2D uVelocity, uCurl;\nuniform float uStrength, uDt;\nvoid main(){\n vec2 uv=here();\n float l=texture(uCurl,uv-vec2(uTexel.x,0.)).x,r=texture(uCurl,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uCurl,uv+vec2(0.,uTexel.y)).x,b=texture(uCurl,uv-vec2(0.,uTexel.y)).x,c=texture(uCurl,uv).x;\n vec2 force=.5*vec2(abs(t)-abs(b),abs(r)-abs(l));\n force=force/(length(force)+1e-4)*uStrength*c;\n force.y=-force.y;\n outColor=vec4(clamp(texture(uVelocity,uv).xy+force*uDt,-1000.,1000.),0.,1.);\n}",s=i+"\nuniform sampler2D uVelocity;\nvoid main(){\n vec2 uv=here(),c=texture(uVelocity,uv).xy;\n float l=texture(uVelocity,uv-vec2(uTexel.x,0.)).x,r=texture(uVelocity,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uVelocity,uv+vec2(0.,uTexel.y)).y,b=texture(uVelocity,uv-vec2(0.,uTexel.y)).y;\n if(uv.x-uTexel.x<0.)l=-c.x;\n if(uv.x+uTexel.x>1.)r=-c.x;\n if(uv.y+uTexel.y>1.)t=-c.y;\n if(uv.y-uTexel.y<0.)b=-c.y;\n outColor=vec4(.5*(r-l+t-b),0.,0.,1.);\n}",c=i+"\nuniform sampler2D uSource;\nuniform float uAmount;\nvoid main(){outColor=vec4(texture(uSource,here()).x*uAmount,0.,0.,1.);}",u=i+"\nuniform sampler2D uPressure, uDivergence;\nvoid main(){\n vec2 uv=here();\n float l=texture(uPressure,uv-vec2(uTexel.x,0.)).x,r=texture(uPressure,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uPressure,uv+vec2(0.,uTexel.y)).x,b=texture(uPressure,uv-vec2(0.,uTexel.y)).x;\n outColor=vec4((l+r+b+t-texture(uDivergence,uv).x)*.25,0.,0.,1.);\n}",h=i+"\nuniform sampler2D uPressure, uVelocity;\nvoid main(){\n vec2 uv=here();\n float l=texture(uPressure,uv-vec2(uTexel.x,0.)).x,r=texture(uPressure,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uPressure,uv+vec2(0.,uTexel.y)).x,b=texture(uPressure,uv-vec2(0.,uTexel.y)).x;\n outColor=vec4(texture(uVelocity,uv).xy-vec2(r-l,t-b),0.,1.);\n}",f=i+"\nuniform sampler2D uVelocity;\nuniform float uDt, uDissipation;\nvoid main(){\n vec2 uv=here();\n vec2 back=uv-uDt*texture(uVelocity,uv).xy*uTexel;\n outColor=vec4(texture(uVelocity,back).xy/(1.+uDissipation*uDt),0.,1.);\n}";var d=new Set,m=0,p=0,g=null,v=[],x=0,E=1,y=0,w=0;function b(e){m=0,x&&e>x&&(v.push(e-x),v.length>120&&v.shift()),x=e,p=performance.now();const t=[...d];d.clear();for(const n of t)try{n(e)}catch(e){"undefined"!=typeof console&&console.error(e)}te?.endFrame(e);const n=performance.now()-p;if(y=.9*y+.1*n,e-w>500){w=e;const t=R(),n=!!te?.overloaded;(y>.5*t||n)&&E<3?E++:y<.2*t&&!n&&E>1&&E--}d.size||(x=0)}function T(e){d.add(e),m&&g!==requestAnimationFrame&&(m=0),m||(g=requestAnimationFrame,m=requestAnimationFrame(b))}function M(e){d.delete(e),!d.size&&m&&(cancelAnimationFrame(m),m=0,x=0)}function R(){if(v.length<20)return 1e3/60;const e=[...v].sort((e,t)=>e-t);return Math.min(1e3/60,Math.max(1e3/360,e[Math.floor(.2*e.length)]))}var A=new Set,F=new Set,k=new Set,S=new Set,_=new Set,L=!1,D=null,P=null,C=null,U=null,I=e=>{let t=null;for(const n of A){if(n.target===window){(!n.near||n.near()||n.inside)&&n.move(e);continue}t??(t=e.composedPath());t.includes(n.target)?(n.inside=!0,n.move(e)):n.inside&&(n.inside=!1,n.leave())}},B=()=>{for(const e of A)e.inside=!1,e.leave()},N=()=>{for(const e of[...F])e()},G=()=>{for(const e of[...k])e()},X=()=>{for(const e of[...S])e()},q=e=>{for(const t of[..._])t(e)};function H(){const e=A.size+F.size+k.size+S.size+_.size>0;if("undefined"==typeof document)return;if(D!==document&&(L=!1,D=document,P=C=null,U=null),e===L)return;L=e;const t=e?"addEventListener":"removeEventListener";if("undefined"!=typeof window&&(window[t]?.("pointermove",I,{capture:!0,passive:!0}),window[t]?.("pointerdown",I,{capture:!0,passive:!0})),document[t]?.("pointerleave",B),document[t]?.("visibilitychange",N),("undefined"==typeof document?void 0:document.fonts)?.[t]?.("loadingdone",q),P??(P="function"==typeof matchMedia?matchMedia("(prefers-reduced-motion: reduce)"):null),C??(C="function"==typeof matchMedia?matchMedia("(prefers-color-scheme: dark)"):null),P?.[t]?.("change",G),C?.[t]?.("change",X),e){U??(U="function"==typeof MutationObserver?new MutationObserver(X):null);for(const e of[document.documentElement,document.body])e&&U?.observe(e,{attributes:!0,attributeFilter:["class","data-theme","data-mode","style"]})}else U?.disconnect()}var z=(e,t)=>(e.add(t),H(),()=>{e.delete(t)&&H()});function V(e){const t=e.target;if("undefined"==typeof window||t===window||"undefined"==typeof document)return z(A,e);const n=t,r=n.getRootNode?.();if(n.ownerDocument===document&&(!r||r===document))return z(A,e);const i=e.move,o=()=>e.leave();return n.addEventListener("pointermove",i,{passive:!0}),n.addEventListener("pointerdown",i,{passive:!0}),n.addEventListener("pointerleave",o),()=>{n.removeEventListener("pointermove",i),n.removeEventListener("pointerdown",i),n.removeEventListener("pointerleave",o)}}var O=new Map,j=null,W=new Map,Y=e=>t=>{for(const n of t)for(const t of[...e.get(n.target)??[]])t(n)},K=(e,t,n)=>{const r=e.get(t);return r?(r.add(n),!1):(e.set(t,new Set([n])),!0)},$=(e,t,n)=>{const r=e.get(t);return!(!r?.delete(n)||r.size)&&(e.delete(t),!0)};function Q(e,t){return"function"!=typeof ResizeObserver?()=>{}:(j??(j=new ResizeObserver(Y(O))),K(O,e,t)?j.observe(e):queueMicrotask(()=>{O.get(e)?.has(t)&&t({target:e})}),()=>{$(O,e,t)&&j?.unobserve(e),O.size||(j?.disconnect(),j=null)})}var J=268435456,Z=[1,.85,.7,.58,.5],ee=class{constructor(){this.lost=!1,this.level=0,this.programs=new Map,this.atlases=new Map,this.vertex=null,this.vao=null,this.clients=new Set,this.parallel=null,this.timer=null,this.queries=[],this.open=null,this.drew=!1,this.gpuMs=[],this.cpuMs=[],this.changedAt=0,this.lostTimer=0,this.renderer="",this.overloaded=!1,this.onLost=e=>{e.preventDefault(),this.lost=!0,this.reset();for(const e of[...this.clients])e.lost();clearTimeout(this.lostTimer),this.lostTimer=setTimeout(()=>{if(this.lost){this.canvas.removeEventListener?.("webglcontextlost",this.onLost),this.canvas.removeEventListener?.("webglcontextrestored",this.onRestored);try{this.create()}catch{return}this.restored()}},1e3)},this.onRestored=()=>{clearTimeout(this.lostTimer),this.lost=!1,this.restored()},this.idleTimer=0,this.create()}create(){let e=null,t=null;const i={alpha:!0,antialias:!1,depth:!1,stencil:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!0,powerPreference:"high-performance"};if("undefined"!=typeof document&&(e=document.createElement("canvas"),t=e.getContext("webgl2",i)),!t&&"function"==typeof OffscreenCanvas)try{e=new OffscreenCanvas(1,1),t=e.getContext("webgl2",i)}catch{t=null}if(!t||!e)throw new Error("WebGL2 is not available for the glyph field.");this.canvas=e,this.gl=t,this.lost=!1,e.width=e.height=1,this.parallel=t.getExtension("KHR_parallel_shader_compile"),this.timer=t.getExtension("EXT_disjoint_timer_query_webgl2");const o=t.getExtension("WEBGL_debug_renderer_info");this.renderer=String(t.getParameter(o?o.UNMASKED_RENDERER_WEBGL:t.RENDERER)??""),e.addEventListener?.("webglcontextlost",this.onLost),e.addEventListener?.("webglcontextrestored",this.onRestored);const a=!t.getExtension("EXT_color_buffer_float")&&!t.getExtension("EXT_color_buffer_half_float");this.program(n(a)),this.program(r)}restored(){for(const e of[...this.clients])e.restored()}reset(){this.programs.clear(),this.atlases.clear(),this.vertex=null,this.vao=null,this.queries=[],this.open=null,this.gpuMs=[],this.cpuMs=[]}join(e){this.clients.add(e),clearTimeout(this.idleTimer)}leave(e){this.clients.delete(e),this.clients.size?this.fit():(this.lost||(this.canvas.width=this.canvas.height=1,this.level=0),clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.clients.size||this.dispose()},3e3))}dispose(){if(clearTimeout(this.lostTimer),this.canvas.removeEventListener?.("webglcontextlost",this.onLost),this.canvas.removeEventListener?.("webglcontextrestored",this.onRestored),!this.lost)try{this.gl.getExtension("WEBGL_lose_context")?.loseContext()}catch{}this.reset(),te===this&&(te=null)}program(e){const t=this.programs.get(e);if(t)return t;const n=this.gl,r=(e,t)=>{const r=n.createShader(e);return n.shaderSource(r,t),n.compileShader(r),r};this.vertex??(this.vertex=r(n.VERTEX_SHADER,"#version 300 es\nvoid main(){vec2 p=vec2((gl_VertexID<<1)&2,gl_VertexID&2);gl_Position=vec4(p*2.-1.,0.,1.);}"));const i=n.createProgram(),o=r(n.FRAGMENT_SHADER,e);n.attachShader(i,this.vertex),n.attachShader(i,o),n.linkProgram(i);const a={program:i,locations:null,fragment:o};return this.programs.set(e,a),a}linked(e,t=!1){if(e.locations)return!0;const n=this.gl;if(!t&&this.parallel&&!n.getProgramParameter(e.program,this.parallel.COMPLETION_STATUS_KHR))return!1;if(!n.getProgramParameter(e.program,n.LINK_STATUS)){if(n.isContextLost())return!1;throw new Error(e.fragment&&n.getShaderInfoLog(e.fragment)||n.getProgramInfoLog(e.program)||"Glyph field program failed to link.")}const r={};for(let t=n.getProgramParameter(e.program,n.ACTIVE_UNIFORMS)-1;t>=0;t--){const i=n.getActiveUniform(e.program,t).name.replace(/\[0\]$/,"");r[i]=n.getUniformLocation(e.program,i)}return e.locations=r,!0}get canCompileInParallel(){return!!this.parallel}vertexArray(){return this.vao??(this.vao=this.gl.createVertexArray())}atlas(e,t,n){let r=this.atlases.get(e);if(r)r.refs||(this.atlases.delete(e),this.atlases.set(e,r));else{const n=this.gl,i=n.createTexture();n.bindTexture(n.TEXTURE_2D,i);for(const[e,t]of[[n.TEXTURE_MIN_FILTER,n.NEAREST],[n.TEXTURE_MAG_FILTER,n.NEAREST],[n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE],[n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE]])n.texParameteri(n.TEXTURE_2D,e,t);r={key:e,texture:i,refs:0,final:!1,users:new Set,bytes:0},this.atlases.set(e,r),this.paintAtlas(r,t)}return r.refs++,r.users.add(n),r}paintAtlas(e,t){const n=this.gl,{image:r,final:i}=t();n.bindTexture(n.TEXTURE_2D,e.texture),n.pixelStorei(n.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),n.pixelStorei(n.UNPACK_FLIP_Y_WEBGL,!1),n.texImage2D(n.TEXTURE_2D,0,n.RGBA8,n.RGBA,n.UNSIGNED_BYTE,r),e.bytes=r.width*r.height*4,e.final=i;for(const t of[...e.users])t()}releaseAtlas(e,t){e&&e.users.delete(t)&&(--e.refs>0||this.evictAtlases())}evictAtlases(){const e=[...this.atlases.values()].filter(e=>!e.refs);let t=e.length-8;for(const n of e){if(t<=0&&!this.overBudget)break;t--,this.atlases.delete(n.key),this.lost||this.gl.deleteTexture(n.texture)}}fit(){if(this.lost)return;let e=1,t=1;for(const n of this.clients){const[r,i]=n.size();e=Math.max(e,r),t=Math.max(t,i)}const n=this.canvas,r=e=>256*Math.ceil(e/256);n.width*n.height>r(e)*r(t)*2&&(n.width=r(e),n.height=r(t))}get bytes(){let e=this.canvas.width*this.canvas.height*4*2;for(const t of this.clients)e+=t.bytes();for(const t of this.atlases.values())e+=t.bytes;return e}get overBudget(){return this.bytes>J}get roomy(){return this.bytes<228170137.6}begin(e,t){const n=this.canvas;if(n.width<e||n.height<t){const r=e=>256*Math.ceil(e/256);n.width=Math.max(n.width,r(e)),n.height=Math.max(n.height,r(t))}if(!this.drew&&(this.drew=!0,this.timer&&!this.open&&this.queries.length<4)){const e=this.gl.createQuery();e&&(this.gl.beginQuery(this.timer.TIME_ELAPSED_EXT,e),this.open=e)}}present(e,t,n){e.globalCompositeOperation="copy",e.imageSmoothingEnabled=!1,e.drawImage(this.canvas,0,this.canvas.height-n,t,n,0,0,t,n)}endFrame(e){if(this.lost)return void(this.drew=!1);const t=this.gl,n=this.timer;if(this.drew&&(this.cpuMs.push(performance.now()-p),this.cpuMs.length>60&&this.cpuMs.shift(),n&&this.open&&(t.endQuery(n.TIME_ELAPSED_EXT),this.queries.push({query:this.open,frame:e}),this.open=null)),this.drew=!1,n){const e=t.getParameter(n.GPU_DISJOINT_EXT);for(;this.queries.length&&t.getQueryParameter(this.queries[0].query,t.QUERY_RESULT_AVAILABLE);){const{query:n}=this.queries.shift();e||(this.gpuMs.push(t.getQueryParameter(n,t.QUERY_RESULT)/1e6),this.gpuMs.length>60&&this.gpuMs.shift()),t.deleteQuery(n)}}this.adapt(e)}adapt(e){const t=R(),n=this.gpuMs.length>=5&&Math.min(...this.gpuMs.slice(-5))>1.5*t,r=this.gpuMs.length>=10||n?this.gpuMs:null;let i;if(r)i=[...r].sort((e,t)=>e-t)[Math.floor(.75*r.length)]/t;else{if(v.length<30||this.cpuMs.length<10)return;const e=v.slice(-30).sort((e,t)=>e-t),n=[...this.cpuMs].sort((e,t)=>e-t)[this.cpuMs.length>>1];i=e[Math.floor(.75*e.length)]/t>1.6&&n<.5*t?1:.5}if(this.overloaded=i>.8&&this.atMinimum,e-this.changedAt<(i>.8?800:4e3))return;let o=this.level;if(i>2?o=Z.length-1:i>.8&&o<Z.length-1?o++:i<.3&&o>0&&o--,o!==this.level){this.level=o,this.changedAt=e,this.gpuMs=[],this.cpuMs=[];for(const e of[...this.clients])e.rescale()}}get scale(){return Z[this.level]}get atMinimum(){return this.level===Z.length-1}},te=null,ne=!1;function re(){if(te||ne)return te;try{te=new ee}catch{ne=!0}return te}var ie=new WeakSet,oe=class{constructor(e,t){this.previous=null,this.peak=0,this.width=e,this.height=t;const n=e*t;this.pixels=new Uint8Array(4*n),this.signal=new Float32Array(n),this.offsetX=new Float32Array(n),this.offsetY=new Float32Array(n),this.driftX=new Float32Array(n),this.driftY=new Float32Array(n),this.u=new Float32Array(n),this.v=new Float32Array(n),this.ink=new Float32Array(n),this.a=new Float32Array(n),this.b=new Float32Array(n),this.c=new Float32Array(n),this.pressure=new Float32Array(n),this.pressureNext=new Float32Array(n),this.divergence=new Float32Array(n),this.curl=new Float32Array(n)}get active(){return this.peak>2e-4}clear(){for(const e 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])e.fill(0);this.previous=null,this.peak=0}leave(){this.previous=null}move(e,t,n,r=performance.now()){if(!Number.isFinite(e+t+n+r))return;e=Math.max(0,Math.min(1,e)),t=Math.max(0,Math.min(1,t)),n=Math.max(.1,Math.min(1,n));const i=this.previous;if(this.previous={x:e,y:t,time:r},!i)return;const o=(e-i.x)*(this.width-1),a=(t-i.y)*(this.height-1),l=Math.hypot(o,a);if(l<.001)return;const s=Math.min(this.width,this.height),c=r>i.time?Math.max(1/240,(r-i.time)/1e3):1/60,u=Math.min(12,l/s/c),h=1-Math.exp(-u/2.2),f=s*(.022+.075*n)*(.65+.95*h),d=Math.min(128,Math.max(1,Math.ceil(l/(.4*f)))),m=l/f*(.32+.22*h)/d,p=o/l,g=a/l,v=-g,x=p,E=l*(2+18*h)/d;for(let n=0;n<d;n++){const r=(n+.5)/d,o=(i.x+(e-i.x)*r)*(this.width-1),a=(i.y+(t-i.y)*r)*(this.height-1),l=Math.max(1,Math.floor(o-3*f)),s=Math.min(this.width-2,Math.ceil(o+3*f)),c=Math.max(1,Math.floor(a-3*f)),u=Math.min(this.height-2,Math.ceil(a+3*f));for(let e=c;e<=u;e++)for(let t=l;t<=s;t++){const n=((t-o)*p+(e-a)*g)/f,r=((t-o)*v+(e-a)*x)/f,i=Math.exp(-n*n*.65-r*r*1.7),l=e*this.width+t;this.ink[l]=1-(1-this.ink[l])*Math.exp(-i*m);const s=1-r*r*.55,c=n*r*.7;this.u[l]=Math.max(-80,Math.min(80,this.u[l]+(p*s+v*c)*i*E)),this.v[l]=Math.max(-80,Math.min(80,this.v[l]+(g*s+x*c)*i*E))}}this.peak=1}read(e,t,n){const r=0|(t=Math.max(.5,Math.min(this.width-1.5,t))),i=0|(n=Math.max(.5,Math.min(this.height-1.5,n))),o=t-r,a=n-i,l=i*this.width+r;return(e[l]*(1-o)+e[l+1]*o)*(1-a)+(e[l+this.width]*(1-o)+e[l+this.width+1]*o)*a}sample(e,t){return this.read(this.signal,e*(this.width-1),t*(this.height-1))}displacement(e,t,n){n[0]=this.read(this.offsetX,e*(this.width-1),t*(this.height-1)),n[1]=this.read(this.offsetY,e*(this.width-1),t*(this.height-1))}step(e){if(!this.active||!Number.isFinite(e))return;let t=Math.max(0,Math.min(.05,e));const n=this.width,r=this.height;for(;t>1e-7;){const e=Math.min(1/60,t);t-=e;const i=Math.exp(-1.9*e),o=Math.exp(-3.2*e);for(let t=1;t<r-1;t++)for(let a=1;a<n-1;a++){const l=t*n+a,s=Math.max(.5,Math.min(n-1.5,a-this.u[l]*e)),c=Math.max(.5,Math.min(r-1.5,t-this.v[l]*e)),u=0|s,h=0|c,f=s-u,d=c-h,m=h*n+u,p=(1-f)*(1-d),g=f*(1-d),v=(1-f)*d,x=f*d;this.a[l]=(this.u[m]*p+this.u[m+1]*g+this.u[m+n]*v+this.u[m+n+1]*x)*i,this.b[l]=(this.v[m]*p+this.v[m+1]*g+this.v[m+n]*v+this.v[m+n+1]*x)*i,this.c[l]=(this.ink[m]*p+this.ink[m+1]*g+this.ink[m+n]*v+this.ink[m+n+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 e=1;e<r-1;e++)for(let t=1;t<n-1;t++){const r=e*n+t;this.curl[r]=.5*(this.v[r+1]-this.v[r-1]-this.u[r+n]+this.u[r-n])}for(let t=1;t<r-1;t++)for(let r=1;r<n-1;r++){const i=t*n+r,o=Math.abs(this.curl[i+1])-Math.abs(this.curl[i-1]),a=Math.abs(this.curl[i+n])-Math.abs(this.curl[i-n]),l=Math.hypot(o,a)+1e-4,s=this.curl[i]*e*10,c=Math.hypot(this.u[i],this.v[i]);this.u[i]+=a/l*s,this.v[i]-=o/l*s;const u=Math.min(1,c/(Math.hypot(this.u[i],this.v[i])+1e-6));this.u[i]*=u,this.v[i]*=u,this.divergence[i]=-.5*(this.u[i+1]-this.u[i-1]+this.v[i+n]-this.v[i-n])}this.pressure.fill(0);for(let e=0;e<4;e++){for(let e=1;e<r-1;e++)for(let t=1;t<n-1;t++){const r=e*n+t;this.pressureNext[r]=.25*(this.divergence[r]+this.pressure[r-1]+this.pressure[r+1]+this.pressure[r-n]+this.pressure[r+n])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let a=0;for(let t=1;t<r-1;t++)for(let r=1;r<n-1;r++){const i=t*n+r;this.u[i]=Math.max(-80,Math.min(80,this.u[i]-.5*(this.pressure[i+1]-this.pressure[i-1]))),this.v[i]=Math.max(-80,Math.min(80,this.v[i]-.5*(this.pressure[i+n]-this.pressure[i-n]))),this.driftX[i]+=(3.6*this.u[i]-58*this.offsetX[i]-12*this.driftX[i])*e,this.driftY[i]+=(3.6*this.v[i]-58*this.offsetY[i]-12*this.driftY[i])*e,this.offsetX[i]=Math.max(-2,Math.min(2,this.offsetX[i]+this.driftX[i]*e)),this.offsetY[i]=Math.max(-2,Math.min(2,this.offsetY[i]+this.driftY[i]*e)),this.signal[i]=1-Math.exp(.06*-Math.hypot(this.u[i],this.v[i])-.16*this.ink[i]),a=Math.max(a,this.signal[i])}this.peak=a}if(this.active)for(let e=0;e<this.ink.length;e++){const t=Math.round(65535*Math.min(1,this.signal[e]));this.pixels[4*e]=t>>>8,this.pixels[4*e+1]=255&t,this.pixels[4*e+2]=Math.round(128+63.5*this.offsetX[e]),this.pixels[4*e+3]=Math.round(128+63.5*this.offsetY[e])}else this.clear()}};function ae(e,t,n,r,i){if(!(i<1))for(let o=0;o<2;o++){for(let o=0;o<r;o++){let r=0;const a=o*n;for(let t=-i;t<=i;t++)r+=e[a+Math.max(0,Math.min(n-1,t))];for(let o=0;o<n;o++)t[a+o]=r/(2*i+1),r+=e[a+Math.min(n-1,o+i+1)]-e[a+Math.max(0,o-i)]}for(let o=0;o<n;o++){let a=0;for(let e=-i;e<=i;e++)a+=t[Math.max(0,Math.min(r-1,e))*n+o];for(let l=0;l<r;l++)e[l*n+o]=a/(2*i+1),a+=t[Math.min(r-1,l+i+1)*n+o]-t[Math.max(0,l-i)*n+o]}}}var le=new Float32Array(0);var se,ce=["none","flow","orb","drift","swell","caustics","contour","aurora","ripple","halo","interference","mesh","cascade","constellation"],ue=["glyph","dot","pixel","mosaic","lego","voxel","disco","dither","hex","led","cmyk","stipple","engraving","crosshatch","woodblock","risograph","pointillism"],he=[{value:"fluid",label:"Fluid",description:"An ink-in-water wake that bends the image and swirls the characters."},{value:"lantern",label:"Lantern",description:"A soft light follows the pointer and lifts the characters it passes, without distortion."},{value:"trail",label:"Trail",description:"The Asciify Trail: in the wake, sparse characters fill in and dense ones open up, then settle. No distortion."},{value:"loupe",label:"Loupe",description:"A glass loupe glides after the pointer and magnifies the characters it covers."},{value:"reveal",label:"Reveal",description:"Under a soft spotlight the characters take the source image's own colours. Best over a photo or video in one ink."},{value:"none",label:"Off",description:"The field stays still under the pointer."}],fe={radius:.13,strength:.5,trail:.45,follow:12},de={strength:.55,radius:.45},me={radius:.075,force:1,dissipation:1.6,refraction:.03,glow:.55,resolution:128,curl:24},pe={charset:" .,:-=+*#%@",cellSize:12,cellAspect:1,cellFit:"pixel",font:'ui-monospace, "SF Mono", Menlo, Consolas, monospace',fontWeight:500,glyphScale:.8,mark:"glyph",dotScale:.9,color:"ink",ink:"#f3ba32",highlight:"auto",background:"transparent",brightness:0,contrast:1,gamma:1,invert:!1,levels:"auto",blend:"auto",saturation:1.1,shade:.5,backdrop:0,fit:"cover",focus:{x:.5,y:.5},vignette:0,drift:0,scene:"flow",scale:1,clear:!1,speed:1,hover:"fluid",fluid:me,lantern:fe,trail:de,scope:"all",maxPixelRatio:2,respectReducedMotion:!0},ge=(e,t,n,r)=>"number"==typeof e&&Number.isFinite(e)?Math.min(n,Math.max(t,e)):r,ve=(e,t)=>"string"==typeof e&&/^#([\da-f]{3}|[\da-f]{6})$/i.test(e.trim())?e.trim().toLowerCase():t,xe=/^[\u0020-\u007e\u00a0-\u02ff\u0370-\u0482\u048a-\u052f\u2010-\u20cf\u2100-\u2bff]*$/;function Ee(e){if(!xe.test(e)&&void 0===se){const e=Intl.Segmenter;se=e?new e(void 0,{granularity:"grapheme"}):null}return(se&&!xe.test(e)?Array.from(se.segment(e),e=>e.segment):Array.from(e)).filter(e=>"\n"!==e&&"\r"!==e&&"\t"!==e).slice(0,256)}function ye(e={},t=pe){const n="string"==typeof e.charset&&Ee(e.charset).length>=2?e.charset:t.charset,r=t.fluid||me,i=void 0===e.fluid?t.fluid:e.fluid,o=!1!==i&&(()=>{const e=!0!==i&&i?{...r,...i}:r;return{radius:ge(e.radius,.005,.5,me.radius),force:ge(e.force,0,8,me.force),dissipation:ge(e.dissipation,.05,20,me.dissipation),refraction:ge(e.refraction,0,.5,me.refraction),glow:ge(e.glow,0,2,me.glow),resolution:Math.round(ge(e.resolution,16,512,me.resolution)),curl:ge(e.curl,0,80,me.curl)}})(),a=ce.includes(e.scene)?e.scene:t.scene,l=!!e.clear&&"object"==typeof e.clear&&("element"in e.clear||"nodeType"in e.clear),s=void 0===e.clear||l?t.clear:e.clear,c=!!s&&{x:ge(s.x,-.5,1.5,.25),y:ge(s.y,-.5,1.5,.3),width:ge(s.width,0,2,.5),height:ge(s.height,0,2,.4),feather:ge(s.feather,.005,1,.12),shape:"rect"===s.shape?"rect":"ellipse"};return{charset:n,cellSize:ge(e.cellSize,3,96,t.cellSize),cellAspect:ge(e.cellAspect,.3,2,t.cellAspect),cellFit:"fill"===e.cellFit||"pixel"===e.cellFit?e.cellFit:t.cellFit,font:"string"==typeof e.font&&e.font.trim()?e.font:t.font,fontWeight:Math.round(ge(e.fontWeight,100,900,t.fontWeight)),glyphScale:ge(e.glyphScale,.3,1.6,t.glyphScale),mark:ue.includes(e.mark)?e.mark:t.mark,dotScale:ge(e.dotScale,.1,1.4,t.dotScale),color:"source"===e.color||"ink"===e.color?e.color:t.color,ink:ve(e.ink,t.ink),highlight:"auto"===e.highlight?"auto":ve(e.highlight,t.highlight),background:"transparent"===e.background?"transparent":ve(e.background,t.background),brightness:ge(e.brightness,-1,1,t.brightness),contrast:ge(e.contrast,0,4,t.contrast),gamma:ge(e.gamma,.2,5,t.gamma),invert:"boolean"==typeof e.invert?e.invert:t.invert,levels:"none"===e.levels||"auto"===e.levels?e.levels:t.levels,blend:"auto"===e.blend||"coarse"===e.blend||"on"===e.blend||"off"===e.blend?e.blend:t.blend,saturation:ge(e.saturation,0,3,t.saturation),shade:ge(e.shade,0,1,t.shade),backdrop:ge(e.backdrop,0,1,t.backdrop),fit:"contain"===e.fit||"cover"===e.fit?e.fit:t.fit,focus:{x:ge(e.focus?.x,0,1,t.focus.x),y:ge(e.focus?.y,0,1,t.focus.y)},vignette:ge(e.vignette,0,1,t.vignette),drift:ge(e.drift,0,2,t.drift),scene:a,scale:ge(e.scale,.2,6,t.scale),clear:c,speed:ge(e.speed,0,5,t.speed),hover:he.some(t=>t.value===e.hover)?e.hover:t.hover,fluid:o,lantern:{radius:ge(e.lantern?.radius,.02,.6,t.lantern.radius),strength:ge(e.lantern?.strength,0,1.5,t.lantern.strength),trail:ge(e.lantern?.trail,0,3,t.lantern.trail),follow:ge(e.lantern?.follow,1,60,t.lantern.follow)},trail:{strength:ge(e.trail?.strength,0,1,t.trail.strength),radius:ge(e.trail?.radius,.1,1,t.trail.radius)},scope:void 0===e.scope?t.scope:(u=e.scope,"subject"===u||"outside"===u?u:"all"),maxPixelRatio:ge(e.maxPixelRatio,.5,4,t.maxPixelRatio),respectReducedMotion:"boolean"==typeof e.respectReducedMotion?e.respectReducedMotion:t.respectReducedMotion};var u}function we(e,t,n,r,i,o={x:.5,y:.5}){if(!(e>0&&t>0&&n>0&&r>0))return{scale:[1,1],offset:[0,0]};const a=e/t,l=n/r,s=l>a,c="cover"===i?s?[a/l,1]:[1,l/a]:s?[1,l/a]:[a/l,1];return{scale:c,offset:"cover"===i?[(1-c[0])*o.x,(1-c[1])*o.y]:[.5*(1-c[0]),.5*(1-c[1])]}}function be(e,t,n,r){const i=Math.max(2,Math.round(e*n)),o=Math.max(2,Math.round(i*t)),a=Math.min(16,Math.max(1,r)),l=Math.ceil(r/a);return{width:o,height:i,columns:a,rows:l,atlasWidth:a*o,atlasHeight:l*i}}function Te(e){const t=e.replace("#",""),n=3===t.length?t.split("").map(e=>e+e).join(""):t,r=Number.parseInt(n,16);return Number.isFinite(r)&&6===n.length?[(r>>16&255)/255,(r>>8&255)/255,(255&r)/255]:[0,0,0]}function Me(e){const t=new Uint32Array(256);let n=0;for(let r=0;r+3<e.length;r+=4)e[r+3]<8||(t[Math.round(.2126*e[r]+.7152*e[r+1]+.0722*e[r+2])]++,n++);if(!n)return[0,1];const r=e=>{let r=0;for(let i=0;i<256;i++)if(r+=t[i],r>=n*e)return i/255;return 1},i=r(.02),o=r(.98);return o-i<.08?[0,1]:[i,o]}var Re=e=>"fluid"!==e.hover||e.fluid?e.hover:"none";function Ae(e,t,n=24,r=.12,i="ellipse"){return e.width>0&&e.height>0&&{x:(t.left-n-e.left)/e.width,y:(t.top-n-e.top)/e.height,width:(t.width+2*n)/e.width,height:(t.height+2*n)/e.height,feather:r,shape:i}}var Fe,ke=/\.(mp4|webm|mov|m4v|ogv)(\?|#|$)/i,Se=/swiftshader|llvmpipe|softpipe|software|basic render/i;function _e(){if(Fe)return Fe;if("undefined"==typeof document||void 0===globalThis.WebGL2RenderingContext)return Fe="none";try{const e=re();if(e)return Fe=Se.test(e.renderer)?"software":"gpu";const t=document.createElement("canvas").getContext("webgl2");if(!t)return Fe="none";const n=t.getExtension("WEBGL_debug_renderer_info"),r=String(t.getParameter(n?n.UNMASKED_RENDERER_WEBGL:t.RENDERER)??"");return t.getExtension("WEBGL_lose_context")?.loseContext(),Fe=Se.test(r)?"software":"gpu"}catch{return Fe="none"}}exports.DEFAULT_FIELD_FLUID=me,exports.DEFAULT_FIELD_LANTERN=fe,exports.DEFAULT_FIELD_SETTINGS=pe,exports.DEFAULT_FIELD_TRAIL=de,exports.FIELD_HOVERS=he,exports.FIELD_MARKS=ue,exports.FIELD_SCENES=ce,exports.activeFieldHover=Re,exports.fieldCellLayout=be,exports.fieldClearFromRects=Ae,exports.fieldGlyphs=Ee,exports.fieldLevels=Me,exports.fieldSourceRect=we,exports.glyphFieldTier=_e,exports.isGlyphFieldSupported=function(e={}){const t=_e();return"gpu"===t||"software"===t&&!!e.allowSoftware},exports.mountGlyphField=function(i,d={}){const m=e=>"undefined"!=typeof HTMLElement&&e instanceof HTMLElement,p=e=>{const t=e.clear;return m(t)?{element:{element:t},rest:{...e,clear:void 0}}:t&&"object"==typeof t&&m(t.element)?{element:t,rest:{...e,clear:void 0}}:{element:null,rest:e}};let g=p(d).element,v=ye(p(d).rest);const x=d.onError,y=i.ownerDocument,w=y&&"undefined"!=typeof document&&y!==document?null:re(),b=w?i.getContext("2d",{alpha:!0}):null,R=!(!w||!b),A=R?w.gl:i.getContext("webgl2",{alpha:!0,antialias:!1,depth:!1,stencil:!1,premultipliedAlpha:!0,powerPreference:"high-performance"});if(!A)throw new Error("WebGL2 is not available for the glyph field.");let S=A;R&&(e=>{ie.add(e)})(i),i.setAttribute("role","img"),i.setAttribute("aria-label",d.label??"ASCII artwork"),i.dataset.renderer="glyph-field";let L=!1;const D=R?null:S.getExtension("KHR_parallel_shader_compile");let P,C,U=null,I=null,B=null,N=null,G=null,X=[],q=[],H=null,O=!1,j=null,J=null;const Z=[];let ee=0,te=0,ne=1,se=0,ce=be(v.cellSize,v.cellAspect,1,2),he=2,fe=0,de=0,me=0,pe=null,ge=!1,ve=null,xe=0,Fe=0,Se=0,_e=null,Le=0,De=0,Pe=!0,Ce=0,Ue=[0,1],Ie=-1/0,Be=-1/0,Ne=!1;const Ge=(()=>{const e="undefined"==typeof navigator?void 0:navigator;return 1e3/(e&&(e.hardwareConcurrency>0&&e.hardwareConcurrency<=2||e.deviceMemory&&e.deviceMemory<=2||e.connection?.saveData)?30:60)-2})();let Xe=!1,qe=0,He=0,ze=!0,Ve=!1,Oe=!1,je=!1,We=!1,Ye=!0,Ke=null,$e=null,Qe=1/60,Je=0,Ze=0,et=[];const tt=new Float32Array(16),nt=()=>{if(!g)return;const{element:e,padding:t=32,feather:n=.16,shape:r="rect"}=g,o=Ae(i.getBoundingClientRect(),e.getBoundingClientRect(),t,n,r),a=v.clear;JSON.stringify(a)!==JSON.stringify(o)&&(v={...v,clear:o},ze=!0)},rt=e=>"lantern"===e||"loupe"===e||"reveal"===e,it={target:null,at:null,strength:0,trail:[]},ot=new Float32Array(36);let at=null,lt=null,st=!1;const ct=()=>{if(!ee||!te)return null;const e=ee/te,t=Math.round(e>=1?128:128*e),n=Math.round(e>=1?128/e:128);return at&&at.width===t&&at.height===n||(at=new oe(t,n),lt||(lt=wt(S.LINEAR)),S.bindTexture(S.TEXTURE_2D,lt),S.texImage2D(S.TEXTURE_2D,0,S.RGBA8,t,n,0,S.RGBA,S.UNSIGNED_BYTE,at.pixels),st=!0),at};let ut=0;const ht="function"==typeof matchMedia?matchMedia("(prefers-reduced-motion: reduce)"):null,ft=()=>v.respectReducedMotion&&!!ht?.matches;let dt;const mt=new Promise(e=>{dt=e});let pt=!0;const gt=e=>x?.(e instanceof Error?e:new Error(String(e))),vt=(e,t)=>{const n=S.createShader(e);return Z.push(n),S.shaderSource(n,t),S.compileShader(n),n},xt=e=>{if(R)return w.program(e);J??(J=vt(S.VERTEX_SHADER,"#version 300 es\nvoid main(){vec2 p=vec2((gl_VertexID<<1)&2,gl_VertexID&2);gl_Position=vec4(p*2.-1.,0.,1.);}"));const t=S.createProgram(),n=vt(S.FRAGMENT_SHADER,e);return S.attachShader(t,J),S.attachShader(t,n),S.linkProgram(t),{program:t,locations:null,fragment:n}},Et=(e,t=!1)=>{if(e.locations)return!0;if(R)return w.linked(e,t);const{program:n,fragment:r}=e;if(!t&&D&&!S.getProgramParameter(n,D.COMPLETION_STATUS_KHR))return!1;if(!S.getProgramParameter(n,S.LINK_STATUS)){if(S.isContextLost())return!1;throw new Error(S.getShaderInfoLog(r)||S.getProgramInfoLog(n)||"Glyph field program failed to link.")}const i={};for(let e=S.getProgramParameter(n,S.ACTIVE_UNIFORMS)-1;e>=0;e--){const t=S.getActiveUniform(n,e).name.replace(/\[0\]$/,"");i[t]=S.getUniformLocation(n,t)}return e.locations=i,!0},yt=(e=!1)=>!!U&&!!I&&Et(U,e)&&Et(I,e),wt=e=>{const t=S.createTexture();return S.bindTexture(S.TEXTURE_2D,t),S.texParameteri(S.TEXTURE_2D,S.TEXTURE_MIN_FILTER,e),S.texParameteri(S.TEXTURE_2D,S.TEXTURE_MAG_FILTER,e===S.LINEAR_MIPMAP_LINEAR?S.LINEAR:e),S.texParameteri(S.TEXTURE_2D,S.TEXTURE_WRAP_S,S.CLAMP_TO_EDGE),S.texParameteri(S.TEXTURE_2D,S.TEXTURE_WRAP_T,S.CLAMP_TO_EDGE),t},bt=()=>{G&&(S.deleteTexture(G.ink),S.deleteTexture(G.under),S.deleteFramebuffer(G.buffer),G=null)},Tt=()=>function(e,t,n,r,i,o,a){if("fill"!==e||!(i>0&&o>0))return[a.width,a.height];const l=t*r,s=l*n;return[i/Math.max(1,Math.floor(i/s+1e-6)),o/Math.max(1,Math.floor(o/l+1e-6))]}(v.cellFit,v.cellSize,v.cellAspect,ne,ee,te,ce),Mt=()=>!!v.fluid&&"fluid"===Re(v),Rt=()=>{H?.release(),O=!1,X.forEach(e=>S.deleteTexture(e)),q.forEach(e=>S.deleteFramebuffer(e)),X=[],q=[]};function At(){B&&!R&&S.deleteProgram(B.program),B=xt((e=>`#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform sampler2D uPrevious;\nuniform vec2 uSize;\nuniform float uAspect, uDt, uDecay, uEnergyDecay, uRadius, uSplat;\nuniform vec2 uFrom, uTo, uForce;\nout vec4 outColor;\n${t(e)}\nfloat segment(vec2 p,vec2 a,vec2 b){vec2 pa=p-a,ba=b-a;float h=clamp(dot(pa,ba)/max(dot(ba,ba),1e-8),0.,1.);return length(pa-ba*h);}\nvoid main(){\n vec2 uv=gl_FragCoord.xy/uSize;\n vec4 here=decodeFluid(texture(uPrevious,uv));\n vec4 state=decodeFluid(texture(uPrevious,uv-uDt*here.xy*vec2(1./uAspect,1.)));\n state.xy*=exp(-uDt*uDecay);\n state.z*=exp(-uDt*uEnergyDecay);\n if(uSplat>.5){\n vec2 scale=vec2(uAspect,1.);\n float d=segment(uv*scale,uFrom*scale,uTo*scale);\n float g=exp(-d*d/(uRadius*uRadius));\n state.xy+=uForce*g;\n state.z=min(1.,state.z+g*min(1.,length(uForce)*.5+.08));\n }\n float speed=length(state.xy);\n if(speed>5.)state.xy*=5./speed;\n outColor=encodeFluid(state);\n}`)(L)),R?H?.release():H?.dispose(),H=L?null:function(e,t,n){const r={splat:t(o),curl:t(a),vorticity:t(l),divergence:t(s),fade:t(c),pressure:t(u),gradient:t(h),advect:t(f)},i=Object.values(r);let d=0,m=0,p=[],g=[],v=null,x=null;const E=t=>{const n=e.createTexture();e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texImage2D(e.TEXTURE_2D,0,e.RGBA16F,d,m,0,e.RGBA,e.HALF_FLOAT,null);const r=e.createFramebuffer();return e.bindFramebuffer(e.FRAMEBUFFER,r),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,n,0),e.checkFramebufferStatus(e.FRAMEBUFFER)!==e.FRAMEBUFFER_COMPLETE?(e.deleteFramebuffer(r),e.deleteTexture(n),null):(e.viewport(0,0,d,m),e.clearColor(0,0,0,1),e.clear(e.COLOR_BUFFER_BIT),{texture:n,buffer:r})},y=t=>{t&&(e.deleteTexture(t.texture),e.deleteFramebuffer(t.buffer))},w=()=>{[...p,...g,v,x].forEach(y),p=[],g=[],v=x=null},b=(t,n)=>{const r=t.locations;return e.useProgram(t.program),e.bindFramebuffer(e.FRAMEBUFFER,n.buffer),e.uniform2f(r.uTexel,1/d,1/m),r},T=(t,n,r,i)=>{e.activeTexture(e.TEXTURE0+r),e.bindTexture(e.TEXTURE_2D,i),e.uniform1i(t[n],r)},M=()=>e.drawArrays(e.TRIANGLES,0,3),R=e=>{const t=e[0];e[0]=e[1],e[1]=t};return{resize(t,n){w(),d=t,m=n;const r=[E(e.LINEAR),E(e.LINEAR),E(e.NEAREST),E(e.NEAREST),E(e.NEAREST),E(e.NEAREST)];return e.bindFramebuffer(e.FRAMEBUFFER,null),r.some(e=>!e)?(r.forEach(y),!1):(p=[r[0],r[1]],g=[r[2],r[3]],v=r[4],x=r[5],!0)},ready:()=>i.every(n),step(t,n){if(!p.length||!v||!x)return;let i;e.viewport(0,0,d,m),t&&(i=b(r.splat,p[1]),T(i,"uVelocity",0,p[0].texture),e.uniform2f(i.uFrom,t.from[0],t.from[1]),e.uniform2f(i.uTo,t.to[0],t.to[1]),e.uniform2f(i.uForce,t.force[0],t.force[1]),e.uniform1f(i.uAspect,n.aspect),e.uniform1f(i.uRadius,n.radius),M(),R(p)),n.curl>0&&(i=b(r.curl,x),T(i,"uVelocity",0,p[0].texture),M(),i=b(r.vorticity,p[1]),T(i,"uVelocity",0,p[0].texture),T(i,"uCurl",1,x.texture),e.uniform1f(i.uStrength,n.curl),e.uniform1f(i.uDt,n.dt),M(),R(p)),i=b(r.divergence,v),T(i,"uVelocity",0,p[0].texture),M(),i=b(r.fade,g[1]),T(i,"uSource",0,g[0].texture),e.uniform1f(i.uAmount,.8),M(),R(g);for(let e=0;e<20;e++)i=b(r.pressure,g[1]),T(i,"uPressure",0,g[0].texture),T(i,"uDivergence",1,v.texture),M(),R(g);i=b(r.gradient,p[1]),T(i,"uPressure",0,g[0].texture),T(i,"uVelocity",1,p[0].texture),M(),R(p),i=b(r.advect,p[1]),T(i,"uVelocity",0,p[0].texture),e.uniform1f(i.uDt,n.dt),e.uniform1f(i.uDissipation,n.dissipation),M(),R(p),e.bindFramebuffer(e.FRAMEBUFFER,null)},get velocity(){return p[0]?.texture??null},get size(){return[d,m]},release:w,dispose(){w(),i.forEach(({program:t})=>e.deleteProgram(t))}}}(S,xt,e=>Et(e))}const Ft=()=>{Rt();const e=v.fluid;if(!(e&&Mt()&&ee&&te))return;B||At();const t=e.resolution,n=ee/te;if(fe=n>=1?t:Math.max(8,Math.round(t*n)),de=n>=1?Math.max(8,Math.round(t/n)):t,O=!!H&&H.resize(fe,de),O)return void(me=0);const r=()=>{Rt();for(let e=0;e<2;e++){const e=wt(S.LINEAR);S.texImage2D(S.TEXTURE_2D,0,L?S.RGBA8:S.RGBA16F,fe,de,0,S.RGBA,L?S.UNSIGNED_BYTE:S.HALF_FLOAT,null);const t=S.createFramebuffer();S.bindFramebuffer(S.FRAMEBUFFER,t),S.framebufferTexture2D(S.FRAMEBUFFER,S.COLOR_ATTACHMENT0,S.TEXTURE_2D,e,0),X.push(e),q.push(t)}return S.checkFramebufferStatus(S.FRAMEBUFFER)===S.FRAMEBUFFER_COMPLETE};if(!r()){if(L)throw new Error("The glyph field could not allocate its fluid buffers.");L=!0,kt(),At(),r()}for(const e of q)S.bindFramebuffer(S.FRAMEBUFFER,e),S.viewport(0,0,fe,de),S.clearColor(L?.5:0,L?.5:0,0,1),S.clear(S.COLOR_BUFFER_BIT);S.bindFramebuffer(S.FRAMEBUFFER,null),me=0};function kt(){U&&!R&&S.deleteProgram(U.program),I&&!R&&S.deleteProgram(I.program),bt(),U=xt(n(L)),I=xt(r),(R?w.canCompileInParallel:D)||yt(!0)}const St=()=>`${v.fontWeight} ${Math.max(1,ce.height*v.glyphScale)}px ${v.font}`,_t=()=>{ze=!0,sn()},Lt=()=>`${Ee(v.charset).join("")}\0${St()}\0${ce.width}x${ce.height}x${ce.columns}`,Dt=()=>{const e=Ee(v.charset);if(he=e.length,ce=be(v.cellSize,v.cellAspect,ne,he),se=ne,R){const e=Lt();if(N?.key!==e){const t=N;N=w.atlas(e,Pt,_t),w.releaseAtlas(t,_t),P=N.texture}return void(ze=!0)}const{image:t}=Pt();S.bindTexture(S.TEXTURE_2D,P),S.pixelStorei(S.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),S.texImage2D(S.TEXTURE_2D,0,S.RGBA8,S.RGBA,S.UNSIGNED_BYTE,t),t.width=t.height=1,ze=!0};function Pt(){const e=Ee(v.charset),t=document.createElement("canvas");t.width=ce.atlasWidth,t.height=ce.atlasHeight;const n=t.getContext("2d");n.fillStyle="#fff",n.textAlign="center",n.textBaseline="alphabetic",n.font=St();const r=n.measureText("M"),i=r.actualBoundingBoxAscent||ce.height*v.glyphScale*.7,o=r.actualBoundingBoxDescent||0,a=(ce.height+i-o)/2;e.forEach((e,t)=>{const r=t%ce.columns*ce.width+ce.width/2,i=Math.floor(t/ce.columns)*ce.height+a,o=n.measureText(e).width;n.save(),n.beginPath(),n.rect(r-ce.width/2,i-a,ce.width,ce.height),n.clip(),n.translate(r,i),o>.96*ce.width&&n.scale(.96*ce.width/o,1),n.fillText(e,0,0),n.restore()});let l=!0;try{l=!Ct?.check||Ct.check(n.font,e.join(""))}catch{}return R&&queueMicrotask(()=>{t.width=t.height=1}),{image:t,final:l}}const Ct="undefined"==typeof document?void 0:document.fonts,Ut=()=>{if(!Ct?.load)return;const e=St();Ct.load(e,Ee(v.charset).join("")).then(()=>{if(!Ve&&!Oe&&St()===e)return R?void(N&&!N.final&&N.key===Lt()&&w.paintAtlas(N,Pt)):(Dt(),void sn())},()=>{})},It=e=>e.trim().replace(/^["']|["']$/g,"").toLowerCase(),Bt=()=>{if(Ue=[0,1],pe&&"none"!==v.levels)try{const e=document.createElement("canvas");e.width=e.height=64;const t=e.getContext("2d",{willReadFrequently:!0});pe===_e&&(t.imageSmoothingQuality="medium"),t.drawImage(pe,0,0,64,64),Ue=Me(t.getImageData(0,0,64,64).data)}catch{Ue=[0,1]}};let Nt=null,Gt=null,Xt=!1,qt=-1/0,Ht=new Uint8Array(0),zt=null;const Vt=()=>{if(Xt=!1,!pe||"all"===v.scope)return;const e=xe||1,t=Fe||1,n=Math.max(8,Math.round(e>=t?96:96*e/t)),r=Math.max(8,Math.round(t>=e?96:96*t/e));try{if(zt??(zt=document.createElement("canvas").getContext("2d",{willReadFrequently:!0})),!zt)return;const e=zt.canvas;e.width!==n||e.height!==r?(e.width=n,e.height=r):zt.clearRect(0,0,n,r),zt.drawImage(pe,0,0,n,r),Gt=function(e,t,n,r,i){const o=t*n,a=i&&i.width===t&&i.height===n?i:{width:t,height:n,subject:new Float32Array(o),depth:new Float32Array(o),key:"none"},{subject:l,depth:s}=a;let c=0;for(let t=0;t<o;t++)e[4*t+3]<250&&c++;const u=t=>(.2126*e[4*t]+.7152*e[4*t+1]+.0722*e[4*t+2])/255;let h="none",f=0;if(c>.01*o)h="alpha";else{let e=0,r=0,i=0;const o=Math.max(1,Math.round(.03*Math.min(t,n)));for(let a=0;a<n;a++)for(let l=0;l<t;l++){if(l>=o&&a>=o&&l<t-o&&a<n-o)continue;const s=u(a*t+l);e+=s,r+=s*s,i++}f=e/Math.max(1,i),Math.sqrt(Math.max(0,r/Math.max(1,i)-f*f))<.07&&(h="ground")}for(let t=0;t<o;t++){const n=e[4*t+3]/255,r=u(t);let i=1;if("alpha"===h)i=n;else if("ground"===h){const e=Math.max(0,Math.min(1,(Math.abs(r-f)-.035)/.12));i=e*e*(3-2*e)}l[t]=1*i,s[t]=r*n}a.key=h,le.length<o&&(le=new Float32Array(o));const d=le;return ae(l,d,t,n,Math.max(1,Math.round(.02*Math.min(t,n)))),ae(s,d,t,n,Math.max(1,Math.round(.035*Math.min(t,n)))),a}(zt.getImageData(0,0,n,r).data,n,r,0,Gt)}catch{return}if("none"!==Gt.key){Ht.length!==n*r*4&&(Ht=new Uint8Array(n*r*4));for(let e=0;e<n*r;e++)Ht[4*e+3]=Math.round(255*Gt.subject[e]);Nt??(Nt=wt(S.LINEAR)),S.bindTexture(S.TEXTURE_2D,Nt),S.pixelStorei(S.UNPACK_FLIP_Y_WEBGL,!1),S.pixelStorei(S.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),S.texImage2D(S.TEXTURE_2D,0,S.RGBA8,n,r,0,S.RGBA,S.UNSIGNED_BYTE,Ht),Xt=!0}},Ot=()=>{if(!pe)return;const e=performance.now();pe instanceof HTMLVideoElement&&!(e-Ie>1500)||(Bt(),Ie=e),pe instanceof HTMLVideoElement&&!(e-qt>160)||(Vt(),qt=e),S.bindTexture(S.TEXTURE_2D,C),S.pixelStorei(S.UNPACK_FLIP_Y_WEBGL,!1),S.pixelStorei(S.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);try{S.texImage2D(S.TEXTURE_2D,0,S.RGBA8,S.RGBA,S.UNSIGNED_BYTE,pe),S.generateMipmap(S.TEXTURE_2D);const e=pe;De=(e.videoWidth||e.naturalWidth||e.width)*(e.videoHeight||e.naturalHeight||e.height)*4*4/3}catch(e){gt(e)}},jt=()=>{L=!S.getExtension("EXT_color_buffer_float")&&!S.getExtension("EXT_color_buffer_half_float"),kt(),j=R?w.vertexArray():S.createVertexArray(),R||(P=wt(S.NEAREST)),C=wt(S.LINEAR_MIPMAP_LINEAR),S.bindTexture(S.TEXTURE_2D,C),S.texImage2D(S.TEXTURE_2D,0,S.RGBA8,1,1,0,S.RGBA,S.UNSIGNED_BYTE,new Uint8Array([0,0,0,255])),S.generateMipmap(S.TEXTURE_2D),ee=te=0,se=0,Wt(),Ut(),pe&&Ot()};function Wt(){const e=i.clientWidth||i.clientHeight?{width:i.clientWidth,height:i.clientHeight}:i.getBoundingClientRect();Ne=!e.width||!e.height;const t=Math.min(globalThis.devicePixelRatio||1,v.maxPixelRatio,Math.sqrt(8294400/Math.max(1,e.width*e.height))),n=R&&w.scale<1&&t>1?Math.max(1,t*w.scale):t,r=Math.max(1,Math.round(e.width*n)),o=Math.max(1,Math.round(e.height*n));if(r===ee&&o===te&&n===ne)return!1;const a=!ee||Math.abs(r/o-ee/te)>.01;return ne=n,ee=r,te=o,i.width=ee,i.height=te,se!==ne&&Dt(),(a||Mt()&&!X.length&&!O)&&Ft(),ze=!0,!0}let Yt=null,Kt=[0,0,0],$t=[1,1,1],Qt=[0,0,0,0],Jt=we(1,1,1,1,"cover"),Zt=null,en=0,tn=0,nn=0,rn=0;const on=()=>{Yt!==v&&(Yt=v,Kt=Te(v.ink),$t=Te("auto"===v.highlight?"#ffffff":v.highlight),Qt="transparent"===v.background?[0,0,0,0]:[...Te(v.background),1]),Zt===v&&en===ee&&tn===te&&nn===xe&&rn===Fe||(Zt=v,en=ee,tn=te,nn=xe,rn=Fe,Jt=we(ee,te,xe||1,Fe||1,v.fit,v.focus)),R&&w.begin(ee,te);const t=v.fluid,n=pe&&Le?ce.height/te*Le*Jt.scale[1]:1,r=(()=>{const[e,t]=Tt(),n=Math.ceil(ee/e-1e-4),r=Math.ceil(te/t-1e-4);if(G&&G.columns===n&&G.rows===r)return G;bt();const i=()=>{const e=wt(S.NEAREST);return S.texStorage2D(S.TEXTURE_2D,1,L?S.RGBA8:S.RGBA16F,n,r),e},o=i(),a=i(),l=S.createFramebuffer();return S.bindFramebuffer(S.FRAMEBUFFER,l),S.framebufferTexture2D(S.FRAMEBUFFER,S.COLOR_ATTACHMENT0,S.TEXTURE_2D,o,0),S.framebufferTexture2D(S.FRAMEBUFFER,S.COLOR_ATTACHMENT1,S.TEXTURE_2D,a,0),S.drawBuffers([S.COLOR_ATTACHMENT0,S.COLOR_ATTACHMENT1]),G={ink:o,under:a,buffer:l,columns:n,rows:r}})(),i=U.locations,o=I.locations,a=Re(v),l=!ft();S.bindFramebuffer(S.FRAMEBUFFER,r.buffer),S.viewport(0,0,r.columns,r.rows),S.useProgram(U.program),S.activeTexture(S.TEXTURE0),S.bindTexture(S.TEXTURE_2D,C),S.uniform1i(i.uSource,0),S.activeTexture(S.TEXTURE2),S.bindTexture(S.TEXTURE_2D,(O?H?.velocity:X[me])??C),S.uniform1i(i.uFluid,2),S.activeTexture(S.TEXTURE3),S.bindTexture(S.TEXTURE_2D,lt??C),S.uniform1i(i.uTrailMap,3),S.activeTexture(S.TEXTURE6),S.bindTexture(S.TEXTURE_2D,Nt??C),S.uniform1i(i.uScope,6),S.uniform1f(i.uScopeMode,Xt&&"all"!==v.scope?"subject"===v.scope?1:2:0),S.uniform1f(i.uFluidMode,O?1:0),S.uniform1i(i.uHoverMode,"fluid"===a?1:"lantern"===a?2:"trail"===a&&st?3:"loupe"===a?4:"reveal"===a?5:0),S.uniform1f(i.uTrailAmount,v.trail.strength),S.uniform3f(i.uLight,it.at?.[0]??-1,it.at?.[1]??-1,rt(a)?it.strength:0),S.uniform3fv(i.uTrail,ot),S.uniform1f(i.uLightRadius,v.lantern.radius),S.uniform1f(i.uLightGain,v.lantern.strength),S.uniform1f(i.uClock,performance.now()/1e3),S.uniform1f(i.uFlicker,l?1:0),S.uniform2f(i.uFluidTexel,1/Math.max(1,fe),1/Math.max(1,de)),S.uniform2f(i.uResolution,ee,te);const[s,c]=Tt();var u;S.uniform2f(i.uCell,s,c),S.uniform1f(i.uCount,he),S.uniform1f(i.uBlend,"on"===v.blend||he<=9&&("coarse"===v.blend||"auto"===v.blend&&ge)?1:0),S.uniform4f(i.uSourceMap,Jt.scale[0],Jt.scale[1],Jt.offset[0],Jt.offset[1]),S.uniform1i(i.uScene,pe?0:(u=v.scene,e[u]??3)),S.uniform1i(i.uMark,ue.indexOf(v.mark)),S.uniform1f(i.uScale,v.scale);const h=v.clear;S.uniform4f(i.uClear,h?h.x:0,h?h.y:0,h?h.width:0,h?h.height:0),S.uniform1f(i.uClearFeather,h?h.feather:.1),S.uniform1f(i.uClearShape,h&&"rect"===h.shape?1:0);const f=performance.now();tt.fill(0);for(let e=0;e<et.length;e++){const t=et[e],n=4*e;tt[n]=t.x,tt[n+1]=t.y,tt[n+2]=(f-t.born)/1e3,tt[n+3]=t.strength}S.uniform4fv(i.uPulse,tt),S.uniform3fv(i.uInk,Kt),S.uniform3fv(i.uHighlight,$t),S.uniform1f(i.uHighlightAuto,"auto"===v.highlight?1:0),S.uniform4fv(i.uBackground,Qt),S.uniform1f(i.uBrightness,v.brightness),S.uniform1f(i.uContrast,v.contrast),S.uniform1f(i.uGamma,v.gamma),S.uniform1f(i.uInvert,v.invert?1:0),S.uniform1f(i.uVignette,v.vignette),S.uniform1f(i.uSourceColor,"source"===v.color?1:0),S.uniform1f(i.uRefraction,t?t.refraction*(l?1:.25):0),S.uniform1f(i.uGlow,t?t.glow:0),S.uniform1f(i.uTime,He),S.uniform1f(i.uDrift,l?v.drift:0),S.uniform1f(i.uFluidOn,t&&"fluid"===a&&(X.length||O)?1:0),S.uniform1f(i.uLod,Math.max(0,Math.log2(Math.max(1,n))-.5)),S.uniform1f(i.uSaturation,v.saturation),S.uniform1f(i.uShade,v.shade),S.uniform1f(i.uBackdrop,pe?v.backdrop:0),S.uniform2f(i.uLevels,pe&&"auto"===v.levels?Ue[0]:0,pe&&"auto"===v.levels?Ue[1]:1),S.bindVertexArray(j),S.drawArrays(S.TRIANGLES,0,3),S.bindFramebuffer(S.FRAMEBUFFER,null),S.viewport(0,0,ee,te),S.useProgram(I.program),S.activeTexture(S.TEXTURE1),S.bindTexture(S.TEXTURE_2D,P),S.uniform1i(o.uAtlas,1),S.activeTexture(S.TEXTURE4),S.bindTexture(S.TEXTURE_2D,r.ink),S.uniform1i(o.uCells,4),S.activeTexture(S.TEXTURE5),S.bindTexture(S.TEXTURE_2D,r.under),S.uniform1i(o.uUnder,5),S.uniform2f(o.uResolution,ee,te),S.uniform2f(o.uCell,ce.width,ce.height),S.uniform2f(o.uPitch,s,c),S.uniform1f(o.uColumns,ce.columns),S.uniform1f(o.uDotScale,v.dotScale),S.uniform1i(o.uMark,ue.indexOf(v.mark)),S.uniform1f(o.uSourceColor,"source"===v.color?1:0),S.drawArrays(S.TRIANGLES,0,3),R&&w.present(b,ee,te)},an=()=>!Ve&&!Oe&&!je&&!Ne&&(Ye||pt)&&!("undefined"!=typeof document&&document.hidden),ln=e=>{if(Xe=!1,!an())return;const t=(e-qe)/1e3,n=Math.min(1/30,Math.max(1/480,t));qe=e,Qe=.9*Qe+.1*Math.min(t,.25),Je=Qe>1/24?Je+1:0;try{R&&w.overloaded&&Ze<2&&Je>10&&(Ze=2),Je>45&&Ze<2&&(!R||w.atMinimum)&&(Je=0,Ze++,1===Ze&&ne>1?(v={...v,maxPixelRatio:1},Wt()):Ze=2);const t=yt(),r=!(We||Ze>=2&&!(pe instanceof HTMLVideoElement)||(!(pe instanceof HTMLVideoElement)||pe.paused||pe.ended)&&(ft()||!(!pe&&"none"!==v.scene||v.drift>0)));r&&(He+=n*v.speed),pe instanceof HTMLVideoElement&&pe.readyState>=2&&Pe&&(Pe=!("requestVideoFrameCallback"in pe),Ot(),ze=!0);const i=Re(v);let o="fluid"===i&&(null!==$e||e<ut);if(o?((e,t)=>{const n=v.fluid;if(!n||!q.length&&!O)return;if(O?!H?.ready():!B||!Et(B))return;const r=ee/te,i=$e;if($e=null,O&&H){const o=5200*n.force*(ft()?.35:1);return i&&(ut=t+1e3*Math.min(9,6/Math.max(.3,n.dissipation))),void H.step(i?{from:i.from,to:i.to,force:[(i.to[0]-i.from[0])*o,(i.to[1]-i.from[1])*o]}:null,{dt:Math.min(e,1/60),radius:1.1*n.radius,curl:n.curl,dissipation:n.dissipation,aspect:r})}let o=0,a=0;if(i){const e=(ft()?1:3)*n.force;o=(i.to[0]-i.from[0])*r*e*4,a=(i.to[1]-i.from[1])*e*4,ut=t+7/Math.min(n.dissipation,1.1*n.dissipation)*1e3}const l=B.locations;S.bindFramebuffer(S.FRAMEBUFFER,q[1-me]),S.viewport(0,0,fe,de),S.useProgram(B.program),S.activeTexture(S.TEXTURE0),S.bindTexture(S.TEXTURE_2D,X[me]),S.uniform1i(l.uPrevious,0),S.uniform2f(l.uSize,fe,de),S.uniform1f(l.uAspect,r),S.uniform1f(l.uDt,e),S.uniform1f(l.uDecay,n.dissipation),S.uniform1f(l.uEnergyDecay,1.1*n.dissipation),S.uniform1f(l.uRadius,n.radius),S.uniform1f(l.uSplat,i?1:0),S.uniform2f(l.uFrom,i?.from[0]??0,i?.from[1]??0),S.uniform2f(l.uTo,i?.to[0]??0,i?.to[1]??0),S.uniform2f(l.uForce,o,a),S.drawArrays(S.TRIANGLES,0,3),me=1-me})(n,e):$e=null,rt(i)&&(o=((e,t)=>{const n=v.lantern,r=it.target;if(r){const i=it.at;if(i)if(ft())i[0]=r[0],i[1]=r[1];else{const t=1-Math.exp(-n.follow*e);i[0]+=(r[0]-i[0])*t,i[1]+=(r[1]-i[1])*t}else it.at=[r[0],r[1]];const o=it.at,a=it.trail[it.trail.length-1];n.trail>0&&(!a||t-a.born>28&&Math.hypot(o[0]-a.x,o[1]-a.y)>.004)&&(it.trail.push({x:o[0],y:o[1],born:t}),it.trail.length>12&&it.trail.shift())}it.strength+=((r?1:0)-it.strength)*(1-Math.exp(-e*(r?9:5)));const i=it.trail;for(let e=i.length-1;e>=0;e--)n.trail>0&&t-i[e].born<4e3*n.trail||i.splice(e,1);ot.fill(0);for(let e=0;e<i.length;e++){const r=i[e];ot[3*e]=r.x,ot[3*e+1]=r.y,ot[3*e+2]=.55*Math.exp(-(t-r.born)/1e3/Math.max(.01,n.trail))}return it.strength>.003||i.length>0})(n,e)||o),"trail"===i){const e=!!at?.active;o=(e=>{const t=ct();return!(!t||!t.active||(t.step(e),S.bindTexture(S.TEXTURE_2D,lt),S.texSubImage2D(S.TEXTURE_2D,0,0,0,t.width,t.height,S.RGBA,S.UNSIGNED_BYTE,t.pixels),st=!0,0))})(n)||o,e&&!at?.active&&(ze=!0)}if(et.length){for(let t=et.length-1;t>=0;t--)e-et[t].born>=2400&&et.splice(t,1);o=!0,et.length||(ze=!0)}t&&(o||ze||r&&e-Be>=Ge*E)&&(on(),Be=e,ze=!1,!pt||Se&&!pe||(pt=!1,dt())),(r||o||$e||!t)&&(Xe=!0,T(ln))}catch(e){je=!0,gt(e)}};function sn(){!Xe&&an()&&(qe=performance.now(),Xe=!0,T(ln))}const cn=(e,t)=>{const n=i.getBoundingClientRect();if(!n.width||!n.height)return null;const r=(e-n.left)/n.width,o=(t-n.top)/n.height;return r<-.05||r>1.05||o<-.05||o>1.05?null:[r,1-o]},un=e=>{const t=Re(v);if("none"===t||We)return Ke=null,void(it.target=null);if(rt(t))return it.target=e?[e[0],1-e[1]]:null,Ke=null,void sn();if("trail"===t){const t=ct();if(!t)return;return e?t.move(e[0],1-e[1],v.trail.radius,performance.now()):t.leave(),Ke=null,void sn()}e?(Ke&&($e=$e?{from:$e.from,to:e}:{from:Ke,to:e}),Ke=e,sn()):Ke=null},hn=d.interactionTarget??window,fn={target:hn,move:e=>{const t=cn(e.clientX,e.clientY);hn===window&&(fn.inside=!!t),un(t)},leave:()=>{Ke=null,at?.leave(),it.target&&(it.target=null,sn())},near:()=>Ye},dn=[V(fn)],mn=()=>{const e=Wt();nt(),(e||ze)&&sn()};let pn=g?Q(g.element,mn):()=>{};dn.push(Q(i,mn),()=>pn()),dn.push(function(e,t,n){if("function"!=typeof IntersectionObserver)return()=>{};let r=W.get(t);if(!r){const e=new Map;r={observer:new IntersectionObserver(Y(e),{rootMargin:t}),watch:e},W.set(t,r)}const{observer:i,watch:o}=r;return K(o,e,n)||i.unobserve(e),i.observe(e),()=>{$(o,e,n)&&i.unobserve(e),o.size||(i.disconnect(),W.delete(t))}}(i,"120px",e=>{Ye=e.isIntersecting,Ye&&(ze=!0,sn())})),dn.push(z(F,()=>{document.hidden||(ze=!0,sn())})),dn.push((e=>z(k,e))(()=>{ze=!0,sn()})),dn.push((e=>z(_,e))(e=>{const t=e.fontfaces??[],n=v.font.split(",").map(It);t.some(e=>n.includes(It(e.family)))&&Ut()}));const gn=e=>{e?.preventDefault(),Oe=!0,Xe&&M(ln),Xe=!1},vn=()=>{Oe=!1,R&&(S=w.gl),Z.length=0,J=null,N=null,U=I=B=null,G=null,X=[],q=[],H=null,O=!1,lt=null,at=null,st=!1,Nt=null,Xt=!1;try{jt(),ze=!0,sn()}catch(e){gt(e)}},xn={lost:()=>gn(),restored:vn,rescale:()=>{Wt()&&sn()},size:()=>[ee,te],bytes:()=>{const e=L?4:8;return ee*te*4+De+(G?G.columns*G.rows*e*2:0)+fe*de*e*(O?6:X.length)+(at?at.width*at.height*4:0)}};R?w.join(xn):(i.addEventListener("webglcontextlost",gn),i.addEventListener("webglcontextrestored",vn));const En=()=>{ve&&(ve.pause(),ve.removeAttribute("src"),ve.load(),ve=null),Ce&&pe instanceof HTMLVideoElement&&"cancelVideoFrameCallback"in pe&&pe.cancelVideoFrameCallback(Ce),Ce=0},yn=()=>{_e?.close(),_e=null},wn=async e=>{const t=await createImageBitmap(e,{premultiplyAlpha:"none"}),n=[t.width,t.height],r=function(e,t,n,r,i,o,a=8){if(!(n>=16&&r>=16&&e>0&&t>0&&i>0))return 1;const l=a/i/("cover"===o?Math.min(e/n,t/r):Math.max(e/n,t/r));return l>.5?1:2**-Math.floor(Math.log2(1/l))}(t.width,t.height,ee,te,ce.height,v.fit);if(1===r)return{element:t,owned:!0,natural:n};try{return{element:await createImageBitmap(t,{resizeWidth:Math.max(1,Math.round(t.width*r)),resizeHeight:Math.max(1,Math.round(t.height*r)),resizeQuality:"medium",premultiplyAlpha:"none"}),owned:!0,natural:n}}finally{t.close()}},bn=e=>new Promise((t,n)=>{const r=new Image;r.crossOrigin="anonymous",r.decoding="async",r.onload=()=>t({element:r,owned:!1}),r.onerror=()=>n(new Error("The glyph field could not load this image.")),r.src=e}),Tn=(e,t,n)=>{const{element:r,owned:i}=e;if(Ve||n!==Se)return void(i&&r instanceof HTMLVideoElement?(r.pause(),r.removeAttribute("src"),r.load()):i&&r.close());r!==pe&&(En(),yn()),ve=i&&r instanceof HTMLVideoElement?r:null,!i||r instanceof HTMLVideoElement||(_e=r);const o=r!==pe;pe=r,ge="string"==typeof t||t instanceof HTMLImageElement||t instanceof HTMLVideoElement,Le=r instanceof HTMLVideoElement?r.videoHeight:r instanceof HTMLImageElement?r.naturalHeight:r.height,xe=e.natural?.[0]??(r instanceof HTMLVideoElement?r.videoWidth:r instanceof HTMLImageElement?r.naturalWidth:r.width),Fe=e.natural?.[1]??Le,Pe=!0,r instanceof HTMLVideoElement&&o&&(e=>{const t=e;if(!t.requestVideoFrameCallback)return;const n=()=>{Ve||pe!==e||(Pe=!0,sn(),Ce=t.requestVideoFrameCallback(n))};Ce=t.requestVideoFrameCallback(n)})(r),Oe||Ot(),ze=!0,sn()},Mn=(e,t)=>{pt&&e===Se&&(pt=!1,dt()),gt(t)},Rn=e=>{const t=++Se;if(!e)return En(),yn(),pe=null,xe=Fe=Le=De=0,ge=!1,ze=!0,sn(),Promise.resolve();if((e=>!("string"==typeof e||e instanceof HTMLImageElement&&!e.complete||e instanceof HTMLVideoElement&&e.readyState<2))(e)){try{Tn({element:e,owned:!1},e,t)}catch(e){Mn(t,e)}return Promise.resolve()}return(async e=>{if("string"!=typeof e)return e instanceof HTMLImageElement&&!e.complete?e.decode().then(()=>({element:e,owned:!1})):e instanceof HTMLVideoElement&&e.readyState<2?new Promise((t,n)=>{e.addEventListener("loadeddata",()=>t({element:e,owned:!1}),{once:!0}),e.addEventListener("error",()=>n(new Error("The glyph field could not load this video.")),{once:!0})}):{element:e,owned:!1};if(ke.test(e))return new Promise((t,n)=>{const r=document.createElement("video");r.crossOrigin="anonymous",r.muted=!0,r.loop=!0,r.playsInline=!0,r.preload="auto",r.addEventListener("loadeddata",()=>{r.play().catch(()=>{}),t({element:r,owned:!0})},{once:!0}),r.addEventListener("error",()=>n(new Error("The glyph field could not load this video.")),{once:!0}),r.src=e});if("function"!=typeof createImageBitmap||"function"!=typeof fetch)return bn(e);let t;try{t=await(await fetch(e).then(e=>{if(!e.ok)throw new Error("The glyph field could not load this image.");return e})).blob()}catch(t){if(t instanceof Error&&t.message.startsWith("The glyph field"))throw t;return bn(e)}if(!/svg/i.test(t.type))try{return await wn(t)}catch{}const n=URL.createObjectURL(t);try{return await bn(n)}finally{URL.revokeObjectURL(n)}})(e).then(n=>Tn(n,e,t),e=>Mn(t,e))};jt(),nt();const An=d.source??null;return An?(Se=1,Rn(An)):sn(),{canvas:i,ready:mt,get settings(){return v},update(e){const t=v,{element:n,rest:r}=p(e);"clear"in e&&g?.element!==n?.element?(pn(),g=n,pn=n?Q(n.element,mn):()=>{}):"clear"in e&&(g=n),v=ye(n?{...r,clear:v.clear}:r,v),nt(),e.label&&i.setAttribute("aria-label",e.label),v.maxPixelRatio!==t.maxPixelRatio&&Wt(),v.charset===t.charset&&v.cellSize===t.cellSize&&v.cellAspect===t.cellAspect&&v.font===t.font&&v.fontWeight===t.fontWeight&&v.glyphScale===t.glyphScale||(Dt(),Ut()),v.levels!==t.levels&&Bt(),v.scope===t.scope||Oe||(Vt(),qt=performance.now());((!!t.fluid&&"fluid"===Re(t))!==Mt()||v.fluid&&t.fluid&&v.fluid.resolution!==t.fluid.resolution)&&Ft(),"source"in e&&Rn(e.source??null),ze=!0,sn()},setSource:Rn,pointer(e,t=0){if(null===e)return void un(null);const n=i.getBoundingClientRect();un(cn(n.left+e,n.top+t))},redraw(){if(!(Ve||Oe||je)&&ee)try{yt(!(pt&&(R?w.canCompileInParallel:D)))&&(on(),pt||(ze=!1))}catch(e){je=!0,gt(e)}},pulse(e={}){if(Ve||ft())return;const t=i.getBoundingClientRect();if(!t.width||!t.height)return;let n=e.x??t.width/2,r=e.y??t.height/2;if(e.element){const i=e.element.getBoundingClientRect();n=i.left+i.width/2-t.left,r=i.top+i.height/2-t.top}const o=Math.max(0,Math.min(2,e.strength??1));et=[...et,{x:n/t.width,y:r/t.height,born:performance.now(),strength:o}].slice(-4),sn()},play(){We=!1,pe instanceof HTMLVideoElement&&pe.play().catch(()=>{}),ze=!0,sn()},pause(){We=!0,pe instanceof HTMLVideoElement&&pe.pause()},resize(){Wt()&&sn()},destroy(){if(!Ve){if(Ve=!0,Xe&&M(ln),Xe=!1,dn.forEach(e=>e()),R?w.leave(xn):(i.removeEventListener("webglcontextlost",gn),i.removeEventListener("webglcontextrestored",vn)),En(),yn(),pe=null,!Oe)if(Rt(),bt(),S.deleteTexture(C),lt&&S.deleteTexture(lt),Nt&&S.deleteTexture(Nt),R)w.releaseAtlas(N,_t),H?.release();else{S.deleteTexture(P);for(const e of[U,I,B])e&&S.deleteProgram(e.program);H?.dispose(),Z.forEach(e=>S.deleteShader(e)),j&&S.deleteVertexArray(j)}N=null}}}},exports.normalizeFieldSettings=ye;//# sourceMappingURL=field.cjs.map
|
|
1
|
+
"use strict";var e={none:3,flow:1,orb:2,drift:4,swell:5,caustics:6,contour:7,aurora:8,ripple:9,halo:10,interference:11,mesh:12,cascade:13,constellation:14},t=e=>e?"\nconst float VSCALE=6.;\nvec4 decodeFluid(vec4 t){return vec4((t.xy*2.-1.)*VSCALE,t.z,t.w);}\nvec4 encodeFluid(vec4 v){return vec4(clamp(v.xy/VSCALE*.5+.5,0.,1.),clamp(v.z,0.,1.),1.);}":"\nvec4 decodeFluid(vec4 t){return t;}\nvec4 encodeFluid(vec4 v){return vec4(v.xyz,1.);}",n=e=>`#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform sampler2D uSource, uFluid;\nuniform vec2 uResolution, uCell;\nuniform float uCount, uBlend;\nconst float BAYER[16]=float[16](0.,8.,2.,10.,12.,4.,14.,6.,3.,11.,1.,9.,15.,7.,13.,5.);\nuniform vec4 uSourceMap;\nuniform int uScene;\nuniform vec3 uInk, uHighlight;\nuniform vec4 uBackground;\nuniform float uBrightness, uContrast, uGamma, uInvert, uVignette, uSourceColor;\nuniform float uRefraction, uGlow, uTime, uDrift, uFluidOn, uLod, uSaturation, uBackdrop, uShade, uHighlightAuto, uFluidMode;\nuniform vec2 uFluidTexel;\nuniform int uHoverMode;\nuniform vec3 uLight;\nuniform vec3 uTrail[12];\nuniform float uLightRadius, uLightGain, uClock, uFlicker, uTrailAmount;\nuniform sampler2D uTrailMap, uScope;\nuniform float uScopeMode;\nuniform vec2 uLevels;\nuniform int uMark;\nuniform float uScale, uClearFeather, uClearShape;\nuniform vec4 uClear;\nuniform vec4 uPulse[4];\nlayout(location=0) out vec4 outInk;\nlayout(location=1) out vec4 outUnder;\n${t(e)}\nfloat hash(vec2 p){p=fract(p*vec2(123.34,456.21));p+=dot(p,p+45.32);return fract(p.x*p.y);}\nfloat noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.-2.*f);\n return mix(mix(hash(i),hash(i+vec2(1,0)),u.x),mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),u.x),u.y);}\nfloat fbm(vec2 p){float v=0.,a=.5;for(int i=0;i<5;i++){v+=a*noise(p);p=p*2.03+vec2(1.7,9.2);a*=.5;}return v;}\nvec3 generated(vec2 uv,float aspect){\n vec2 p=(uv-.5)*vec2(aspect,1.)*uScale;\n if(uScene==1){\n float t=uTime*.08;\n vec2 q=vec2(fbm(p*1.6+t),fbm(p*1.6-t+3.1));\n return vec3(smoothstep(.28,.86,fbm(p*1.8+q*1.6+vec2(t*.6,-t*.4))));\n }\n if(uScene==2){\n float r=.36,d=length(p),a=uTime*.25;\n vec3 l=normalize(vec3(cos(a)*.8,.55,sin(a)*.6+.6));\n if(d<r){\n vec3 n=normalize(vec3(p.x,-p.y,sqrt(r*r-d*d)));\n float diffuse=max(dot(n,l),0.),rim=pow(1.-n.z,2.5);\n float lon=atan(n.x,n.z)+uTime*.35,lat=asin(clamp(n.y,-1.,1.));\n float bands=.5+.25*sin(lat*14.)+.25*sin(lon*6.);\n return vec3(clamp(diffuse*.85+rim*.5+bands*.12,0.,1.));\n }\n return vec3(exp(-pow((d-r)*9.,2.))*.35);\n }\n if(uScene==4){\n // Drift: a few broad lobes that wander slowly. Built for halftone, where large soft shapes read best.\n float t=uTime*.045;\n vec2 q=p*1.15;\n vec2 w=vec2(fbm(q*.7+vec2(t,-t*.7)),fbm(q*.7+vec2(4.3-t*.8,t+1.7)));\n float n=fbm(q+w*1.3+vec2(t*.4,t*.25));\n return vec3(smoothstep(.36,.74,n));\n }\n if(uScene==5){\n // Swell: three crossing swells, the second bent by the first, so crests roll diagonally instead of pooling.\n float t=uTime;\n float s=sin((dot(p,vec2(.94,.33))/.95-t/9.)*6.2831853);\n float c=sin((dot(p,vec2(.6,-.8))/.58-t/13.)*6.2831853+s*.9);\n float k=sin((dot(p,vec2(-.29,.96))/.36+t/17.)*6.2831853);\n return vec3(smoothstep(.3,.9,.5+.5*(s*.5+c*.35+k*.15)));\n }\n // The kit's background scenes. Each starts a little way in, so a reduced-motion still is already composed.\n float t=uTime+40.,px=uCell.y/uResolution.y*uScale;\n if(uScene==6){\n // Caustics: light focused by a moving water surface. Two layers of warped sine waves drift against each other; each draws\n // smooth filaments along its zero line, about a character wide. Where they cross the light lifts a little, never to a blot.\n float tt=t*.12,a=0.,b=0.;\n for(int l=0;l<2;l++){\n float f=float(l),sc=5.4+f*2.4;\n vec2 q=(l==0?p:mat2(.8,-.6,.6,.8)*p)*sc;\n q+=vec2(sin(q.y*.45+tt*(1.+f*.3)),cos(q.x*.4-tt*(.8+f*.4)))*1.3;\n float v=sin(q.x+1.4*sin(q.y*.7+tt))+sin(q.y*1.1+1.2*sin(q.x*.8-tt*1.3))*.9;\n float wv=max(fwidth(v),1e-4);\n float line=(1.-smoothstep(.2,1.5,abs(v)/wv))*(l==0?.78:.62)+exp(-abs(v)/(wv*5.))*.16;\n if(l==0)a=line;else b=line;\n }\n float pulse=.85+.15*sin(tt*3.+p.x*1.7-p.y*1.1);\n float light=max(a,b)+.3*min(a,b);\n return vec3(clamp(light*light*pulse,0.,.78));\n }\n if(uScene==7){\n // Contour: a slow terrain read as survey lines about a character wide at any size; every fifth is an index line.\n float tt=t*.02;\n vec2 q=p*1.15+vec2(tt,-tt*.6);\n float h=noise(q)*.62+noise(q*2.07+3.1)*.27+noise(q*4.3-tt+7.)*.11;\n h+=.08*sin(tt*2.+p.x*.8);\n float k=h*13.,w=max(fwidth(k),1e-4),d=abs(fract(k+.5)-.5)/w;\n float major=mod(floor(k+.5),5.)<.5?1.:0.;\n return vec3((1.-smoothstep(.35,1.25-major*.25,d))*mix(.55,1.,major));\n }\n if(uScene==8){\n // Aurora: three curtains at different distances hang from the top. Far ones sit higher and dimmer; the nearest is tallest\n // and brightest. Each folds slowly and is brightest along its lower hem, fading upward. The rays are set per character\n // column, so the curtains read as vertical strokes at any stage size, from a small card to a phone.\n float tt=t*.05,a=0.,cw=uCell.x/uResolution.x;\n float col=floor(uv.x/cw+.5);\n for(int n=0;n<3;n++){\n float f=float(n),near=f/2.;\n float x=p.x*(1.3-near*.4)+f*3.7;\n float hem=-.28+near*.3+.16*sin(x*1.3+tt*(.9+f*.25)+f*2.)+.045*sin(x*3.4-tt*1.5+f);\n float d=hem-p.y;\n float body=d>0.?exp(-d/(.14+near*.26))*(.45+.55*exp(-d/.03)):exp(-d*d/.0002);\n float fold=.5+.5*sin(x*2.1+tt*.9+f*1.7+.7*sin(x*.8-tt*.6));\n float ray=mix(hash(vec2(col,f*7.1)),noise(vec2(col*.18+f*9.,tt*.7+f)),.55);\n float layer=clamp(body*(.1+.9*fold*fold)*(.2+.8*ray)*(.4+near*.6)*4.2,0.,1.);\n a=1.-(1.-a)*(1.-layer);\n }\n return vec3(smoothstep(.12,.9,a));\n }\n if(uScene==9){\n // Ripple: still water. Drops land here and there, each a few rings that widen and fade; the pointer drops its own.\n float tone=0.,g=.72;\n vec2 q=p/g,id=floor(q);\n for(int j=-1;j<=1;j++)for(int i=-1;i<=1;i++){\n vec2 c=id+vec2(i,j),h=vec2(hash(c),hash(c+7.3));\n float period=5.+h.x*5.,age=fract(t*.3/period*4.+h.y);\n vec2 at=(c+.2+.6*h)*g;\n float d=length(p-at),r=age*.62;\n float rings=max(0.,cos((d-r)*34.))*exp(-pow((d-r)/.11,2.));\n tone+=rings*pow(1.-age,1.8)*smoothstep(0.,.06,age)*(.7+.3*h.x);\n }\n return vec3(clamp(tone*1.25,0.,1.));\n }\n if(uScene==10){\n // Halo: a slow breathing corona that frames the content, its rays turning. The ring fits the stage: wide on a desktop\n // hero, tall on a phone, so the whole halo stays on screen; the middle stays empty for a headline.\n vec2 r=vec2(min(.46,aspect*.4),min(.34,.36/max(aspect,.01)*.5+.2));\n vec2 e=p/r;\n float d=length(e),a=atan(e.y,e.x),tt=t*.07,k=min(r.x,r.y);\n float breathe=1.+.04*sin(tt*3.1);\n float rays=.5+.5*noise(vec2(a*3.2+tt,tt*.5))*(.6+.4*noise(vec2(a*7.-tt*1.2,3.+tt*.4)));\n float s=(d-breathe)*k;\n float rim=exp(-pow(s/.03,2.));\n float corona=exp(-max(0.,s)/(.1+.08*rays))*smoothstep(-.04,.015,s)*rays*smoothstep(.36,.12,s);\n return vec3(clamp(rim*(.55+.45*rays)+corona*.85,0.,1.));\n }\n if(uScene==11){\n // Interference: two ring grids from slowly orbiting centres. Where they cross, broad moire bands open and close.\n float tt=t*.05;\n vec2 a=vec2(-.3+.12*sin(tt),.07*cos(tt*1.3)),b=vec2(.3+.1*cos(tt*.8),-.06*sin(tt*1.1));\n float f=6.2831853/max(px*4.6,.004);\n float m=cos(length(p-a)*f)+cos(length(p-b)*f);\n return vec3(smoothstep(.7,2.,m));\n }\n if(uScene==12){\n // Mesh: four soft lights on slow Lissajous paths, a gradient mesh written in characters.\n float tt=t*.07,m=0.;\n for(int n=0;n<4;n++){\n float f=float(n)*1.7;\n vec2 c=vec2(.66*sin(tt*(.7+f*.13)+f),.34*cos(tt*(.9-f*.07)+f*1.3));\n float s=.3+.07*sin(tt+f);\n m+=exp(-dot(p-c,p-c)/(s*s))*(.8-float(n)*.1);\n }\n return vec3(smoothstep(.06,1.1,m));\n }\n if(uScene==13){\n // Cascade: streaks fall in three depths. Far ones are frequent, faint, short and slow; near ones rare, long, bright and\n // quick. Each has a bright head and a tail that fades behind it, and a column can carry two streaks at once.\n float tone=0.,cw=uCell.x/uResolution.x,ch=uCell.y/uResolution.y;\n float col=floor(uv.x/cw+.5);\n for(int n=0;n<3;n++){\n float f=float(n);\n for(int k=0;k<2;k++){\n float seed=f*13.1+float(k)*41.7,h=hash(vec2(col,seed));\n if(h<1.-(.5-f*.15))continue;\n float speed=(.045+f*.07)*(.75+.5*hash(vec2(col,seed+2.)));\n float tail=.12+f*.16,y=fract(t*speed+hash(vec2(col,seed+5.)))*(1.+tail*2.)-tail;\n float d=y-uv.y;\n if(d<0.||d>tail)continue;\n float head=d<ch*1.2?1.:0.;\n tone=max(tone,max(head*(.55+f*.22),pow(1.-d/tail,1.7)*(.28+f*.3)));\n }\n }\n return vec3(clamp(tone,0.,1.));\n }\n if(uScene==14){\n // Constellation: points wander in their own cells; neighbours close enough are linked by fine lines. Each point is a\n // bright core in a soft halo, so it reads at card size as well as full width.\n float g=.23,tt=t*.18;\n vec2 q=p/g,id=floor(q);\n vec2 pts[9];\n for(int j=-1;j<=1;j++)for(int i=-1;i<=1;i++){\n vec2 c=id+vec2(i,j);\n float h=hash(c),k=hash(c+3.7);\n pts[(j+1)*3+i+1]=c+.5+.36*vec2(sin(tt*(.6+h)+h*6.28),cos(tt*(.5+k)+k*6.28));\n }\n float line=0.,star=0.,lw=max(px/g,.02);\n for(int n=0;n<9;n++){\n vec2 e=q-pts[n];\n float d2=dot(e,e),tw=.8+.2*sin(tt*3.+float(n)*1.7);\n star=max(star,max(exp(-d2/(lw*lw*1.6)),.38*exp(-d2/(lw*lw*7.)))*tw);\n for(int m=n+1;m<9;m++){\n vec2 a=pts[n],ba=pts[m]-a;\n float len=length(ba);\n if(len>1.35)continue;\n float hh=clamp(dot(q-a,ba)/dot(ba,ba),0.,1.);\n float d=length(q-a-ba*hh);\n line=max(line,(1.-smoothstep(lw*.3,lw*.75,d))*smoothstep(1.35,.6,len)*.72);\n }\n }\n return vec3(clamp(max(line,star),0.,1.));\n }\n return vec3(0.);\n}\n// Hover scope: 1 where the pointer response may act. The map holds the source's soft subject coverage in alpha.\nfloat hoverScope(vec2 uv){\n if(uScopeMode<.5||uScene!=0)return 1.;\n vec2 s=uv*uSourceMap.xy+uSourceMap.zw;\n float c=(s.x<0.||s.y<0.||s.x>1.||s.y>1.)?0.:texture(uScope,s).a;\n return uScopeMode<1.5?c:1.-c;\n}\nvoid main(){\n vec2 cell=floor(gl_FragCoord.xy);\n vec2 uv=(cell+.5)*uCell/uResolution;\n float aspect=uResolution.x/uResolution.y;\n float hs=hoverScope(uv);\n vec4 fluid=vec4(0.);\n // lift: signed tone change. The solver's flow brightens one side of each eddy and opens the other into gaps.\n float lift=0.,wake=0.,bend=1.,swirl=0.,speed=0.;\n if(uFluidOn>.5){\n vec4 raw=texture(uFluid,vec2(uv.x,1.-uv.y));\n if(uFluidMode>.5){\n vec2 v=raw.xy*uFluidTexel*vec2(aspect,1.)*hs;\n fluid=vec4(v,0.,1.);\n swirl=clamp(dot(v,vec2(.4,.65))*uGlow*.32,-.65,.65);\n speed=clamp(length(v)*uGlow*.055,0.,.38);\n bend=.4;\n } else {\n fluid=decodeFluid(raw);\n fluid.xyz*=hs;\n wake=clamp(fluid.z*uGlow,0.,1.);\n lift=wake*.55;\n }\n }\n vec2 drift=uDrift*.006*vec2(sin(uv.y*5.3+uTime*.6),cos(uv.x*4.1-uTime*.5));\n vec2 sampleAt=uv-vec2(fluid.x/aspect,-fluid.y)*uRefraction*bend+drift;\n float spot=0.;\n if(uHoverMode==4||uHoverMode==5){\n vec2 d=(uv-uLight.xy)*vec2(aspect,1.);\n float q2=dot(d,d)/(uLightRadius*uLightRadius*2.2);\n // Loupe: flat-topped zoom with a soft rim. Reveal: a soft spot in the source's colours.\n if(uHoverMode==4) sampleAt-=(uv-uLight.xy)*exp(-q2*q2)*.45*uLight.z*min(1.,uLightGain*1.6)*hs;\n else spot=exp(-q2*1.6)*uLight.z*min(1.,uLightGain*1.6)*hs;\n }\n vec3 rgb,glow=vec3(0.);\n if(uScene==0){\n vec2 s=sampleAt*uSourceMap.xy+uSourceMap.zw;\n bool inside=!(s.x<0.||s.y<0.||s.x>1.||s.y>1.);\n rgb=inside?textureLod(uSource,s,uLod).rgb:vec3(0.);\n if(uBackdrop>0.){\n vec2 b=(uv-vec2(fluid.x/aspect,-fluid.y)*uRefraction*bend*.5)*uSourceMap.xy+uSourceMap.zw;\n glow=(b.x<0.||b.y<0.||b.x>1.||b.y>1.)?vec3(0.):textureLod(uSource,b,uLod+3.).rgb*uBackdrop;\n }\n } else rgb=generated(sampleAt,aspect);\n float tone=dot(rgb,vec3(.2126,.7152,.0722));\n tone=clamp((tone-uLevels.x)/max(uLevels.y-uLevels.x,.01),0.,1.);\n tone=clamp((tone-.5)*uContrast+.5+uBrightness,0.,1.);\n tone=pow(tone,1./uGamma);\n if(uInvert>.5)tone=1.-tone;\n float flick=0.,trailFold=0.;\n // Reveal: under the spot the characters take the source's own colour and a little more ink.\n if(spot>0.)lift=spot*.22;\n if(uHoverMode==2){\n // Lantern: a soft light and its fading tail lift the characters they pass. Nothing moves the image.\n vec2 ap=vec2(aspect,1.),d=(uv-uLight.xy)*ap;\n float r2=uLightRadius*uLightRadius,glowL=uLight.z*exp(-dot(d,d)/r2);\n for(int i=0;i<12;i++){vec2 e=(uv-uTrail[i].xy)*ap;glowL+=uTrail[i].z*exp(-dot(e,e)/(r2*.55));}\n glowL=min(glowL,1.)*hs;\n float grain=fract(sin(dot(cell,vec2(12.9898,78.233)))*43758.5453);\n lift=glowL*uLightGain*(.7+.6*grain);\n wake=glowL*.4;\n // A few letters at the light's rim step up the ramp and back, as if being retyped.\n flick=uFlicker*step(.9,fract(grain*13.7+floor(uClock*7.+grain*5.)*.37))*glowL*(1.-glowL)*4.;\n }\n if(uHoverMode==3){\n // Trail: the studio's ink field, as a 16-bit density. Sparse marks fill in, dense marks open up.\n vec4 ink=texture(uTrailMap,uv);\n float density=(ink.r*65280.+ink.g*255.)/65535.*uTrailAmount;\n float t=clamp(density/.38,0.,1.);\n trailFold=t*t*(3.-2.*t)*hs;\n }\n if(uFluidMode>.5&&uHoverMode==1){\n // Dark ground: any motion lights the characters. Lit ground: the flow lights one side of each eddy and opens the other.\n // A little cell-to-cell grain keeps the lit area a shimmer of letters rather than a solid block.\n float grain=fract(sin(dot(cell,vec2(12.9898,78.233)))*43758.5453);\n lift=mix(abs(swirl)*.5+speed,swirl+speed*.35,smoothstep(.12,.55,tone))*(.65+.7*grain);\n wake=clamp(lift*1.6,0.,1.);\n }\n tone=clamp(tone+lift,0.,1.);\n tone+=(1.-2.*tone)*trailFold;\n // Pulses: rings sent by the interface (field.pulse()), e.g. on a save or a notification.\n for(int i=0;i<4;i++){\n if(uPulse[i].w<=0.)continue;\n float dist=length((uv-uPulse[i].xy)*vec2(aspect,1.)),front=uPulse[i].z*.95;\n float ring=exp(-pow((dist-front)/.1,2.))*uPulse[i].w*exp(-uPulse[i].z*.85);\n tone=clamp(tone+ring*.85,0.,1.);\n }\n tone*=1.-uVignette*smoothstep(.35,1.05,length((uv-.5)*vec2(min(aspect,1.8),1.)*2.));\n if(uClear.z>0.){\n // Clear zone: the field fades out around content so text above it stays readable.\n vec2 half_=uClear.zw*.5*vec2(aspect,1.),q=(uv-uClear.xy-uClear.zw*.5)*vec2(aspect,1.);\n float dz;\n if(uClearShape>.5){vec2 e=abs(q)-half_;dz=length(max(e,0.))+min(max(e.x,e.y),0.);}\n else dz=(length(q/max(half_,vec2(1e-4)))-1.)*min(half_.x,half_.y);\n tone*=smoothstep(0.,uClearFeather,dz);\n }\n // Blend: a shade between two characters takes the upper one in the share of cells a 4x4 Bayer pattern gives it.\n float level=tone*(uCount-1.),upper=fract(level)>=.5?1.:0.;\n if(uBlend>.5&&tone>.02&&tone<.98){\n ivec2 q=ivec2(mod(gl_FragCoord.xy,4.));\n upper=fract(level)>(BAYER[q.y*4+q.x]+.5)/16.?1.:0.;\n }\n float index=min(uCount-1.,floor(level)+upper+(flick>.5&&tone>.02?1.:0.));\n vec3 hue=rgb/max(max(rgb.r,rgb.g),max(rgb.b,.03));\n hue=mix(vec3(dot(hue,vec3(.2126,.7152,.0722))),hue,uSaturation);\n vec3 ink=mix(uInk*mix(1.,.3+.7*tone,uShade),clamp(hue*(.38+.62*tone),0.,1.),uSourceColor);\n vec3 lifted=uHighlightAuto>.5?ink/max(max(ink.r,ink.g),max(ink.b,.06)):uHighlight;\n ink=mix(ink,lifted,wake*.7);\n if(spot>0.)ink=mix(ink,clamp(rgb/max(max(rgb.r,rgb.g),max(rgb.b,.08))*(.45+.55*tone),0.,1.),spot);\n float underAlpha=max(uBackground.a,min(1.,max(glow.r,max(glow.g,glow.b))));\n vec3 under=min(uBackground.rgb*uBackground.a+glow,vec3(underAlpha));\n // Glyphs keep their atlas index, exact in 8 bits; the other marks keep the tone, and empty where the charset is blank.\n outInk=vec4(ink,uMark==0?index/255.:uMark==1?(tone>.003?tone:0.):index>0.?max(tone,1./255.):0.);\n outUnder=vec4(under,underAlpha);\n}`,r="#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform sampler2D uAtlas, uCells, uUnder;\nuniform vec2 uResolution, uCell, uPitch;\nuniform float uColumns, uDotScale, uSourceColor;\nuniform int uMark;\nout vec4 outColor;\nconst float BAYER[16]=float[16](0.,8.,2.,10.,12.,4.,14.,6.,3.,11.,1.,9.,15.,7.,13.,5.);\n// The Studio's print defaults: screen angle -35deg, roughness .35, seed 7, registration .2 and its coral second ink.\nconst vec2 DIR=vec2(.81915,-.57358);\nconst float ROUGH=.35,SEED=7.;\nconst vec3 SECOND=vec3(.925,.404,.322);\nfloat hash(vec2 p){p=fract(p*vec2(123.34,456.21));p+=dot(p,p+45.32);return fract(p.x*p.y);}\n// Coverage of a signed distance given in device pixels.\nfloat cover(float d){return clamp(.5-d,0.,1.);}\nfloat box(vec2 p,vec2 lo,vec2 hi){vec2 a=clamp(p-lo,0.,1.)*clamp(hi-p,0.,1.);return a.x*a.y;}\nfloat disc(vec2 p,vec2 c,float r){return r>.05?cover(length(p-c)-r):0.;}\nfloat ellipse(vec2 p,vec2 c,vec2 r,float a){vec2 d=p-c;d=vec2(cos(a)*d.x+sin(a)*d.y,-sin(a)*d.x+cos(a)*d.y);float k=length(d/r);return cover((k-1.)*min(r.x,r.y));}\n// World-anchored parallel cuts across direction d: period and width in cell heights, so lines run on from cell to cell.\nfloat cuts(vec2 w,vec2 d,float period,float width,float px){\n if(width<=0.)return 0.;\n float proj=dot(vec2(-d.y,d.x),w);\n return cover((abs(fract(proj/period+.5)-.5)*period-width*.5)*px);\n}\n// Lays an ink over what is already down, multiplying where they overlap, as transparent inks do on paper.\nvoid lay(inout vec3 rgb,inout float a,vec3 c,float k){\n float next=a+k*(1.-a);\n rgb=next>0.?(rgb*a*(1.-k)+mix(c,rgb*c,a)*k)/next:c;\n a=next;\n}\nvoid main(){\n vec2 frag=vec2(gl_FragCoord.x,uResolution.y-gl_FragCoord.y);\n // The pitch is the atlas cell, or a fractional one under cellFit 'fill', where each glyph sits centred in its stretched cell.\n vec2 cell=floor(frag/uPitch);\n vec4 ink=texelFetch(uCells,ivec2(cell),0),under=texelFetch(uUnder,ivec2(cell),0);\n vec2 local=frag-cell*uPitch;\n float coverage;\n vec3 rgb=ink.rgb;\n if(uMark==0){\n float index=floor(ink.a*255.+.5);\n ivec2 tile=ivec2(int(mod(index,uColumns)),int(floor(index/uColumns)));\n vec2 texel=floor(local-floor((uPitch-uCell)*.5));\n coverage=all(greaterThanEqual(texel,vec2(0.)))&&all(lessThan(texel,uCell))?texelFetch(uAtlas,tile*ivec2(uCell)+ivec2(texel),0).a:0.;\n } else if(uMark==1){\n // Halftone: dot area follows tone, so midtones read true; edges are antialiased to one device pixel.\n float r=sqrt(ink.a)*min(uPitch.x,uPitch.y)*.5*uDotScale;\n coverage=ink.a>.003?clamp(r-length(local-uPitch*.5)+.5,0.,1.):0.;\n } else if(ink.a<=0.){\n coverage=0.;\n } else {\n float tone=ink.a,side=min(uPitch.x,uPitch.y);\n vec2 q=local/uPitch,c=uPitch*.5,p=local+.5;\n // Tiles fade with the tone in one ink, as the Studio's do; in source colour the colour already carries it.\n float fade=uSourceColor>.5?1.:tone,gap=max(.5,uPitch.x*.06),grain=hash(cell+SEED);\n vec2 w=(cell+q)*uPitch/uPitch.y;\n if(uMark==2)coverage=fade;\n else if(uMark==3)coverage=box(p,vec2(0.),uPitch-gap)*fade;\n else if(uMark==4){\n // Lego: a gapped brick, lit from above, with a raised stud ringed by its shadow.\n coverage=box(p,vec2(0.),uPitch-gap)*fade;\n rgb*=1.06-.14*q.y;\n float r=side*.28,d=length(local-c)-r,lit=clamp(dot(c-local,vec2(.6,.8))/r,-1.,1.);\n rgb=mix(rgb,mix(rgb,vec3(1.),.2+.12*lit),cover(d));\n rgb=mix(rgb,rgb*.72,cover(abs(d)-max(.5,side*.04)));\n } else if(uMark==5){\n // Voxel: an isometric cube; top, left and right faces at full, .72 and .42 strength.\n float h=.5*abs(q.x-.5);\n coverage=cover(-min(q.y-h,1.-h-q.y)*uPitch.y)*cover(-min(q.x,1.-q.x)*uPitch.x);\n coverage*=mix(q.x<.5?.72:.42,1.,cover((q.y-(.5-h))*uPitch.y))*fade;\n } else if(uMark==6){\n // Disco: a gapped mirror tile, its upper facet catching light and its lower in shade.\n coverage=box(p,vec2(0.),uPitch-gap)*fade;\n rgb=q.y<.35?mix(rgb,vec3(1.),.1+grain*.25):q.y>.65?rgb*.75:rgb;\n } else if(uMark==7){\n // Dither: an ordered 4x4 Bayer screen at about five dots a cell, lit where the cell's tone passes the threshold.\n ivec2 b=ivec2(mod(floor(frag/max(1.,floor(side/5.))),4.));\n coverage=tone>(BAYER[b.y*4+b.x]+.5)/16.?1.:0.;\n } else if(uMark==8){\n // Hex: a flat-topped hexagon filling the cell.\n vec2 h=abs((local-c)/(uPitch*.49));\n coverage=cover(max(h.y-.866,h.x*.866+h.y*.5-.866)*side*.49)*fade;\n } else if(uMark==9){\n // LED: a round lamp with a soft halo and a specular glint, separated by an unlit matrix.\n float r=side*.39,d=length(local-c);\n coverage=max(cover(d-r),.3*exp(-pow(max(0.,d-r)/(side*.12),2.)))*fade;\n rgb=mix(rgb,vec3(1.),.35*disc(local,uPitch*vec2(.43,.4),side*.11));\n } else if(uMark==10){\n // CMYK: the cell's hue separated into offset cyan, magenta and yellow dots, each sized by its share of the tone. The\n // key screen carries the neutral share in the ink's own lightness, since a light ink on a dark page has no black.\n float top=max(rgb.r,max(rgb.g,rgb.b)),low=min(rgb.r,min(rgb.g,rgb.b));\n vec3 cmy=(top-rgb)/max(top,.001);\n float a=0.;vec3 col=vec3(1.);\n lay(col,a,vec3(top),disc(local,c,side*.48*sqrt(tone*low/max(top,.001))));\n lay(col,a,vec3(0.,1.,1.),disc(local,uPitch*vec2(.36,.36),side*.48*sqrt(tone*cmy.x)));\n lay(col,a,vec3(1.,0.,1.),disc(local,uPitch*vec2(.64,.36),side*.48*sqrt(tone*cmy.y)));\n lay(col,a,vec3(1.,1.,0.),disc(local,uPitch*vec2(.5,.66),side*.48*sqrt(tone*cmy.z)));\n rgb=col;coverage=a;\n } else if(uMark==11||uMark==16){\n // Stipple and pointillism: four jittered marks a cell, their size following the tone.\n coverage=0.;vec3 col=rgb;\n for(int m=0;m<4;m++){\n vec2 o=vec2(float(m%2),float(m/2));\n float j=hash(cell*2.+o+SEED),jy=hash(cell+o*11.+SEED+1.);\n vec2 at=((o+.5)/2.+(vec2(j,jy)-.5)*ROUGH*.28)*uPitch;\n float r=min(min(min(at.x,uPitch.x-at.x),min(at.y,uPitch.y-at.y)),side*min(.245,.21*sqrt(tone)*(1.-ROUGH*j*.35)));\n float k=uMark==11?disc(local,at,r):ellipse(local,at,vec2(r,r*.64),j*3.14159);\n if(uMark==16&&k>coverage)col=uSourceColor>.5?clamp(rgb+(j-.5)*ROUGH*.25*vec3(1.,-.4,-1.),0.,1.):rgb*(1.+(j-.5)*ROUGH*.5);\n coverage=max(coverage,k);\n }\n rgb=col;\n } else if(uMark==12||uMark==13){\n // Engraving and crosshatch: parallel cuts whose weight follows the tone; crossings join only in the darker tones.\n float cv=tone*(1.-ROUGH*grain*.3),px=uPitch.y;\n coverage=cuts(w,DIR,.5,min(.47,.36*cv),px);\n if(uMark==13){\n coverage=max(coverage,cuts(w,vec2(-DIR.y,DIR.x),.5,min(.47,.36*max(0.,cv*1.5-.3)),px)*step(.2,cv));\n coverage=max(coverage,cuts(w,normalize(DIR+vec2(-DIR.y,DIR.x)),.5,min(.47,.36*max(0.,cv*2.-1.2)),px)*step(.6,cv));\n }\n } else if(uMark==14){\n // Woodblock: broad carved bands in five stepped weights, their edges wavering along the grain.\n float cv=ceil(tone*(1.-ROUGH*grain*.3)*5.)/5.,width=min(.94,.72*cv);\n float proj=dot(vec2(-DIR.y,DIR.x),w),line=floor(proj+.5),along=dot(DIR,w);\n float cut=sin(along*5.3+line*1.9+SEED)*.5+sin(along*13.1+line)*.25;\n coverage=cover((abs(proj-line)-width*.5*(1.+ROUGH*cut*.5))*uPitch.y);\n } else if(uMark==15){\n // Risograph: two offset screens, the main ink and the coral second ink, misregistered along the screen angle.\n float split=uSourceColor>.5?clamp(.5+(rgb.r-rgb.b)*.5,0.,1.):.5,r=side*min(.48,.44*sqrt(tone));\n float a=0.;vec3 col=rgb;\n lay(col,a,rgb,disc(local,c,r*sqrt(.35+(1.-split)*.65)));\n lay(col,a,SECOND,disc(local,c+DIR*.2*.38*side,r*sqrt(.3+split*.7)*(1.-ROUGH*hash(cell+SEED+13.)*.3)));\n rgb=col;coverage=a;\n } else coverage=0.;\n }\n outColor=vec4(rgb*coverage+under.rgb*(1.-coverage),coverage+under.a*(1.-coverage));\n}",i="#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform vec2 uTexel;\nout vec4 outColor;\nvec2 here(){return gl_FragCoord.xy*uTexel;}\n",o=i+"\nuniform sampler2D uVelocity;\nuniform vec2 uFrom, uTo, uForce;\nuniform float uAspect, uRadius;\nfloat segment(vec2 p,vec2 a,vec2 b){vec2 pa=p-a,ba=b-a;float h=clamp(dot(pa,ba)/max(dot(ba,ba),1e-8),0.,1.);return length(pa-ba*h);}\nvoid main(){\n vec2 uv=here(),scale=vec2(uAspect,1.);\n float d=segment(uv*scale,uFrom*scale,uTo*scale);\n outColor=vec4(texture(uVelocity,uv).xy+uForce*exp(-d*d/(uRadius*uRadius)),0.,1.);\n}",a=i+"\nuniform sampler2D uVelocity;\nvoid main(){\n vec2 uv=here();\n float l=texture(uVelocity,uv-vec2(uTexel.x,0.)).y,r=texture(uVelocity,uv+vec2(uTexel.x,0.)).y;\n float t=texture(uVelocity,uv+vec2(0.,uTexel.y)).x,b=texture(uVelocity,uv-vec2(0.,uTexel.y)).x;\n outColor=vec4(.5*(r-l-t+b),0.,0.,1.);\n}",l=i+"\nuniform sampler2D uVelocity, uCurl;\nuniform float uStrength, uDt;\nvoid main(){\n vec2 uv=here();\n float l=texture(uCurl,uv-vec2(uTexel.x,0.)).x,r=texture(uCurl,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uCurl,uv+vec2(0.,uTexel.y)).x,b=texture(uCurl,uv-vec2(0.,uTexel.y)).x,c=texture(uCurl,uv).x;\n vec2 force=.5*vec2(abs(t)-abs(b),abs(r)-abs(l));\n force=force/(length(force)+1e-4)*uStrength*c;\n force.y=-force.y;\n outColor=vec4(clamp(texture(uVelocity,uv).xy+force*uDt,-1000.,1000.),0.,1.);\n}",s=i+"\nuniform sampler2D uVelocity;\nvoid main(){\n vec2 uv=here(),c=texture(uVelocity,uv).xy;\n float l=texture(uVelocity,uv-vec2(uTexel.x,0.)).x,r=texture(uVelocity,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uVelocity,uv+vec2(0.,uTexel.y)).y,b=texture(uVelocity,uv-vec2(0.,uTexel.y)).y;\n if(uv.x-uTexel.x<0.)l=-c.x;\n if(uv.x+uTexel.x>1.)r=-c.x;\n if(uv.y+uTexel.y>1.)t=-c.y;\n if(uv.y-uTexel.y<0.)b=-c.y;\n outColor=vec4(.5*(r-l+t-b),0.,0.,1.);\n}",c=i+"\nuniform sampler2D uSource;\nuniform float uAmount;\nvoid main(){outColor=vec4(texture(uSource,here()).x*uAmount,0.,0.,1.);}",u=i+"\nuniform sampler2D uPressure, uDivergence;\nvoid main(){\n vec2 uv=here();\n float l=texture(uPressure,uv-vec2(uTexel.x,0.)).x,r=texture(uPressure,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uPressure,uv+vec2(0.,uTexel.y)).x,b=texture(uPressure,uv-vec2(0.,uTexel.y)).x;\n outColor=vec4((l+r+b+t-texture(uDivergence,uv).x)*.25,0.,0.,1.);\n}",h=i+"\nuniform sampler2D uPressure, uVelocity;\nvoid main(){\n vec2 uv=here();\n float l=texture(uPressure,uv-vec2(uTexel.x,0.)).x,r=texture(uPressure,uv+vec2(uTexel.x,0.)).x;\n float t=texture(uPressure,uv+vec2(0.,uTexel.y)).x,b=texture(uPressure,uv-vec2(0.,uTexel.y)).x;\n outColor=vec4(texture(uVelocity,uv).xy-vec2(r-l,t-b),0.,1.);\n}",f=i+"\nuniform sampler2D uVelocity;\nuniform float uDt, uDissipation;\nvoid main(){\n vec2 uv=here();\n vec2 back=uv-uDt*texture(uVelocity,uv).xy*uTexel;\n outColor=vec4(texture(uVelocity,back).xy/(1.+uDissipation*uDt),0.,1.);\n}";var d=new Set,m=0,p=0,g=null,v=[],x=0,y=1,E=0,w=0;function b(e){m=0,x&&e>x&&(v.push(e-x),v.length>120&&v.shift()),x=e,p=performance.now();const t=[...d];d.clear();for(const n of t)try{n(e)}catch(e){"undefined"!=typeof console&&console.error(e)}ie?.endFrame(e);const n=performance.now()-p;if(E=.9*E+.1*n,e-w>500){w=e;const t=A(),n=!!ie?.overloaded;(E>.5*t||n)&&y<3?y++:E<.2*t&&!n&&y>1&&y--}d.size||(x=0)}var T=()=>y;function M(e){d.add(e),m&&g!==requestAnimationFrame&&(m=0),m||(g=requestAnimationFrame,m=requestAnimationFrame(b))}function R(e){d.delete(e),!d.size&&m&&(cancelAnimationFrame(m),m=0,x=0)}function A(){if(v.length<20)return 1e3/60;const e=[...v].sort((e,t)=>e-t);return Math.min(1e3/60,Math.max(1e3/360,e[Math.floor(.2*e.length)]))}var F=new Set,k=new Set,S=new Set,_=new Set,L=new Set,D=!1,P=null,C=null,U=null,I=null,B=e=>{let t=null;for(const n of F){if(n.target===window){(!n.near||n.near()||n.inside)&&n.move(e);continue}t??(t=e.composedPath());t.includes(n.target)?(n.inside=!0,n.move(e)):n.inside&&(n.inside=!1,n.leave())}},G=()=>{for(const e of F)e.inside=!1,e.leave()},N=()=>{for(const e of[...k])e()},X=()=>{for(const e of[...S])e()},q=()=>{for(const e of[..._])e()},H=e=>{for(const t of[...L])t(e)};function z(){const e=F.size+k.size+S.size+_.size+L.size>0;if("undefined"==typeof document)return;if(P!==document&&(D=!1,P=document,C=U=null,I=null),e===D)return;D=e;const t=e?"addEventListener":"removeEventListener";if("undefined"!=typeof window&&(window[t]?.("pointermove",B,{capture:!0,passive:!0}),window[t]?.("pointerdown",B,{capture:!0,passive:!0})),document[t]?.("pointerleave",G),document[t]?.("visibilitychange",N),("undefined"==typeof document?void 0:document.fonts)?.[t]?.("loadingdone",H),C??(C="function"==typeof matchMedia?matchMedia("(prefers-reduced-motion: reduce)"):null),U??(U="function"==typeof matchMedia?matchMedia("(prefers-color-scheme: dark)"):null),C?.[t]?.("change",X),U?.[t]?.("change",q),e){I??(I="function"==typeof MutationObserver?new MutationObserver(q):null);for(const e of[document.documentElement,document.body])e&&I?.observe(e,{attributes:!0,attributeFilter:["class","data-theme","data-mode","style"]})}else I?.disconnect()}var V=(e,t)=>(e.add(t),z(),()=>{e.delete(t)&&z()});function O(e){const t=e.target;if("undefined"==typeof window||t===window||"undefined"==typeof document)return V(F,e);const n=t,r=n.getRootNode?.();if(n.ownerDocument===document&&(!r||r===document))return V(F,e);const i=e.move,o=()=>e.leave();return n.addEventListener("pointermove",i,{passive:!0}),n.addEventListener("pointerdown",i,{passive:!0}),n.addEventListener("pointerleave",o),()=>{n.removeEventListener("pointermove",i),n.removeEventListener("pointerdown",i),n.removeEventListener("pointerleave",o)}}var j=e=>V(k,e),W=e=>V(S,e),Y=new Map,K=null,$=new Map,Q=e=>t=>{for(const n of t)for(const t of[...e.get(n.target)??[]])t(n)},J=(e,t,n)=>{const r=e.get(t);return r?(r.add(n),!1):(e.set(t,new Set([n])),!0)},Z=(e,t,n)=>{const r=e.get(t);return!(!r?.delete(n)||r.size)&&(e.delete(t),!0)};function ee(e,t){return"function"!=typeof ResizeObserver?()=>{}:(K??(K=new ResizeObserver(Q(Y))),J(Y,e,t)?K.observe(e):queueMicrotask(()=>{Y.get(e)?.has(t)&&t({target:e})}),()=>{Z(Y,e,t)&&K?.unobserve(e),Y.size||(K?.disconnect(),K=null)})}var te=268435456,ne=[1,.85,.7,.58,.5],re=class{constructor(){this.lost=!1,this.level=0,this.programs=new Map,this.atlases=new Map,this.vertex=null,this.vao=null,this.clients=new Set,this.parallel=null,this.timer=null,this.queries=[],this.open=null,this.drew=!1,this.gpuMs=[],this.cpuMs=[],this.changedAt=0,this.lostTimer=0,this.renderer="",this.overloaded=!1,this.onLost=e=>{e.preventDefault(),this.lost=!0,this.reset();for(const e of[...this.clients])e.lost();clearTimeout(this.lostTimer),this.lostTimer=setTimeout(()=>{if(this.lost){this.canvas.removeEventListener?.("webglcontextlost",this.onLost),this.canvas.removeEventListener?.("webglcontextrestored",this.onRestored);try{this.create()}catch{return}this.restored()}},1e3)},this.onRestored=()=>{clearTimeout(this.lostTimer),this.lost=!1,this.restored()},this.idleTimer=0,this.create()}create(){let e=null,t=null;const i={alpha:!0,antialias:!1,depth:!1,stencil:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!0,powerPreference:"high-performance"};if("undefined"!=typeof document&&(e=document.createElement("canvas"),t=e.getContext("webgl2",i)),!t&&"function"==typeof OffscreenCanvas)try{e=new OffscreenCanvas(1,1),t=e.getContext("webgl2",i)}catch{t=null}if(!t||!e)throw new Error("WebGL2 is not available for the glyph field.");this.canvas=e,this.gl=t,this.lost=!1,e.width=e.height=1,this.parallel=t.getExtension("KHR_parallel_shader_compile"),this.timer=t.getExtension("EXT_disjoint_timer_query_webgl2");const o=t.getExtension("WEBGL_debug_renderer_info");this.renderer=String(t.getParameter(o?o.UNMASKED_RENDERER_WEBGL:t.RENDERER)??""),e.addEventListener?.("webglcontextlost",this.onLost),e.addEventListener?.("webglcontextrestored",this.onRestored);const a=!t.getExtension("EXT_color_buffer_float")&&!t.getExtension("EXT_color_buffer_half_float");this.program(n(a)),this.program(r)}restored(){for(const e of[...this.clients])e.restored()}reset(){this.programs.clear(),this.atlases.clear(),this.vertex=null,this.vao=null,this.queries=[],this.open=null,this.gpuMs=[],this.cpuMs=[]}join(e){this.clients.add(e),clearTimeout(this.idleTimer)}leave(e){this.clients.delete(e),this.clients.size?this.fit():(this.lost||(this.canvas.width=this.canvas.height=1,this.level=0),clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.clients.size||this.dispose()},3e3))}dispose(){if(clearTimeout(this.lostTimer),this.canvas.removeEventListener?.("webglcontextlost",this.onLost),this.canvas.removeEventListener?.("webglcontextrestored",this.onRestored),!this.lost)try{this.gl.getExtension("WEBGL_lose_context")?.loseContext()}catch{}this.reset(),ie===this&&(ie=null)}program(e){const t=this.programs.get(e);if(t)return t;const n=this.gl,r=(e,t)=>{const r=n.createShader(e);return n.shaderSource(r,t),n.compileShader(r),r};this.vertex??(this.vertex=r(n.VERTEX_SHADER,"#version 300 es\nvoid main(){vec2 p=vec2((gl_VertexID<<1)&2,gl_VertexID&2);gl_Position=vec4(p*2.-1.,0.,1.);}"));const i=n.createProgram(),o=r(n.FRAGMENT_SHADER,e);n.attachShader(i,this.vertex),n.attachShader(i,o),n.linkProgram(i);const a={program:i,locations:null,fragment:o};return this.programs.set(e,a),a}linked(e,t=!1){if(e.locations)return!0;const n=this.gl;if(!t&&this.parallel&&!n.getProgramParameter(e.program,this.parallel.COMPLETION_STATUS_KHR))return!1;if(!n.getProgramParameter(e.program,n.LINK_STATUS)){if(n.isContextLost())return!1;throw new Error(e.fragment&&n.getShaderInfoLog(e.fragment)||n.getProgramInfoLog(e.program)||"Glyph field program failed to link.")}const r={};for(let t=n.getProgramParameter(e.program,n.ACTIVE_UNIFORMS)-1;t>=0;t--){const i=n.getActiveUniform(e.program,t).name.replace(/\[0\]$/,"");r[i]=n.getUniformLocation(e.program,i)}return e.locations=r,!0}get canCompileInParallel(){return!!this.parallel}vertexArray(){return this.vao??(this.vao=this.gl.createVertexArray())}atlas(e,t,n){let r=this.atlases.get(e);if(r)r.refs||(this.atlases.delete(e),this.atlases.set(e,r));else{const n=this.gl,i=n.createTexture();n.bindTexture(n.TEXTURE_2D,i);for(const[e,t]of[[n.TEXTURE_MIN_FILTER,n.NEAREST],[n.TEXTURE_MAG_FILTER,n.NEAREST],[n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE],[n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE]])n.texParameteri(n.TEXTURE_2D,e,t);r={key:e,texture:i,refs:0,final:!1,users:new Set,bytes:0},this.atlases.set(e,r),this.paintAtlas(r,t)}return r.refs++,r.users.add(n),r}hasAtlas(e){return this.atlases.has(e)}paintAtlas(e,t){const n=this.gl,{image:r,final:i}=t();n.bindTexture(n.TEXTURE_2D,e.texture),n.pixelStorei(n.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),n.pixelStorei(n.UNPACK_FLIP_Y_WEBGL,!1),n.texImage2D(n.TEXTURE_2D,0,n.RGBA8,n.RGBA,n.UNSIGNED_BYTE,r),e.bytes=r.width*r.height*4,e.final=i;for(const t of[...e.users])t()}releaseAtlas(e,t){e&&e.users.delete(t)&&(--e.refs>0||this.evictAtlases())}evictAtlases(){const e=[...this.atlases.values()].filter(e=>!e.refs);let t=e.length-32;for(const n of e){if(t<=0&&!this.overBudget)break;t--,this.atlases.delete(n.key),this.lost||this.gl.deleteTexture(n.texture)}}fit(){if(this.lost)return;let e=1,t=1;for(const n of this.clients){const[r,i]=n.size();e=Math.max(e,r),t=Math.max(t,i)}const n=this.canvas,r=e=>256*Math.ceil(e/256);n.width*n.height>r(e)*r(t)*2&&(n.width=r(e),n.height=r(t))}get bytes(){let e=this.canvas.width*this.canvas.height*4*2;for(const t of this.clients)e+=t.bytes();for(const t of this.atlases.values())e+=t.bytes;return e}get overBudget(){return this.bytes>te}get roomy(){return this.bytes<228170137.6}begin(e,t){const n=this.canvas;if(n.width<e||n.height<t){const r=e=>256*Math.ceil(e/256);n.width=Math.max(n.width,r(e)),n.height=Math.max(n.height,r(t))}if(!this.drew&&(this.drew=!0,this.timer&&!this.open&&this.queries.length<4)){const e=this.gl.createQuery();e&&(this.gl.beginQuery(this.timer.TIME_ELAPSED_EXT,e),this.open=e)}}present(e,t,n){e.globalCompositeOperation="copy",e.imageSmoothingEnabled=!1,e.drawImage(this.canvas,0,this.canvas.height-n,t,n,0,0,t,n)}endFrame(e){if(this.lost)return void(this.drew=!1);const t=this.gl,n=this.timer;if(this.drew&&(this.cpuMs.push(performance.now()-p),this.cpuMs.length>60&&this.cpuMs.shift(),n&&this.open&&(t.endQuery(n.TIME_ELAPSED_EXT),this.queries.push({query:this.open,frame:e}),this.open=null)),this.drew=!1,n){const e=t.getParameter(n.GPU_DISJOINT_EXT);for(;this.queries.length&&t.getQueryParameter(this.queries[0].query,t.QUERY_RESULT_AVAILABLE);){const{query:n}=this.queries.shift();e||(this.gpuMs.push(t.getQueryParameter(n,t.QUERY_RESULT)/1e6),this.gpuMs.length>60&&this.gpuMs.shift()),t.deleteQuery(n)}}this.adapt(e)}adapt(e){const t=A(),n=this.gpuMs.length>=5&&Math.min(...this.gpuMs.slice(-5))>1.5*t,r=this.gpuMs.length>=10||n?this.gpuMs:null;let i;if(r)i=[...r].sort((e,t)=>e-t)[Math.floor(.75*r.length)]/t;else{if(v.length<30||this.cpuMs.length<10)return;const e=v.slice(-30).sort((e,t)=>e-t),n=[...this.cpuMs].sort((e,t)=>e-t)[this.cpuMs.length>>1];i=e[Math.floor(.75*e.length)]/t>1.6&&n<.5*t?1:.5}if(this.overloaded=i>.8&&this.atMinimum,e-this.changedAt<(i>.8?800:4e3))return;let o=this.level;if(i>2?o=ne.length-1:i>.8&&o<ne.length-1?o++:i<.3&&o>0&&o--,o!==this.level){this.level=o,this.changedAt=e,this.gpuMs=[],this.cpuMs=[];for(const e of[...this.clients])e.rescale()}}get scale(){return ne[this.level]}get atMinimum(){return this.level===ne.length-1}},ie=null,oe=!1;function ae(){if(ie||oe)return ie;try{ie=new re}catch{oe=!0}return ie}var le=new WeakSet,se=class{constructor(e,t){this.previous=null,this.peak=0,this.width=e,this.height=t;const n=e*t;this.pixels=new Uint8Array(4*n),this.signal=new Float32Array(n),this.offsetX=new Float32Array(n),this.offsetY=new Float32Array(n),this.driftX=new Float32Array(n),this.driftY=new Float32Array(n),this.u=new Float32Array(n),this.v=new Float32Array(n),this.ink=new Float32Array(n),this.a=new Float32Array(n),this.b=new Float32Array(n),this.c=new Float32Array(n),this.pressure=new Float32Array(n),this.pressureNext=new Float32Array(n),this.divergence=new Float32Array(n),this.curl=new Float32Array(n)}get active(){return this.peak>2e-4}clear(){for(const e 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])e.fill(0);this.previous=null,this.peak=0}leave(){this.previous=null}move(e,t,n,r=performance.now()){if(!Number.isFinite(e+t+n+r))return;e=Math.max(0,Math.min(1,e)),t=Math.max(0,Math.min(1,t)),n=Math.max(.1,Math.min(1,n));const i=this.previous;if(this.previous={x:e,y:t,time:r},!i)return;const o=(e-i.x)*(this.width-1),a=(t-i.y)*(this.height-1),l=Math.hypot(o,a);if(l<.001)return;const s=Math.min(this.width,this.height),c=r>i.time?Math.max(1/240,(r-i.time)/1e3):1/60,u=Math.min(12,l/s/c),h=1-Math.exp(-u/2.2),f=s*(.022+.075*n)*(.65+.95*h),d=Math.min(128,Math.max(1,Math.ceil(l/(.4*f)))),m=l/f*(.32+.22*h)/d,p=o/l,g=a/l,v=-g,x=p,y=l*(2+18*h)/d;for(let n=0;n<d;n++){const r=(n+.5)/d,o=(i.x+(e-i.x)*r)*(this.width-1),a=(i.y+(t-i.y)*r)*(this.height-1),l=Math.max(1,Math.floor(o-3*f)),s=Math.min(this.width-2,Math.ceil(o+3*f)),c=Math.max(1,Math.floor(a-3*f)),u=Math.min(this.height-2,Math.ceil(a+3*f));for(let e=c;e<=u;e++)for(let t=l;t<=s;t++){const n=((t-o)*p+(e-a)*g)/f,r=((t-o)*v+(e-a)*x)/f,i=Math.exp(-n*n*.65-r*r*1.7),l=e*this.width+t;this.ink[l]=1-(1-this.ink[l])*Math.exp(-i*m);const s=1-r*r*.55,c=n*r*.7;this.u[l]=Math.max(-80,Math.min(80,this.u[l]+(p*s+v*c)*i*y)),this.v[l]=Math.max(-80,Math.min(80,this.v[l]+(g*s+x*c)*i*y))}}this.peak=1}read(e,t,n){const r=0|(t=Math.max(.5,Math.min(this.width-1.5,t))),i=0|(n=Math.max(.5,Math.min(this.height-1.5,n))),o=t-r,a=n-i,l=i*this.width+r;return(e[l]*(1-o)+e[l+1]*o)*(1-a)+(e[l+this.width]*(1-o)+e[l+this.width+1]*o)*a}sample(e,t){return this.read(this.signal,e*(this.width-1),t*(this.height-1))}displacement(e,t,n){n[0]=this.read(this.offsetX,e*(this.width-1),t*(this.height-1)),n[1]=this.read(this.offsetY,e*(this.width-1),t*(this.height-1))}step(e){if(!this.active||!Number.isFinite(e))return;let t=Math.max(0,Math.min(.05,e));const n=this.width,r=this.height;for(;t>1e-7;){const e=Math.min(1/60,t);t-=e;const i=Math.exp(-1.9*e),o=Math.exp(-3.2*e);for(let t=1;t<r-1;t++)for(let a=1;a<n-1;a++){const l=t*n+a,s=Math.max(.5,Math.min(n-1.5,a-this.u[l]*e)),c=Math.max(.5,Math.min(r-1.5,t-this.v[l]*e)),u=0|s,h=0|c,f=s-u,d=c-h,m=h*n+u,p=(1-f)*(1-d),g=f*(1-d),v=(1-f)*d,x=f*d;this.a[l]=(this.u[m]*p+this.u[m+1]*g+this.u[m+n]*v+this.u[m+n+1]*x)*i,this.b[l]=(this.v[m]*p+this.v[m+1]*g+this.v[m+n]*v+this.v[m+n+1]*x)*i,this.c[l]=(this.ink[m]*p+this.ink[m+1]*g+this.ink[m+n]*v+this.ink[m+n+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 e=1;e<r-1;e++)for(let t=1;t<n-1;t++){const r=e*n+t;this.curl[r]=.5*(this.v[r+1]-this.v[r-1]-this.u[r+n]+this.u[r-n])}for(let t=1;t<r-1;t++)for(let r=1;r<n-1;r++){const i=t*n+r,o=Math.abs(this.curl[i+1])-Math.abs(this.curl[i-1]),a=Math.abs(this.curl[i+n])-Math.abs(this.curl[i-n]),l=Math.hypot(o,a)+1e-4,s=this.curl[i]*e*10,c=Math.hypot(this.u[i],this.v[i]);this.u[i]+=a/l*s,this.v[i]-=o/l*s;const u=Math.min(1,c/(Math.hypot(this.u[i],this.v[i])+1e-6));this.u[i]*=u,this.v[i]*=u,this.divergence[i]=-.5*(this.u[i+1]-this.u[i-1]+this.v[i+n]-this.v[i-n])}this.pressure.fill(0);for(let e=0;e<4;e++){for(let e=1;e<r-1;e++)for(let t=1;t<n-1;t++){const r=e*n+t;this.pressureNext[r]=.25*(this.divergence[r]+this.pressure[r-1]+this.pressure[r+1]+this.pressure[r-n]+this.pressure[r+n])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let a=0;for(let t=1;t<r-1;t++)for(let r=1;r<n-1;r++){const i=t*n+r;this.u[i]=Math.max(-80,Math.min(80,this.u[i]-.5*(this.pressure[i+1]-this.pressure[i-1]))),this.v[i]=Math.max(-80,Math.min(80,this.v[i]-.5*(this.pressure[i+n]-this.pressure[i-n]))),this.driftX[i]+=(3.6*this.u[i]-58*this.offsetX[i]-12*this.driftX[i])*e,this.driftY[i]+=(3.6*this.v[i]-58*this.offsetY[i]-12*this.driftY[i])*e,this.offsetX[i]=Math.max(-2,Math.min(2,this.offsetX[i]+this.driftX[i]*e)),this.offsetY[i]=Math.max(-2,Math.min(2,this.offsetY[i]+this.driftY[i]*e)),this.signal[i]=1-Math.exp(.06*-Math.hypot(this.u[i],this.v[i])-.16*this.ink[i]),a=Math.max(a,this.signal[i])}this.peak=a}if(this.active)for(let e=0;e<this.ink.length;e++){const t=Math.round(65535*Math.min(1,this.signal[e]));this.pixels[4*e]=t>>>8,this.pixels[4*e+1]=255&t,this.pixels[4*e+2]=Math.round(128+63.5*this.offsetX[e]),this.pixels[4*e+3]=Math.round(128+63.5*this.offsetY[e])}else this.clear()}};function ce(e,t,n,r,i){if(!(i<1))for(let o=0;o<2;o++){for(let o=0;o<r;o++){let r=0;const a=o*n;for(let t=-i;t<=i;t++)r+=e[a+Math.max(0,Math.min(n-1,t))];for(let o=0;o<n;o++)t[a+o]=r/(2*i+1),r+=e[a+Math.min(n-1,o+i+1)]-e[a+Math.max(0,o-i)]}for(let o=0;o<n;o++){let a=0;for(let e=-i;e<=i;e++)a+=t[Math.max(0,Math.min(r-1,e))*n+o];for(let l=0;l<r;l++)e[l*n+o]=a/(2*i+1),a+=t[Math.min(r-1,l+i+1)*n+o]-t[Math.max(0,l-i)*n+o]}}}var ue=new Float32Array(0);var he,fe=["none","flow","orb","drift","swell","caustics","contour","aurora","ripple","halo","interference","mesh","cascade","constellation"],de=["glyph","dot","pixel","mosaic","lego","voxel","disco","dither","hex","led","cmyk","stipple","engraving","crosshatch","woodblock","risograph","pointillism"],me=[{value:"fluid",label:"Fluid",description:"An ink-in-water wake that bends the image and swirls the characters."},{value:"lantern",label:"Lantern",description:"A soft light follows the pointer and lifts the characters it passes, without distortion."},{value:"trail",label:"Trail",description:"The Asciify Trail: in the wake, sparse characters fill in and dense ones open up, then settle. No distortion."},{value:"loupe",label:"Loupe",description:"A glass loupe glides after the pointer and magnifies the characters it covers."},{value:"reveal",label:"Reveal",description:"Under a soft spotlight the characters take the source image's own colours. Best over a photo or video in one ink."},{value:"none",label:"Off",description:"The field stays still under the pointer."}],pe={radius:.13,strength:.5,trail:.45,follow:12},ge={strength:.55,radius:.45},ve={radius:.075,force:1,dissipation:1.6,refraction:.03,glow:.55,resolution:128,curl:24},xe={charset:" .,:-=+*#%@",cellSize:12,cellAspect:1,cellFit:"pixel",font:'ui-monospace, "SF Mono", Menlo, Consolas, monospace',fontWeight:500,glyphScale:.8,mark:"glyph",dotScale:.9,color:"ink",ink:"#f3ba32",highlight:"auto",background:"transparent",brightness:0,contrast:1,gamma:1,invert:!1,levels:"auto",blend:"auto",saturation:1.1,shade:.5,backdrop:0,fit:"cover",focus:{x:.5,y:.5},vignette:0,drift:0,scene:"flow",scale:1,clear:!1,speed:1,hover:"fluid",fluid:ve,lantern:pe,trail:ge,scope:"all",maxPixelRatio:2,respectReducedMotion:!0},ye=(e,t,n,r)=>"number"==typeof e&&Number.isFinite(e)?Math.min(n,Math.max(t,e)):r,Ee=(e,t)=>"string"==typeof e&&/^#([\da-f]{3}|[\da-f]{6})$/i.test(e.trim())?e.trim().toLowerCase():t,we=/^[\u0020-\u007e\u00a0-\u02ff\u0370-\u0482\u048a-\u052f\u2010-\u20cf\u2100-\u2bff]*$/;function be(e){if(!we.test(e)&&void 0===he){const e=Intl.Segmenter;he=e?new e(void 0,{granularity:"grapheme"}):null}return(he&&!we.test(e)?Array.from(he.segment(e),e=>e.segment):Array.from(e)).filter(e=>"\n"!==e&&"\r"!==e&&"\t"!==e).slice(0,256)}function Te(e={},t=xe){const n="string"==typeof e.charset&&be(e.charset).length>=2?e.charset:t.charset,r=t.fluid||ve,i=void 0===e.fluid?t.fluid:e.fluid,o=!1!==i&&(()=>{const e=!0!==i&&i?{...r,...i}:r;return{radius:ye(e.radius,.005,.5,ve.radius),force:ye(e.force,0,8,ve.force),dissipation:ye(e.dissipation,.05,20,ve.dissipation),refraction:ye(e.refraction,0,.5,ve.refraction),glow:ye(e.glow,0,2,ve.glow),resolution:Math.round(ye(e.resolution,16,512,ve.resolution)),curl:ye(e.curl,0,80,ve.curl)}})(),a=fe.includes(e.scene)?e.scene:t.scene,l=!!e.clear&&"object"==typeof e.clear&&("element"in e.clear||"nodeType"in e.clear),s=void 0===e.clear||l?t.clear:e.clear,c=!!s&&{x:ye(s.x,-.5,1.5,.25),y:ye(s.y,-.5,1.5,.3),width:ye(s.width,0,2,.5),height:ye(s.height,0,2,.4),feather:ye(s.feather,.005,1,.12),shape:"rect"===s.shape?"rect":"ellipse"};return{charset:n,cellSize:ye(e.cellSize,3,96,t.cellSize),cellAspect:ye(e.cellAspect,.3,2,t.cellAspect),cellFit:"fill"===e.cellFit||"pixel"===e.cellFit?e.cellFit:t.cellFit,font:"string"==typeof e.font&&e.font.trim()?e.font:t.font,fontWeight:Math.round(ye(e.fontWeight,100,900,t.fontWeight)),glyphScale:ye(e.glyphScale,.3,1.6,t.glyphScale),mark:de.includes(e.mark)?e.mark:t.mark,dotScale:ye(e.dotScale,.1,1.4,t.dotScale),color:"source"===e.color||"ink"===e.color?e.color:t.color,ink:Ee(e.ink,t.ink),highlight:"auto"===e.highlight?"auto":Ee(e.highlight,t.highlight),background:"transparent"===e.background?"transparent":Ee(e.background,t.background),brightness:ye(e.brightness,-1,1,t.brightness),contrast:ye(e.contrast,0,4,t.contrast),gamma:ye(e.gamma,.2,5,t.gamma),invert:"boolean"==typeof e.invert?e.invert:t.invert,levels:"none"===e.levels||"auto"===e.levels?e.levels:t.levels,blend:"auto"===e.blend||"coarse"===e.blend||"on"===e.blend||"off"===e.blend?e.blend:t.blend,saturation:ye(e.saturation,0,3,t.saturation),shade:ye(e.shade,0,1,t.shade),backdrop:ye(e.backdrop,0,1,t.backdrop),fit:"contain"===e.fit||"cover"===e.fit?e.fit:t.fit,focus:{x:ye(e.focus?.x,0,1,t.focus.x),y:ye(e.focus?.y,0,1,t.focus.y)},vignette:ye(e.vignette,0,1,t.vignette),drift:ye(e.drift,0,2,t.drift),scene:a,scale:ye(e.scale,.2,6,t.scale),clear:c,speed:ye(e.speed,0,5,t.speed),hover:me.some(t=>t.value===e.hover)?e.hover:t.hover,fluid:o,lantern:{radius:ye(e.lantern?.radius,.02,.6,t.lantern.radius),strength:ye(e.lantern?.strength,0,1.5,t.lantern.strength),trail:ye(e.lantern?.trail,0,3,t.lantern.trail),follow:ye(e.lantern?.follow,1,60,t.lantern.follow)},trail:{strength:ye(e.trail?.strength,0,1,t.trail.strength),radius:ye(e.trail?.radius,.1,1,t.trail.radius)},scope:void 0===e.scope?t.scope:(u=e.scope,"subject"===u||"outside"===u?u:"all"),maxPixelRatio:ye(e.maxPixelRatio,.5,4,t.maxPixelRatio),respectReducedMotion:"boolean"==typeof e.respectReducedMotion?e.respectReducedMotion:t.respectReducedMotion};var u}function Me(e,t,n,r,i,o={x:.5,y:.5}){if(!(e>0&&t>0&&n>0&&r>0))return{scale:[1,1],offset:[0,0]};const a=e/t,l=n/r,s=l>a,c="cover"===i?s?[a/l,1]:[1,l/a]:s?[1,l/a]:[a/l,1];return{scale:c,offset:"cover"===i?[(1-c[0])*o.x,(1-c[1])*o.y]:[.5*(1-c[0]),.5*(1-c[1])]}}function Re(e,t,n,r){const i=Math.max(2,Math.round(e*n)),o=Math.max(2,Math.round(i*t)),a=Math.min(16,Math.max(1,r)),l=Math.ceil(r/a);return{width:o,height:i,columns:a,rows:l,atlasWidth:a*o,atlasHeight:l*i}}function Ae(e){const t=e.replace("#",""),n=3===t.length?t.split("").map(e=>e+e).join(""):t,r=Number.parseInt(n,16);return Number.isFinite(r)&&6===n.length?[(r>>16&255)/255,(r>>8&255)/255,(255&r)/255]:[0,0,0]}function Fe(e){const t=new Uint32Array(256);let n=0;for(let r=0;r+3<e.length;r+=4)e[r+3]<8||(t[Math.round(.2126*e[r]+.7152*e[r+1]+.0722*e[r+2])]++,n++);if(!n)return[0,1];const r=e=>{let r=0;for(let i=0;i<256;i++)if(r+=t[i],r>=n*e)return i/255;return 1},i=r(.02),o=r(.98);return o-i<.08?[0,1]:[i,o]}var ke=e=>"fluid"!==e.hover||e.fluid?e.hover:"none";function Se(e,t,n=24,r=.12,i="ellipse"){return e.width>0&&e.height>0&&{x:(t.left-n-e.left)/e.width,y:(t.top-n-e.top)/e.height,width:(t.width+2*n)/e.width,height:(t.height+2*n)/e.height,feather:r,shape:i}}var _e,Le=/\.(mp4|webm|mov|m4v|ogv)(\?|#|$)/i,De=/swiftshader|llvmpipe|softpipe|software|basic render/i;function Pe(){if(_e)return _e;if("undefined"==typeof document||void 0===globalThis.WebGL2RenderingContext)return _e="none";try{const e=ae();if(e)return _e=De.test(e.renderer)?"software":"gpu";const t=document.createElement("canvas").getContext("webgl2");if(!t)return _e="none";const n=t.getExtension("WEBGL_debug_renderer_info"),r=String(t.getParameter(n?n.UNMASKED_RENDERER_WEBGL:t.RENDERER)??"");return t.getExtension("WEBGL_lose_context")?.loseContext(),_e=De.test(r)?"software":"gpu"}catch{return _e="none"}}var Ce=(e,t)=>`${e.fontWeight} ${Math.max(1,t.height*e.glyphScale)}px ${e.font}`,Ue=(e,t)=>`${be(e.charset).join("")}\0${Ce(e,t)}\0${t.width}x${t.height}x${t.columns}`;function Ie(e,t,n,r){const i=Math.min(globalThis.devicePixelRatio||1,e.maxPixelRatio,Math.sqrt(8294400/Math.max(1,t*n)));return r<1&&i>1?Math.max(1,i*r):i}function Be(e,t,n){const r=be(e.charset),i=document.createElement("canvas");i.width=t.atlasWidth,i.height=t.atlasHeight;const o=i.getContext("2d");o.fillStyle="#fff",o.textAlign="center",o.textBaseline="alphabetic",o.font=Ce(e,t);const a=o.measureText("M"),l=a.actualBoundingBoxAscent||t.height*e.glyphScale*.7,s=a.actualBoundingBoxDescent||0,c=(t.height+l-s)/2;r.forEach((e,n)=>{const r=n%t.columns*t.width+t.width/2,i=Math.floor(n/t.columns)*t.height+c,a=o.measureText(e).width;o.save(),o.beginPath(),o.rect(r-t.width/2,i-c,t.width,t.height),o.clip(),o.translate(r,i),a>.96*t.width&&o.scale(.96*t.width/a,1),o.fillText(e,0,0),o.restore()});let u=!0;const h=document.fonts;try{u=!h?.check||h.check(o.font,r.join(""))}catch{}return n&&queueMicrotask(()=>{i.width=i.height=1}),{image:i,final:u}}var Ge=()=>{};exports.DEFAULT_FIELD_FLUID=ve,exports.DEFAULT_FIELD_LANTERN=pe,exports.DEFAULT_FIELD_SETTINGS=xe,exports.DEFAULT_FIELD_TRAIL=ge,exports.FIELD_HOVERS=me,exports.FIELD_MARKS=de,exports.FIELD_SCENES=fe,exports.activeFieldHover=ke,exports.ambientFactor=T,exports.cancelFieldFrame=R,exports.currentFieldContext=()=>ie,exports.fieldCellLayout=Re,exports.fieldClearFromRects=Se,exports.fieldGlyphs=be,exports.fieldLevels=Fe,exports.fieldSourceRect=Me,exports.glyphFieldTier=Pe,exports.isGlyphFieldSupported=function(e={}){const t=Pe();return"gpu"===t||"software"===t&&!!e.allowSoftware},exports.isSharedFieldCanvas=e=>le.has(e),exports.mountGlyphField=function(i,d={}){const m=e=>"undefined"!=typeof HTMLElement&&e instanceof HTMLElement,p=e=>{const t=e.clear;return m(t)?{element:{element:t},rest:{...e,clear:void 0}}:t&&"object"==typeof t&&m(t.element)?{element:t,rest:{...e,clear:void 0}}:{element:null,rest:e}};let g=p(d).element,v=Te(p(d).rest);const x=d.onError,y=i.ownerDocument,E=y&&"undefined"!=typeof document&&y!==document?null:ae(),w=E?i.getContext("2d",{alpha:!0}):null,b=!(!E||!w),A=b?E.gl:i.getContext("webgl2",{alpha:!0,antialias:!1,depth:!1,stencil:!1,premultipliedAlpha:!0,powerPreference:"high-performance"});if(!A)throw new Error("WebGL2 is not available for the glyph field.");let F=A;b&&(e=>{le.add(e)})(i),i.setAttribute("role","img"),i.setAttribute("aria-label",d.label??"ASCII artwork"),i.dataset.renderer="glyph-field";let k=!1;const S=b?null:F.getExtension("KHR_parallel_shader_compile");let _,D,P=null,C=null,U=null,I=null,B=null,G=[],N=[],X=null,q=!1,H=null,z=null;const Y=[];let K=0,te=0,ne=1,re=0,ie=Re(v.cellSize,v.cellAspect,1,2),oe=2,he=0,fe=0,me=0,pe=null,ge=!1,ve=null,xe=0,ye=0,Ee=0,we=null,_e=0,De=0,Pe=!0,Ge=0,Ne=[0,1],Xe=-1/0,qe=-1/0,He=!1;const ze=(()=>{const e="undefined"==typeof navigator?void 0:navigator;return 1e3/(e&&(e.hardwareConcurrency>0&&e.hardwareConcurrency<=2||e.deviceMemory&&e.deviceMemory<=2||e.connection?.saveData)?30:60)-2})();let Ve=!1,Oe=0,je=0,We=!0,Ye=!1,Ke=!1,$e=!1,Qe=!1,Je=!0,Ze=null,et=null,tt=1/60,nt=0,rt=0,it=[];const ot=new Float32Array(16),at=()=>{if(!g)return;const{element:e,padding:t=32,feather:n=.16,shape:r="rect"}=g,o=Se(i.getBoundingClientRect(),e.getBoundingClientRect(),t,n,r),a=v.clear;JSON.stringify(a)!==JSON.stringify(o)&&(v={...v,clear:o},We=!0)},lt=e=>"lantern"===e||"loupe"===e||"reveal"===e,st={target:null,at:null,strength:0,trail:[]},ct=new Float32Array(36);let ut=null,ht=null,ft=!1;const dt=()=>{if(!K||!te)return null;const e=K/te,t=Math.round(e>=1?128:128*e),n=Math.round(e>=1?128/e:128);return ut&&ut.width===t&&ut.height===n||(ut=new se(t,n),ht||(ht=Rt(F.LINEAR)),F.bindTexture(F.TEXTURE_2D,ht),F.texImage2D(F.TEXTURE_2D,0,F.RGBA8,t,n,0,F.RGBA,F.UNSIGNED_BYTE,ut.pixels),ft=!0),ut};let mt=0;const pt="function"==typeof matchMedia?matchMedia("(prefers-reduced-motion: reduce)"):null,gt=()=>v.respectReducedMotion&&!!pt?.matches;let vt;const xt=new Promise(e=>{vt=e});let yt=!0;const Et=e=>x?.(e instanceof Error?e:new Error(String(e))),wt=(e,t)=>{const n=F.createShader(e);return Y.push(n),F.shaderSource(n,t),F.compileShader(n),n},bt=e=>{if(b)return E.program(e);z??(z=wt(F.VERTEX_SHADER,"#version 300 es\nvoid main(){vec2 p=vec2((gl_VertexID<<1)&2,gl_VertexID&2);gl_Position=vec4(p*2.-1.,0.,1.);}"));const t=F.createProgram(),n=wt(F.FRAGMENT_SHADER,e);return F.attachShader(t,z),F.attachShader(t,n),F.linkProgram(t),{program:t,locations:null,fragment:n}},Tt=(e,t=!1)=>{if(e.locations)return!0;if(b)return E.linked(e,t);const{program:n,fragment:r}=e;if(!t&&S&&!F.getProgramParameter(n,S.COMPLETION_STATUS_KHR))return!1;if(!F.getProgramParameter(n,F.LINK_STATUS)){if(F.isContextLost())return!1;throw new Error(F.getShaderInfoLog(r)||F.getProgramInfoLog(n)||"Glyph field program failed to link.")}const i={};for(let e=F.getProgramParameter(n,F.ACTIVE_UNIFORMS)-1;e>=0;e--){const t=F.getActiveUniform(n,e).name.replace(/\[0\]$/,"");i[t]=F.getUniformLocation(n,t)}return e.locations=i,!0},Mt=(e=!1)=>!!P&&!!C&&Tt(P,e)&&Tt(C,e),Rt=e=>{const t=F.createTexture();return F.bindTexture(F.TEXTURE_2D,t),F.texParameteri(F.TEXTURE_2D,F.TEXTURE_MIN_FILTER,e),F.texParameteri(F.TEXTURE_2D,F.TEXTURE_MAG_FILTER,e===F.LINEAR_MIPMAP_LINEAR?F.LINEAR:e),F.texParameteri(F.TEXTURE_2D,F.TEXTURE_WRAP_S,F.CLAMP_TO_EDGE),F.texParameteri(F.TEXTURE_2D,F.TEXTURE_WRAP_T,F.CLAMP_TO_EDGE),t},At=()=>{B&&(F.deleteTexture(B.ink),F.deleteTexture(B.under),F.deleteFramebuffer(B.buffer),B=null)},Ft=()=>function(e,t,n,r,i,o,a){if("fill"!==e||!(i>0&&o>0))return[a.width,a.height];const l=t*r,s=l*n;return[i/Math.max(1,Math.floor(i/s+1e-6)),o/Math.max(1,Math.floor(o/l+1e-6))]}(v.cellFit,v.cellSize,v.cellAspect,ne,K,te,ie),kt=()=>!!v.fluid&&"fluid"===ke(v),St=()=>{X?.release(),q=!1,G.forEach(e=>F.deleteTexture(e)),N.forEach(e=>F.deleteFramebuffer(e)),G=[],N=[]};function _t(){U&&!b&&F.deleteProgram(U.program),U=bt((e=>`#version 300 es\nprecision highp float;\nprecision highp sampler2D;\nuniform sampler2D uPrevious;\nuniform vec2 uSize;\nuniform float uAspect, uDt, uDecay, uEnergyDecay, uRadius, uSplat;\nuniform vec2 uFrom, uTo, uForce;\nout vec4 outColor;\n${t(e)}\nfloat segment(vec2 p,vec2 a,vec2 b){vec2 pa=p-a,ba=b-a;float h=clamp(dot(pa,ba)/max(dot(ba,ba),1e-8),0.,1.);return length(pa-ba*h);}\nvoid main(){\n vec2 uv=gl_FragCoord.xy/uSize;\n vec4 here=decodeFluid(texture(uPrevious,uv));\n vec4 state=decodeFluid(texture(uPrevious,uv-uDt*here.xy*vec2(1./uAspect,1.)));\n state.xy*=exp(-uDt*uDecay);\n state.z*=exp(-uDt*uEnergyDecay);\n if(uSplat>.5){\n vec2 scale=vec2(uAspect,1.);\n float d=segment(uv*scale,uFrom*scale,uTo*scale);\n float g=exp(-d*d/(uRadius*uRadius));\n state.xy+=uForce*g;\n state.z=min(1.,state.z+g*min(1.,length(uForce)*.5+.08));\n }\n float speed=length(state.xy);\n if(speed>5.)state.xy*=5./speed;\n outColor=encodeFluid(state);\n}`)(k)),b?X?.release():X?.dispose(),X=k?null:function(e,t,n){const r={splat:t(o),curl:t(a),vorticity:t(l),divergence:t(s),fade:t(c),pressure:t(u),gradient:t(h),advect:t(f)},i=Object.values(r);let d=0,m=0,p=[],g=[],v=null,x=null;const y=t=>{const n=e.createTexture();e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texImage2D(e.TEXTURE_2D,0,e.RGBA16F,d,m,0,e.RGBA,e.HALF_FLOAT,null);const r=e.createFramebuffer();return e.bindFramebuffer(e.FRAMEBUFFER,r),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,n,0),e.checkFramebufferStatus(e.FRAMEBUFFER)!==e.FRAMEBUFFER_COMPLETE?(e.deleteFramebuffer(r),e.deleteTexture(n),null):(e.viewport(0,0,d,m),e.clearColor(0,0,0,1),e.clear(e.COLOR_BUFFER_BIT),{texture:n,buffer:r})},E=t=>{t&&(e.deleteTexture(t.texture),e.deleteFramebuffer(t.buffer))},w=()=>{[...p,...g,v,x].forEach(E),p=[],g=[],v=x=null},b=(t,n)=>{const r=t.locations;return e.useProgram(t.program),e.bindFramebuffer(e.FRAMEBUFFER,n.buffer),e.uniform2f(r.uTexel,1/d,1/m),r},T=(t,n,r,i)=>{e.activeTexture(e.TEXTURE0+r),e.bindTexture(e.TEXTURE_2D,i),e.uniform1i(t[n],r)},M=()=>e.drawArrays(e.TRIANGLES,0,3),R=e=>{const t=e[0];e[0]=e[1],e[1]=t};return{resize(t,n){w(),d=t,m=n;const r=[y(e.LINEAR),y(e.LINEAR),y(e.NEAREST),y(e.NEAREST),y(e.NEAREST),y(e.NEAREST)];return e.bindFramebuffer(e.FRAMEBUFFER,null),r.some(e=>!e)?(r.forEach(E),!1):(p=[r[0],r[1]],g=[r[2],r[3]],v=r[4],x=r[5],!0)},ready:()=>i.every(n),step(t,n){if(!p.length||!v||!x)return;let i;e.viewport(0,0,d,m),t&&(i=b(r.splat,p[1]),T(i,"uVelocity",0,p[0].texture),e.uniform2f(i.uFrom,t.from[0],t.from[1]),e.uniform2f(i.uTo,t.to[0],t.to[1]),e.uniform2f(i.uForce,t.force[0],t.force[1]),e.uniform1f(i.uAspect,n.aspect),e.uniform1f(i.uRadius,n.radius),M(),R(p)),n.curl>0&&(i=b(r.curl,x),T(i,"uVelocity",0,p[0].texture),M(),i=b(r.vorticity,p[1]),T(i,"uVelocity",0,p[0].texture),T(i,"uCurl",1,x.texture),e.uniform1f(i.uStrength,n.curl),e.uniform1f(i.uDt,n.dt),M(),R(p)),i=b(r.divergence,v),T(i,"uVelocity",0,p[0].texture),M(),i=b(r.fade,g[1]),T(i,"uSource",0,g[0].texture),e.uniform1f(i.uAmount,.8),M(),R(g);for(let e=0;e<20;e++)i=b(r.pressure,g[1]),T(i,"uPressure",0,g[0].texture),T(i,"uDivergence",1,v.texture),M(),R(g);i=b(r.gradient,p[1]),T(i,"uPressure",0,g[0].texture),T(i,"uVelocity",1,p[0].texture),M(),R(p),i=b(r.advect,p[1]),T(i,"uVelocity",0,p[0].texture),e.uniform1f(i.uDt,n.dt),e.uniform1f(i.uDissipation,n.dissipation),M(),R(p),e.bindFramebuffer(e.FRAMEBUFFER,null)},get velocity(){return p[0]?.texture??null},get size(){return[d,m]},release:w,dispose(){w(),i.forEach(({program:t})=>e.deleteProgram(t))}}}(F,bt,e=>Tt(e))}const Lt=()=>{St();const e=v.fluid;if(!(e&&kt()&&K&&te))return;U||_t();const t=e.resolution,n=K/te;if(he=n>=1?t:Math.max(8,Math.round(t*n)),fe=n>=1?Math.max(8,Math.round(t/n)):t,q=!!X&&X.resize(he,fe),q)return void(me=0);const r=()=>{St();for(let e=0;e<2;e++){const e=Rt(F.LINEAR);F.texImage2D(F.TEXTURE_2D,0,k?F.RGBA8:F.RGBA16F,he,fe,0,F.RGBA,k?F.UNSIGNED_BYTE:F.HALF_FLOAT,null);const t=F.createFramebuffer();F.bindFramebuffer(F.FRAMEBUFFER,t),F.framebufferTexture2D(F.FRAMEBUFFER,F.COLOR_ATTACHMENT0,F.TEXTURE_2D,e,0),G.push(e),N.push(t)}return F.checkFramebufferStatus(F.FRAMEBUFFER)===F.FRAMEBUFFER_COMPLETE};if(!r()){if(k)throw new Error("The glyph field could not allocate its fluid buffers.");k=!0,Dt(),_t(),r()}for(const e of N)F.bindFramebuffer(F.FRAMEBUFFER,e),F.viewport(0,0,he,fe),F.clearColor(k?.5:0,k?.5:0,0,1),F.clear(F.COLOR_BUFFER_BIT);F.bindFramebuffer(F.FRAMEBUFFER,null),me=0};function Dt(){P&&!b&&F.deleteProgram(P.program),C&&!b&&F.deleteProgram(C.program),At(),P=bt(n(k)),C=bt(r),(b?E.canCompileInParallel:S)||Mt(!0)}const Pt=()=>Ce(v,ie),Ct=()=>{We=!0,fn()},Ut=()=>Ue(v,ie),It=()=>{const e=be(v.charset);if(oe=e.length,ie=Re(v.cellSize,v.cellAspect,ne,oe),re=ne,b){const e=Ut();if(I?.key!==e){const t=I;I=E.atlas(e,Bt,Ct),E.releaseAtlas(t,Ct),_=I.texture}return void(We=!0)}const{image:t}=Bt();F.bindTexture(F.TEXTURE_2D,_),F.pixelStorei(F.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),F.texImage2D(F.TEXTURE_2D,0,F.RGBA8,F.RGBA,F.UNSIGNED_BYTE,t),t.width=t.height=1,We=!0};function Bt(){return Be(v,ie,b)}const Gt="undefined"==typeof document?void 0:document.fonts,Nt=()=>{if(!Gt?.load)return;const e=Pt();Gt.load(e,be(v.charset).join("")).then(()=>{if(!Ye&&!Ke&&Pt()===e)return b?void(I&&!I.final&&I.key===Ut()&&E.paintAtlas(I,Bt)):(It(),void fn())},()=>{})},Xt=e=>e.trim().replace(/^["']|["']$/g,"").toLowerCase(),qt=()=>{if(Ne=[0,1],pe&&"none"!==v.levels)try{const e=document.createElement("canvas");e.width=e.height=64;const t=e.getContext("2d",{willReadFrequently:!0});pe===we&&(t.imageSmoothingQuality="medium"),t.drawImage(pe,0,0,64,64),Ne=Fe(t.getImageData(0,0,64,64).data)}catch{Ne=[0,1]}};let Ht=null,zt=null,Vt=!1,Ot=-1/0,jt=new Uint8Array(0),Wt=null;const Yt=()=>{if(Vt=!1,!pe||"all"===v.scope)return;const e=xe||1,t=ye||1,n=Math.max(8,Math.round(e>=t?96:96*e/t)),r=Math.max(8,Math.round(t>=e?96:96*t/e));try{if(Wt??(Wt=document.createElement("canvas").getContext("2d",{willReadFrequently:!0})),!Wt)return;const e=Wt.canvas;e.width!==n||e.height!==r?(e.width=n,e.height=r):Wt.clearRect(0,0,n,r),Wt.drawImage(pe,0,0,n,r),zt=function(e,t,n,r,i){const o=t*n,a=i&&i.width===t&&i.height===n?i:{width:t,height:n,subject:new Float32Array(o),depth:new Float32Array(o),key:"none"},{subject:l,depth:s}=a;let c=0;for(let t=0;t<o;t++)e[4*t+3]<250&&c++;const u=t=>(.2126*e[4*t]+.7152*e[4*t+1]+.0722*e[4*t+2])/255;let h="none",f=0;if(c>.01*o)h="alpha";else{let e=0,r=0,i=0;const o=Math.max(1,Math.round(.03*Math.min(t,n)));for(let a=0;a<n;a++)for(let l=0;l<t;l++){if(l>=o&&a>=o&&l<t-o&&a<n-o)continue;const s=u(a*t+l);e+=s,r+=s*s,i++}f=e/Math.max(1,i),Math.sqrt(Math.max(0,r/Math.max(1,i)-f*f))<.07&&(h="ground")}for(let t=0;t<o;t++){const n=e[4*t+3]/255,r=u(t);let i=1;if("alpha"===h)i=n;else if("ground"===h){const e=Math.max(0,Math.min(1,(Math.abs(r-f)-.035)/.12));i=e*e*(3-2*e)}l[t]=1*i,s[t]=r*n}a.key=h,ue.length<o&&(ue=new Float32Array(o));const d=ue;return ce(l,d,t,n,Math.max(1,Math.round(.02*Math.min(t,n)))),ce(s,d,t,n,Math.max(1,Math.round(.035*Math.min(t,n)))),a}(Wt.getImageData(0,0,n,r).data,n,r,0,zt)}catch{return}if("none"!==zt.key){jt.length!==n*r*4&&(jt=new Uint8Array(n*r*4));for(let e=0;e<n*r;e++)jt[4*e+3]=Math.round(255*zt.subject[e]);Ht??(Ht=Rt(F.LINEAR)),F.bindTexture(F.TEXTURE_2D,Ht),F.pixelStorei(F.UNPACK_FLIP_Y_WEBGL,!1),F.pixelStorei(F.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),F.texImage2D(F.TEXTURE_2D,0,F.RGBA8,n,r,0,F.RGBA,F.UNSIGNED_BYTE,jt),Vt=!0}},Kt=()=>{if(!pe)return;const e=performance.now();pe instanceof HTMLVideoElement&&!(e-Xe>1500)||(qt(),Xe=e),pe instanceof HTMLVideoElement&&!(e-Ot>160)||(Yt(),Ot=e),F.bindTexture(F.TEXTURE_2D,D),F.pixelStorei(F.UNPACK_FLIP_Y_WEBGL,!1),F.pixelStorei(F.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);try{F.texImage2D(F.TEXTURE_2D,0,F.RGBA8,F.RGBA,F.UNSIGNED_BYTE,pe),F.generateMipmap(F.TEXTURE_2D);const e=pe;De=(e.videoWidth||e.naturalWidth||e.width)*(e.videoHeight||e.naturalHeight||e.height)*4*4/3}catch(e){Et(e)}},$t=()=>{k=!F.getExtension("EXT_color_buffer_float")&&!F.getExtension("EXT_color_buffer_half_float"),Dt(),H=b?E.vertexArray():F.createVertexArray(),b||(_=Rt(F.NEAREST)),D=Rt(F.LINEAR_MIPMAP_LINEAR),F.bindTexture(F.TEXTURE_2D,D),F.texImage2D(F.TEXTURE_2D,0,F.RGBA8,1,1,0,F.RGBA,F.UNSIGNED_BYTE,new Uint8Array([0,0,0,255])),F.generateMipmap(F.TEXTURE_2D),K=te=0,re=0,Qt(),Nt(),pe&&Kt()};function Qt(){const e=i.clientWidth||i.clientHeight?{width:i.clientWidth,height:i.clientHeight}:i.getBoundingClientRect();He=!e.width||!e.height;const t=Ie(v,e.width,e.height,b?E.scale:1),n=Math.max(1,Math.round(e.width*t)),r=Math.max(1,Math.round(e.height*t));if(n===K&&r===te&&t===ne)return!1;const o=!K||Math.abs(n/r-K/te)>.01;return ne=t,K=n,te=r,i.width=K,i.height=te,re!==ne&&It(),(o||kt()&&!G.length&&!q)&&Lt(),We=!0,!0}let Jt=null,Zt=[0,0,0],en=[1,1,1],tn=[0,0,0,0],nn=Me(1,1,1,1,"cover"),rn=null,on=0,an=0,ln=0,sn=0;const cn=()=>{Jt!==v&&(Jt=v,Zt=Ae(v.ink),en=Ae("auto"===v.highlight?"#ffffff":v.highlight),tn="transparent"===v.background?[0,0,0,0]:[...Ae(v.background),1]),rn===v&&on===K&&an===te&&ln===xe&&sn===ye||(rn=v,on=K,an=te,ln=xe,sn=ye,nn=Me(K,te,xe||1,ye||1,v.fit,v.focus)),b&&E.begin(K,te);const t=v.fluid,n=pe&&_e?ie.height/te*_e*nn.scale[1]:1,r=(()=>{const[e,t]=Ft(),n=Math.ceil(K/e-1e-4),r=Math.ceil(te/t-1e-4);if(B&&B.columns===n&&B.rows===r)return B;At();const i=()=>{const e=Rt(F.NEAREST);return F.texStorage2D(F.TEXTURE_2D,1,k?F.RGBA8:F.RGBA16F,n,r),e},o=i(),a=i(),l=F.createFramebuffer();return F.bindFramebuffer(F.FRAMEBUFFER,l),F.framebufferTexture2D(F.FRAMEBUFFER,F.COLOR_ATTACHMENT0,F.TEXTURE_2D,o,0),F.framebufferTexture2D(F.FRAMEBUFFER,F.COLOR_ATTACHMENT1,F.TEXTURE_2D,a,0),F.drawBuffers([F.COLOR_ATTACHMENT0,F.COLOR_ATTACHMENT1]),B={ink:o,under:a,buffer:l,columns:n,rows:r}})(),i=P.locations,o=C.locations,a=ke(v),l=!gt();F.bindFramebuffer(F.FRAMEBUFFER,r.buffer),F.viewport(0,0,r.columns,r.rows),F.useProgram(P.program),F.activeTexture(F.TEXTURE0),F.bindTexture(F.TEXTURE_2D,D),F.uniform1i(i.uSource,0),F.activeTexture(F.TEXTURE2),F.bindTexture(F.TEXTURE_2D,(q?X?.velocity:G[me])??D),F.uniform1i(i.uFluid,2),F.activeTexture(F.TEXTURE3),F.bindTexture(F.TEXTURE_2D,ht??D),F.uniform1i(i.uTrailMap,3),F.activeTexture(F.TEXTURE6),F.bindTexture(F.TEXTURE_2D,Ht??D),F.uniform1i(i.uScope,6),F.uniform1f(i.uScopeMode,Vt&&"all"!==v.scope?"subject"===v.scope?1:2:0),F.uniform1f(i.uFluidMode,q?1:0),F.uniform1i(i.uHoverMode,"fluid"===a?1:"lantern"===a?2:"trail"===a&&ft?3:"loupe"===a?4:"reveal"===a?5:0),F.uniform1f(i.uTrailAmount,v.trail.strength),F.uniform3f(i.uLight,st.at?.[0]??-1,st.at?.[1]??-1,lt(a)?st.strength:0),F.uniform3fv(i.uTrail,ct),F.uniform1f(i.uLightRadius,v.lantern.radius),F.uniform1f(i.uLightGain,v.lantern.strength),F.uniform1f(i.uClock,performance.now()/1e3),F.uniform1f(i.uFlicker,l?1:0),F.uniform2f(i.uFluidTexel,1/Math.max(1,he),1/Math.max(1,fe)),F.uniform2f(i.uResolution,K,te);const[s,c]=Ft();var u;F.uniform2f(i.uCell,s,c),F.uniform1f(i.uCount,oe),F.uniform1f(i.uBlend,"on"===v.blend||oe<=9&&("coarse"===v.blend||"auto"===v.blend&&ge)?1:0),F.uniform4f(i.uSourceMap,nn.scale[0],nn.scale[1],nn.offset[0],nn.offset[1]),F.uniform1i(i.uScene,pe?0:(u=v.scene,e[u]??3)),F.uniform1i(i.uMark,de.indexOf(v.mark)),F.uniform1f(i.uScale,v.scale);const h=v.clear;F.uniform4f(i.uClear,h?h.x:0,h?h.y:0,h?h.width:0,h?h.height:0),F.uniform1f(i.uClearFeather,h?h.feather:.1),F.uniform1f(i.uClearShape,h&&"rect"===h.shape?1:0);const f=performance.now();ot.fill(0);for(let e=0;e<it.length;e++){const t=it[e],n=4*e;ot[n]=t.x,ot[n+1]=t.y,ot[n+2]=(f-t.born)/1e3,ot[n+3]=t.strength}F.uniform4fv(i.uPulse,ot),F.uniform3fv(i.uInk,Zt),F.uniform3fv(i.uHighlight,en),F.uniform1f(i.uHighlightAuto,"auto"===v.highlight?1:0),F.uniform4fv(i.uBackground,tn),F.uniform1f(i.uBrightness,v.brightness),F.uniform1f(i.uContrast,v.contrast),F.uniform1f(i.uGamma,v.gamma),F.uniform1f(i.uInvert,v.invert?1:0),F.uniform1f(i.uVignette,v.vignette),F.uniform1f(i.uSourceColor,"source"===v.color?1:0),F.uniform1f(i.uRefraction,t?t.refraction*(l?1:.25):0),F.uniform1f(i.uGlow,t?t.glow:0),F.uniform1f(i.uTime,je),F.uniform1f(i.uDrift,l?v.drift:0),F.uniform1f(i.uFluidOn,t&&"fluid"===a&&(G.length||q)?1:0),F.uniform1f(i.uLod,Math.max(0,Math.log2(Math.max(1,n))-.5)),F.uniform1f(i.uSaturation,v.saturation),F.uniform1f(i.uShade,v.shade),F.uniform1f(i.uBackdrop,pe?v.backdrop:0),F.uniform2f(i.uLevels,pe&&"auto"===v.levels?Ne[0]:0,pe&&"auto"===v.levels?Ne[1]:1),F.bindVertexArray(H),F.drawArrays(F.TRIANGLES,0,3),F.bindFramebuffer(F.FRAMEBUFFER,null),F.viewport(0,0,K,te),F.useProgram(C.program),F.activeTexture(F.TEXTURE1),F.bindTexture(F.TEXTURE_2D,_),F.uniform1i(o.uAtlas,1),F.activeTexture(F.TEXTURE4),F.bindTexture(F.TEXTURE_2D,r.ink),F.uniform1i(o.uCells,4),F.activeTexture(F.TEXTURE5),F.bindTexture(F.TEXTURE_2D,r.under),F.uniform1i(o.uUnder,5),F.uniform2f(o.uResolution,K,te),F.uniform2f(o.uCell,ie.width,ie.height),F.uniform2f(o.uPitch,s,c),F.uniform1f(o.uColumns,ie.columns),F.uniform1f(o.uDotScale,v.dotScale),F.uniform1i(o.uMark,de.indexOf(v.mark)),F.uniform1f(o.uSourceColor,"source"===v.color?1:0),F.drawArrays(F.TRIANGLES,0,3),b&&E.present(w,K,te)},un=()=>!Ye&&!Ke&&!$e&&!He&&(Je||yt)&&!("undefined"!=typeof document&&document.hidden),hn=e=>{if(Ve=!1,!un())return;const t=(e-Oe)/1e3,n=Math.min(1/30,Math.max(1/480,t));Oe=e,tt=.9*tt+.1*Math.min(t,.25),nt=tt>1/24?nt+1:0;try{b&&E.overloaded&&rt<2&&nt>10&&(rt=2),nt>45&&rt<2&&(!b||E.atMinimum)&&(nt=0,rt++,1===rt&&ne>1?(v={...v,maxPixelRatio:1},Qt()):rt=2);const t=Mt(),r=!(Qe||rt>=2&&!(pe instanceof HTMLVideoElement)||(!(pe instanceof HTMLVideoElement)||pe.paused||pe.ended)&&(gt()||!(!pe&&"none"!==v.scene||v.drift>0)));r&&(je+=n*v.speed),pe instanceof HTMLVideoElement&&pe.readyState>=2&&Pe&&(Pe=!("requestVideoFrameCallback"in pe),Kt(),We=!0);const i=ke(v);let o="fluid"===i&&(null!==et||e<mt);if(o?((e,t)=>{const n=v.fluid;if(!n||!N.length&&!q)return;if(q?!X?.ready():!U||!Tt(U))return;const r=K/te,i=et;if(et=null,q&&X){const o=5200*n.force*(gt()?.35:1);return i&&(mt=t+1e3*Math.min(9,6/Math.max(.3,n.dissipation))),void X.step(i?{from:i.from,to:i.to,force:[(i.to[0]-i.from[0])*o,(i.to[1]-i.from[1])*o]}:null,{dt:Math.min(e,1/60),radius:1.1*n.radius,curl:n.curl,dissipation:n.dissipation,aspect:r})}let o=0,a=0;if(i){const e=(gt()?1:3)*n.force;o=(i.to[0]-i.from[0])*r*e*4,a=(i.to[1]-i.from[1])*e*4,mt=t+7/Math.min(n.dissipation,1.1*n.dissipation)*1e3}const l=U.locations;F.bindFramebuffer(F.FRAMEBUFFER,N[1-me]),F.viewport(0,0,he,fe),F.useProgram(U.program),F.activeTexture(F.TEXTURE0),F.bindTexture(F.TEXTURE_2D,G[me]),F.uniform1i(l.uPrevious,0),F.uniform2f(l.uSize,he,fe),F.uniform1f(l.uAspect,r),F.uniform1f(l.uDt,e),F.uniform1f(l.uDecay,n.dissipation),F.uniform1f(l.uEnergyDecay,1.1*n.dissipation),F.uniform1f(l.uRadius,n.radius),F.uniform1f(l.uSplat,i?1:0),F.uniform2f(l.uFrom,i?.from[0]??0,i?.from[1]??0),F.uniform2f(l.uTo,i?.to[0]??0,i?.to[1]??0),F.uniform2f(l.uForce,o,a),F.drawArrays(F.TRIANGLES,0,3),me=1-me})(n,e):et=null,lt(i)&&(o=((e,t)=>{const n=v.lantern,r=st.target;if(r){const i=st.at;if(i)if(gt())i[0]=r[0],i[1]=r[1];else{const t=1-Math.exp(-n.follow*e);i[0]+=(r[0]-i[0])*t,i[1]+=(r[1]-i[1])*t}else st.at=[r[0],r[1]];const o=st.at,a=st.trail[st.trail.length-1];n.trail>0&&(!a||t-a.born>28&&Math.hypot(o[0]-a.x,o[1]-a.y)>.004)&&(st.trail.push({x:o[0],y:o[1],born:t}),st.trail.length>12&&st.trail.shift())}st.strength+=((r?1:0)-st.strength)*(1-Math.exp(-e*(r?9:5)));const i=st.trail;for(let e=i.length-1;e>=0;e--)n.trail>0&&t-i[e].born<4e3*n.trail||i.splice(e,1);ct.fill(0);for(let e=0;e<i.length;e++){const r=i[e];ct[3*e]=r.x,ct[3*e+1]=r.y,ct[3*e+2]=.55*Math.exp(-(t-r.born)/1e3/Math.max(.01,n.trail))}return st.strength>.003||i.length>0})(n,e)||o),"trail"===i){const e=!!ut?.active;o=(e=>{const t=dt();return!(!t||!t.active||(t.step(e),F.bindTexture(F.TEXTURE_2D,ht),F.texSubImage2D(F.TEXTURE_2D,0,0,0,t.width,t.height,F.RGBA,F.UNSIGNED_BYTE,t.pixels),ft=!0,0))})(n)||o,e&&!ut?.active&&(We=!0)}if(it.length){for(let t=it.length-1;t>=0;t--)e-it[t].born>=2400&&it.splice(t,1);o=!0,it.length||(We=!0)}t&&(o||We||r&&e-qe>=ze*T())&&(cn(),qe=e,We=!1,!yt||Ee&&!pe||(yt=!1,vt())),(r||o||et||!t)&&(Ve=!0,M(hn))}catch(e){$e=!0,Et(e)}};function fn(){!Ve&&un()&&(Oe=performance.now(),Ve=!0,M(hn))}const dn=(e,t)=>{const n=i.getBoundingClientRect();if(!n.width||!n.height)return null;const r=(e-n.left)/n.width,o=(t-n.top)/n.height;return r<-.05||r>1.05||o<-.05||o>1.05?null:[r,1-o]},mn=e=>{const t=ke(v);if("none"===t||Qe)return Ze=null,void(st.target=null);if(lt(t))return st.target=e?[e[0],1-e[1]]:null,Ze=null,void fn();if("trail"===t){const t=dt();if(!t)return;return e?t.move(e[0],1-e[1],v.trail.radius,performance.now()):t.leave(),Ze=null,void fn()}e?(Ze&&(et=et?{from:et.from,to:e}:{from:Ze,to:e}),Ze=e,fn()):Ze=null},pn=d.interactionTarget??window,gn={target:pn,move:e=>{const t=dn(e.clientX,e.clientY);pn===window&&(gn.inside=!!t),mn(t)},leave:()=>{Ze=null,ut?.leave(),st.target&&(st.target=null,fn())},near:()=>Je},vn=[O(gn)],xn=()=>{const e=Qt();at(),(e||We)&&fn()};let yn=g?ee(g.element,xn):()=>{};vn.push(ee(i,xn),()=>yn()),vn.push(function(e,t,n){if("function"!=typeof IntersectionObserver)return()=>{};let r=$.get(t);if(!r){const e=new Map;r={observer:new IntersectionObserver(Q(e),{rootMargin:t}),watch:e},$.set(t,r)}const{observer:i,watch:o}=r;return J(o,e,n)||i.unobserve(e),i.observe(e),()=>{Z(o,e,n)&&i.unobserve(e),o.size||(i.disconnect(),$.delete(t))}}(i,"25% 0px",e=>{Je=e.isIntersecting,Je&&(We=!0,fn())})),vn.push(j(()=>{document.hidden||(We=!0,fn())})),vn.push(W(()=>{We=!0,fn()})),vn.push(V(L,e=>{const t=e.fontfaces??[],n=v.font.split(",").map(Xt);t.some(e=>n.includes(Xt(e.family)))&&Nt()}));const En=e=>{e?.preventDefault(),Ke=!0,Ve&&R(hn),Ve=!1},wn=()=>{Ke=!1,b&&(F=E.gl),Y.length=0,z=null,I=null,P=C=U=null,B=null,G=[],N=[],X=null,q=!1,ht=null,ut=null,ft=!1,Ht=null,Vt=!1;try{$t(),We=!0,fn()}catch(e){Et(e)}},bn={lost:()=>En(),restored:wn,rescale:()=>{Qt()&&fn()},size:()=>[K,te],bytes:()=>{const e=k?4:8;return K*te*4+De+(B?B.columns*B.rows*e*2:0)+he*fe*e*(q?6:G.length)+(ut?ut.width*ut.height*4:0)}};b?E.join(bn):(i.addEventListener("webglcontextlost",En),i.addEventListener("webglcontextrestored",wn));const Tn=()=>{ve&&(ve.pause(),ve.removeAttribute("src"),ve.load(),ve=null),Ge&&pe instanceof HTMLVideoElement&&"cancelVideoFrameCallback"in pe&&pe.cancelVideoFrameCallback(Ge),Ge=0},Mn=()=>{we?.close(),we=null},Rn=async e=>{const t=await createImageBitmap(e,{premultiplyAlpha:"none"}),n=[t.width,t.height],r=function(e,t,n,r,i,o,a=8){if(!(n>=16&&r>=16&&e>0&&t>0&&i>0))return 1;const l=a/i/("cover"===o?Math.min(e/n,t/r):Math.max(e/n,t/r));return l>.5?1:2**-Math.floor(Math.log2(1/l))}(t.width,t.height,K,te,ie.height,v.fit);if(1===r)return{element:t,owned:!0,natural:n};try{return{element:await createImageBitmap(t,{resizeWidth:Math.max(1,Math.round(t.width*r)),resizeHeight:Math.max(1,Math.round(t.height*r)),resizeQuality:"medium",premultiplyAlpha:"none"}),owned:!0,natural:n}}finally{t.close()}},An=e=>new Promise((t,n)=>{const r=new Image;r.crossOrigin="anonymous",r.decoding="async",r.onload=()=>t({element:r,owned:!1}),r.onerror=()=>n(new Error("The glyph field could not load this image.")),r.src=e}),Fn=(e,t,n)=>{const{element:r,owned:i}=e;if(Ye||n!==Ee)return void(i&&r instanceof HTMLVideoElement?(r.pause(),r.removeAttribute("src"),r.load()):i&&r.close());r!==pe&&(Tn(),Mn()),ve=i&&r instanceof HTMLVideoElement?r:null,!i||r instanceof HTMLVideoElement||(we=r);const o=r!==pe;pe=r,ge="string"==typeof t||t instanceof HTMLImageElement||t instanceof HTMLVideoElement,_e=r instanceof HTMLVideoElement?r.videoHeight:r instanceof HTMLImageElement?r.naturalHeight:r.height,xe=e.natural?.[0]??(r instanceof HTMLVideoElement?r.videoWidth:r instanceof HTMLImageElement?r.naturalWidth:r.width),ye=e.natural?.[1]??_e,Pe=!0,r instanceof HTMLVideoElement&&o&&(e=>{const t=e;if(!t.requestVideoFrameCallback)return;const n=()=>{Ye||pe!==e||(Pe=!0,fn(),Ge=t.requestVideoFrameCallback(n))};Ge=t.requestVideoFrameCallback(n)})(r),Ke||Kt(),We=!0,fn()},kn=(e,t)=>{yt&&e===Ee&&(yt=!1,vt()),Et(t)},Sn=e=>{const t=++Ee;if(!e)return Tn(),Mn(),pe=null,xe=ye=_e=De=0,ge=!1,We=!0,fn(),Promise.resolve();if((e=>!("string"==typeof e||e instanceof HTMLImageElement&&!e.complete||e instanceof HTMLVideoElement&&e.readyState<2))(e)){try{Fn({element:e,owned:!1},e,t)}catch(e){kn(t,e)}return Promise.resolve()}return(async e=>{if("string"!=typeof e)return e instanceof HTMLImageElement&&!e.complete?e.decode().then(()=>({element:e,owned:!1})):e instanceof HTMLVideoElement&&e.readyState<2?new Promise((t,n)=>{e.addEventListener("loadeddata",()=>t({element:e,owned:!1}),{once:!0}),e.addEventListener("error",()=>n(new Error("The glyph field could not load this video.")),{once:!0})}):{element:e,owned:!1};if(Le.test(e))return new Promise((t,n)=>{const r=document.createElement("video");r.crossOrigin="anonymous",r.muted=!0,r.loop=!0,r.playsInline=!0,r.preload="auto",r.addEventListener("loadeddata",()=>{r.play().catch(()=>{}),t({element:r,owned:!0})},{once:!0}),r.addEventListener("error",()=>n(new Error("The glyph field could not load this video.")),{once:!0}),r.src=e});if("function"!=typeof createImageBitmap||"function"!=typeof fetch)return An(e);let t;try{t=await(await fetch(e).then(e=>{if(!e.ok)throw new Error("The glyph field could not load this image.");return e})).blob()}catch(t){if(t instanceof Error&&t.message.startsWith("The glyph field"))throw t;return An(e)}if(!/svg/i.test(t.type))try{return await Rn(t)}catch{}const n=URL.createObjectURL(t);try{return await An(n)}finally{URL.revokeObjectURL(n)}})(e).then(n=>Fn(n,e,t),e=>kn(t,e))};$t(),at();const _n=d.source??null;return _n?(Ee=1,Sn(_n)):fn(),{canvas:i,ready:xt,get settings(){return v},update(e){const t=v,{element:n,rest:r}=p(e);"clear"in e&&g?.element!==n?.element?(yn(),g=n,yn=n?ee(n.element,xn):()=>{}):"clear"in e&&(g=n),v=Te(n?{...r,clear:v.clear}:r,v),at(),e.label&&i.setAttribute("aria-label",e.label),v.maxPixelRatio!==t.maxPixelRatio&&Qt(),v.charset===t.charset&&v.cellSize===t.cellSize&&v.cellAspect===t.cellAspect&&v.font===t.font&&v.fontWeight===t.fontWeight&&v.glyphScale===t.glyphScale||(It(),Nt()),v.levels!==t.levels&&qt(),v.scope===t.scope||Ke||(Yt(),Ot=performance.now());((!!t.fluid&&"fluid"===ke(t))!==kt()||v.fluid&&t.fluid&&v.fluid.resolution!==t.fluid.resolution)&&Lt(),"source"in e&&Sn(e.source??null),We=!0,fn()},setSource:Sn,pointer(e,t=0){if(null===e)return void mn(null);const n=i.getBoundingClientRect();mn(dn(n.left+e,n.top+t))},redraw(){if(!(Ye||Ke||$e)&&K)try{Mt(!(yt&&(b?E.canCompileInParallel:S)))&&(cn(),yt||(We=!1))}catch(e){$e=!0,Et(e)}},pulse(e={}){if(Ye||gt())return;const t=i.getBoundingClientRect();if(!t.width||!t.height)return;let n=e.x??t.width/2,r=e.y??t.height/2;if(e.element){const i=e.element.getBoundingClientRect();n=i.left+i.width/2-t.left,r=i.top+i.height/2-t.top}const o=Math.max(0,Math.min(2,e.strength??1));it=[...it,{x:n/t.width,y:r/t.height,born:performance.now(),strength:o}].slice(-4),fn()},play(){Qe=!1,pe instanceof HTMLVideoElement&&pe.play().catch(()=>{}),We=!0,fn()},pause(){Qe=!0,pe instanceof HTMLVideoElement&&pe.pause()},resize(){Qt()&&fn()},destroy(){if(!Ye){if(Ye=!0,Ve&&R(hn),Ve=!1,vn.forEach(e=>e()),b?E.leave(bn):(i.removeEventListener("webglcontextlost",En),i.removeEventListener("webglcontextrestored",wn)),Tn(),Mn(),pe=null,!Ke)if(St(),At(),F.deleteTexture(D),ht&&F.deleteTexture(ht),Ht&&F.deleteTexture(Ht),b)E.releaseAtlas(I,Ct),X?.release();else{F.deleteTexture(_);for(const e of[P,C,U])e&&F.deleteProgram(e.program);X?.dispose(),Y.forEach(e=>F.deleteShader(e)),H&&F.deleteVertexArray(H)}I=null}}}},exports.normalizeFieldSettings=Te,exports.prewarmGlyphAtlas=function(e,t={}){if("undefined"==typeof document||e.ownerDocument!==document)return!1;const n=e.clientWidth,r=e.clientHeight;if(!n||!r)return!1;const i=ae();if(!i||i.lost)return!1;const{clear:o,source:a,interactionTarget:l,onError:s,label:c,...u}=t,h=Te(u),f=Re(h.cellSize,h.cellAspect,Ie(h,n,r,i.scale),be(h.charset).length),d=Ue(h,f);if(i.hasAtlas(d))return!1;try{i.releaseAtlas(i.atlas(d,()=>Be(h,f,!0),Ge),Ge)}catch{return!1}return!0},exports.requestFieldFrame=M,exports.watchMotionPreference=W,exports.watchPointer=O,exports.watchTheme=e=>V(_,e),exports.watchVisibility=j;//# sourceMappingURL=field.cjs.map
|