import { useEffect, useRef } from 'react'; export default function Background() { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); let raf; let w, h, dpr; const stars = []; const drift = []; const resize = () => { dpr = Math.min(window.devicePixelRatio || 1, 2); w = canvas.width = window.innerWidth * dpr; h = canvas.height = window.innerHeight * dpr; canvas.style.width = window.innerWidth + 'px'; canvas.style.height = window.innerHeight + 'px'; stars.length = 0; const density = Math.min(260, Math.floor((window.innerWidth * window.innerHeight) / 9000)); for (let i = 0; i < density; i++) { stars.push({ x: Math.random() * w, y: Math.random() * h, r: Math.random() * 1.3 * dpr + 0.3 * dpr, baseAlpha: Math.random() * 0.6 + 0.2, twinkleSpeed: Math.random() * 0.003 + 0.0005, twinklePhase: Math.random() * Math.PI * 2, hue: Math.random() < 0.2 ? 'moon' : 'white', }); } drift.length = 0; for (let i = 0; i < 18; i++) { drift.push({ x: Math.random() * w, y: Math.random() * h, vx: (Math.random() - 0.5) * 0.15, vy: (Math.random() - 0.5) * 0.1 - 0.02, r: Math.random() * 2 * dpr + 0.5 * dpr, alpha: Math.random() * 0.3 + 0.05, }); } }; const draw = (t) => { ctx.clearRect(0, 0, w, h); for (const s of stars) { const a = s.baseAlpha * (0.5 + 0.5 * Math.sin(t * s.twinkleSpeed + s.twinklePhase)); ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); ctx.fillStyle = s.hue === 'moon' ? `rgba(200, 230, 255, ${a})` : `rgba(244, 236, 207, ${a})`; ctx.fill(); } for (const d of drift) { d.x += d.vx; d.y += d.vy; if (d.x < 0) d.x = w; if (d.x > w) d.x = 0; if (d.y < 0) d.y = h; if (d.y > h) d.y = 0; const grad = ctx.createRadialGradient(d.x, d.y, 0, d.x, d.y, d.r * 6); grad.addColorStop(0, `rgba(176, 136, 238, ${d.alpha})`); grad.addColorStop(1, 'rgba(176, 136, 238, 0)'); ctx.fillStyle = grad; ctx.beginPath(); ctx.arc(d.x, d.y, d.r * 6, 0, Math.PI * 2); ctx.fill(); } raf = requestAnimationFrame(draw); }; resize(); draw(0); window.addEventListener('resize', resize); return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); }; }, []); return ( <>