)discard;gl_FragColor=vec4(vCol,(1.0-d*2.0)*vA*0.85);}`;const vsK=`attribute vec3 aPos;uniform float uTime,uPulse;uniform vec2 uMouse;varying vec3 vP;varying float vE;void main(){vec3 p=aPos;p*=(1.0+uPulse*0.5);float cx=cos(uMouse.x*0.25),sx=sin(uMouse.x*0.25),cy=cos(uMouse.y*0.2),sy=sin(uMouse.y*0.2);mat3 ry=mat3(cx,0.0,sx,0.0,1.0,0.0,-sx,0.0,cx),rx=mat3(1.0,0.0,0.0,0.0,cy,-sy,0.0,sy,cy);p=ry*rx*p;p.z+=uTime*0.08;vP=p;vE=mod(aPos.x*10.0+aPos.y*8.0+aPos.z*6.0+uTime*3.0,1.0);gl_Position=vec4(p*0.1,1.0);}`,fsK=`precision mediump float;varying vec3 vP;varying float vE;uniform float uTime;void main(){float t=vE;vec3 c1=vec3(0.0,0.96,0.82),c2=vec3(0.97,0.14,0.52),c3=vec3(0.48,0.17,0.75);vec3 col=mix(mix(c1,c2,t),c3,sin(t*3.14159)*0.5+0.5);gl_FragColor=vec4(col,0.35+sin(vP.x*15.0+uTime*4.0)*0.1);}`;function createProgram(vsSrc,fsSrc){const p=gl.createProgram(),vs=gl.createShader(gl.VERTEX_SHADER),fs=gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(vs,vsSrc);gl.shaderSource(fs,fsSrc);gl.compileShader(vs);gl.compileShader(fs);gl.attachShader(p,vs);gl.attachShader(p,fs);gl.linkProgram(p);return p}function createBuffer(data){const b=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,b);gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);return b}const prog=createProgram(vs,fs),progK=createProgram(vsK,fsK);const colors=[[0,.96,.82],[.97,.14,.52],[.48,.17,.75],[1,.42,.42],[.99,.9,.34],[.33,.89,.89]];const posData=new Float32Array(PARTICLE_COUNT*3),colData=new Float32Array(PARTICLE_COUNT*3),phaseData=new Float32Array(PARTICLE_COUNT);for(let i=0;i<PARTICLE_COUNT;i++){const r=Math.pow(Math.random(),.4)*25,theta=Math.random()*6.283,phi=Math.acos(2*Math.random()-1);posData[i*3]=r*Math.sin(phi)*Math.cos(theta);posData[i*3+1]=r*Math.sin(phi)*Math.sin(theta);posData[i*3+2]=r*Math.cos(phi);const c=colors[Math.floor(Math.random()*colors.length)];colData[i*3]=c[0];colData[i*3+1]=c[1];colData[i*3+2]=c[2];phaseData[i]=Math.random()}const posBuf=createBuffer(posData),colBuf=createBuffer(colData),phaseBuf=createBuffer(phaseData);const res=60,knotData=[];for(let i=0;i<res;i++){const t=i/res*6.283185,u=2+Math.cos(3*t),v=Math.sin(3*t),w=Math.cos(3*t),x=u*(v+Math.cos(t)),y=u*(w+Math.sin(t)),z=Math.sin(t);for(let j=0;j<res;j++){const sj=j/res*6.283185,sx=Math.cos(sj)*0.08,sz=Math.sin(sj)*0.08;knotData.push(x+sx,y+sz,z)}}const knotBuf=createBuffer(new Float32Array(knotData));let mouseX=0,mouseY=0,targetX=0,targetY=0,dragX=0,dragY=0,isDragging=false;window.addEventListener('mousemove',e=>{targetX=(e.clientX/window.innerWidth)*2-1;targetY=-(e.clientY/window.innerHeight)*2+1});window.addEventListener('mousedown',()=>isDragging=true);window.addEventListener('mouseup',()=>isDragging=false);function resize(){const w=window.innerWidth,h=window.innerHeight,dpr=Math.min(devicePixelRatio,2);canvas.width=w*dpr;canvas.height=h*dpr;canvas.style.width=w+'px';canvas.style.height=h+'px';gl.viewport(0,0,w*dpr,h*dpr)}window.addEventListener('resize',resize);resize();function render(time){const pulse=Math.sin(time*2)*0.4+0.4;mouseX+=(targetX-mouseX)*0.05;mouseY+=(targetY-mouseY)*0.05;const mx=mouseX+dragX*0.3,my=mouseY+dragY*0.3;if(isDragging){dragX+=(targetX-dragX)*0.08;dragY+=(targetY-dragY)*0.08}else{dragX*=0.95;dragY*=0.95}gl.clearColor(0,0,0,0);gl.clear(16384);gl.enable(gl.BLEND);gl.blendFunc(gl.SRC_ALPHA,gl.ONE);gl.useProgram(prog);gl.uniform1f(gl.getUniformLocation(prog,'uTime'),time);gl.uniform1f(gl.getUniformLocation(prog,'uPulse'),pulse);gl.uniform2f(gl.getUniformLocation(prog,'uMouse'),mx*0.5,my*0.3);const aPos=gl.getAttribLocation(prog,'aPos'),aCol=gl.getAttribLocation(prog,'aCol'),aPhase=gl.getAttribLocation(prog,'aPhase');gl.bindBuffer(gl.ARRAY_BUFFER,posBuf);gl.enableVertexAttribArray(aPos);gl.vertexAttribPointer(aPos,3,gl.FLOAT,false,0,0);gl.bindBuffer(gl.ARRAY_BUFFER,colBuf);gl.enableVertexAttribArray(aCol);gl.vertexAttribPointer(aCol,3,gl.FLOAT,false,0,0);gl.bindBuffer(gl.ARRAY_BUFFER,phaseBuf);gl.enableVertexAttribArray(aPhase);gl.vertexAttribPointer(aPhase,1,gl.FLOAT,false,0,0);gl.drawArrays(gl.POINTS,0,PARTICLE_COUNT);gl.useProgram(progK);gl.uniform1f(gl.getUniformLocation(progK,'uTime'),time);gl.uniform1f(gl.getUniformLocation(progK,'uPulse'),pulse);gl.uniform2f(gl.getUniformLocation(progK,'uMouse'),mx*0.3,my*0.2);const aK=gl.getAttribLocation(progK,'aPos');gl.bindBuffer(gl.ARRAY_BUFFER,knotBuf);gl.enableVertexAttribArray(aK);gl.vertexAttribPointer(aK,3,gl.FLOAT,false,0,0);gl.drawArrays(gl.POINTS,0,knotData.length/3);requestAnimationFrame(render)}requestAnimationFrame(render)}();</script><style>#webgl-bg{position:fixed;inset:0;z-index:-4;pointer-events:none}
