/* EYE C — "From your screen": the desktop CTA (not live in browser) */

function EyeC() {
  const [ref, shown] = useReveal();
  const [playing, setPlaying] = React.useState(false);
  const [t, setT] = React.useState(0);
  const tick = React.useRef(null);

  React.useEffect(() => {
    if (playing) {
      tick.current = setInterval(() => setT(v => (v >= 100 ? (setPlaying(false), 100) : v + 0.5)), 40);
    } else clearInterval(tick.current);
    return () => clearInterval(tick.current);
  }, [playing]);

  const fmt = (p) => { const s = Math.round((p / 100) * 38); return `0:${String(s).padStart(2, "0")}`; };
  // staged captions describing the live ritual
  const captions = [
    { at: 0, txt: "⌥⌘G — Grain wakes, a floating window appears" },
    { at: 22, txt: "it watches the screen — a shader playing in the corner" },
    { at: 48, txt: "capture — the frame freezes, structure traced" },
    { at: 72, txt: "reconstructed → parametric, on your canvas" },
    { at: 90, txt: "you own it. change anything." },
  ];
  const cap = captions.filter(c => t >= c.at).slice(-1)[0] || captions[0];

  return (
    <section className="section" id="eye-c" ref={ref}>
      <div className="wrap">
        <SectionHead idx="EYE C — 03" kind="WATCH" title="From your screen" sub="Some things aren't a repo or a tutorial — they're just on your screen. Grain can watch those too. This one lives on your desktop, one hotkey away." shown={shown} motif="assets/eye-c-watch.png" accent="#57C4C0" />

        <div className="eyec-grid" style={{ marginTop: 56 }}>
          {/* video / viewport */}
          <div className={`panel ${shown ? "in" : ""}`} style={{ padding: 0, transition: "all 0.7s var(--spring)" }}>
            <div className="viewport eyec-vp" style={{ borderRadius: "var(--r-xl)", border: "none" }}>
              <div className="vp-grid" style={{ opacity: playing ? 0.5 : 1, transition: "opacity 0.5s" }} />
              <span className="vp-tick tl" /><span className="vp-tick tr" /><span className="vp-tick bl" /><span className="vp-tick br" />
              <div className="vp-label">
                <span className={playing ? "live-dot" : ""} style={{ position: "relative", display: "inline-block", width: 7, height: 7, borderRadius: "50%", background: playing ? "var(--grain)" : "var(--text-faint)" }} />
                {playing ? "SCREEN-CAPTURE · macOS" : "RITUAL — 0:38"}
              </div>

              {/* faux desktop scene — placeholder for screen recording */}
              <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>
                <div style={{ textAlign: "center", opacity: playing ? 1 : 0.85, transition: "opacity 0.4s" }}>
                  <div style={{ position: "relative", display: "inline-block" }}>
                    <Wireframe shape={t > 48 ? "torus" : "sphere"} color="#E8893B" size={150} spin={playing} assembling={playing && t < 48} />
                    {/* floating grain window frame appears while watching */}
                    {playing && t > 6 && t < 70 && (
                      <div style={{ position: "absolute", left: "50%", top: "50%", width: 210, height: 150, marginLeft: -105, marginTop: -75, border: "1px solid var(--grain-deep)", borderRadius: 10, boxShadow: "0 0 0 1px var(--bg), 0 0 30px var(--grain-glow)", animation: "winpulse 2.2s infinite" }}>
                        <span className="mono" style={{ position: "absolute", top: -8, left: 8, fontSize: 9, background: "var(--bg)", padding: "0 5px", color: "var(--grain-bright)", letterSpacing: "0.1em" }}>grain · watching</span>
                      </div>
                    )}
                  </div>
                </div>
              </div>

              {/* play button */}
              {!playing && (
                <button onClick={() => { if (t >= 100) setT(0); setPlaying(true); }} aria-label="Play"
                  style={{ position: "absolute", inset: 0, margin: "auto", width: 76, height: 76, borderRadius: "50%", background: "var(--grain)", border: "none", cursor: "pointer", display: "grid", placeItems: "center", boxShadow: "0 12px 40px var(--grain-glow), inset 0 1px 0 rgba(255,255,255,0.25)", zIndex: 6, transition: "transform 0.4s var(--spring)" }}
                  onMouseEnter={e => e.currentTarget.style.transform = "scale(1.08)"} onMouseLeave={e => e.currentTarget.style.transform = "scale(1)"}>
                  <span style={{ width: 0, height: 0, borderLeft: "20px solid #1a0e04", borderTop: "13px solid transparent", borderBottom: "13px solid transparent", marginLeft: 5 }} />
                </button>
              )}

              {/* caption */}
              <div style={{ position: "absolute", bottom: 56, left: 0, right: 0, textAlign: "center", zIndex: 5 }}>
                <span className="mono" style={{ fontSize: 12, color: "var(--text-soft)", background: "rgba(10,11,13,0.7)", padding: "5px 12px", borderRadius: 6, backdropFilter: "blur(6px)", opacity: playing ? 1 : 0, transition: "opacity 0.4s" }}>{cap.txt}</span>
              </div>

              {/* scrubber */}
              <div style={{ position: "absolute", bottom: 0, left: 0, right: 0, padding: "14px 18px", display: "flex", alignItems: "center", gap: 12, zIndex: 6, background: "linear-gradient(transparent, rgba(8,9,11,0.85))" }}>
                <button onClick={() => setPlaying(p => !p)} className="mono" style={{ background: "none", border: "none", color: "var(--text)", cursor: "pointer", fontSize: 13, width: 16 }}>{playing ? "❚❚" : "▶"}</button>
                <div onClick={(e) => { const r = e.currentTarget.getBoundingClientRect(); setT(Math.max(0, Math.min(100, ((e.clientX - r.left) / r.width) * 100))); }}
                  style={{ flex: 1, height: 4, background: "var(--surface-3)", borderRadius: 4, cursor: "pointer", position: "relative" }}>
                  <div style={{ position: "absolute", left: 0, top: 0, bottom: 0, width: `${t}%`, background: "var(--grain)", borderRadius: 4 }} />
                  <div style={{ position: "absolute", left: `${t}%`, top: "50%", width: 11, height: 11, marginLeft: -5, marginTop: -5, borderRadius: "50%", background: "var(--grain-bright)", boxShadow: "0 0 8px var(--grain-glow)" }} />
                </div>
                <span className="mono faint" style={{ fontSize: 11 }}>{fmt(t)} / 0:38</span>
              </div>
            </div>
          </div>

          {/* desktop framing copy */}
          <div className={`eyec-copy sec-head ${shown ? "in" : ""}`}>
            <p style={{ fontFamily: "var(--font-display)", fontSize: 26, fontWeight: 500, letterSpacing: "-0.02em", lineHeight: 1.2, marginBottom: 20 }}>
              Grain's desktop app lives on your machine — <span className="muted">always watching, one hotkey away.</span>
            </p>
            <div style={{ display: "flex", flexDirection: "column", gap: 12, marginBottom: 26 }}>
              {[["⌥⌘G", "summon the floating watcher"], ["◉", "it reads whatever's on screen"], ["⌘↩", "capture → reconstruct → own it"]].map(([k, v]) => (
                <div key={k} style={{ display: "flex", alignItems: "center", gap: 14 }}>
                  <span className="mono" style={{ fontSize: 12, color: "var(--grain-bright)", border: "1px solid var(--hairline)", background: "var(--surface-2)", borderRadius: 6, padding: "5px 9px", minWidth: 48, textAlign: "center" }}>{k}</span>
                  <span className="muted" style={{ fontSize: 14.5 }}>{v}</span>
                </div>
              ))}
            </div>
            <div style={{ padding: "14px 16px", background: "var(--surface)", border: "1px solid var(--hairline)", borderRadius: "var(--r-md)" }}>
              <p className="mono" style={{ fontSize: 12, color: "var(--text-soft)", marginBottom: 10 }}>Notarized macOS app <span style={{ color: "var(--grain)" }}>coming soon.</span></p>
              <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
                <a href="https://github.com" target="_blank" rel="noreferrer" className="btn btn-ghost mono" style={{ fontSize: 13, padding: "10px 16px" }}>Developer? Run from source → GitHub</a>
              </div>
            </div>
          </div>
        </div>

        <EyeCDemo />
      </div>
    </section>
  );
}

