PageSourceSearch

https://twozero.ai/_app/immutable/chunks/B26VrfiM.js

js twozero.ai collected 2026-10-05 13:13:42 UTC 55,958 bytes, 289 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./_8_OUpGa.js","./PPVm8Dsz.js"])))=>i.map(i=>d[i]);
2import{_ as re}from"./PPVm8Dsz.js";import{a as $,i as Q,F as J,D as O,P as Z,M as oe}from"./DXLP7_vQ.js";const ne=[4,8,12,16,20],Y=[0,5,9,13,17],j=.08;function ee(){return{present:!1,joints:null,smooth:null,vel:null,score:0,pinch:0,pinchX:0,pinchY:0,armed:!1,burst:0,bx:0,by:0,enter:0,calm:0,palmX:0,palmY:0,palmSpeed:1}}class ce{constructor(){this.slots=[ee(),ee()],this.aspect=16/9}get count(){return this.slots.reduce((t,i)=>t+(i.present?1:0),0)}update(t,i,e){const s=this.aspect,a=[null,null],r=[!0,!0];for(const o of t.slice(0,2)){let u=-1,h=1/0;this.slots.forEach((n,l)=>{if(!r[l])return;const d=n.present?((n.joints[0][0]-o.joints[0][0])*s)**2+(n.joints[0][1]-o.joints[0][1])**2:1+l;d<h&&(h=d,u=l)}),r[u]=!1,a[u]=o}const c=1-Math.exp(-i/j);this.slots.forEach((o,u)=>{const h=a[u];if(o.burst*=Math.exp(-i/e.burstTime),o.enter*=Math.exp(-i/.3),!h){o.present=!1,o.pinch=0,o.armed=!1,o.calm+=(0-o.calm)*Math.min(i/.12,1);return}const n=h.joints;o.present||(o.smooth=n.map(b=>[b[0],b[1]]),o.vel=n.map(()=>[0,0]),o.enter=1,o.palmSpeed=e.breakAbove),o.present=!0,o.joints=n,o.score=h.score;for(let b=0;b<21;b++){const w=o.smooth[b];w[0]+=(n[b][0]-w[0])*c,w[1]+=(n[b][1]-w[1])*c,o.vel[b][0]=(n[b][0]-w[0])*s/j,o.vel[b][1]=(n[b][1]-w[1])/j}const l=Math.hypot((n[4][0]-n[8][0])*s,n[4][1]-n[8][1]),d=Math.hypot((n[0][0]-n[9][0])*s,n[0][1]-n[9][1]),y=l/Math.max(d,1e-4);o.pinch=Math.min(Math.max((e.pinchOpen-y)/(e.pinchOpen-e.pinchClosed),0),1),o.pinchX=(n[4][0]+n[8][0])*.5*s,o.pinchY=(n[4][1]+n[8][1])*.5,o.pinch>.7?(o.armed=!0,o.bx=o.pinchX,o.by=o.pinchY):o.armed&&o.pinch<.3&&(o.armed=!1,o.burst=1);let v=0,g=0;for(const b of Y)v+=n[b][0],g+=n[b][1];v=v/Y.length*s,g/=Y.length;const p=Math.hypot(v-o.palmX,g-o.palmY)/Math.max(i,1e-4);o.palmSpeed+=(p-o.palmSpeed)*.2,o.palmX=v,o.palmY=g;const m=Math.min(Math.max((o.palmSpeed-e.calmBelow)/Math.max(e.breakAbove-e.calmBelow,.001),0),1),x=1-m*m*(3-2*m),A=x>o.calm?Math.min(i/e.orbBuild,1):Math.min(i/.12,1);o.calm+=(x-o.calm)*A})}}const le=[[0,0],[-.25,-.12],[-.45,-.28],[-.58,-.45],[-.68,-.6],[-.22,-.72],[-.26,-1.02],[-.28,-1.2],[-.3,-1.36],[0,-.78],[0,-1.1],[0,-1.3],[0,-1.47],[.2,-.72],[.23,-1],[.25,-1.17],[.27,-1.32],[.38,-.6],[.45,-.8],[.5,-.93],[.54,-1.06]];function he(f,t){const i=[];return[{cx:.33,cy:.62,ax:.1,ay:.12,fx:.23,fy:.31,ph:0,mirror:1},{cx:.67,cy:.58,ax:.1,ay:.13,fx:.19,fy:.27,ph:2.1,mirror:-1}].forEach((s,a)=>{const r=(f*.16+a*.5)%1,c=r>.55&&r<.8?Math.sin((r-.55)/.25*Math.PI):0,o=s.cx+s.ax*Math.sin(f*s.fx*2*Math.PI+s.ph),u=s.cy+s.ay*Math.sin(f*s.fy*2*Math.PI+s.ph*.7),h=.17*Math.min(1,t),n=.25*Math.sin(f*.4+a),l=le.map(([d,y],v)=>{let g=d*s.mirror,p=y;if(v>=2&&v<=4||v>=6&&v<=8){const A=-.46*s.mirror,b=-.95,w=v===4||v===8?1:.6;g+=(A-g)*c*w,p+=(b-p)*c*w}const m=g*Math.cos(n)-p*Math.sin(n),x=g*Math.sin(n)+p*Math.cos(n);return[o+m*h/t,u+x*h]});i.push({joints:l,score:.95})}),i}const ue=.5*(Math.sqrt(3)-1),z=(3-Math.sqrt(3))/6,K=[[1,1],[-1,1],[1,-1],[-1,-1],[1,0],[-1,0],[0,1],[0,-1]],G=new Uint8Array(512);{const f=Array.from({length:256},(i,e)=>e);let t=404;for(let i=255;i>0;i--){t=t*16807%2147483647;const e=t%(i+1);[f[i],f[e]]=[f[e],f[i]]}for(let i=0;i<512;i++)G[i]=f[i&255]}function I(f,t){const i=(f+t)*ue,e=Math.floor(f+i),s=Math.floor(t+i),a=(e+s)*z,r=f-(e-a),c=t-(s-a),o=r>c?1:0,u=r>c?0:1,h=r-o+z,n=c-u+z,l=r-1+2*z,d=c-1+2*z,y=e&255,v=s&255;let g=0,p;if(p=.5-r*r-c*c,p>0){p*=p;const m=K[G[y+G[v]]&7];g+=p*p*(m[0]*r+m[1]*c)}if(p=.5-h*h-n*n,p>0){p*=p;const m=K[G[y+o+G[v+u]]&7];g+=p*p*(m[0]*h+m[1]*n)}if(p=.5-l*l-d*d,p>0){p*=p;const m=K[G[y+1+G[v+1]]&7];g+=p*p*(m[0]*l+m[1]*d)}return 70*g}const X=(f,t,i)=>{const e=Math.min(Math.max((f-i*t)/((1-i)*t),0),1);return 1-e*e*(3-2*e)};class fe{constructor(t=4e3){this.max=t,this.n=0,this.x=new Float32Array(t),this.y=new Float32Array(t),this.vx=new Float32Array(t),this.vy=new Float32Array(t),this.age=new Float32Array(t),this.life=new Float32Array(t),this.rnd=new Float32Array(t),this.carry=0,this.t=0}idlePoints(t){const i=[];for(let e=0;e<5;e++)for(let s=0;s<8;s++){const a=(s+.5)/8*t*.9+t*.05,r=(e+.5)/5*.9+.05;i.push([a+.12*I(a*1.7+this.t*.07,r*1.7),r+.12*I(a*1.7+31.4,r*1.7-this.t*.07)])}return i}spawn(t,i,e,s,a){if(this.n>=this.max)return;const r=this.n++;this.x[r]=t,this.y[r]=i,this.vx[r]=e,this.vy[r]=s,this.age[r]=0,this.life[r]=a.life*(1+(Math.random()*2-1)*.4),this.rnd[r]=Math.random()}step(t,i,e,s){this.t+=t;const a=i.slots,r=a.filter(m=>m.present);let c;r.length?c=e.rate*21*r.reduce((m,x)=>m+x.score,0)+e.enterBurst*a.reduce((m,x)=>m+x.enter,0):c=e.idleRate,this.carry+=c*t;let o=Math.floor(this.carry);this.carry-=o;const u=r.length?null:this.idlePoints(s);for(;o-- >0;)if(u){const m=u[Math.random()*u.length|0];this.spawn(m[0],m[1],0,-e.drift,e)}else{const m=r[Math.random()*r.length|0],x=Math.random()*21|0,A=Math.random()*Math.PI*2,b=e.spread*Math.random();this.spawn(m.joints[x][0]*s+(Math.random()-.5)*.006,m.joints[x][
21]+(Math.random()-.5)*.006,m.vel[x][0]*e.follow+Math.cos(A)*b,m.vel[x][1]*e.follow+Math.sin(A)*b-e.drift,e)}const h=[],n=[];for(const m of r){for(const x of ne)h.push([m.joints[x][0]*s,m.joints[x][1]]);for(let x=0;x<21;x++)n.push([m.joints[x][0]*s,m.joints[x][1],m.vel[x][0],m.vel[x][1]])}this.flows=n,this.aspect=s;const l=a.filter(m=>m.present&&m.pinch>.01),d=a.filter(m=>m.burst>.01),y=e.orb>0?a.filter(m=>m.present&&m.calm>.01):[],v=2*e.reach*e.reach,g=Math.exp(-e.drag*t);let p=0;for(let m=0;m<this.n;m++){const x=this.age[m]+t;if(x>this.life[m])continue;let A=this.x[m],b=this.y[m],w=this.vx[m],S=this.vy[m],D=0,U=0;if(e.turbulence>0){const T=2.857142857142857,_=.01,E=this.t*.25,M=I(A*T+E,(b+_)*T-E),R=I(A*T+E,(b-_)*T-E),B=I((A+_)*T+E,b*T-E),H=I((A-_)*T+E,b*T-E);D+=(M-R)/(2*_)*.5*e.turbulence,U-=(B-H)/(2*_)*.5*e.turbulence}const k=Math.min(Math.max((x-.15)*4,0),1);if(k>0&&e.touch>0)for(const[T,_]of h){const E=A-T,M=b-_,R=Math.hypot(E,M);if(R<e.touchRadius&&R>1e-5){const B=e.touch*X(R,e.touchRadius,.3)*k/R;D+=E*B,U+=M*B}}for(const T of l){const _=A-T.pinchX,E=b-T.pinchY,M=Math.hypot(_,E);if(M<e.gatherRadius&&M>1e-5){const R=X(M,e.gatherRadius,.2)*T.pinch;D+=(-_*e.gather+E*e.swirl)*R/M,U+=(-E*e.gather-_*e.swirl)*R/M}}for(const T of d){const _=A-T.bx,E=b-T.by,M=Math.hypot(_,E);if(M<e.gatherRadius&&M>1e-5){const R=e.burst*T.burst*X(M,e.gatherRadius,.3)/M;D+=_*R,U+=E*R}}for(const T of y){const _=A-T.palmX,E=b-T.palmY,M=Math.hypot(_,E);if(M<e.orbRadius&&M>1e-5){const R=X(M,e.orbRadius,.15)*T.calm;D+=(-_*e.orb+E*e.orbSwirl)*R/M,U+=(-E*e.orb-_*e.orbSwirl)*R/M}}if(e.grip>0&&n.length){let T=0,_=0,E=0;for(const[M,R,B,H]of n){const P=(A-M)**2+(b-R)**2;if(P<v*4){const W=Math.exp(-P/v);T+=W,_+=B*W,E+=H*W}}if(T>1e-4){const M=Math.min(T,1);D+=(_/T-w)*e.grip*M,U+=(E/T-S)*e.grip*M}}w=(w+D*t)*g,S=(S+U*t)*g,A+=w*t,b+=S*t,this.x[p]=A,this.y[p]=b,this.vx[p]=w,this.vy[p]=S,this.age[p]=x,this.life[p]=this.life[m],this.rnd[p]=this.rnd[m],p++}this.n=p}}const V=`#version 300 es
3layout(location=0) in vec2 aPos;
4out vec2 vUV;
5void main(){ vUV = aPos * 0.5 + 0.5; gl_Position = vec4(aPos, 0.0, 1.0); }`,me=`#version 300 es
6layout(location=0) in vec2 aCorner;   // unit quad corner, -0.5..0.5
7layout(location=1) in vec4 aInst;     // x, y (mirrored video uv, y down), width, height (fractions of canvas height)
8layout(location=2) in float aAlpha;
9uniform vec2 uScale;                  // cover fit: videoUV = 0.5 + (canvasUV - 0.5) * uScale
10uniform float uAspectC;               // canvas width / height
11out vec2 vCorner; out float vA;
12void main(){
13  vec2 cuv = (aInst.xy - 0.5) / uScale + 0.5;
14  vec2 clip = vec2(cuv.x * 2.0 - 1.0, 1.0 - cuv.y * 2.0);
15  clip += aCorner * aInst.zw * 2.0 * vec2(1.0 / uAspectC, 1.0);
16  vCorner = aCorner * 2.0; vA = aAlpha;
17  gl_Position = vec4(clip, 0.0, 1.0);
18}`,de=`#version 300 es
19precision highp float;
20in vec2 vCorner; in float vA;
21uniform int uKind;                    // 0 lens (beads), 1 soft blob (liquid), 2 bevelled tile, 3 gem profile, 4 blind slat
22uniform vec2 uTile;                   // tiles: x rim height, y bevel width (fraction of half a tile)
23uniform vec4 uCut;                    // gems: x facets, y table radius, z girdle height, w star facets
24uniform vec4 uSlat;                   // slats: x 0 = thickness along V (rows) / 1 = along U (columns), y low edge, z bulge, w end softness
25out vec4 o;
26void main(){
27  float r = length(vCorner);
28  if (uKind == 0) {                   // a glass BEAD: offset ~ sphere normal, so the centre magnifies and
29    float m = 1.0 - smoothstep(0.85, 1.0, r);          // the rim squeezes the picture hard; A = coverage
30    float z = sqrt(max(1.0 - r * r, 0.04));
31    o = vec4(-vCorner / z * 0.55 * m * vA, 0.0, m * vA);
32  } else if (uKind == 1) {
33    float g = exp(-4.0 * r * r) * step(r, 1.0);
34    o = vec4(g * vA, 0.0, 0.0, g * vA);
35  } else if (uKind == 2) {            // tile_profile: flat top, chamfer round the rim, so touching tiles keep a seam
36    float e = max(abs(vCorner.x), abs(vCorner.y));   // and a tile lying over its neighbour shows its edge (max blend)
37    float h = mix(1.0, uTile.x, smoothstep(1.0 - uTile.y, 1.0, e));
38    o = vec4(h * vA, 0.0, 0.0, vA);
39  } else if (uKind == 4) {            // slat_profile: across the slat the height ramps up (a tilted pane, like an
40    vec2 uv = vCorner * 0.5 + 0.5;      // open blind) with a slight bulge; the next slat starts low again -> a seam
41    float a = mix(uv.y, uv.x, uSlat.x), l = mix(uv.x, uv.y, uSlat.x);
42    float h = mix(uSlat.y, 1.0, a) + uSlat.z * sin(3.14159 * a);
43    h *= smoothstep(0.0, uSlat.w, l) * smoothstep(0.0, uSlat.w, 1.0 - l);   // rounded ends
44    o = vec4(h * vA, 0.0, 0.0, vA);
45  } else {                            // gem_profile: flat table, planar crown + star facets down to the girdle
46    float a = atan(vCorner.y, vCorner.x);
47    float seg = 6.2831853 / max(uCut.x, 3.0), tb = uCut.y, gd = uCut.z;
48    float a1 = mod(a + 0.5 * seg, seg) - 0.5 * seg;
49    float crown = mix(1.0, gd, clamp((r * cos(a1) - tb) / max(1.0 - tb, 1e-3), 0.0, 1.0));
50    float a2 = mod(a, seg) - 0.5 * seg;
51    float t2 = tb * (1.0 - 0.6 * uCut.w);
52    float star = mix(1.0 + 0.5 * uCut.w, gd, clamp((r * cos(a2) - t2) / max(1.0 - t2, 1e-3), 0.0, 1.0));
53    float cov = 1.0 - smoothstep(0.96, 1.0, r);
54    float h = min(min(crown, star), 1.0) * cov;
55    o = vec4(h * vA, 0.0, 0.0, cov * vA);
56  }
57}`,N=`
58uniform sampler2D uCam; uniform highp sampler2DArray uPast;
59uniform vec2 uScale; uniform float uAspectC; uniform float uMirror; uniform float uPastOn;
60uniform float uDelay;                 // camera frames the glass looks back (the Time chip)
61uniform vec3 uPastRing;               // x newest layer, y layers filled, z ring size
62uniform vec4 uLadder;                 // staircase: x extra frames per row/column, y rows per cycle, z row size (canvas height), w 0 rows / 1 columns
63vec2 camUV(vec2 uv){ vec2 v = 0.5 + (uv - 0.5) * uScale; v.x = mix(v.x, 1.0 - v.x, uMirror); return clamp(v, 0.0, 1.0); }
64vec3 cam(vec2 uv){ return texture(uCam, camUV(uv)).rgb; }   // the camera keeps its own colours
65// time machine: inside the glass the picture comes from a camera frame N frames ago, outside it is live.
66// ladderDelay: in bands / panes / gems every row (or column) looks a few frames further back.
67float ladderDelay(vec2 uv){
68  if (uLadder.x <= 0.0) return uDelay;
69  float k = uLadder.w < 0.5 ? floor((uv.y - 0.5) / uLadder.z + 0.5) : floor((uv.x - 0.5) * uAspectC / uLadder.z + 0.5);
70  return uDelay + uLadder.x * mod(k, max(uLadder.y, 1.0));
71}
72vec3 camT(vec2 uv, float inside, float delay){
73  vec3 now = cam(uv);
74  if (uPastOn < 0.5) return now;
75  float d = min(floor(delay + 0.5), min(uPastRing.y, uPastRing.z) - 1.0);
76  float layer = mod(uPastRing.x - d + uPastRing.z, uPastRing.z);
77  return mix(now, texture(uPast, vec3(camUV(uv), layer)).rgb, clamp(inside, 0.0, 1.0));
78}`,se=`
79uniform vec4 uFlow[42]; uniform int uFlowN; uniform float uReach2; uniform float uFlowK; uniform float uAspectV;
80uniform vec2 uScaleF;                 // cover fit of the video in the canvas
81vec2 flowUV(vec2 uv){                 // UV offset (canvas) to read the previous frame from
82  if (uFlowN == 0) return vec2(0.0);
83  vec2 p = vec2((0.5 + (uv.x - 0.5) * uScaleF.x) * uAspectV, 0.5 + (0.5 - uv.y) * uScaleF.y);
84  float ws = 0.0; vec2 v = vec2(0.0);
85  for (int i = 0; i < 42; i++) {
86    if (i >= uFlowN) break;
87    vec2 d = p - uFlow[i].xy;
88    float w = exp(-dot(d, d) / uReach2);
89    ws += w; v += uFlow[i].zw * w;
90  }
91  if (ws < 1e-4) return vec2(0.0);
92  v = v / ws * min(ws, 1.0);
93  return vec2(v.x / uAspectV / uScaleF.x, -v.y / uScaleF.y) * uFlowK;
94}`,ve=`#version 300 es
95precision highp float;
96in vec2 vUV; out vec4 o;
97${se}
98uniform sampler2D uAcc, uPrev; uniform float uDecay;
99void main(){
100  vec4 a = texture(uAcc, vUV);
101  float cov = a.a;
102  vec2 off = cov > 1e-4 ? a.rg / cov : vec2(0.0);      // average of overlapping lenses, not their sum
103  off *= min(cov, 1.0);
104  vec4 now = vec4(off, 0.0, min(cov, 1.0));
105  vec4 prev = texture(uPrev, vUV - flowUV(vUV)) * uDecay;
106  o = now + prev * (1.0 - clamp(now.a, 0.0, 1.0));
107}`,pe=`#version 300 es
108precision highp float;
109in vec2 vUV; out vec4 o;
110${N}
111uniform sampler2D uGlass; uniform float uRefr;
112void main(){
113  vec4 g = texture(uGlass, vUV);
114  vec2 k = uRefr * vec2(1.0 / uAspectC, 1.0);
115  float inside = g.a;
116  vec3 col = camT(vUV + g.rg * k, inside, ladderDelay(vUV));   // clear glass: no colour dispersion
117  o = vec4(col, 1.0);                               // (a darker rim was tried: in dense clusters it turned to grey fog)
118}`,ge=`#version 300 es
119precision highp float;
120in vec2 vUV; out vec4 o;
121uniform sampler2D uSrc; uniform vec2 uDir;
122void main(){
123  float w[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
124  vec4 s = texture(uSrc, vUV) * w[0];
125  for (int i = 1; i < 5; i++) s += (texture(uSrc, vUV + uDir * float(i)) + texture(uSrc, vUV - uDir * float(i))) * w[i];
126  o = s;
127}`,xe=`#version 300 es
128precision highp float;
129in vec2 vUV; out vec4 o;
130${se}
131uniform sampler2D uCur, uPrev; uniform float uDecay;
132void main(){ o = max(texture(uCur, vUV), texture(uPrev, vUV - flowUV(vUV)) * uDecay); }`,ae=`
133uniform vec4 uGem;                    // x dispersion, y sparkle, z light angle (turns, animated), w facet contrast
134uniform vec3 uSlatGrid;               // x slat spacing (canvas height), y 0 rows / 1 columns, z on (1) / off (0)
135float fireHash(vec2 c){ return fract(sin(dot(c, vec2(127.1, 311.7))) * 43758.5453); }
136vec3 fireLight(vec2 uv){
137  float k = uSlatGrid.y < 0.5 ? floor((uv.y - 0.5) / uSlatGrid.x + 0.5) : floor((uv.x - 0.5) * uAspectC / uSlatGrid.x + 0.5);
138  float ang = (uGem.z + fireHash(vec2(k, uSlatGrid.y))) * 6.2831853;
139  return normalize(vec3(cos(ang), sin(ang), 0.9));
140}
141vec3 fireCam(vec2 uv, vec2 off, float cover, float delay){   // refraction with dispersion: red bends least, blue most
142  if (uSlatGrid.z < 0.5) return camT(uv + off, cover, delay);
143  return vec3(camT(uv + off * (1.0 - uGem.x), cover, delay).r, camT(uv + off, cover, delay).g,
144              camT(uv + off * (1.0 + uGem.x), cover, delay).b);
145}
146vec3 fireShade(vec3 col, vec3 n, float cover, vec3 Lg){      // facet brilliance + rainbow flash
147  if (uSlatGrid.z < 0.5) return col;
148  float face = dot(normalize(n.xy + 1e-5), Lg.xy);
149  col *= mix(1.0, 0.7 + 0.6 * face, uGem.w * clamp((1.0 - n.z) * 6.0, 0.0, 1.0) * cover);
150  vec3 Hg = normalize(Lg + vec3(0.0, 0.0, 1.0));
151  float flash = pow(max(dot(n, Hg), 0.0), 60.0) * cover;
152  vec3 fire = 0.5 + 0.5 * cos(6.2831853 * (uGem.z + dot(n.xy, vec2(3.0, 2.0)) + vec3(0.0, 0.33, 0.67)));
153  return col + flash * uGem.y * mix(vec3(1.0), fire, 0.6 * uGem.x);
154}`,ye=`#version 300 es
155precision highp float;
156in vec2 vUV; out vec4 o;
157${N}
158${ae}
159uniform sampler2D uDens; uniform vec2 uTexel;
160uniform vec4 uLiq;                    // x surface level, y edge softness, z refraction, w highlight
161uniform float uFlat;                  // 0 liquid, 1 tiles: flat tops, edges refract, 2 blinds: height = the slat profile itself
162uniform float uGrad;                  // blinds: slope scale, so a slat tilts the same at any buffer size
163float dens(vec2 uv){ return texture(uDens, uv).r; }
164float height(vec2 uv){
165  float d = dens(uv);
166  if (uFlat > 1.5) return d * uGrad;
167  if (uFlat > 0.5) d = min(d, uLiq.x + uLiq.y);
168  return smoothstep(uLiq.x, uLiq.x + uLiq.y, d) + 0.15 * d;
169}
170void main(){
171  float cover = smoothstep(uLiq.x, uLiq.x + uLiq.y, dens(vUV));
172  float hx = height(vUV + vec2(uTexel.x, 0.0)) - height(vUV - vec2(uTexel.x, 0.0));
173  float hy = height(vUV + vec2(0.0, uTexel.y)) - height(vUV - vec2(0.0, uTexel.y));
174  vec3 n = normalize(vec3(-hx, -hy, 0.12));
175  vec3 col = fireCam(vUV, n.xy * uLiq.z * cover * vec2(1.0 / uAspectC, 1.0), cover, ladderDelay(vUV));
176  col = fireShade(col, n, cover, fireLight(vUV));
177  vec3 L = normalize(vec3(-0.45, 0.6, 1.0));
178  vec3 H = normalize(L + vec3(0.0, 0.0, 1.0));
179  float spec = pow(max(dot(n, H), 0.0), 80.0) * cover;
180  float rim = pow(1.0 - n.z, 2.0) * cover;
181  col += (spec * 1.3 + rim * 0.4) * uLiq.w;
182  o = vec4(col, 1.0);
183}`,be=`#version 300 es
184precision highp float;
185in vec2 vUV; out vec4 o;
186${N}
187uniform sampler2D uDens; uniform vec2 uTexel;
188uniform vec4 uLiq;                    // x surface level, y edge softness, z refraction, w highlight
189uniform vec4 uLayer;                  // x shade per layer, y shift per layer (canvas uv x), z max layers, w delay per layer
190${ae}
191float dens(vec2 uv){ return texture(uDens, uv).r; }
192void main(){
193  float d = dens(vUV);
194  float cover = smoothstep(uLiq.x, uLiq.x + uLiq.y, d);
195  float extra = clamp(d - 1.0, 0.0, uLayer.z);         // layers above the first
196  float hx = dens(vUV + vec2(uTexel.x, 0.0)) - dens(vUV - vec2(uTexel.x, 0.0));
197  float hy = dens(vUV + vec2(0.0, uTexel.y)) - dens(vUV - vec2(0.0, uTexel.y));
198  vec3 n = normalize(vec3(-hx, -hy, 0.12));
199  float layers = clamp(d, 0.0, uLayer.z + 1.0) * cover; // every pane shifts the camera a bit more
200  vec2 base = vUV + vec2(uLayer.y * layers, 0.0);
201  vec3 col = fireCam(base, n.xy * uLiq.z * cover * vec2(1.0 / uAspectC, 1.0), cover, ladderDelay(vUV) + uLayer.w * extra)
202             * pow(1.0 - uLayer.x, extra);
203  col = fireShade(col, n, cover, fireLight(vUV));
204  vec3 L = normalize(vec3(-0.45, 0.6, 1.0));
205  vec3 H = normalize(L + vec3(0.0, 0.0, 1.0));
206  float spec = pow(max(dot(n, H), 0.0), 80.0) * cover;
207  float rim = pow(1.0 - n.z, 2.0) * cover;
208  o = vec4(col + (spec * 1.3 + rim * 0.4) * uLiq.w, 1.0);
209}`,Te=`#version 300 es
210precision highp float;
211in vec2 vUV; out vec4 o;
212${N}
213uniform sampler2D uDens; uniform vec2 uTexel;
214uniform vec4 uLiq;                    // x surface level, y edge softness, z refraction, w highlight
215uniform vec4 uGem;                    // x dispersion, y sparkle, z light angle (turns, animated), w facet contrast
216uniform vec2 uGrid;                   // x grid cell (canvas height), y facet slope scale (gem size in texels)
217float hgt(vec2 uv){ return texture(uDens, uv).r; }
218float hash(vec2 c){ return fract(sin(dot(c, vec2(127.1, 311.7))) * 43758.5453); }
219void main(){
220  float d = hgt(vUV);
221  float cover = smoothstep(uLiq.x, uLiq.x + uLiq.y, d);
222  float hx = (hgt(vUV + vec2(uTexel.x, 0.0)) - hgt(vUV - vec2(uTexel.x, 0.0))) * uGrid.y;
223  float hy = (hgt(vUV + vec2(0.0, uTexel.y)) - hgt(vUV - vec2(0.0, uTexel.y))) * uGrid.y;
224  vec3 n = normalize(vec3(-hx, -hy, 0.18));
225  float tilt = 1.0 - n.z;
226  float delay = ladderDelay(vUV);
227  vec2 off = n.xy * uLiq.z * cover * vec2(1.0 / uAspectC, 1.0);
228  vec3 col;                                             // red bends least, blue most
229  col.r = camT(vUV + off * (1.0 - uGem.x), cover, delay).r;
230  col.g = camT(vUV + off, cover, delay).g;
231  col.b = camT(vUV + off * (1.0 + uGem.x), cover, delay).b;
232  vec2 cellSize = vec2(uGrid.x / uAspectC, uGrid.x);
233  vec2 cell = floor((vUV - 0.5) / cellSize + 0.5);
234  float ang = (uGem.z + hash(cell)) * 6.2831853;
235  vec3 L = normalize(vec3(cos(ang), sin(ang), 0.9));
236  float face = dot(normalize(n.xy + 1e-5), L.xy);       // facets turned to the light brighten, the rest dim
237  col *= mix(1.0, 0.7 + 0.6 * face, uGem.w * clamp(tilt * 6.0, 0.0, 1.0) * cover);
238  vec3 H = normalize(L + vec3(0.0, 0.0, 1.0));
239  float spec = pow(max(dot(n, H), 0.0), 60.0) * cover;
240  vec3 fire = 0.5 + 0.5 * cos(6.2831853 * (uGem.z + dot(n.xy, vec2(3.0, 2.0)) + vec3(0.0, 0.33, 0.67)));
241  vec3 glint = mix(vec3(1.0), fire, 0.6 * uGem.x);
242  float rim = pow(tilt, 2.0) * cover;
243  o = vec4(col + (spec * uGem.y * glint + rim * 0.3) * uLiq.w, 1.0);
244}`,Ae=`#version 300 es
245precision highp float;
246in vec2 vUV; out vec4 o;
247uniform sampler2D uFrame, uTitle;
248uniform vec2 uTexelT;                 // one texel of the title height map
249uniform float uAspectC, uTitleOn, uRefrT;
250uniform vec2 uTilt;                   // the flat panes' tilt (normal xy)
251uniform vec4 uGem;                    // x dispersion, y sparkle, z light angle (turns, animated), w facet contrast
252uniform vec4 uVeilA;                  // veil darkness at its stops
253uniform vec2 uVeil;                   // x amount (fades with the landing), y 0 = across (desktop) / 1 = down (phone)
254float veil(vec2 uv){
255  if (uVeil.y < 0.5) {
256    float x = uv.x;
257    return x < 0.38 ? mix(uVeilA.x, uVeilA.y, x / 0.38)
258         : x < 0.7  ? mix(uVeilA.y, uVeilA.z, (x - 0.38) / 0.32) : mix(uVeilA.z, uVeilA.w, (x - 0.7) / 0.3);
259  }
260  float y = 1.0 - uv.y;               // from the top
261  return y < 0.6 ? mix(uVeilA.x, uVeilA.y, y / 0.6) : mix(uVeilA.y, uVeilA.z, (y - 0.6) / 0.4);
262}
263float th(vec2 uv){ return texture(uTitle, uv).r; }
264float tHash(float c){ return fract(sin(c * 127.1) * 43758.5453); }
265void main(){
266  vec3 base = mix(texture(uFrame, vUV).rgb, vec3(10.0 / 255.0), veil(vUV) * uVeil.x);
267  float cover = smoothstep(0.2, 0.8, th(vUV)) * uTitleOn;
268  if (cover <= 0.001) { o = vec4(base, 1.0); return; }
269  vec3 n = normalize(vec3(uTilt, 1.0));                                      // one flat, tilted pane
270  vec2 off = n.xy * uRefrT * vec2(1.0 / uAspectC, 1.0);
271  vec3 col = vec3(texture(uFrame, vUV + off * (1.0 - uGem.x)).r, texture(uFrame, vUV + off).g,
272                  texture(uFrame, vUV + off * (1.0 + uGem.x)).b);
273  float ang = (uGem.z + tHash(floor(vUV.x * 14.0))) * 6.2831853;   // its own light for every letter-wide strip
274  vec3 Lg = normalize(vec3(cos(ang), sin(ang), 0.9));
275  float tilt = 1.0 - n.z;
276  col *= mix(1.0, 0.7 + 0.6 * dot(normalize(n.xy + 1e-5), Lg.xy), uGem.w * clamp(tilt * 6.0, 0.0, 1.0));
277  vec3 Hg = normalize(Lg + vec3(0.0, 0.0, 1.0));
278  float flash = pow(max(dot(n, Hg), 0.0), 60.0);
279  vec3 fire = 0.5 + 0.5 * cos(6.2831853 * (uGem.z + dot(n.xy, vec2(3.0, 2.0)) + vec3(0.0, 0.33, 0.67)));
280  vec3 L = normalize(vec3(-0.45, 0.6, 1.0)), H = normalize(L + vec3(0.0, 0.0, 1.0));
281  float spec = pow(max(dot(n, H), 0.0), 80.0);
282  col += (spec * 1.3 + flash * uGem.y * mix(vec3(1.0), fire, 0.6 * uGem.x)) * 0.3;   // highlight as the blinds, no rim
283  o = vec4(mix(base, col, cover), 1.0);
284}`,_e=`#version 300 es
285precision highp float;
286in vec2 vUV; out vec4 o;
287uniform sampler2D uTex;
288void main(){ o = texture(uTex, vUV); }`;function L(f,t,i){const e=(c,o)=>{const u=f.createShader(c);if(f.shaderSource(u,o),f.compileShader(u),!f.getShaderParameter(u,f.COMPILE_STATUS))throw new Error(f.getShaderInfoLog(u)+`
289`+o);return u},s=f.createProgram();if(f.attachShader(s,e(f.VERTEX_SHADER,t)),f.attachShader(s,e(f.FRAGMENT_SHADER,i)),f.linkProgram(s),!f.getProgramParameter(s,f.LINK_STATUS))throw new Error(f.getProgramInfoLog(s));const a={},r=f.getProgramParameter(s,f.ACTIVE_UNIFORMS);for(let c=0;c<r;c++){const o=f.getActiveUniform(s,c).name.replace(/\[0\]$/,"");a[o]=f.getUniformLocation(s,o)}return{p:s,u:a}}class Me{constructor(t){const i=t.getContext("webgl2",{antialias:!1,alpha:!1,premultipliedAlpha:!1,preserveDrawingBuffer:!1});if(!i)throw new Error("WebGL2 is not available in this browser.");this.floatOK=!!(i.getExtension("EXT_color_buffer_float")||i.getExtension("EXT_color_buffer_half_float")),i.getExtension("OES_texture_float_linear"),this.gl=i,this.canvas=t,this.progs={sprite:L(i,me,de),glassTrail:L(i,
289V,ve),beads:L(i,V,pe),blur:L(i,V,ge),densTrail:L(i,V,xe),shade:L(i,V,ye),panes:L(i,V,be),gems:L(i,V,Te),tex:L(i,V,_e),title:L(i,V,Ae)},this.quadVAO=i.createVertexArray(),i.bindVertexArray(this.quadVAO);const e=i.createBuffer();i.bindBuffer(i.ARRAY_BUFFER,e),i.bufferData(i.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),i.STATIC_DRAW),i.enableVertexAttribArray(0),i.vertexAttribPointer(0,2,i.FLOAT,!1,0,0),this.spriteVAO=i.createVertexArray(),i.bindVertexArray(this.spriteVAO);const s=i.createBuffer();i.bindBuffer(i.ARRAY_BUFFER,s),i.bufferData(i.ARRAY_BUFFER,new Float32Array([-.5,-.5,.5,-.5,-.5,.5,.5,.5]),i.STATIC_DRAW),i.enableVertexAttribArray(0),i.vertexAttribPointer(0,2,i.FLOAT,!1,0,0),this.instBuf=i.createBuffer(),i.bindBuffer(i.ARRAY_BUFFER,this.instBuf),i.enableVertexAttribArray(1),i.vertexAttribPointer(1,4,i.FLOAT,!1,20,0),i.vertexAttribDivisor(1,1),i.enableVertexAttribArray(2),i.vertexAttribPointer(2,1,i.FLOAT,!1,20,16),i.vertexAttribDivisor(2,1),i.bindVertexArray(null),this.inst=new Float32Array(5*4096),this.camTex=this._tex(1,1,!1),this.camW=16,this.camH=9,this.fb={},this.w=0,this.h=0,this.mirror=!0,this.pastN=40,this.pastHead=-1,this.pastCount=0,this.delay=15,this.ladder=[0,1,.1,0],this._allocPast(2,2)}_allocPast(t,i){const e=this.gl;this.past&&e.deleteTexture(this.past),this.past=e.createTexture(),e.bindTexture(e.TEXTURE_2D_ARRAY,this.past),e.texStorage3D(e.TEXTURE_2D_ARRAY,1,e.RGBA8,t,i,this.pastN),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),this.pastW=t,this.pastH=i,this.pastHead=-1,this.pastCount=0;const s=e.createTexture();e.bindTexture(e.TEXTURE_2D,s),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,i,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);const a=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,a),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,s,0),this.pastStage={fb:a,tex:s,w:t,h:i}}pushFrame(){const t=this.gl,i=360,e=Math.round(i*this.camW/this.camH);(e!==this.pastW||i!==this.pastH)&&this._allocPast(e,i),this._pass(this.progs.tex,this.pastStage,s=>this._bind(0,this.camTex,s.uTex)),this.pastHead=(this.pastHead+1)%this.pastN,t.bindFramebuffer(t.READ_FRAMEBUFFER,this.pastStage.fb),t.bindTexture(t.TEXTURE_2D_ARRAY,this.past),t.copyTexSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,this.pastHead,0,0,e,i),t.bindFramebuffer(t.READ_FRAMEBUFFER,null),this.pastCount=Math.min(this.pastCount+1,this.pastN)}_tex(t,i,e){const s=this.gl,a=s.createTexture();return s.bindTexture(s.TEXTURE_2D,a),e&&this.floatOK?s.texImage2D(s.TEXTURE_2D,0,s.RGBA16F,t,i,0,s.RGBA,s.HALF_FLOAT,null):s.texImage2D(s.TEXTURE_2D,0,s.RGBA,t,i,0,s.RGBA,s.UNSIGNED_BYTE,null),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MIN_FILTER,s.LINEAR),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MAG_FILTER,s.LINEAR),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),a}_fbo(t,i,e=!0){const s=this.gl,a=this._tex(t,i,e),r=s.createFramebuffer();return s.bindFramebuffer(s.FRAMEBUFFER,r),s.framebufferTexture2D(s.FRAMEBUFFER,s.COLOR_ATTACHMENT0,s.TEXTURE_2D,a,0),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),{fb:r,tex:a,w:t,h:i}}resize(t,i){if(t=Math.max(t|0,2),i=Math.max(i|0,2),t===this.w&&i===this.h&&this.fb.acc)return;this.w=t,this.h=i,this.canvas.width=t,this.canvas.height=i;const e=Math.min(1,960/Math.max(t,i)),s=Math.max(2,Math.round(t*e)),a=Math.max(2,Math.round(i*e));for(const r of["acc","trailA","trailB","dens","blurA","blurB"])this.fb[r]=this._fbo(s,a);this.fb.frame=this._fbo(t,i,!1),this.iw=s,this.ih=a}setCamera(t){const i=this.gl;i.bindTexture(i.TEXTURE_2D,this.camTex),i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!0),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,i.RGBA,i.UNSIGNED_BYTE,t),i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!1),this.camW=t.videoWidth||t.width,this.camH=t.videoHeight||t.height}setTitle(t,i){const e=this.gl,s=t.width,a=t.height;this.titleMask=this.titleMask||this._tex(1,1,!1),e.bindTexture(e.TEXTURE_2D,this.titleMask),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,!0),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,t),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,!1),(!this.fb.titleA||this.fb.titleA.w!==s||this.fb.titleA.h!==a)&&(this.fb.titleA=this._fbo(s,a),this.fb.titleB=this._fbo(s,a));const r=Math.max(i,.5)/4,c=this.fb.titleA,o=this.fb.titleB;this._pass(this.progs.blur,c,u=>{this._bind(0,this.titleMask,u.uSrc),e.uniform2f(u.uDir,r/s,0)}),this._pass(this.progs.blur,o,u=>{this._bind(0,c.tex,u.uSrc),e.uniform2f(u.uDir,0,r/a)}),this.titleTex=o}coverScale(){const t=this.w/this.h,i=this.camW/this.camH;return t>i?[1,i/t]:[t/i,1]}_pass(t,i,e){const s=this.gl;s.bindFramebuffer(s.FRAMEBUFFER,i?i.fb:null),s.viewport(0,0,i?i.w:this.w,i?i.h:this.h),s.useProgram(t.p),e(t.u),s.bindVertexArray(this.quadVAO),s.drawArrays(s.TRIANGLE_STRIP,0,4)}_bind(t,i,e){const s=this.gl;s.activeTexture(s.TEXTURE0+t),s.bindTexture(s.TEXTURE_2D,i),s.uniform1i(e,t)}_camUniforms(t){const i=this.gl,e=this.coverScale();this._bind(0,this.camTex,t.uCam),i.uniform2f(t.uScale,e[0],e[1]),i.uniform1f(t.uAspectC,this.w/this.h),i.uniform1f(t.uMirror,this.mirror?1:0);const s=Math.min(this.delay|0,this.pastN-1),a=s>0&&this.pastCount>1;i.activeTexture(i.TEXTURE5),i.bindTexture(i.TEXTURE_2D_ARRAY,this.past),i.uniform1i(t.uPast,5),i.uniform1f(t.uPastOn,a?1:0),i.uniform1f(t.uDelay,s),i.uniform3f(t.uPastRing,Math.max(this.pastHead,0),this.pastCount,this.pastN),i.uniform4f(t.uLadder,...this.ladder)}_sprites(t,i,e,s,a,r){const c=this.gl,o=this.progs.sprite,u=this.coverScale();c.bindFramebuffer(c.FRAMEBUFFER,t.fb),c.viewport(0,0,t.w,t.h),c.clearColor(0,0,0,0),c.clear(c.COLOR_BUFFER_BIT),e&&(c.useProgram(o.p),c.uniform2f(o.u.uScale,u[0],u[1]),c.uniform1f(o.u.uAspectC,this.w/this.h),c.uniform1i(o.u.uKind,i),a&&c.uniform4f(o.u.uCut,...a),r&&c.uniform4f(o.u.uSlat,...r),i===2&&c.uniform2f(o.u.uTile,this.tileBevel[0],this.tileBevel[1]),c.enable(c.BLEND),c.blendFunc(c.ONE,c.ONE),c.blendEquation(s==="max"?c.MAX:c.FUNC_ADD),c.bindVertexArray(this.spriteVAO),c.bindBuffer(c.ARRAY_BUFFER,this.instBuf),c.bufferData(c.ARRAY_BUFFER,this.inst.subarray(0,e*5),c.DYNAMIC_DRAW),c.drawArraysInstanced(c.TRIANGLE_STRIP,0,4,e),c.disable(c.BLEND),c.blendEquation(c.FUNC_ADD))}setFlow(t,i,e,s,a){const r=Math.min(t?t.length:0,42),c=this.flowArr||(this.flowArr=new Float32Array(168));for(let o=0;o<r;o++)c.set(t[o],o*4);this.flowN=r,this.flowAspect=i,this.flowReach2=2*e*e,this.flowK=s*a}_flowUniforms(t){const i=this.gl,e=this.coverScale();i.uniform4fv(t.uFlow,this.flowArr||new Float32Array(168)),i.uniform1i(t.uFlowN,this.flowN||0),i.uniform1f(t.uReach2,this.flowReach2||.18),i.uniform1f(t.uFlowK,this.flowK||0),i.uniform1f(t.uAspectV,this.flowAspect||1),i.uniform2f(t.uScaleF,e[0],e[1])}_swapTrail(){const t=this.fb.trailA;this.fb.trailA=this.fb.trailB,this.fb.trailB=t}_blur(t){const i=this.fb,e=Math.max(t,.01)/4;return this._pass(this.progs.blur,i.blurA,s=>{this._bind(0,i.dens.tex,s.uSrc),this.gl.uniform2f(s.uDir,e/i.dens.w,0)}),this._pass(this.progs.blur,i.blurB,s=>{this._bind(0,i.blurA.tex,s.uSrc),this.gl.uniform2f(s.uDir,0,e/i.dens.h)}),i.blurB}draw(t,i,e){const s=this.gl,a=this.fb;this.ladder=e.ladder||[0,1,.1,0];const r=this.title||{on:0},c=r.on>.001&&this.titleTex?a.frame:null;if(t==="beads"){this._sprites(a.acc,0,i,"add"),this._pass(this.progs.glassTrail,a.trailA,u=>{this._bind(0,a.acc.tex,u.uAcc),this._bind(1,a.trailB.tex,u.uPrev),s.uniform1f(u.uDecay,e.feedback),this._flowUniforms(u)});const o=a.trailA;this._swapTrail(),this._pass(this.progs.beads,c,u=>{this._camUniforms(u),this._bind(1,o.tex,u.uGlass),s.uniform1f(u.uRefr,e.refraction)})}else{const o={liquid:1,tiles:2,bands:4,panes:4,gems:3}[t];this.tileBevel=[e.bevelRim||.7,e.bevelWidth||.18];const u=t==="liquid"?"add":"max";this._sprites(a.dens,o,i,u,t==="gems"?[e.facets,e.table,e.girdle,e.
289star]:null,o===4?[t==="panes"?1:0,e.slatLow,e.slatBulge,e.slatEnds]:null);const h=this._blur(e.smooth*this.ih/540);this._pass(this.progs.densTrail,a.trailA,d=>{this._bind(0,h.tex,d.uCur),this._bind(1,a.trailB.tex,d.uPrev),s.uniform1f(d.uDecay,e.feedback),this._flowUniforms(d)});const n=a.trailA;this._swapTrail();const l=t==="panes"?this.progs.panes:t==="gems"?this.progs.gems:this.progs.shade;this._pass(l,c,d=>{if(this._camUniforms(d),this._bind(1,n.tex,d.uDens),s.uniform2f(d.uTexel,1/n.w,1/n.h),s.uniform4f(d.uLiq,e.level,e.edge,e.refraction,e.highlight),t==="panes"&&s.uniform4f(d.uLayer,e.layerShade,e.layerShift,e.maxLayers,e.layerDelay),t==="panes"||t==="bands"||t==="tiles"||t==="liquid"){const y=(t==="bands"||t==="panes")&&e.dispersion!==void 0?1:0;s.uniform4f(d.uGem,e.dispersion||0,e.sparkle||0,performance.now()/1e3*(e.sparkleSpeed||0),e.facetContrast||0),s.uniform3f(d.uSlatGrid,e.grid||.1,t==="panes"?1:0,y)}else t==="gems"?(s.uniform4f(d.uGem,e.dispersion,e.sparkle,performance.now()/1e3*e.sparkleSpeed,e.facetContrast),s.uniform2f(d.uGrid,e.grid,Math.max(e.size*.5*n.h/16,.25))):(s.uniform1f(d.uFlat,t==="liquid"?0:2),s.uniform1f(d.uGrad,Math.max(e.grid*n.h/(t==="bands"?13:30),.25)))})}c&&this._pass(this.progs.title,null,o=>{this._bind(0,a.frame.tex,o.uFrame),this._bind(1,this.titleTex.tex,o.uTitle),s.uniform2f(o.uTexelT,1/this.titleTex.w,1/this.titleTex.h),s.uniform1f(o.uAspectC,this.w/this.h),s.uniform1f(o.uTitleOn,r.on),s.uniform1f(o.uRefrT,r.refraction),s.uniform2f(o.uTilt,r.tilt[0],r.tilt[1]),s.uniform4f(o.uGem,r.dispersion,r.sparkle,performance.now()/1e3*r.sparkleSpeed,r.facetContrast),s.uniform4f(o.uVeilA,...r.veilStops),s.uniform2f(o.uVeil,r.veil,r.veilDown?1:0)})}}const F=(f,t,i,e,s,a,r,c,o,u,h,n,l,d,y,v,g)=>({kind:f,lo:t,hi:i,decay:e,density:s,burst:a,idle:r,gain:c,sweep:o,r2:u[0],a2:u[1],r3:u[2],a3:u[3],hid:h,click:n,gateHz:l[0],gateAmt:l[1],gateSq:l[2],wave:d,grid:y,hardpan:v,noise:g}),te={right:{beads:F("blip",9e3,15e3,.012,.6,12,.5,.5,0,[1,0,1,0],1,.4,[0,0,0],"sine",1,1,.35),liquid:F("drone",55,110,0,0,0,0,.6,0,[1,0,1,0],1,0,[0,0,0],"sine",0,0,0),tiles:F("click",3e3,7e3,.001,1,16,.8,.9,0,[1,0,1,0],1,1,[0,0,0],"sine",1,1,.5),bands:F("slats",6e3,1e4,.02,1,8,.4,.55,0,[2.756,.35,5.404,.15],.4,.6,[0,0,0],"sine",0,0,.4),panes:F("tone",4e3,8e3,.08,.2,4,.2,.4,0,[1.004,1,2,.1],.6,.3,[0,0,0],"sine",1,1,.3),gems:F("glitch",12e3,16e3,.006,.8,20,.6,.35,0,[1.5,.4,1,0],.5,.4,[80,.8,1],"sine",1,1,.4)},left:{beads:F("blip",7e3,12e3,.015,.6,12,.5,.5,0,[1,0,1,0],1,.4,[0,0,0],"sine",0,0,.35),liquid:F("drone",41,82,0,0,0,0,.6,0,[1,0,1,0],1,0,[0,0,0],"sine",0,0,0),tiles:F("noise",2e3,5e3,.03,.8,12,.5,.5,0,[1,0,1,0],1,.3,[20,.9,1],"noise",0,0,0),bands:F("slats",3500,7e3,.03,1,8,.3,.6,0,[2.32,.45,4.25,.2],.5,.5,[0,0,0],"sine",0,0,.4),panes:F("pad",3500,7e3,.1,.15,3,.15,.4,0,[1.5,.5,2.01,.3],.6,.3,[0,0,0],"sine",0,0,.3),gems:F("laser",4e3,9e3,.04,.8,14,.6,.4,-3,[2,.2,1,0],.5,.3,[0,0,0],"sine",0,0,.3)}},Ee=[4,8,12,16,20],we=120,Re=40,Se=8;function Ue(f){const t=Math.exp(-f);let i=0,e=1;do i++,e*=Math.random();while(e>t&&i<20);return i-1}const C=(f,t)=>f+Math.random()*(t-f);class Fe{constructor(){this.ctx=null,this.on=!1,this.dest=null,this.active=0,this.st=[0,1].map(()=>({seen:!1,prev:null,row:null,burst:0})),this.hitsThisFrame=0}async enable(){if(!this.ctx){const t=window.AudioContext||window.webkitAudioContext;if(!t)return!1;const i=this.ctx=new t;this.master=i.createGain(),this.master.gain.value=.8;const e=i.createDynamicsCompressor();e.threshold.value=-26,e.knee.value=4,e.ratio.value=8,e.attack.value=.001,e.release.value=.06;const s=i.createGain();s.gain.value=2.2;const a=i.createDynamicsCompressor();a.threshold.value=-3,a.knee.value=0,a.ratio.value=20,a.attack.value=.001,a.release.value=.05,this.master.connect(e),e.connect(s),s.connect(a),a.connect(i.destination),i.createMediaStreamDestination&&(this.dest=i.createMediaStreamDestination(),a.connect(this.dest));const r=i.createBuffer(1,i.sampleRate*2,i.sampleRate),c=r.getChannelData(0);for(let o=0;o<c.length;o++)c[o]=Math.random()*2-1;this.noise=r,this.streams={right:this.makeStream(9),left:this.makeStream(-11)}}try{await this.ctx.resume()}catch{return!1}return this.on=!0,this.ctx.state==="running"}makeStream(t){const i=this.ctx,e=i.createBiquadFilter();e.type="lowpass",e.frequency.value=150,e.Q.value=1.2;const s=[["sawtooth",1,.35,0],["sawtooth",1,.35,t],["sine",.5,.6,0]].map(([c,o,u,h])=>
289{const n=i.createOscillator();n.type=c,n.frequency.value=60*o,n.detune.value=h;const l=i.createGain();return l.gain.value=u,n.connect(l),l.connect(e),n.start(),{o:n,ratio:o}}),a=i.createGain();a.gain.value=0,e.connect(a);let r=null;return i.createStereoPanner?(r=i.createStereoPanner(),a.connect(r),r.connect(this.master)):a.connect(this.master),{osc:s,lp:e,g:a,p:r,lvl:0,swell:0,speed:0}}disable(){this.on=!1,this.ctx&&this.ctx.suspend().catch(()=>{})}get running(){return this.on&&this.ctx&&this.ctx.state==="running"}pitch(t,i,e=.1){return t=Math.min(Math.max(t,0),1),i.lo*Math.pow(i.hi/i.lo,t)*C(1-e,1+e)}rowFreq(t,i){return(t%2+2)%2?i.hi*.82:i.hi}hit(t,i,e,s,a,r=.1,c=null){if(this.hitsThisFrame>=Se)return;this.hitsThisFrame++;let u=this.ctx.currentTime+.01+t;if(a.grid){const l=60/we/4;u=Math.ceil(u/l)*l}let h=Math.min(Math.max(e,0),1);a.hardpan&&(h=h<.33?0:h>.66?1:.5);const n=c||this.pitch(i,a,r);this.play(u,n,h,s*a.gain,a),a.kind==="heart"&&this.play(u+.18,n*.94,h,s*a.gain*.7,a)}play(t,i,e,s,a){if(this.active>=Re)return;const r=this.ctx,c=Math.min(a.decay*6+.05,8),o=(v,g)=>{const p=r.createGain();return p.gain.setValueAtTime(0,t),p.gain.linearRampToValueAtTime(g,t+5e-4),p.gain.setTargetAtTime(0,t+5e-4,Math.max(v,3e-4)/3),p},u=r.createGain();u.gain.value=s;let h=u;if(r.createStereoPanner){const v=r.createStereoPanner();v.pan.value=e*2-1,u.connect(v),h=v}h.connect(this.master);const n=r.createGain(),l=[];if(a.gateAmt>0){const v=r.createGain();v.gain.value=1-a.gateAmt/2;const g=r.createOscillator();g.type=a.gateSq?"square":"sine",g.frequency.value=Math.max(a.gateHz,.01);const p=r.createGain();p.gain.value=a.gateAmt/2,g.connect(p),p.connect(v.gain),n.connect(v),v.connect(u),l.push(g)}else n.connect(u);const d=i*Math.pow(2,-a.sweep),y=(v,g,p)=>{const m=r.createOscillator();m.type=a.wave==="triangle"||a.wave==="square"?a.wave:"sine",m.frequency.setValueAtTime(d*v,t),a.sweep&&m.frequency.exponentialRampToValueAtTime(i*v,t+.012);const x=r.createGain();x.gain.value=g,m.connect(x),x.connect(p),p.connect(n),l.push(m)};if(a.wave==="noise"){const v=r.createBufferSource();v.buffer=this.noise,v.loop=!0;const g=r.createBiquadFilter();g.type="highpass",g.frequency.value=Math.min(Math.max(i*.7,2e3),12e3);const p=o(a.decay,1);v.connect(g),g.connect(p),p.connect(n),l.push(v)}else y(1,1,o(a.decay,1));if(a.a2>0||a.a3>0){const v=o(a.decay*a.hid,1);a.a2>0&&y(a.r2,a.a2,v),a.a3>0&&y(a.r3,a.a3,v)}if(a.noise>0){const v=r.createBufferSource();v.buffer=this.noise,v.loop=!0;const g=r.createBiquadFilter();g.type="highpass",g.frequency.value=Math.min(Math.max(i*.7,2500),12e3);const p=o(Math.max(a.decay*.8,.004),a.noise);v.connect(g),g.connect(p),p.connect(n),l.push(v)}if(a.click>0){const v=r.createBufferSource();v.buffer=this.noise;const g=r.createBiquadFilter();g.type="highpass",g.frequency.value=3e3;const p=o(8e-4,a.click);v.connect(g),g.connect(p),p.connect(n),l.push(v)}this.active++,l.forEach(v=>{v.start(t),v.stop(t+c)}),l[0].onended=()=>{this.active--;try{u.disconnect()}catch{}}}update(t,i,e,s){if(!this.running)return;this.hitsThisFrame=0;const a=i.slots,r=i.aspect||16/9,c=[0,1].filter(h=>a[h].present),o={};if(c.length===2){const h=a[c[0]].joints[0][0]>=a[c[1]].joints[0][0]?c[0]:c[1];c.forEach(n=>{o[n]=n===h?"right":"left"})}else c.forEach(h=>{o[h]=a[h].joints[0][0]>=.5?"right":"left"});const u={right:null,left:null};if(a.forEach((h,n)=>{const l=this.st[n];if(!h.present){l.seen=!1,l.prev=null,l.row=null,l.burst=0;return}const d=te[o[n]][e],y=h.joints,v=Ee.map(m=>[y[m][0],1-y[m][1]]),g=v.reduce((m,x)=>m+x[0],0)/5,p=v.reduce((m,x)=>m+x[1],0)/5;if(d.kind==="drone"){const m=this.streams[o[n]];let x=0;const A=this.ctx.currentTime;l.prev&&l.t!==void 0&&(v.forEach(([b,w],S)=>{x+=Math.hypot(b-l.prev[S][0],w-l.prev[S][1])}),x/=5*Math.max(A-l.t,.001)),l.t=A,l.seen||(m.swell=Math.max(m.swell,.35)),h.burst>l.burst+.5&&(m.swell=1),u[o[n]]={v:d,speed:x,cx:g,cy:p},l.burst=h.burst,l.seen=!0,l.prev=v;return}
289if(!l.seen)[0,.07,.15].forEach((m,x)=>this.hit(m,p+.08*x,g,.5,d));else if(l.prev)if(d.kind==="slats"&&s){const m=s(y[8][1]);if(l.row!==null&&m!==l.row){const x=Math.hypot(v[1][0]-l.prev[1][0],v[1][1]-l.prev[1][1])/Math.max(t,.001),A=m>l.row?1:-1;for(let b=0;b<Math.min(Math.abs(m-l.row),2);b++){const w=l.row+(b+1)*A;this.hit(0,.5,v[1][0],Math.min(.35+.4*x,1),d,0,this.rowFreq(-w,d))}}}else d.density>0&&v.forEach(([m,x],A)=>{const[b,w]=l.prev[A],S=Math.hypot(m-b,x-w)/Math.max(t,.001),D=Math.min(Ue(d.density*2.2*Math.max(0,S-.08)*t),2);for(let U=0;U<D;U++)this.hit(C(0,t),x,m,Math.min(.3+.35*S,1)*C(.55,1),d)});if(d.kind==="slats"&&s&&(l.row=s(y[8][1])),h.burst>l.burst+.5){const m=h.bx/r,x=1-h.by;for(let A=0;A<d.burst;A++)this.hit(.45*Math.pow(Math.random(),1.8),x+C(-.25,.25),m+C(-.3,.3),C(.35,.9),d,.15)}l.burst=h.burst,l.seen=!0,l.prev=v}),!c.length){const h=te.right[e];h.idle>0&&Math.random()<h.idle*t&&this.hit(0,C(0,.4),C(.2,.8),C(.3,.6),h),h.kind==="drone"&&(u.idle=h)}this.steerStreams(t,u)}steerStreams(t,i){const e=this.ctx.currentTime;for(const s of["right","left"]){const a=this.streams[s],r=i[s];a.swell*=Math.exp(-t/.5);let c=0,o=150,u=null,h=null;if(r){a.speed+=(r.speed-a.speed)*Math.min(t/.08,1);const l=Math.pow(Math.min(Math.max((a.speed-.05)/1.6,0),1),.8);c=Math.min(.3+.7*l+.5*a.swell,1)*r.v.gain,o=120*Math.pow(2500/120,Math.min(.15+.75*l+.4*a.swell,1)),u=r.v.lo*Math.pow(r.v.hi/r.v.lo,Math.min(Math.max(r.cy,0),1)),h=r.cx*2-1}else if(a.speed=0,s==="right"&&i.idle){const l=i.idle;c=.15*l.gain,o=140,u=Math.sqrt(l.lo*l.hi),h=0}const n=c>a.lvl?.15:.6;a.g.gain.setTargetAtTime(c,e,n),a.lp.frequency.setTargetAtTime(o,e,.12),u&&a.osc.forEach(({o:l,ratio:d})=>l.frequency.setTargetAtTime(u*d,e,.4)),a.p&&h!==null&&a.p.pan.setTargetAtTime(h,e,.2),a.lvl=c}}}const De="#c92a1d";function q(f,t,i,e,s,a="overlay",r=!0){const c=Math.max(2,Math.round(e)),o=Math.max(2,Math.round(e*i/t)),u=document.createElement("canvas");u.width=c,u.height=o;const h=u.getContext("2d"),n=h.createImageData(c,o);for(let l=0;l<c*o;l++){const d=Math.random()*255;n.data[l*4]=n.data[l*4+1]=n.data[l*4+2]=d,n.data[l*4+3]=255}h.putImageData(n,0,0),f.save(),f.globalAlpha=s,f.globalCompositeOperation=a,f.imageSmoothingEnabled=r,f.imageSmoothingQuality="high",f.drawImage(u,0,0,t,i),f.restore()}function Le(f,t){const i=document.createElement("canvas");i.width=f,i.height=t;const e=i.getContext("2d");e.fillStyle="#5b5b59",e.fillRect(0,0,f,t),q(e,f,t,4,.26),q(e,f,t,14,.24),q(e,f,t,48,.2),q(e,f,t,180,.16);for(let n=0;n<14;n++){const l=Math.random()*f,d=Math.random()*t,y=(.08+Math.random()*.2)*f,v=e.createRadialGradient(l,d,0,l,d,y);v.addColorStop(0,`rgba(20,20,20,${.12+Math.random()*.18})`),v.addColorStop(1,"rgba(20,20,20,0)"),e.fillStyle=v,e.fillRect(l-y,d-y,2*y,2*y)}const s=t/3;for(let n=1;n<3;n++){const l=n*s+(Math.random()-.5)*6;e.fillStyle="rgba(15,15,15,0.55)",e.fillRect(0,l,f,2),e.fillStyle="rgba(255,255,255,0.08)",e.fillRect(0,l+2,f,1)}const a=f/2.4;for(let n=a*(.4+Math.random()*.3);n<f;n+=a)e.fillStyle="rgba(15,15,15,0.45)",e.fillRect(n,0,2,t);e.strokeStyle="rgba(12,12,12,0.55)",e.lineWidth=1;for(let n=0;n<5;n++){let l=Math.random()*f,d=Math.random()*t,y=Math.random()*Math.PI*2;e.beginPath(),e.moveTo(l,d);for(let v=0;v<40;v++)y+=(Math.random()-.5)*.9,l+=Math.cos(y)*7,d+=Math.sin(y)*7,e.lineTo(l,d);e.stroke()}for(let n=0;n<f*t/900;n++){const l=Math.random()*f,d=Math.random()*t,y=.6+Math.random()**3*3;e.fillStyle="rgba(10,10,10,0.7)",e.fillRect(l,d,y,y*.8),e.fillStyle="rgba(255,255,255,0.12)",e.fillRect(l,d+y*.8,y,1)}const r=Math.min(f*.15,t*.2),c=document.createElement("canvas");c.width=f,c.height=t;const o=c.getContext("2d");o.font=`700 ${r}px "Space Grotesk", "Arial Black", sans-serif`,o.textAlign="center",o.textBaseline="middle",o.fillStyle=De;const u=t>f?t*.7:t/2;o.fillText("404.ZERO",f/2,u),o.fillRect(f/2-r*3.1,u+r*.62,r*6.2,r*.07),o.globalCompositeOperation="destination-out";for(let n=0;n<f*t/60;n++)o.fillStyle=`rgba(0,0,0,${Math.random()*.8})`,o.fillRect(Math.random()*f,Math.random()*t,1+Math.random()*2,1+Math.random()*2);
289e.save(),e.globalAlpha=.9,e.drawImage(c,0,0),e.restore(),e.save(),e.strokeStyle="rgba(235,235,230,0.75)",e.fillStyle="rgba(235,235,230,0.75)",e.lineWidth=2;const h=(n,l,d)=>{e.beginPath(),e.moveTo(n-d,l),e.lineTo(n+d,l),e.moveTo(n,l-d),e.lineTo(n,l+d),e.stroke()};return h(f*.2,t*.24,14),h(f*.83,t*.72,14),e.font=`400 ${Math.round(r*.16)}px "PT Mono", monospace`,e.textAlign="left",e.fillText("+0.404",f*.2+22,t*.24-10),e.fillText("B-04",f*.83+22,t*.72-10),e.restore(),q(e,f,t,f/2,.3,"overlay",!1),i}class ke{constructor(){this.wall=null,this.frame=null}reset(){this.wall=null}draw(t=1280,i=720,e=0){const s=Math.round(t*1.3),a=Math.round(i*1.3);(!this.wall||this.wall.width!==s||this.wall.height!==a)&&(this.wall=Le(s,a)),(!this.frame||this.frame.width!==t||this.frame.height!==i)&&(this.frame=document.createElement("canvas"),this.frame.width=t,this.frame.height=i);const r=this.frame.getContext("2d"),c=this.wall,o=(.5+.5*Math.sin(e*.11))*(s-t),u=(.5+.5*Math.sin(e*.083+1.3))*(a-i);r.drawImage(c,-o,-u);const h=t*(.5+.38*Math.sin(e*.37)),n=i*(.5+.32*Math.sin(e*.53+.7)),l=Math.max(t,i)*.45,d=r.createRadialGradient(h,n,0,h,n,l);d.addColorStop(0,"rgba(255,255,255,0.28)"),d.addColorStop(1,"rgba(255,255,255,0)"),r.save(),r.globalCompositeOperation="soft-light",r.fillStyle=d,r.fillRect(0,0,t,i),r.restore();const y=r.createRadialGradient(t/2,i/2,Math.min(t,i)*.3,t/2,i/2,Math.max(t,i)*.75);return y.addColorStop(0,"rgba(0,0,0,0)"),y.addColorStop(1,"rgba(0,0,0,0.55)"),r.fillStyle=y,r.fillRect(0,0,t,i),this.frame}}const Ve=250,Ce=12e3,Ge=4e3;function ie(f){const t=f&&f.name;return t==="NotAllowedError"||t==="SecurityError"?"blocked":t==="NotFoundError"||t==="OverconstrainedError"?"none":t==="NotReadableError"||t==="AbortError"?"busy":"other"}class ze{constructor(t,{onState:i=()=>{},onClip:e=()=>{},look:s=$,delay:a=J,debug:r=!1}={}){this.canvas=t,this.onState=i,this.onClip=e,this.debug=r,this.renderer=new Me(t),this.renderer.mirror=!1,this.hands=new ce,this.sim=new fe(4e3),this.sound=new Fe,this.wall=new ke,this.video=document.createElement("video"),this.video.playsInline=!0,this.video.muted=!0,this.video.autoplay=!0,this.video.setAttribute("playsinline",""),this.look=Q(s)?s:$,this.delayIdx=O[a]?a:J,this.renderer.delay=O[this.delayIdx].frames,this.source="demo",this.facing="user",this.stream=null,this.tracker=null,this.trackerLoading=null,this.camToken=0,this.rec=null,this.chunks=[],this.recStart=0,this.recTimer=0,this.detected=[],this.last=performance.now(),this.lastVideoTime=-1,this.lastDemoFrame=-1/0,this.coachUntil=0,this.handsSeenAt=0,this.fpsAvg=60,this.statusAt=0,this.raf=0,this.alive=!0,this.state={look:this.look,delay:this.delayIdx,source:"demo",camera:"off",cameraError:null,track:"demo",hands:0,fps:0,sound:!1,soundUnavailable:!1,rec:!1,recSeconds:0,canRecord:typeof t.captureStream=="function"&&typeof window.MediaRecorder=="function",canFlip:!1,coaching:!1,lost:!1},this._frame=this._frame.bind(this),this._rowOfBands=c=>{const o=this.renderer.coverScale(),u=(c-.5)/o[1]+.5;return Math.round((u-.5)/Z.bands.grid)},this._onLost=c=>{c.preventDefault(),this._set({lost:!0})},t.addEventListener("webglcontextlost",this._onLost),document.fonts&&document.fonts.ready&&document.fonts.ready.then(()=>this.wall.reset())}start(){!this.alive||this.raf||(this.last=performance.now(),this.raf=requestAnimationFrame(this._frame),this._emit())}_set(t){Object.assign(this.state,t),this._emit()}_emit(){try{this.onState({...this.state})}catch(t){console.warn("[glass-hands] onState",t)}}setLook(t){!Q(t)||t===this.look||(this.look=t,this._set({look:t}))}setDelay(t){const i=O.length;this.delayIdx=(t%i+i)%i,this.renderer.delay=O[this.delayIdx].frames,this._set({delay:this.delayIdx})}nextDelay(){this.setDelay(this.delayIdx+1)}async setSound(t){let i=!1;if(t?i=await this.sound.enable():this.sound.disable(),!this.alive)return!1;const e=!!(t&&i&&this.sound.running);return this._set({sound:e,soundUnavailable:!!t&&!i}),e}_stopStream(){this.stream&&this.stream.getTracks().forEach(t=>t.stop()),this.stream=null}async _openCamera(){const t=typeof navigator<"u"?navigator.mediaDevices:null;if(!t||!t.getUserMedia)return"insecure";this._stopStream();const i=[{video:{facingMode:this.facing,width:{ideal:1280},height:{ideal:720}},audio:!1},{video:{facingMode:this.facing},audio:!1},{video:!0,audio:!1}];let e=null;for(const s of i){let a=null;try{return a=await t.getUserMedia(s),this.alive?(this.stream=a,this.video.srcObject=a,await this.video.play(),null):(a.getTracks().forEac
289h(r=>r.stop()),"gone")}catch(r){if(e=r,a&&a!==this.stream&&a.getTracks().forEach(o=>o.stop()),console.warn("[glass-hands] getUserMedia",r&&r.name,r&&r.message),ie(r)==="blocked")break}}return this._stopStream(),ie(e)}_loadTracker(){return this.trackerLoading||(this.trackerLoading=re(()=>import("./_8_OUpGa.js"),__vite__mapDeps([0,1]),import.meta.url).then(t=>t.createTracker()).then(t=>this.alive?(this.tracker=t,t):(t.close(),null)).catch(t=>{throw console.warn("[glass-hands] tracker",t),this.trackerLoading=null,t})),this.trackerLoading}_trackLive(){this.coachUntil=performance.now()+Ce,this.handsSeenAt=0,this._set({track:"live"})}async startCamera(){const t=++this.camToken;this._set({camera:"starting",cameraError:null}),this._loadTracker().catch(()=>{});const i=await this._openCamera();return!this.alive||t!==this.camToken?!1:i?(this._set({camera:this.source==="camera"?"on":"error",cameraError:i==="gone"?null:i}),!1):(this.source="camera",this.renderer.mirror=this.facing==="user",this.lastVideoTime=-1,this.detected=[],this._set({source:"camera",camera:"on",cameraError:null}),this._countCameras(),this.tracker?this._trackLive():await this.retryTracking(),!0)}async _countCameras(){try{const i=(await navigator.mediaDevices.enumerateDevices()).filter(e=>e.kind==="videoinput").length;this.alive&&this._set({canFlip:i>1})}catch{}}async retryTracking(){if(this.tracker)return this.source==="camera"&&this._trackLive(),!0;this._set({track:"loading"});try{return await this._loadTracker(),this.alive?(this.source==="camera"&&this._trackLive(),!0):!1}catch{return this.alive&&this._set({track:"error"}),!1}}useDemo(){++this.camToken,this._stopStream(),this.video.srcObject=null,this.source="demo",this.renderer.mirror=!1,this.detected=[],this.lastDemoFrame=-1/0,this._set({source:"demo",camera:"off",cameraError:null,track:"demo",canFlip:!1,coaching:!1,hands:0})}async flipCamera(){if(this.source!=="camera")return;this.facing=this.facing==="user"?"environment":"user";let t=await this._openCamera();t&&this.alive&&(this.facing=this.facing==="user"?"environment":"user",await this._openCamera(),this._set({cameraError:t==="gone"?null:t})),this.alive&&(this.renderer.mirror=this.facing==="user",this.lastVideoTime=-1)}toggleRecord(){if(this.rec){this.rec.stop();return}if(!this.state.canRecord)return;const t=this.canvas.captureStream(30),i=this.sound.running&&this.sound.dest?this.sound.dest.stream.getAudioTracks()[0]:null;i&&t.addTrack(i);const s=(i?["video/mp4;codecs=avc1,mp4a.40.2","video/mp4","video/webm;codecs=vp9,opus","video/webm;codecs=vp8,opus","video/webm"]:["video/mp4;codecs=avc1","video/mp4","video/webm;codecs=vp9","video/webm"]).find(r=>MediaRecorder.isTypeSupported(r));let a;try{a=new MediaRecorder(t,s?{mimeType:s,videoBitsPerSecond:12e6}:void 0)}catch{t.getVideoTracks().forEach(c=>c.stop()),this._set({canRecord:!1});return}this.rec=a,this.chunks=[],a.ondataavailable=r=>{r.data&&r.data.size&&this.chunks.push(r.data)},a.onstop=()=>{clearTimeout(this.recTimer);const r=a.mimeType||s||"video/webm",c=new Blob(this.chunks,{type:r}),o=(performance.now()-this.recStart)/1e3;if(this.chunks=[],t.getVideoTracks().forEach(h=>h.stop()),this.rec=null,!this.alive)return;this._set({rec:!1,recSeconds:0});const u=r.includes("mp4")?"mp4":"webm";this.onClip({blob:c,mime:r,ext:u,name:`glass-hands-${this.look}.${u}`,seconds:o,look:this.look,sound:!!i})},a.start(250),this.recStart=performance.now(),this.recTimer=setTimeout(()=>this.rec&&this.rec.stop(),oe*1e3),this._set({rec:!0,recSeconds:0})}_buildInstances(t,i){const e=this.look,s=this.sim,a=this.renderer,r=a.inst,c=Math.min(s.n,4096),o=a.coverScale(),u=a.w/a.h;let h=0;for(let n=0;n<c;n++){const l=1-s.age[n]/s.life[n],d=s.rnd[n],y=1-t.sizeVar+t.sizeVar*d*d;let v=s.x[n]/i,g=s.y[n],p=t.size*y,m=l;e==="beads"&&(p*=l);const x=t.wobble||0,A=x*Math.sin(2*Math.PI*(s.t*.35+d*7))*o[0]/u,b=x*Math.cos(2*Math.PI*(s.t*.29+d*5))*o[1];if(e==="beads"){v+=A,g+=b;const k=.5+.5*Math.sin(2*Math.PI*(d*3.7+s.t*t.pulseSpeed));p*=t.pulseMin+(1-t.pulseMin)*k}let w=p,S=p;const D=.5+.5*Math.sin(2*Math.PI*(d+s.t*(t.pulseSpeed||0))),U=t.pulseMin!==void 0?t.pulseMin+(1-t.pulseMin)*D:1;if(e==="tiles"||e==="gems"||e==="bands"||e==="panes"){let k=(v-.5)/o[0]+.5,T=(g-.5)/
289o[1]+.5;const _=t.grid,E=.5+Math.round((k-.5)*u/_)*_/u,M=.5+Math.round((T-.5)/_)*_;e==="bands"?T=M:e==="panes"?k=E:(k=E,T=M),v=.5+(k-.5)*o[0]+(e==="tiles"||e==="gems"?A:0),g=.5+(T-.5)*o[1]+(e==="tiles"||e==="gems"?b:0),e==="bands"?(w=t.length*y,S=_,m*=U):e==="panes"?(w=_,S=t.length*y,m*=U):w=S=p*U}r[h++]=v,r[h++]=g,r[h++]=w,r[h++]=S,r[h++]=m}return c}_frame(t){if(this.raf=0,!this.alive)return;const i=Math.min((t-this.last)/1e3,1/20);this.last=t;const e=this.canvas,s=this.renderer,a=Math.min(window.devicePixelRatio||1,2);s.resize(Math.round(e.clientWidth*a),Math.round(e.clientHeight*a));const r=Z[this.look];let c;if(this.source==="demo"){if(t-this.lastDemoFrame>1e3/30){this.lastDemoFrame=t;const h=e.clientWidth/Math.max(e.clientHeight,1),n=h>=1?1280:Math.round(1280*h),l=h>=1?Math.round(1280/h):1280;s.setCamera(this.wall.draw(n,l,t/1e3)),s.pushFrame()}c=s.camW/s.camH,this.detected=he(t/1e3,c)}else{const h=this.video;if(h.readyState>=2&&h.currentTime!==this.lastVideoTime&&(this.lastVideoTime=h.currentTime,s.setCamera(h),s.pushFrame(),this.tracker))try{const n=this.facing==="user";this.detected=this.tracker.detect(h,t).map(l=>({score:l.score,joints:n?l.joints.map(([d,y])=>[1-d,y]):l.joints}))}catch(n){console.warn("[glass-hands] detect",n)}c=(h.videoWidth||16)/(h.videoHeight||9)}this.hands.aspect=c,this.hands.update(this.detected,i,r),this.sound.update(i,this.hands,this.look,this.look==="bands"?this._rowOfBands:null),this.sim.step(i,this.hands,r,c),s.setFlow(this.sim.flows,c,r.reach,r.trailFollow,i),s.draw(this.look,this._buildInstances(r,c),r);const o=this.hands.count;this.source==="camera"&&o>0&&!this.handsSeenAt&&(this.handsSeenAt=t);const u=this.source==="camera"&&this.state.track==="live"&&t<this.coachUntil&&(!this.handsSeenAt||t-this.handsSeenAt<Ge);if(u!==this.state.coaching&&this._set({coaching:u}),this.fpsAvg+=(1/Math.max(i,.001)-this.fpsAvg)*.1,t-this.statusAt>=Ve){this.statusAt=t;const h={};o!==this.state.hands&&(h.hands=o);const n=this.rec?Math.floor((t-this.recStart)/1e3):0;n!==this.state.recSeconds&&(h.recSeconds=n);const l=Math.round(this.fpsAvg);this.debug&&l!==this.state.fps&&(h.fps=l),Object.keys(h).length&&this._set(h)}this.raf=requestAnimationFrame(this._frame)}destroy(){if(!this.alive)return;if(this.alive=!1,this.raf&&cancelAnimationFrame(this.raf),this.raf=0,clearTimeout(this.recTimer),this.rec)try{this.rec.stop()}catch{}this._stopStream(),this.video.srcObject=null,this.tracker&&this.tracker.close(),this.tracker=null,this.sound.ctx&&this.sound.ctx.close().catch(()=>{}),this.canvas.removeEventListener("webglcontextlost",this._onLost);const t=this.renderer.gl.getExtension("WEBGL_lose_context");t&&t.loseContext()}}export{ze as GlassHandsEngine};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.