1import{r as p,j as S}from"./index-_Sg_1KT6.js";import{u as lt}from"./useCanvas-DRXw8nFR.js";import{u as dt}from"./useMouseInteraction-DqIzV1q4.js";import{E as ut}from"./ExperimentControls-DmwC3FZh.js";import{E as ft}from"./ExperimentMetrics-D-l2z47K.js";import{E as mt}from"./ExperimentNav-CPfQyQAJ.js";const e=128,Y=(e+2)*(e+2),r=(h,n)=>h+(e+2)*n,et=10;function D(h,n,o){for(let b=0;b<Y;b++)h[b]+=o*n[b]}function q(h,n){for(let o=1;o<=e;o++)n[r(0,o)]=h===1?-n[r(1,o)]:n[r(1,o)],n[r(e+1,o)]=h===1?-n[r(e,o)]:n[r(e,o)],n[r(o,0)]=h===2?-n[r(o,1)]:n[r(o,1)],n[r(o,e+1)]=h===2?-n[r(o,e)]:n[r(o,e)];n[r(0,0)]=.5*(n[r(1,0)]+n[r(0,1)]),n[r(0,e+1)]=.5*(n[r(1,e+1)]+n[r(0,e)]),n[r(e+1,0)]=.5*(n[r(e,0)]+n[r(e+1,1)]),n[r(e+1,e+1)]=.5*(n[r(e,e+1)]+n[r(e+1,e)])}function Q(h,n,o,b,k){const i=k*b*e*e;if(i===0){for(let u=0;u<Y;u++)n[u]=o[u];return}const s=1+4*i;for(let u=0;u<et;u++){for(let f=1;f<=e;f++)for(let w=1;w<=e;w++)n[r(w,f)]=(o[r(w,f)]+i*(n[r(w-1,f)]+n[r(w+1,f)]+n[r(w,f-1)]+n[r(w,f+1)]))/s;q(h,n)}}function U(h,n,o,b,k,i){const s=i*e;for(let u=1;u<=e;u++)for(let f=1;f<=e;f++){let w=f-s*b[r(f,u)],A=u-s*k[r(f,u)];w=Math.max(.5,Math.min(e+.5,w)),A=Math.max(.5,Math.min(e+.5,A));const T=Math.floor(w),E=T+1,N=Math.floor(A),O=N+1,B=w-T,I=1-B,F=A-N,J=1-F;n[r(f,u)]=I*(J*o[r(T,N)]+F*o[r(T,O)])+B*(J*o[r(E,N)]+F*o[r(E,O)])}q(h,n)}function tt(h,n,o,b){const k=1/e;for(let i=1;i<=e;i++)for(let s=1;s<=e;s++)b[r(s,i)]=-.5*k*(h[r(s+1,i)]-h[r(s-1,i)]+n[r(s,i+1)]-n[r(s,i-1)]),o[r(s,i)]=0;q(0,b),q(0,o);for(let i=0;i<et;i++){for(let s=1;s<=e;s++)for(let u=1;u<=e;u++)o[r(u,s)]=(b[r(u,s)]+o[r(u-1,s)]+o[r(u+1,s)]+o[r(u,s-1)]+o[r(u,s+1)])/4;q(0,o)}for(let i=1;i<=e;i++)for(let s=1;s<=e;s++)h[r(s,i)]-=.5*(o[r(s+1,i)]-o[r(s-1,i)])*e,n[r(s,i)]-=.5*(o[r(s,i+1)]-o[r(s,i-1)])*e;q(1,h),q(2,n)}function X(h,n,o){h=(h%360+360)%360/360;const b=o+n-o*n,k=2*o-b,i=(s,u,f)=>(f<0&&(f+=1),f>1&&(f-=1),f<1/6?s+(u-s)*6*f:f<1/2?u:f<2/3?s+(u-s)*(2/3-f)*6:s);return[i(k,b,h+1/3),i(k,b,h),i(k,b,h-1/3)]}const ht=[{id:"laminar",label:"laminar()"},{id:"chaotic",label:"chaotic()"},{id:"paint",label:"paint()"}],bt={laminar:8e-5,chaotic:2e-6,paint:0},gt={laminar:2e-5,chaotic:1e-6,paint:0},C=.1,wt=({category:h,experiment:n})=>{const{canvasRef:o,ctx:b,dimensions:k}=lt(),i=dt(o),[s,u]=p.useState("chaotic"),[f,w]=p.useState("drag to inscribe fluid intention into the field"),[A,T]=p.useState(0),E=p.useRef(null),N=p.useRef(null),O=p.useRef(null),B=p.useRef({x:-1,y:-1}),I=p.useRef(0),F=p.useRef({energy:"0",ink:0,curl:"0"}),J=p.useRef(0);p.useEffect(()=>{const t=()=>new Float32Array(Y);E.current={u:t(),v:t(),u0:t(),v0:t(),dr:t(),dg:t(),db:t(),dr0:t(),dg0:t(),db0:t()},N.current=document.createElement("canvas"),N.current.width=e+2,N.current.height=e+2,O.current=new ImageData(e+2,e+2)},[]);const $=p.useCallback((t,d,M,a,v,g,m,c=4)=>{const l=E.current;if(!l)return;const x=c*c,R=Math.max(1,t-c),j=Math.min(e,t+c),y=Math.max(1,d-c),V=Math.min(e,d+c);for(let z=y;z<=V;z++)for(let G=R;G<=j;G++){const _=(G-t)*(G-t)+(z-d)*(z-d);if(_>x)continue;const H=1-Math.sqrt(_)/c,P=r(G,z);l.u0[P]+=M*H,l.v0[P]+=a*H,l.dr0[P]+=v*H,l.dg0[P]+=g*H,l.db0[P]+=m*H}},[]),K=p.useCallback(()=>{if(!i.isDown||!i.isInBounds||k.width===0){i.isDown||(B.current={x:-1,y:-1});return}const t=i.positionRef.current,d=B.current,M=Math.max(1,Math.min(e,Math.floor(t.x/k.width*e)+1)),a=Math.max(1,Math.min(e,Math.floor(t.y/k.height*e)+1)),[v,g,m]=X(I.current,.9,.6);if(d.x>=0){const c=Math.max(1,Math.min(e,Math.floor(d.x/k.width*e)+1)),l=Math.max(1,Math.min(e,Math.floor(d.y/k.height*e)+1)),x=M-c,R=a-l,j=5;$(M,a,x*j,R*j,v*200,g*200,m*200)}else $(M,a,0,0,v*120,g*120,m*120);B.current={x:t.x,y:t.y}},[i.isDown,i.isInBounds,i.positionRef,k,$]),L=p.useCallback(()=>{const t=E.current;if(!t)return;const d=bt[s],M=gt[s];if(s==="paint"){D(t.dr,t.dr0,C),D(t.dg,t.dg0,C),D(t.db,t.db0,C),t.u0.fill(0),t.v0.fill(0),t.dr0.fill(0),t.dg0.fill(0),t.db0.fill(0);return}D(t.u,t.u0,C),D(t.v,t.v0,C);let a;a=t.u0,t.u0=t.u,t.u=a,Q(1,t.u,t.u0,d,C),a=t.v0,t.v0=t.v,t.v=a,Q(2,t.v,t.v0,d,C),tt(t.u,t.v,t.u0,t.v0),a=t.u0,t.u0=t.u,t.u=a,a=t.v0,t.v0=t.v,t.v=a,U(1,t.u,t.u0,t.u0,t.v0,C),U(2,t.v,t.v0,t.u0,t.v0,C),tt(t.u,t.v,t.u0,t.v0),D(t.dr,t.dr0,C),D(t.dg,t.dg0,C),D(t.db,t.db0,C),a=t.dr0,t.dr0=t.dr,t.dr=a,Q(0,t.dr,t.dr0,M,C),a=t.dr0,t.dr0=t.dr,t.dr=a,U(0,t.dr,t.dr0,t.u,t.v,C),a=t.dg0,t.dg0=t.dg,t.dg=a,Q(0,t.dg,t.dg0,M,C),a=t.dg0,t.dg0=t.dg,t.dg=a,U(0,t.dg,t.dg0,t.u,t.v,C),a=t.db0,t.db0=t.db,t.db=a,Q(0,t.db,t.db0,M,C),a=t.db0,t.db0=t.db,t.db=a,U(0,t.db,t.db0,t.u,t.v,C);for(let v=0;v<Y;v++)t.dr[v]*=.998,t.dg[v]*=.998,t.db[v]*=.998;t.u0.fill(0),t.v0.fill(0),t.dr0.fill(0),t.dg0.fill(0),t.db0.fill(0)},[s]),W=p.useCallback(()=>
1{if(!b||!E.current||k.width===0)return;const t=E.current,d=O.current,M=d.data;for(let v=0;v<e+2;v++)for(let g=0;g<e+2;g++){const m=r(g,v),c=(v*(e+2)+g)*4,l=Math.sqrt(t.u[m]*t.u[m]+t.v[m]*t.v[m]),x=Math.min(25,l*8);M[c]=Math.min(255,t.dr[m]*2.5+1+x*.2),M[c+1]=Math.min(255,t.dg[m]*2.5+3+x*.5),M[c+2]=Math.min(255,t.db[m]*2.5+6+x*.8),M[c+3]=255}N.current.getContext("2d").putImageData(d,0,0),b.imageSmoothingEnabled=!0,b.imageSmoothingQuality="high",b.drawImage(N.current,0,0,k.width,k.height)},[b,k]),Z=p.useCallback(()=>{const t=E.current;if(!t)return;let d=0,M=0,a=0;for(let g=1;g<=e;g++)for(let m=1;m<=e;m++){const c=r(m,g);d+=t.u[c]*t.u[c]+t.v[c]*t.v[c],M+=t.dr[c]+t.dg[c]+t.db[c];const l=t.u[r(m,g+1)]-t.u[r(m,g-1)],x=t.v[r(m+1,g)]-t.v[r(m-1,g)];a+=Math.abs(x-l)}const v=e*e;F.current={energy:(d/v).toFixed(3),ink:Math.floor(M/3),curl:(a/v).toFixed(3)},T(g=>g+1)},[]);p.useEffect(()=>{if(!b||k.width===0)return;let t;const d=()=>{I.current=(I.current+.3)%360,K(),L(),W(),J.current++,J.current%10===0&&Z(),t=requestAnimationFrame(d)};return t=requestAnimationFrame(d),()=>cancelAnimationFrame(t)},[b,k.width,K,L,W,Z]);const rt=p.useCallback(()=>{const t=E.current;if(!t)return;const d=e/2,M=e/2,a=e/4,[v,g,m]=X(I.current,.9,.6);for(let c=1;c<=e;c++)for(let l=1;l<=e;l++){const x=l-d,R=c-M,j=Math.sqrt(x*x+R*R);if(j<a&&j>2){const y=5*(1-j/a);t.u0[r(l,c)]+=-R/j*y,t.v0[r(l,c)]+=x/j*y}if(j<a*.8&&j>a*.2){const y=250*Math.sin(j/a*Math.PI);t.dr0[r(l,c)]+=v*y,t.dg0[r(l,c)]+=g*y,t.db0[r(l,c)]+=m*y}}I.current=(I.current+60)%360,w("vortex inscribed // watch the spiral unfold")},[]),nt=p.useCallback(()=>{const t=E.current;if(!t)return;const d=e/2,M=e/2,a=e/3,[v,g,m]=X(I.current,.9,.6);for(let c=1;c<=e;c++)for(let l=1;l<=e;l++){const x=l-d,R=c-M,j=Math.sqrt(x*x+R*R);if(j<a&&j>1){const y=4*(1-j/a);t.u0[r(l,c)]+=x/j*y,t.v0[r(l,c)]+=R/j*y,t.dr0[r(l,c)]+=v*y*80,t.dg0[r(l,c)]+=g*y*80,t.db0[r(l,c)]+=m*y*80}}I.current=(I.current+45)%360,w("radial burst released from center")},[]),ot=p.useCallback(()=>{const t=E.current;if(t){for(let d=0;d<12;d++){const M=5+Math.floor(Math.random()*(e-10)),a=5+Math.floor(Math.random()*(e-10)),v=(I.current+d*30)%360,[g,m,c]=X(v,.9,.6),l=3+Math.floor(Math.random()*3);for(let x=-l;x<=l;x++)for(let R=-l;R<=l;R++){const j=R*R+x*x;if(j>l*l)continue;const y=(1-Math.sqrt(j)/l)*150,V=r(M+R,a+x);t.dr0[V]+=g*y,t.dg0[V]+=m*y,t.db0[V]+=c*y}}I.current=(I.current+90)%360,w("ink rain scattered across the field")}},[]),st=p.useCallback(()=>{const t=E.current;if(t){for(const d of Object.keys(t))t[d].fill(0);w("all fields dissolved")}},[]),ct=p.useCallback(t=>{u(t),w({laminar:"laminar flow // viscous, meditative ink",chaotic:"chaotic regime // turbulence finds its own forms",paint:"paint mode // dye without physics, switch modes to release"}[t])},[]),at=p.useMemo(()=>[{label:"energy",value:F.current.energy},{label:"ink",value:F.current.ink},{label:"curl",value:F.current.curl},{label:"hue",value:`${Math.floor(I.current)}`}],[A]),it=[{id:"vortex",label:"vortex()",onClick:rt},{id:"burst",label:"burst()",onClick:nt},{id:"rain",label:"rain()",onClick:ot},{id:"clear",label:"clear()",onClick:st,variant:"reset"}];return S.jsxs("div",{className:"fixed inset-0 flex flex-col",children:[S.jsxs("header",{className:"relative z-50 flex items-center justify-between p-2 sm:p-4 border-b border-void-green/20 bg-void-dark/80 backdrop-blur-sm",children:[S.jsxs("div",{className:"flex items-center gap-2 sm:gap-4",children:[S.jsx(mt,{currentCategory:h.slug,currentExperiment:n.slug}),S.jsx("h1",{className:"text-xl text-glow hidden sm:block",style:{color:n.color},children:n.name})]}),S.jsx(ft,{metrics:at})]}),S.jsxs("div",{className:"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 sm:gap-3 p-2 sm:p-4 border-b border-void-green/10 bg-void-dark/60 backdrop-blur-sm",children:[S.jsx(ut,{modes:ht,currentMode:s,onModeChange:ct,controls:it}),S.jsx("p",{className:"text-void-green/50 text-xs sm:text-right max-w-lg",children:f})]}),S.jsx("div",{className:"flex-1 min-h-0 relative bg-void-dark",children:S.jsx("canvas",{ref:o,className:"absolute inset-0 w-full h-full cursor-crosshair","data-testid":"fluid-rites-canvas"})})]})};export{wt as default};
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.