/* EYE C demo — the intent picker. One watched capture; you choose the intent and it compiles
   to a parametric rig OR a collected UI component. Same capture, intent decides the output.
   Scripted by default; ?live streams the real eye_c agent reasoning (falls back to recorded). */
const EYEC_TEAL = "#57C4C0";
const EC_INTENTS = {
  rig: {
    label: "editable 3D rig", accent: EYEC_TEAL, watch: "Houdini · viewport",
    script: [
      { arrow: "→", text: "watching · ", em: "Houdini viewport" },
      { arrow: "→", text: "reading the captured frame" },
      { arrow: "→", text: "inferring geometry + materials" },
      { arrow: "→", text: "exposing editable params · ", wire: "rust, scale" },
      { arrow: "→", text: "compiled → ", em: "parametric rig", done: true },
    ],
  },
  component: {
    label: "UI component", accent: "#5BA8D4", watch: "Safari · stripe.com/pricing",
    script: [
      { arrow: "→", text: "watching · ", em: "stripe.com/pricing" },
      { arrow: "→", text: "reading the captured UI" },
      { arrow: "→", text: "extracting structure + tokens" },
      { arrow: "→", text: "naming states · ", wire: "default, hover" },
      { arrow: "→", text: "collected → ", em: "component library", done: true },
    ],
  },
};
const EC_SEED = [{ name: "nav_bar", source: "linear.app", accent: "#5BA8D4", colors: ["#0E0F12", "#5BA8D4"], states: ["default", "scrolled"] }];
const EC_NEW = { name: "pricing_card", source: "stripe.com", accent: "#E8893B", colors: ["#0E0F12", "#E8893B"], states: ["default", "hover"] };

