/* ============================================================ THE ALETHEAN LEGACY — site app ============================================================ */ const { useState, useEffect, useRef } = React; /* ---------- Holo-mesh background canvas (Earth + hex mesh + ship) ---------- */ function HoloMeshCanvas({ density = 1, showShip = true }) { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); let raf; let t = 0; const stars = []; const resize = () => { const dpr = window.devicePixelRatio || 1; const rect = canvas.getBoundingClientRect(); canvas.width = rect.width * dpr; canvas.height = rect.height * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); stars.length = 0; const count = Math.floor((rect.width * rect.height) / 2200); for (let i = 0; i < count; i++) { stars.push({ x: Math.random() * rect.width, y: Math.random() * rect.height, r: Math.random() * 1.2 + 0.2, tw: Math.random() * Math.PI * 2, spd: Math.random() * 0.6 + 0.2, }); } }; resize(); window.addEventListener("resize", resize); const draw = () => { const w = canvas.clientWidth; const h = canvas.clientHeight; ctx.clearRect(0, 0, w, h); // gradient backdrop const g = ctx.createLinearGradient(0, 0, 0, h); g.addColorStop(0, "#05080F"); g.addColorStop(0.55, "#0A1426"); g.addColorStop(1, "#04070D"); ctx.fillStyle = g; ctx.fillRect(0, 0, w, h); // stars for (const s of stars) { s.tw += 0.02 * s.spd; const a = 0.4 + 0.6 * (0.5 + 0.5 * Math.sin(s.tw)); ctx.fillStyle = `rgba(220, 232, 248, ${a * 0.7})`; ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); ctx.fill(); } // Earth — large, anchored bottom, partly clipped const earthCx = w * 0.5; const earthCy = h * 1.15; const earthR = Math.max(w, h) * 0.85; // earth glow rim const rimGrad = ctx.createRadialGradient(earthCx, earthCy, earthR * 0.95, earthCx, earthCy, earthR * 1.08); rimGrad.addColorStop(0, "rgba(125,184,212,0)"); rimGrad.addColorStop(0.5, "rgba(125,184,212,0.12)"); rimGrad.addColorStop(1, "rgba(125,184,212,0)"); ctx.fillStyle = rimGrad; ctx.beginPath(); ctx.arc(earthCx, earthCy, earthR * 1.08, 0, Math.PI * 2); ctx.fill(); // earth body const eGrad = ctx.createRadialGradient( earthCx - earthR * 0.4, earthCy - earthR * 0.4, earthR * 0.1, earthCx, earthCy, earthR ); eGrad.addColorStop(0, "#2C4866"); eGrad.addColorStop(0.6, "#13243C"); eGrad.addColorStop(1, "#070C18"); ctx.fillStyle = eGrad; ctx.beginPath(); ctx.arc(earthCx, earthCy, earthR, 0, Math.PI * 2); ctx.fill(); // earth top-rim highlight ctx.save(); ctx.beginPath(); ctx.arc(earthCx, earthCy, earthR, 0, Math.PI * 2); ctx.clip(); const rim = ctx.createRadialGradient(earthCx, earthCy - earthR + 4, 0, earthCx, earthCy - earthR + 4, earthR * 0.5); rim.addColorStop(0, "rgba(160, 210, 240, 0.28)"); rim.addColorStop(1, "rgba(160, 210, 240, 0)"); ctx.fillStyle = rim; ctx.fillRect(0, 0, w, h); ctx.restore(); // hex-mesh holo overlay (clipped to earth) ctx.save(); ctx.beginPath(); ctx.arc(earthCx, earthCy, earthR + 6, 0, Math.PI * 2); ctx.clip(); drawHexMesh(ctx, w, h, earthCx, earthCy - earthR, t, density); ctx.restore(); // ship silhouette over earth (matches cover) if (showShip) { drawShip(ctx, w * 0.5, h * 0.35 + Math.sin(t * 0.6) * 4, w * 0.06); } t += 0.016; raf = requestAnimationFrame(draw); }; draw(); return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", resize); }; }, [density, showShip]); return