/* ============================================================
   v2 hero — interactive glyph field + typed line
   ============================================================ */

// Canvas field: a Swiss dot-lattice that displaces and turns into
// mono glyphs near the cursor. Variants: 'lattice' | 'glyphs' | 'off'.
function HeroField({ toy, motion }) {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas || toy === "off") return;
    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const ctx = canvas.getContext("2d");
    const GLYPHS = "+x*:/\\|—·";
    let w = 0, h = 0, dpr = 1, cells = [], raf = 0, running = true;
    const mouse = { x: -9999, y: -9999 };
    const R = 90 + motion * 16; // cursor influence radius

    const accent = () => {
      const v = getComputedStyle(document.documentElement).getPropertyValue("--acc").trim();
      return v || "#ff5a1f";
    };

    function resize() {
      const rect = canvas.getBoundingClientRect();
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      w = rect.width; h = rect.height;
      canvas.width = Math.round(w * dpr);
      canvas.height = Math.round(h * dpr);
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const gap = w < 700 ? 26 : 32;
      cells = [];
      for (let y = gap; y < h - 4; y += gap) {
        for (let x = gap; x < w - 4; x += gap) {
          cells.push({
            x, y,
            seed: Math.random() * 1000,
            ch: GLYPHS[(Math.random() * GLYPHS.length) | 0],
          });
        }
      }
    }

    const inkc = () => {
      const v = getComputedStyle(document.documentElement).getPropertyValue("--ink").trim();
      return v || "#f2f1ee";
    };

    function draw(t) {
      if (!running) return;
      ctx.clearRect(0, 0, w, h);
      const acc = accent();
      const ink = inkc();
      ctx.font = "11px 'JetBrains Mono', monospace";
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      for (let i = 0; i < cells.length; i++) {
        const c = cells[i];
        const dx = c.x - mouse.x, dy = c.y - mouse.y;
        const dist = Math.hypot(dx, dy);
        const p = Math.max(0, 1 - dist / R); // 0..1 proximity
        // ambient drift
        const amb = reduced ? 0 : Math.sin(t * 0.0009 + c.seed) * (1.2 * motion / 6);
        let ox = amb, oy = Math.cos(t * 0.0011 + c.seed) * amb;
        if (p > 0 && dist > 0.01) {
          const push = p * p * 16;
          ox += (dx / dist) * push;
          oy += (dy / dist) * push;
        }
        const isGlyph = toy === "glyphs" ? true : p > 0.18;
        if (isGlyph) {
          // occasional scramble — faster near the cursor
          const rate = toy === "glyphs" ? 0.004 + p * 0.18 : 0.1 * p;
          if (!reduced && Math.random() < rate) {
            c.ch = GLYPHS[(Math.random() * GLYPHS.length) | 0];
          }
          const baseA = toy === "glyphs" ? 0.16 : 0.1;
          if (p > 0.12) {
            ctx.fillStyle = acc;
            ctx.globalAlpha = Math.min(0.95, baseA + p * 0.85);
          } else {
            ctx.fillStyle = ink;
            ctx.globalAlpha = baseA;
          }
          ctx.fillText(c.ch, c.x + ox, c.y + oy);
        } else {
          ctx.fillStyle = ink;
          ctx.globalAlpha = 0.13;
          ctx.beginPath();
          ctx.arc(c.x + ox, c.y + oy, 1.1, 0, Math.PI * 2);
          ctx.fill();
        }
      }
      ctx.globalAlpha = 1;
      if (!reduced) raf = requestAnimationFrame(draw);
    }

    function onMove(e) {
      const rect = canvas.getBoundingClientRect();
      mouse.x = e.clientX - rect.left;
      mouse.y = e.clientY - rect.top;
      if (reduced) { cancelAnimationFrame(raf); raf = requestAnimationFrame(draw); }
    }
    function onLeave() { mouse.x = -9999; mouse.y = -9999; }
    function onVis() {
      running = !document.hidden;
      if (running && !reduced) { cancelAnimationFrame(raf); raf = requestAnimationFrame(draw); }
    }

    resize();
    raf = requestAnimationFrame(draw);
    window.addEventListener("resize", resize);
    window.addEventListener("pointermove", onMove);
    window.addEventListener("pointerleave", onLeave);
    document.addEventListener("visibilitychange", onVis);
    return () => {
      running = false;
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
      window.removeEventListener("pointermove", onMove);
      window.removeEventListener("pointerleave", onLeave);
      document.removeEventListener("visibilitychange", onVis);
    };
  }, [toy, motion]);

  if (toy === "off") return null;
  return <canvas ref={ref} className="hero-canvas" aria-hidden="true"></canvas>;
}

// Typed, cycling specialty line.
const TYPED_PHRASES = [
  "narrative creation",
  "content production",
  "video production",
  "audio production",
  "editorial judgment",
  "developer education",
  "AI model communication",
  "technical communication",
];

function TypedLine({ motion }) {
  const [text, setText] = React.useState("");
  React.useEffect(() => {
    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced || motion === 0) { setText(TYPED_PHRASES[0]); return; }
    let i = 0, j = 0, deleting = false, timer = 0, cancelled = false;
    const tick = () => {
      if (cancelled) return;
      const phrase = TYPED_PHRASES[i];
      if (!deleting) {
        j++;
        setText(phrase.slice(0, j));
        if (j === phrase.length) { deleting = true; timer = setTimeout(tick, 1900); return; }
        timer = setTimeout(tick, 34 + Math.random() * 40);
      } else {
        j--;
        setText(phrase.slice(0, j));
        if (j === 0) { deleting = false; i = (i + 1) % TYPED_PHRASES.length; timer = setTimeout(tick, 320); return; }
        timer = setTimeout(tick, 16);
      }
    };
    timer = setTimeout(tick, 700);
    return () => { cancelled = true; clearTimeout(timer); };
  }, [motion]);
  return (
    <div className="hero-typed">
      <span className="arrow">→</span>
      <span>A career of demonstrated </span>
      <span style={{ color: "var(--ink)" }}>{text}</span>
      <span className="caret"></span>
    </div>
  );
}

function HeroV2({ toy, motion }) {
  return (
    <section className="hero-v2" data-screen-label="01 Hero">
      <HeroField toy={toy} motion={motion} />
      <div className="hero-inner wrap">
        <div className="hero-kicker">Jason O'Grady · Content Producer · Bay Area</div>
        <h1>Find the story. Ship it.</h1>
        <TypedLine motion={motion} />
        <div className="hero-base">
          <p className="hero-bio">
            Over a decade inside Google across <strong>Ads, Security, and
            Payments</strong> — most recently the launch story for
            <strong> Agent Payments Protocol (AP2)</strong>, Google's open
            standard for agentic commerce: announcement blog,
            protocol site, and GitHub repo, shipped to a 60+ partner ecosystem.
            Eight published books. 200+ podcast episodes. One Apple blog,
            daily since 1995.
          </p>
          <div className="hero-ctas">
            <a className="btn primary magnetic" href="#work" data-track="hero-cta-work">View work ↓</a>
            <a className="btn magnetic" href="/contact" data-track="hero-cta-contact">Contact</a>
          </div>
          <image-slot id="headshot-dispatch" shape="rect" placeholder="Drop headshot"></image-slot>
        </div>
      </div>
    </section>
  );
}

window.HeroV2 = HeroV2;