function ComponentCard({ comp, fresh }) {
  return (
    <div className={`component-card ${fresh ? "fresh" : ""}`} style={{ "--cc": comp.accent }}>
      <div className="cc-preview" aria-hidden="true">
        <span className="cc-bar" />
        <span className="cc-line" style={{ width: "72%" }} />
        <span className="cc-line" style={{ width: "46%" }} />
        <span className="cc-cta" />
      </div>
      <div className="cc-meta">
        <span className="mono cc-name">{comp.name}</span>
        <span className="mono faint" style={{ fontSize: 10 }}>{comp.source}</span>
      </div>
      <div className="cc-tokens">
        {comp.colors.map((c) => <span key={c} className="cc-swatch" style={{ background: c }} title={c} />)}
        {comp.states.map((s) => <span key={s} className="cc-state mono">{s}</span>)}
      </div>
    </div>
  );
}

function EyeCDemo() {
  const [ref, shown] = useReveal();
  const [intent, setIntent] = React.useState("rig");
  const [stage, setStage] = React.useState("idle");          // idle | compiling | done
  const [rig, setRig] = React.useState({ rust: 0.4, scale: 1 });
  const [lib, setLib] = React.useState(EC_SEED);
  const [liveState, setLiveState] = React.useState("off");
  const { lines, running, run, clear, begin, push, end } = useStream();
  const feedRef = React.useRef(null);
  const closeRef = React.useRef(null);
  const ex = EC_INTENTS[intent];

  const Q = new URLSearchParams(location.search);
  const LIVE = Q.has("live");
  const SSE = Q.get("sse") || window.GRAIN_AGENT_SSE || "http://localhost:8770/events";

  React.useEffect(() => { if (feedRef.current) feedRef.current.scrollTop = feedRef.current.scrollHeight; }, [lines]);
  React.useEffect(() => () => closeRef.current && closeRef.current(), []);

  const pickIntent = (k) => { if (running) return; setIntent(k); setStage("idle"); clear(); if (closeRef.current) closeRef.current(); };

  const finishOutput = () => {
    setStage("done");
    if (intent === "component") setLib((l) => l.some((c) => c.name === EC_NEW.name) ? l : [EC_NEW, ...l]);
    else setRig({ rust: 0.55, scale: 1.15 });
  };

  const mapEv = (ev) => {
    switch (ev.stage) {
      case "run": begin(); setStage("compiling"); push({ arrow: "●", text: "agent run · ", em: ev.label || "eye C" }); break;
      case "think": if (ev.text) push({ arrow: "→", text: ev.text }); break;
      case "act": push({ arrow: "→", text: "", em: ev.tool, wire: " " + shortVal(ev.args) }); break;
      case "result": push({ arrow: ev.ok ? "✓" : "✗", text: "", em: ev.tool, wire: " " + shortVal(ev.detail) }); break;
      case "approval": push({ arrow: "⏸", text: "human approval — ", wire: shortVal(ev.args) }); break;
      case "final": push({ arrow: "→", text: ev.text || "compiled", done: true }); end(); finishOutput(); break;
      default: break;
    }
  };
  const compileLive = () => {
    if (closeRef.current) closeRef.current();
    setStage("compiling"); setLiveState("connecting"); begin();
    push({ arrow: "→", text: "attaching to live agent · ", wire: SSE });
    closeRef.current = subscribeAgent(SSE, {
      onEvent: (ev) => { setLiveState("live"); mapEv(ev); },
      onError: () => { setLiveState("offline"); push({ arrow: "✗", text: "agent unreachable — ", wire: "showing recorded compile" }); run(ex.script, finishOutput); },
    });
  };
  const compile = () => { if (LIVE) return compileLive(); setStage("compiling"); run(ex.script, finishOutput); };

  const setP = (k, v) => setRig((p) => ({ ...p, [k]: v }));
  const compiled = stage === "done";

  return (
    <div className={`panel ${shown ? "in" : ""}`} ref={ref} style={{ marginTop: 24 }}>
      <div className="panel-head">
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <span className="panel-dots"><i></i><i></i><i></i></span>
          <span className="panel-title">grain · compile.screen</span>
        </div>
        <span className="panel-title" style={{ color: compiled || liveState === "live" ? EYEC_TEAL : "var(--text-faint)" }}>
          {LIVE
            ? (liveState === "live" ? "● LIVE — agent" : liveState === "offline" ? "OFFLINE — recorded" : liveState === "connecting" ? "CONNECTING…" : "LIVE MODE")
            : (stage === "idle" ? "READY" : stage === "compiling" ? "COMPILING…" : "● COMPILED")}
        </span>
      </div>

      <div className="compile-grid">
        {/* LEFT — capture + intent + reasoning */}
        <div className="compile-left">
          <label className="param-label" style={{ display: "block", marginBottom: 9, color: "var(--text-faint)" }}>// watched capture</label>
          <div className={`capture-frame ${intent}`} style={{ "--cc": ex.accent }}>
            <span className="mono capture-tag">◉ {ex.watch}</span>
            {intent === "rig"
              ? <div className="cap-render"><Wireframe shape="sphere" color={ex.accent} size={104} spin={true} /></div>
              : <div className="cap-ui"><span className="cu-bar" /><span className="cu-line" /><span className="cu-line short" /><span className="cu-cta" /></div>}
          </div>

          <label className="param-label" style={{ display: "block", margin: "16px 0 9px", color: "var(--text-faint)" }}>// your intent</label>
          <div className="segmented" style={{ marginBottom: 14 }}>
            {Object.entries(EC_INTENTS).map(([k, v]) => (
              <button key={k} className={intent === k ? "on" : ""} onClick={() => pickIntent(k)}>{v.label}</button>
            ))}
          </div>

          <button className="btn btn-grain" onClick={compile} disabled={running} style={{ marginBottom: 16, background: ex.accent, borderColor: ex.accent, color: "#0c0e10" }}>
            {running ? (LIVE ? "Watching agent…" : "Compiling…") : compiled ? "Compile again" : (LIVE ? "Attach to live agent" : "Compile")}
            {!running && <span style={{ fontSize: 15 }}>↻</span>}
          </button>

          <div className="feed eyea-feed" ref={feedRef} style={{ minHeight: 118 }}>
            {lines.length === 0 && stage === "idle" && (
              <div className="faint" style={{ opacity: 0.7 }}>// pick an intent, then <span className="mono" style={{ color: EYEC_TEAL }}>Compile</span> — same capture, your intent decides the output</div>
            )}
            {lines.map((ln, i) => (
              <div key={i} className={`feed-line ${ln.done ? "done" : ""}`}>
                <span className="arrow">{ln.arrow}</span>
                <span className="body">{ln.text}{ln.em && <span className="em">{ln.em}</span>}{ln.wire && <span className="wire">{ln.wire}</span>}</span>
              </div>
            ))}
            {running && <div className="feed-line" style={{ animation: "none", opacity: 1 }}><span className="feed-cursor" /></div>}
          </div>
        </div>

        {/* RIGHT — output by intent */}
        <div className="compile-right">
          {intent === "rig" ? (
            <React.Fragment>
              <div className="viewport eyec-out-vp">
                <div className="vp-grid" />
                <span className="vp-tick tl" /><span className="vp-tick tr" /><span className="vp-tick bl" /><span className="vp-tick br" />
                <div className="vp-label">
                  <span style={{ width: 7, height: 7, borderRadius: "50%", background: compiled ? EYEC_TEAL : "var(--text-faint)", display: "inline-block" }} />
                  {stage === "idle" ? "AWAITING INTENT" : stage === "compiling" ? "COMPILING…" : "PARAMETRIC RIG · live"}
                </div>
                <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>
                  {stage === "idle"
                    ? <div className="mono faint" style={{ fontSize: 12, opacity: 0.6 }}>▢ compile to populate the rig</div>
                    : <div style={{ filter: compiled ? `saturate(${0.5 + rig.rust})` : "none", transition: "filter 0.3s" }}>
                        <Wireframe shape="sphere" color={EYEC_TEAL} size={Math.round(110 + rig.scale * 64)} spin={compiled} assembling={stage === "compiling"} />
                      </div>}
                </div>
              </div>
              <div className="param-block" style={{ opacity: compiled ? 1 : 0.4, pointerEvents: compiled ? "auto" : "none", transition: "opacity 0.5s ease" }}>
                <div className="param">
                  <span className="param-label"><span className="sig" style={{ color: EYEC_TEAL }}>num </span>rust_amount</span>
                  <div className="slider"><div className="fill" style={{ width: `${rig.rust * 100}%`, background: EYEC_TEAL }} /><input type="range" min="0" max="1" step="0.01" value={rig.rust} onChange={(e) => setP("rust", +e.target.value)} aria-label="rust_amount" /></div>
                </div>
                <div className="param">
                  <span className="param-label"><span className="sig" style={{ color: EYEC_TEAL }}>num </span>scale</span>
                  <div className="slider"><div className="fill" style={{ width: `${((rig.scale - 0.5) / 1.5) * 100}%`, background: EYEC_TEAL }} /><input type="range" min="0.5" max="2" step="0.01" value={rig.scale} onChange={(e) => setP("scale", +e.target.value)} aria-label="scale" /></div>
                </div>
              </div>
            </React.Fragment>
          ) : (
            <div className="eyec-out-vp eyec-lib">
              <div className="vp-label" style={{ position: "static", marginBottom: 14 }}>
                <span style={{ width: 7, height: 7, borderRadius: "50%", background: compiled ? "#5BA8D4" : "var(--text-faint)", display: "inline-block" }} />
                COMPONENT LIBRARY · {lib.length}
              </div>
              <div className="component-grid">
                {lib.map((cmp, i) => <ComponentCard key={cmp.name} comp={cmp} fresh={compiled && cmp.name === EC_NEW.name && i === 0} />)}
              </div>
              {!compiled && <p className="mono faint" style={{ fontSize: 11.5, marginTop: 14, opacity: 0.7 }}>// compile to collect the watched UI into your library</p>}
            </div>
          )}
        </div>
      </div>

      <p className="mono faint" style={{ fontSize: 12, marginTop: 16, textAlign: "center" }}>
        One capture, one dial. <span style={{ color: "var(--text-soft)" }}>Your intent decides whether it becomes a rig or a component.</span>
      </p>
    </div>
  );
}

/* OVERVIEW — the ladder, directly below the hero: three ways in, one editable outcome.
   Each card links down to the eye that demonstrates it. */
function Overview() {
  const [ref, shown] = useReveal();
  const eyes = [
    { v: "read",  src: "if the source is open", a: "#E8893B", n: "EYE A", href: "#eye-a", motif: "assets/eye-a-read.png" },
    { v: "learn", src: "if it's taught",         a: "#5BA8D4", n: "EYE B", href: "#eye-b", motif: "assets/eye-b-learn.png" },
    { v: "watch", src: "if it's just visible",   a: "#5BC48E", n: "EYE C", href: "#eye-c", motif: "assets/eye-c-watch.png" },
  ];
  return (
    <section className="section" id="overview" ref={ref} style={{ paddingTop: 44 }}>
      <div className="wrap">
        <div className={`sec-head ${shown ? "in" : ""}`} style={{ textAlign: "center", display: "grid", placeItems: "center", marginBottom: 54 }}>
          <div className="eyebrow" style={{ marginBottom: 22 }}><span className="idx">THE THREE EYES</span></div>
          <h2 className="h2" style={{ maxWidth: "18ch" }}>Three ways in. One outcome you can edit.</h2>
        </div>

        <div className="eye-cards">
          {eyes.map((e, i) => (
            <a key={e.v} href={e.href} className={`eye-card ${shown ? "in" : ""}`} style={{ transitionDelay: `${i * 0.09}s`, "--accent": e.a }}>
              <div className="eye-orb" style={{ backgroundImage: `url("${e.motif}")` }} aria-hidden="true">
                <span className="eye-orb-ring" />
              </div>
              <span className="mono faint eye-card-tag">{e.n}</span>
              <p className="mono faint eye-card-src">{e.src},</p>
              <p className="eye-card-verb">we <span style={{ color: e.a }}>{e.v}</span> it.</p>
              <span className="mono eye-card-go">see it live ↓</span>
            </a>
          ))}
        </div>
      </div>
    </section>
  );
}

/* info finance — hover to reveal Vitalik Buterin's Nov 2024 thesis (verified: vitalik.eth.limo, 2024-11-09) */
function InfoFinanceTag() {
  const [open, setOpen] = React.useState(false);
  return (
    <span style={{ position: "relative", display: "inline-block" }} onMouseEnter={() => setOpen(true)} onMouseLeave={() => setOpen(false)}>
      <a href="https://vitalik.eth.limo/general/2024/11/09/infofinance.html" target="_blank" rel="noreferrer"
        onFocus={() => setOpen(true)} onBlur={() => setOpen(false)}
        style={{ color: "var(--wire)", textDecoration: "none", borderBottom: "1px dashed var(--wire)", paddingBottom: 1, cursor: "help" }}>info finance</a>
      <span role="tooltip" style={{
        position: "absolute", bottom: "calc(100% + 14px)", left: "50%",
        transform: open ? "translate(-50%, 0)" : "translate(-50%, 6px)",
        width: "min(366px, 84vw)", padding: "15px 17px", zIndex: 50,
        background: "var(--surface-2)", border: "1px solid var(--hairline)", borderRadius: "var(--r-md)",
        boxShadow: "0 18px 50px rgba(0,0,0,0.6)", textAlign: "left",
        opacity: open ? 1 : 0, visibility: open ? "visible" : "hidden", pointerEvents: "none",
        transition: "opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s",
      }}>
        <span style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 9 }}>
          <span style={{ width: 7, height: 7, borderRadius: "50%", background: "var(--wire)", boxShadow: "0 0 10px var(--wire)" }} />
          <span className="mono" style={{ fontSize: 12, color: "var(--text)", letterSpacing: "0.04em" }}>info finance</span>
          <span className="mono" style={{ marginLeft: "auto", fontSize: 10.5, color: "var(--text-faint)" }}>Vitalik · Nov 2024</span>
        </span>
        <span style={{ display: "block", fontSize: 13, lineHeight: 1.62, color: "var(--text-soft)", marginBottom: 11 }}>
          Markets and mechanism design as a general engine for surfacing truth — producing accurate information as a <span style={{ color: "var(--text)" }}>public good</span>. The same design that lets a market price truth is how an economy of agents prices and pays for each other's work.
        </span>
        <span className="mono" style={{ display: "block", fontSize: 10.5, color: "var(--wire)", letterSpacing: "0.02em" }}>“From prediction markets to info finance” · vitalik.eth.limo ↗</span>
        <span aria-hidden="true" style={{ position: "absolute", top: "100%", left: "50%", transform: "translateX(-50%)", width: 0, height: 0, borderLeft: "7px solid transparent", borderRight: "7px solid transparent", borderTop: "7px solid var(--surface-2)" }} />
      </span>
    </span>
  );
}

