// ==== Projects grid with shader-driven generative covers =============

// Tiny canvas2D "shader" — looks like a glsl flow field, fast on all devices.
function GenerativeCover({ seed = 0.4, accent = "mint" }) {
  const ref = useRef(null);
  useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    const dpr = Math.min(window.devicePixelRatio || 1, 1.5);
    function resize() {
      const r = canvas.getBoundingClientRect();
      canvas.width = r.width * dpr;
      canvas.height = r.height * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(canvas);

    const accentColors = {
      // All five legacy keys collapse onto the disciplined champagne accent.
      // Subtle warmth variance keeps the covers from looking identical, but
      // every project shares the brand colour story.
      mint:    [212, 174, 116],   // base champagne
      blue:    [196, 178, 144],   // slightly cooler
      amber:   [218, 168, 96],    // slightly warmer / brighter
      violet:  [184, 162, 134],   // muted
      magenta: [222, 158, 110],   // higher chroma
    };
    const ca = accentColors[accent] || accentColors.mint;

    const start = performance.now();
    let raf;
    function frame() {
      const r = canvas.getBoundingClientRect();
      const w = r.width, h = r.height;
      const t = (performance.now() - start) / 1000;

      ctx.clearRect(0, 0, w, h);

      // background gradient
      const g = ctx.createRadialGradient(w * 0.5, h * 0.55, 20, w * 0.5, h * 0.55, Math.max(w, h));
      g.addColorStop(0, `rgba(${ca[0]}, ${ca[1]}, ${ca[2]}, 0.18)`);
      g.addColorStop(1, "rgba(6,8,13,0)");
      ctx.fillStyle = g;
      ctx.fillRect(0, 0, w, h);

      // contour lines — Lissajous + perlin-ish noise via seed
      ctx.lineWidth = 1;
      const lines = 24;
      for (let i = 0; i < lines; i++) {
        const phase = (i / lines) * Math.PI * 2;
        ctx.beginPath();
        const segments = 60;
        for (let j = 0; j <= segments; j++) {
          const u = j / segments;
          const a = u * Math.PI * 2;
          const k = seed + i * 0.07;
          const x = w * 0.5 + Math.cos(a * 2 + t * 0.2 + phase) * (60 + i * 6) * (0.8 + Math.sin(t * 0.3 + k) * 0.3);
          const y = h * 0.6 + Math.sin(a * 3 + t * 0.18 + phase + k) * (40 + i * 4);
          if (j === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
        }
        ctx.strokeStyle = `rgba(${ca[0]}, ${ca[1]}, ${ca[2]}, ${0.04 + (i / lines) * 0.12})`;
        ctx.stroke();
      }

      // particle drift
      for (let i = 0; i < 36; i++) {
        const a = (i / 36) * Math.PI * 2 + t * 0.1;
        const px = w * 0.5 + Math.cos(a) * (180 + Math.sin(t * 0.5 + i) * 60);
        const py = h * 0.6 + Math.sin(a * 1.4 + seed * 12) * (90 + Math.cos(t * 0.4 + i) * 40);
        ctx.fillStyle = `rgba(${ca[0]}, ${ca[1]}, ${ca[2]}, 0.35)`;
        ctx.beginPath();
        ctx.arc(px, py, 1.2, 0, Math.PI * 2);
        ctx.fill();
      }

      raf = requestAnimationFrame(frame);
    }
    frame();
    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, [seed, accent]);
  return <canvas ref={ref} />;
}

function ProjectCard({ p }) {
  return (
    <div className={`proj-card ${p.size}`}
      onClick={() => {
        if (p.id === "mantis") scrollToId("mantis");
        else if (p.link) window.open(p.link, "_blank");
      }}>
      <div className="proj-art"><GenerativeCover seed={p.seed} accent={p.accent} /></div>
      <div className="proj-overlay">
        <div className="top">
          <span className={`tag ${p.accent}`}>{p.year}</span>
          <span className="sub" style={{marginLeft: "auto"}}>{p.tags[0]}</span>
        </div>
        <div>
          <div className="sub">{p.sub}</div>
          <h3>{p.name}{p.id === "mantis" && <em>.</em>}</h3>
          <p className="desc">{p.blurb}</p>
          <div className="tags">
            {p.tags.slice(0, 6).map((t, i) => <span key={i} className="tag">{t}</span>)}
          </div>
        </div>
      </div>
    </div>
  );
}

function Projects() {
  return (
    <section id="projects" className="scene" data-screen-label="04 Projects">
      <div className="scene-head">
        <div className="eyebrow">Selected work</div>
        <h2>One thesis.<br /><em>Seven bets on it.</em></h2>
        <p className="lede">
          AI agents will be a load&#8209;bearing tier of every enterprise within five years. Someone has to build the runtime safely. These are my receipts.
        </p>
      </div>

      <div className="proj-grid">
        {AYUSH.PROJECTS.map(p => <ProjectCard key={p.id} p={p} />)}
      </div>
    </section>
  );
}

Object.assign(window, { Projects, GenerativeCover });
