function Starfield({density=1,parallax=1}){const canvasRef=React.useRef(null);const stateRef=React.useRef({stars:[],constellations:[],galaxies:[],w:0,h:0,scrollY:0,t:0});React.useEffect(()=>{const canvas=canvasRef.current;const ctx=canvas.getContext("2d");let raf;function resize(){const dpr=Math.min(2,window.devicePixelRatio||1);const w=window.innerWidth;const h=window.innerHeight;canvas.width=w*dpr;canvas.height=h*dpr;canvas.style.width=w+"px";canvas.style.height=h+"px";ctx.setTransform(dpr,0,0,dpr,0,0);stateRef.current.w=w;stateRef.current.h=h;generate()}function generate(){const{w,h}=stateRef.current;const fieldH=h*4;const baseCount=Math.floor(w*fieldH/4400*density);const stars=[];for(let i=0;i<baseCount;i++){const layer=Math.random();const depth=layer<.55?0:layer<.85?1:2;const r=depth===0?Math.random()*.55+.25:depth===1?Math.random()*.9+.45:Math.random()*1.4+.75;stars.push({x:Math.random()*w,y:Math.random()*fieldH,r,depth,baseA:depth===0?.34+Math.random()*.32:depth===1?.54+Math.random()*.4:.74+Math.random()*.3,tw:Math.random()*Math.PI*2,twSpeed:.4+Math.random()*1.2,warm:Math.random()>.92})}for(let i=0;i<8;i++){stars.push({x:Math.random()*w,y:Math.random()*fieldH,r:1.6+Math.random()*.8,depth:2,baseA:.95,tw:Math.random()*Math.PI*2,twSpeed:.3+Math.random()*.5,flare:true,warm:Math.random()>.6})}stateRef.current.stars=stars;const cons=[];const consPatterns=[[[0,0],[20,-8],[42,-4],[58,10],[78,4]],[[0,0],[24,12],[44,4],[60,22]],[[0,0],[18,-14],[36,-6],[40,12]],[[0,0],[12,-20],[34,-18],[50,-4],[48,18]]];for(let i=0;i<6;i++){const pat=consPatterns[Math.floor(Math.random()*consPatterns.length)];const ox=Math.random()*w;const oy=Math.random()*fieldH;const scale=.7+Math.random()*1.3;const flip=Math.random()>.5?-1:1;cons.push({pts:pat.map(([x,y])=>[ox+x*scale*flip,oy+y*scale])})}stateRef.current.constellations=cons;const galaxies=[];const galaxyCount=3;for(let i=0;i<galaxyCount;i++){galaxies.push({x:Math.random()*w,y:Math.random()*fieldH,r:120+Math.random()*140,a:.06+Math.random()*.06,hue:Math.random()>.5?"cool":"warm"})}stateRef.current.galaxies=galaxies}function draw(){const s=stateRef.current;const{w,h,stars,constellations,galaxies,scrollY,t}=s;ctx.clearRect(0,0,w,h);for(const g of galaxies){const y=g.y-scrollY*.15*parallax;const wrappedY=(y%(h*4)+h*4)%(h*4)-h;if(wrappedY<-g.r*2||wrappedY>h+g.r*2)continue;const grd=ctx.createRadialGradient(g.x,wrappedY,0,g.x,wrappedY,g.r);if(g.hue==="warm"){grd.addColorStop(0,`rgba(230, 210, 170, ${g.a})`);grd.addColorStop(.4,`rgba(180, 160, 130, ${g.a*.4})`)}else{grd.addColorStop(0,`rgba(180, 200, 230, ${g.a})`);grd.addColorStop(.4,`rgba(140, 160, 200, ${g.a*.4})`)}grd.addColorStop(1,"rgba(0,0,0,0)");ctx.fillStyle=grd;ctx.beginPath();ctx.arc(g.x,wrappedY,g.r,0,Math.PI*2);ctx.fill()}ctx.strokeStyle="rgba(200, 192, 168, 0.24)";ctx.lineWidth=.4;for(const c of constellations){ctx.beginPath();for(let i=0;i<c.pts.length;i++){const py=c.pts[i][1]-scrollY*.35*parallax;if(i===0)ctx.moveTo(c.pts[i][0],py);else ctx.lineTo(c.pts[i][0],py)}ctx.stroke();for(const[px,py0]of c.pts){const py=py0-scrollY*.35*parallax;if(py<-10||py>h+10)continue;ctx.fillStyle="rgba(255,255,255,0.85)";ctx.beginPath();ctx.arc(px,py,.9,0,Math.PI*2);ctx.fill()}}for(const st of stars){const factor=st.depth===0?.15:st.depth===1?.45:.8;const yRaw=st.y-scrollY*factor*parallax;const fieldH=h*4;const y=(yRaw%fieldH+fieldH)%fieldH;if(y<-3||y>h+3)continue;const tw=.7+.3*Math.sin(t*st.twSpeed+st.tw);const a=st.baseA*tw;ctx.fillStyle=st.warm?`rgba(240, 220, 180, ${a})`:`rgba(240, 240, 250, ${a})`;ctx.beginPath();ctx.arc(st.x,y,st.r,0,Math.PI*2);ctx.fill();if(st.flare){ctx.strokeStyle=`rgba(255, 245, 220, ${a*.5})`;ctx.lineWidth=.4;ctx.beginPath();ctx.moveTo(st.x-st.r*4,y);ctx.lineTo(st.x+st.r*4,y);ctx.moveTo(st.x,y-st.r*4);ctx.lineTo(st.x,y+st.r*4);ctx.stroke()}}}function loop(time){stateRef.current.t=time/1e3;stateRef.current.scrollY=window.scrollY;draw();raf=requestAnimationFrame(loop)}resize();window.addEventListener("resize",resize);raf=requestAnimationFrame(loop);return()=>{cancelAnimationFrame(raf);window.removeEventListener("resize",resize)}},[density,parallax]);return<canvas ref={canvasRef}className="starfield"/>}Object.assign(window,{Starfield});