/* VISION — the agent economy + the info-finance close + FOOTER */
function Vision() {
  const [ref, shown] = useReveal();
  return (
    <section className="section" id="vision" ref={ref}>
      <div className="wrap">
        <div className={`sec-head ${shown ? "in" : ""}`} style={{ textAlign: "center", display: "grid", placeItems: "center", marginBottom: 12 }}>
          <div className="eyebrow" style={{ marginBottom: 22 }}>
            <span className="idx">THE VISION</span>
            <span style={{ width: 28, height: 1, background: "var(--hairline)" }} />
            <span style={{ color: "var(--grain)" }}>AGENT ECONOMY</span>
          </div>
          <h2 className="h2" style={{ maxWidth: "20ch", textWrap: "balance" }}>
            Agents that don't just <span className="muted">make</span> creative work — they <span style={{ color: "var(--grain)" }}>transact</span> to complete it.
          </h2>
        </div>

        <TransactFlow />

        <div className={`vision-line ${shown ? "in" : ""}`} style={{ marginTop: 80, display: "grid", placeItems: "center" }}>
          <div style={{ maxWidth: 640, padding: "40px clamp(26px,4vw,46px)", textAlign: "center", borderRadius: "var(--r-xl)", border: "1px solid color-mix(in oklab, var(--wire) 24%, var(--hairline))", background: 'linear-gradient(180deg, rgba(12,15,21,0.70), rgba(12,15,21,0.85)), url("assets/info-finance-bg.jpg") center / cover no-repeat', boxShadow: "0 30px 80px -42px rgba(0,0,0,0.75), 0 0 90px -56px var(--wire)" }}>
            <div className="rule" style={{ maxWidth: 64, margin: "0 auto 24px", background: "var(--wire)" }} />
            <p className="lead" style={{ fontSize: "clamp(17px,1.7vw,21px)", color: "var(--text-soft)", margin: "0 auto", maxWidth: "34ch", textWrap: "balance", textShadow: "0 1px 14px rgba(0,0,0,0.55)" }}>
              The same mechanism design that turns markets into public-good information engines is how you build an <span style={{ color: "var(--text)" }}>economy of agents</span> — each producing value, transacting for what it needs, with a human dialing the granularity of judgment.
            </p>
            <p className="mono faint" style={{ fontSize: 11.5, marginTop: 20, letterSpacing: "0.07em" }}>
              an early primitive of the agent economy · <InfoFinanceTag />
            </p>
          </div>
        </div>
      </div>
    </section>
  );
}

