1import{r as n,j as h}from"./index-_Sg_1KT6.js";import{u as V}from"./useCanvas-DRXw8nFR.js";import{u as X}from"./useMouseInteraction-DqIzV1q4.js";import{E as Y}from"./ExperimentControls-DmwC3FZh.js";import{E as q}from"./ExperimentMetrics-D-l2z47K.js";import{E as H}from"./ExperimentNav-CPfQyQAJ.js";class S{constructor(a,m,r,s){this.x=a,this.y=m,this.canvasWidth=r,this.canvasHeight=s,this.vx=(Math.random()-.5)*2,this.vy=(Math.random()-.5)*2,this.length=Math.random()*100+50,this.hue=Math.random()*60+150,this.alpha=.6,this.angle=Math.random()*Math.PI*2,this.angularVelocity=(Math.random()-.5)*.05,this.connections=[],this.age=0,this.maxAge=500+Math.random()*500}update(a){this.age++,a&&(this.vx+=(Math.random()-.5)*.5,this.vy+=(Math.random()-.5)*.5),this.x+=this.vx,this.y+=this.vy,this.angle+=this.angularVelocity,this.x<0&&(this.x=this.canvasWidth),this.x>this.canvasWidth&&(this.x=0),this.y<0&&(this.y=this.canvasHeight),this.y>this.canvasHeight&&(this.y=0),this.vx*=.99,this.vy*=.99,this.age>this.maxAge*.8&&(this.alpha=.6*(1-(this.age-this.maxAge*.8)/(this.maxAge*.2)))}draw(a){const m=this.x+Math.cos(this.angle)*this.length,r=this.y+Math.sin(this.angle)*this.length;a.strokeStyle=`hsla(${this.hue}, 80%, 70%, ${this.alpha})`,a.lineWidth=2,a.beginPath(),a.moveTo(this.x,this.y),a.lineTo(m,r),a.stroke(),a.fillStyle=`hsla(${this.hue}, 90%, 80%, ${this.alpha*1.5})`,a.beginPath(),a.arc(this.x,this.y,3,0,Math.PI*2),a.fill(),a.beginPath(),a.arc(m,r,3,0,Math.PI*2),a.fill()}isDead(){return this.age>this.maxAge}}const Q=({category:k,experiment:a})=>{const{canvasRef:m,ctx:r,dimensions:s}=V(),u=X(m),[p,T]=n.useState(!1),[x,A]=n.useState(!1),[f,M]=n.useState(!1),[N,v]=n.useState("â´ click or drag to weave threads into reality â´"),o=n.useRef([]),b=n.useRef(null),g=n.useCallback((e,t,i=!0)=>{if(s.width===0)return;const c=new S(e,t,s.width,s.height);if(o.current.push(c),x&&i){const d=s.centerX,l=s.centerY,y=d+(d-e),w=l+(l-t),R=new S(y,w,s.width,s.height);R.hue=c.hue,o.current.push(R)}},[s,x]),C=n.useCallback(()=>{!p||o.current.length<2||o.current.forEach((e,t)=>{e.connections=[],o.current.forEach((i,c)=>{if(t>=c)return;const d=i.x-e.x,l=i.y-e.y,y=Math.sqrt(d*d+l*l);y<150&&e.connections.push({thread:i,strength:1-y/150})})})},[p]),E=n.useCallback(e=>{o.current.forEach(t=>{t.connections.forEach(i=>{const c=i.strength*t.alpha*i.thread.alpha*.3;e.strokeStyle=`hsla(180, 70%, 70%, ${c})`,e.lineWidth=1,e.beginPath(),e.moveTo(t.x,t.y),e.lineTo(i.thread.x,i.thread.y),e.stroke()})})},[]),I=n.useMemo(()=>{const e=o.current,t=e.length;let i="minimal";t>=30?i="transcendent":t>=15?i="intricate":t>=5&&(i="developing");const c=e.reduce((y,w)=>y+w.connections.length,0);let d="loose";c>=100?d="collapsed":c>=50?d="tight":c>=10&&(d="medium");let l="dormant";return t===0?l="dormant":t>=40||c>=150?l="transcendent":t>=20||c>=60?l="manifesting":t>=10||c>=20?l="awakening":l="stirring",[{label:"threads",value:t},{label:"complexity",value:i},{label:"weave",value:d},{label:"emergence",value:l}]},[o.current.length,p]),j=n.useCallback(()=>{!r||s.width===0||(r.fillStyle="rgba(0, 0, 0, 0.05)",r.fillRect(0,0,s.width,s.height),o.current=o.current.filter(e=>!e.isDead()),o.current.forEach(e=>{e.update(f)}),C(),E(r),o.current.forEach(e=>{e.draw(r)}))},[r,s,f,C,E]);n.useEffect(()=>{if(!r||s.width===0)return;let e;const t=()=>{j(),e=requestAnimationFrame(t)};return e=requestAnimationFrame(t),()=>cancelAnimationFrame(e)},[r,s.width,j]),n.useEffect(()=>{const e=m.current;if(!e)return;const t=()=>{const i=u.positionRef.current;g(i.x,i.y)};return e.addEventListener("click",t),()=>e.removeEventListener("click",t)},[m,g,u.positionRef]),n.useEffect(()=>{if(!u.isDown||!u.isInBounds)return;const e=u.positionRef.current;g(e.x,e.y)},[u.isDown,u.isInBounds,u.position,g]);const P=n.useCallback(()=>{const e=s.centerX+(Math.random()-.5)*200,t=s.centerY+(Math.random()-.5)*200;g(e,t),v("â´ thread spawned at center â´")},[s,g]),W=n.useCallback(()=>{T(e=>{const t=!e;return v(t?"â´ weave mode active // threads will connect â´":"â´ weave mode disabled // threads float free â´"),t})},[]),D=n.useCallback(()=>{A(e=>{const t=!e;return v(t?"â´ symmetry enforced // mirrored patterns emerge â´":"â´ symmetry disabled // chaos reigns â´"),t})},[]),$=n.useCallback(()=>{f||(M(!0),v("â´ chaos injected // threads scatter â´"),b.current&&clearTimeout(b.current),b.current=setTimeout(()=>{M(!1),v("â´ chaos subsides // order returns â´")},3e3))},[f]),F=n.useCallback(()=>{o.current=[],r&&r.clearRect(0,0,s.width,s.height),v("â´ loom cleared // void awaits new patterns â´")},[r,s]);n.useEffect(()=>()=>{b.current&&clearTimeout(b.current)},[]);const L=[{id:"spawn",label:"spawn.thread()",onClick:P},{id:"weave",label:p?"weave.active()":"weave.enable()",onClick:W,active:p},{id:"symmetry",label:x?"symmetry.active()":"symmetry.enforce()",onClick:D,active:x}
1,{id:"chaos",label:f?"chaos.active()":"chaos.inject()",onClick:$,active:f,disabled:f},{id:"clear",label:"clear.loom()",onClick:F,variant:"reset"}];return h.jsxs("div",{className:"fixed inset-0 flex flex-col",children:[h.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:[h.jsxs("div",{className:"flex items-center gap-2 sm:gap-4",children:[h.jsx(H,{currentCategory:k.slug,currentExperiment:a.slug}),h.jsx("h1",{className:"text-xl text-glow hidden sm:block",style:{color:a.color},children:a.name})]}),h.jsx(q,{metrics:I})]}),h.jsxs("div",{className:"flex items-center justify-between p-2 sm:p-4 border-b border-void-green/10 bg-void-dark/60 backdrop-blur-sm",children:[h.jsx(Y,{modes:[],currentMode:"",onModeChange:()=>{},controls:L}),h.jsx("p",{className:"text-void-green/50 text-xs hidden md:block max-w-md text-right",children:N})]}),h.jsx("div",{className:"flex-1 min-h-0 relative bg-void-dark",children:h.jsx("canvas",{ref:m,className:"absolute inset-0 w-full h-full cursor-crosshair","data-testid":"pattern-loom-canvas"})})]})};export{Q 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.