// node layout on a 940×320 stage (cx,cy = chip centre)
const TX_NODES = {
  gap:     { cx: 60,  cy: 160, color: "var(--text-soft)", icon: "gap",    seq: "01", label: ["missing", "asset"] },
  exa:     { cx: 206, cy: 160, color: "var(--wire)",      icon: "search", seq: "02", label: ["EXA", "retrieve"] },
  approve: { cx: 414, cy: 56,  color: "var(--grain)",     icon: "gate",   seq: "03", label: ["human-in-the-loop", "approve"], gate: true },
  stripe:  { cx: 620, cy: 56,  color: "var(--grain)",     icon: "pay",    seq: "04", label: ["STRIPE", "settle"] },
  verify:  { cx: 414, cy: 264, color: "var(--wire)",      icon: "id",     seq: "03", label: ["verify identity", "ERC-8004"] },
  x402:    { cx: 620, cy: 264, color: "var(--wire)",      icon: "hex",    seq: "04", label: ["x402", "settle"] },
};
// connectors: path in stage coords + accent + token duration (ms)
const TX_CONN = {
  stem: { d: "M90,160 L176,160",                       accent: "var(--wire)",  dur: 760 },
  bUp:  { d: "M236,160 C 318,160 306,56 384,56",       accent: "var(--grain)", dur: 820 },
  bDn:  { d: "M236,160 C 318,160 306,264 384,264",     accent: "var(--wire)",  dur: 820 },
  top:  { d: "M444,56 L590,56",                        accent: "var(--grain)", dur: 780 },
  bot:  { d: "M444,264 L590,264",                      accent: "var(--wire)",  dur: 700 },
};

function TxIcon({ kind }) {
  const s = { width: 25, height: 25, fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" };
  if (kind === "gap")    return <svg {...s}><rect x="4" y="4" width="18" height="18" rx="3" strokeDasharray="3 3" /><path d="M10 13h6M13 10v6" strokeOpacity="0.5" /></svg>;
  if (kind === "search") return <svg {...s}><circle cx="11" cy="11" r="6.5" /><path d="M16 16l5 5" /></svg>;
  if (kind === "gate")   return <svg {...s}><path d="M13 3l8 3v6c0 5-3.5 8-8 9.5C8.5 19 5 16 5 11V6z" /><path d="M9.5 12l2.3 2.3L16 9.5" /></svg>;
  if (kind === "id")     return <svg {...s}><path d="M5 13a8 8 0 0 1 16 0" /><path d="M8 13.5a5 5 0 0 1 10 0V16" /><path d="M11.5 13.5a1.5 1.5 0 0 1 3 0v4" /><circle cx="13" cy="13.5" r="0.6" fill="currentColor" stroke="none" /></svg>;
  if (kind === "hex")    return <svg {...s}><path d="M13 3l8 4.6v9.8L13 22l-8-4.6V7.6z" /><path d="M9.5 13l2.3 2.3L17 10.5" /></svg>;
  // pay (card)
  return <svg {...s}><rect x="3" y="6" width="20" height="14" rx="2.5" /><path d="M3 10.5h20" /><path d="M7 16h4" /></svg>;
}

function TransactFlow() {
  const [ref, shown] = useReveal();
  const wrapRef = React.useRef(null);
  const [scale, setScale] = React.useState(1);
  // lit nodes / filled connectors / live tokens
  const [lit, setLit] = React.useState({});
  const [fill, setFill] = React.useState({});
  const [toks, setToks] = React.useState([]);     // [{conn,k}]
  const [done, setDone] = React.useState({ top: false, bot: false });
  const timers = React.useRef([]);
  const tick = React.useRef(0);

  // scale stage to fit container
  React.useEffect(() => {
    const fit = () => {
      const w = wrapRef.current ? wrapRef.current.clientWidth : 990;
      setScale(Math.min(1, w / 990));
    };
    fit();
    window.addEventListener("resize", fit);
    return () => window.removeEventListener("resize", fit);
  }, []);

  React.useEffect(() => {
    if (!shown) return;
    if (reduceMotion) {
      setLit({ gap: 1, exa: 1, approve: 1, stripe: 1, verify: 1, x402: 1 });
      setFill({ stem: 1, bUp: 1, bDn: 1, top: 1, bot: 1 });
      setDone({ top: true, bot: true });
      return;
    }
    const clearAll = () => { timers.current.forEach(clearTimeout); timers.current = []; };
    const at = (t, fn) => timers.current.push(setTimeout(fn, t));
    const light = (id) => setLit(p => ({ ...p, [id]: 1 }));
    const flow  = (id) => setFill(p => ({ ...p, [id]: 1 }));
    const send  = (conn) => { const k = ++tick.current; setToks(p => [...p, { conn, k }]); return k; };
    const land  = (k) => setToks(p => p.filter(t => t.k !== k));

    const run = () => {
      clearAll();
      setLit({}); setFill({}); setToks([]); setDone({ top: false, bot: false });
      let t = 400;
      // stem: gap -> exa
      at(t, () => light("gap"));
      t += 600; at(t, () => { const k = send("stem"); at2(TX_CONN.stem.dur, () => { land(k); flow("stem"); light("exa"); }); });
      // branch fires down BOTH lanes at once
      t += TX_CONN.stem.dur + 350;
      at(t, () => {
        const ku = send("bUp"), kd = send("bDn");
        at2(TX_CONN.bUp.dur, () => { land(ku); flow("bUp"); light("approve"); });   // gate begins to breathe + HOLD
        at2(TX_CONN.bDn.dur, () => { land(kd); flow("bDn"); light("verify"); });    // autonomous: keep flowing immediately
      });
      // ----- autonomous lane races straight through (machine speed, no pause) -----
      const tBranchEnd = t + TX_CONN.bDn.dur;
      at(tBranchEnd + 140, () => { const k = send("bot"); at2(TX_CONN.bot.dur, () => { land(k); flow("bot"); light("x402"); setDone(p => ({ ...p, bot: true })); }); });
      // ----- human lane HOLDS at the approval gate, then releases -----
      const tGate = t + TX_CONN.bUp.dur;
      at(tGate + 1850, () => { const k = send("top"); at2(TX_CONN.top.dur, () => { land(k); flow("top"); light("stripe"); setDone(p => ({ ...p, top: true })); }); });
      // settle, hold, loop
      const tEnd = tGate + 1850 + TX_CONN.top.dur + 2300;
      at(tEnd, run);
    };
    // helper that schedules relative to "now-ish" using nested timeouts
    const at2 = (delay, fn) => timers.current.push(setTimeout(fn, delay));
    run();
    return clearAll;
  }, [shown]);

  const Node = ({ id }) => {
    const n = TX_NODES[id];
    return (
      <div className={`tx-node ${n.gate ? "gate" : ""} ${lit[id] ? "lit" : ""}`} style={{ left: n.cx, top: n.cy, "--node-c": n.color }}>
        <div className="tx-chip"><TxIcon kind={n.icon} /></div>
        <div className="tx-label">
          <span className="seq">{n.seq}</span>
          {n.label.map((l, j) => <div key={j}>{l}{j === 0 && n.label.length > 1 ? " ·" : ""}</div>)}
        </div>
      </div>
    );
  };

  return (
    <div className={`tx-wrap sec-head ${shown ? "in" : ""}`} ref={ref} style={{ marginTop: 52 }}>
      <div className="txstage-wrap" ref={wrapRef} style={{ height: 320 * scale }}>
        <div className="txstage" style={{ transform: `scale(${scale})` }}>
          {/* connectors */}
          <svg className="tx-svg" viewBox="0 0 990 320" fill="none">
            {Object.entries(TX_CONN).map(([id, c]) => (
              <path key={id} className="tx-base" d={c.d} />
            ))}
            {Object.entries(TX_CONN).map(([id, c]) => (
              <path key={id} className={`tx-flow ${fill[id] ? "on" : ""}`} d={c.d}
                pathLength="1" strokeDasharray="1"
                stroke={c.accent} style={{ filter: `drop-shadow(0 0 3px ${c.accent})` }} />
            ))}
          </svg>

          {/* branch junction */}
          <span className="tx-junction" style={{ left: 236, top: 160 }} />

          {/* traveling tokens */}
          {toks.map(tk => {
            const c = TX_CONN[tk.conn];
            return <span key={tk.k} className="tx-tok run" style={{ offsetPath: `path('${c.d}')`, "--d": `${c.dur}ms`, background: c.accent, boxShadow: `0 0 9px 1px ${c.accent}` }} />;
          })}

          {/* nodes */}
          {Object.keys(TX_NODES).map(id => <Node key={id} id={id} />)}

          {/* lane end captions — mount only when the lane settles */}
          {done.top && (
            <div className="tx-cap" style={{ left: 664, top: 56 }}>
              <div className="cap-state" style={{ color: "var(--grain)" }}>✓ settled</div>
              <div className="cap-desc">for human-approved purchases</div>
            </div>
          )}
          {done.bot && (
            <div className="tx-cap" style={{ left: 664, top: 264 }}>
              <div className="cap-state" style={{ color: "var(--wire)" }}>✓ continues — no human in the loop</div>
              <div className="cap-desc">for autonomous agent-to-agent settlement</div>
            </div>
          )}
        </div>
      </div>

      <p className="tx-summary">
        Two rails. One agent economy. <b>Stripe</b> where a human decides; <span className="wireb">x402</span> where the agent settles on its own.
      </p>
    </div>
  );
}

function Footer() {
  return (
    <footer style={{ borderTop: "1px solid var(--hairline)", padding: "44px 0 60px", position: "relative", zIndex: 1, marginTop: 30 }}>
      <div className="wrap" style={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 24 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 11 }}>
          <GrainLockup size={19} fontSize={17} interactive />
          <span className="mono faint" style={{ fontSize: 11, marginLeft: 6 }}>the visual intent compiler</span>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 22 }}>
          <a href="#eye-a" className="mono faint" style={{ fontSize: 12.5 }}>How it works</a>
          <a href="https://github.com" target="_blank" rel="noreferrer" className="mono faint" style={{ fontSize: 12.5 }}>GitHub ↗</a>
          <span className="mono faint" style={{ fontSize: 12.5 }}>© 2026</span>
        </div>
      </div>
    </footer>
  );
}

Object.assign(window, { EyeC, Overview, Vision, Footer });
