// app.jsx — Profine landing page

const { useState, useEffect, useRef, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "headline_pre": "Profile. Rewrite.",
  "headline_accent": "Ship faster.",
  "subhead": "Profile your PyTorch code on real GPUs. Get a transparent rewrite. Ship measured speedups before the multi-hour run.",
  "density": "comfortable",
  "hero_variant": "lattice"
} /*EDITMODE-END*/;

// ── Code diff content ────────────────────────────────────────────────
const DIFF_LINES = [
{ type: 'meta', text: '@@ training/loop.py @@' },
{ type: 'ctx', code: <><span className="kw">import</span> torch</> },
{ type: 'ctx', code: <><span className="kw">from</span> torch.utils.data <span className="kw">import</span> DataLoader</> },
{ type: 'ctx', code: <><span className="kw">from</span> model <span className="kw">import</span> GPT</> },
{ type: 'ctx', code: '' },
{ type: 'ctx', code: <>model = GPT(config).to(device)</> },
{ type: 'del', code: <>optimizer = torch.optim.<span className="fn">AdamW</span>(model.<span className="fn">parameters</span>(), lr=<span className="num">3e-4</span>)</> },
{ type: 'del', code: <>loader = <span className="fn">DataLoader</span>(ds, batch_size=<span className="num">64</span>, num_workers=<span className="num">2</span>)</> },
{ type: 'add', code: <>optimizer = torch.optim.<span className="fn">AdamW</span>(model.<span className="fn">parameters</span>(), lr=<span className="num">3e-4</span>, fused=<span className="kw">True</span>)</> },
{ type: 'add', code: <>loader = <span className="fn">DataLoader</span>(ds, batch_size=<span className="num">64</span>, num_workers=<span className="num">8</span>, pin_memory=<span className="kw">True</span>, persistent_workers=<span className="kw">True</span>)</> },
{ type: 'add', code: <>scaler = torch.amp.<span className="fn">GradScaler</span>(<span className="str">'cuda'</span>)</> },
{ type: 'add', code: <>model = torch.<span className="fn">compile</span>(model, mode=<span className="str">'max-autotune'</span>)</> },
{ type: 'ctx', code: '' },
{ type: 'ctx', code: <><span className="kw">for</span> step, (x, y) <span className="kw">in</span> <span className="fn">enumerate</span>(loader):</> },
{ type: 'del', code: <>{'    '}logits = <span className="fn">model</span>(x.<span className="fn">to</span>(device))</> },
{ type: 'del', code: <>{'    '}loss = <span className="fn">F.cross_entropy</span>(logits, y.<span className="fn">to</span>(device))</> },
{ type: 'del', code: <>{'    '}loss.<span className="fn">backward</span>()</> },
{ type: 'del', code: <>{'    '}optimizer.<span className="fn">step</span>()</> },
{ type: 'add', code: <>{'    '}x = x.<span className="fn">to</span>(device, non_blocking=<span className="kw">True</span>); y = y.<span className="fn">to</span>(device, non_blocking=<span className="kw">True</span>)</> },
{ type: 'add', code: <>{'    '}<span className="kw">with</span> torch.<span className="fn">autocast</span>(<span className="str">'cuda'</span>, dtype=torch.bfloat16):</> },
{ type: 'add', code: <>{'    '}    logits = <span className="fn">model</span>(x)</> },
{ type: 'add', code: <>{'    '}    loss = <span className="fn">F.cross_entropy</span>(logits, y)</> },
{ type: 'add', code: <>{'    '}scaler.<span className="fn">scale</span>(loss).<span className="fn">backward</span>()</> },
{ type: 'add', code: <>{'    '}scaler.<span className="fn">step</span>(optimizer); scaler.<span className="fn">update</span>()</> },
{ type: 'ctx', code: <>{'    '}optimizer.<span className="fn">zero_grad</span>(set_to_none=<span className="kw">True</span>)</> }];


// give them line numbers (continuous)
const DIFF_NUMBERED = (() => {
  let ln = 1;
  return DIFF_LINES.map((l) => {
    if (l.type === 'meta') return l;
    return { ...l, ln: ln++ };
  });
})();

// ── Magnetic CTA hook ────────────────────────────────────────────────
function useMagnetic() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      el.style.setProperty('--mx', e.clientX - r.left + 'px');
      el.style.setProperty('--my', e.clientY - r.top + 'px');
    };
    el.addEventListener('mousemove', onMove);
    return () => el.removeEventListener('mousemove', onMove);
  }, []);
  return ref;
}

// ── Count-up hook ────────────────────────────────────────────────────
function useCountUp(end, { duration = 1600, decimals = 0, start = 0 } = {}) {
  const [value, setValue] = useState(start);
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let raf,started = false;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !started) {
          started = true;
          const t0 = performance.now();
          const step = (now) => {
            const p = Math.min(1, (now - t0) / duration);
            const eased = 1 - Math.pow(1 - p, 3);
            setValue(start + (end - start) * eased);
            if (p < 1) raf = requestAnimationFrame(step);
          };
          raf = requestAnimationFrame(step);
          io.unobserve(el);
        }
      });
    }, { threshold: 0.4 });
    io.observe(el);
    return () => {io.disconnect();if (raf) cancelAnimationFrame(raf);};
  }, [end, duration, decimals, start]);
  return [ref, value.toFixed(decimals)];
}

function CountUp({ end, decimals = 0, prefix = '', suffix = '', className = '' }) {
  const [ref, val] = useCountUp(end, { decimals });
  return <span ref={ref} className={className}>{prefix}{val}{suffix}</span>;
}
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add('in');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -10% 0px' });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);
}

function useScrollNav() {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 24);
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return scrolled;
}

// ── Components ───────────────────────────────────────────────────────
function Brand() {
  return (
    <a className="brand" href="#top">
      <span className="brand-mark" aria-hidden="true"></span>
      <span>Profine</span>
    </a>);

}

function Nav() {
  const scrolled = useScrollNav();
  return (
    <header className={`nav ${scrolled ? 'nav--scrolled' : ''}`}>
      <div className="container nav-inner">
        <Brand />
        <nav className="nav-links" aria-label="Primary">
          <a href="#how">How it works</a>
          <a href="#flow">Pipeline</a>
          <a href="#diff">Rewrite</a>
          <a href="#metrics">Benchmarks</a>
          <a href="#github" className="btn btn-ghost" style={{ padding: '8px 14px' }}>
            GitHub <span className="arrow">→</span>
          </a>
        </nav>
      </div>
    </header>);

}

function Hero({ tweaks }) {
  const ctaRef = useMagnetic();
  const [telemetry, setTelemetry] = useState({
    stepMs: 142,
    gpuUtil: 59,
    memoryGb: 20.8,
    dataloaderStall: 24.5,
  });
  useEffect(() => {
    let raf = 0;
    let next = {
      stepMs: 142,
      gpuUtil: 59,
      memoryGb: 20.8,
      dataloaderStall: 24.5,
    };
    const onMetrics = (e) => {
      next = e.detail;
      if (raf) return;
      raf = requestAnimationFrame(() => {
        setTelemetry(next);
        raf = 0;
      });
    };
    window.addEventListener('profine:lattice-metrics', onMetrics);
    return () => {
      window.removeEventListener('profine:lattice-metrics', onMetrics);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <section className="hero" id="top" data-screen-label="01 Hero">
      <div className="hero-canvas" id="hero-canvas"></div>
      <div className="hero-vignette"></div>
      <div className="container hero-inner">
        <h1 className="reveal" data-delay="1">
          {tweaks.headline_pre}{' '}
          <span className="accent">{tweaks.headline_accent}</span>
        </h1>
        <p className="hero-sub reveal" data-delay="2">{tweaks.subhead}</p>
        <div className="hero-actions reveal" data-delay="3">
          <a href="#github" className="btn btn-primary" ref={ctaRef}>
            Try it on GitHub <span className="arrow">→</span>
          </a>
          <a href="#diff" className="btn btn-ghost">See the rewrite</a>
        </div>
        <div className="hero-telemetry reveal" data-delay="4" aria-label="Live lattice telemetry">
          <div className="telemetry-cell">
            <span className="telemetry-value">{telemetry.stepMs.toFixed(1)}ms</span>
            <span className="telemetry-label">step median</span>
          </div>
          <div className="telemetry-cell">
            <span className="telemetry-value">{telemetry.gpuUtil}%</span>
            <span className="telemetry-label">GPU util mean</span>
          </div>
          <div className="telemetry-cell">
            <span className="telemetry-value">{telemetry.memoryGb.toFixed(1)}GB</span>
            <span className="telemetry-label">memory peak</span>
          </div>
          <div className="telemetry-cell">
            <span className="telemetry-value">{telemetry.dataloaderStall.toFixed(1)}%</span>
            <span className="telemetry-label">loader stall</span>
          </div>
        </div>
        <div className="hero-meta reveal" data-delay="4">
          <div className="stat">
            <span className="stat-num"><em><CountUp end={8.51} decimals={2} suffix="×" /></em> faster</span>
            <span className="stat-label">Training step, A100</span>
          </div>
          <div className="stat">
            <span className="stat-num"><em>−<CountUp end={56} suffix="%" /></em> memory</span>
            <span className="stat-label">Peak GPU footprint</span>
          </div>
          <div className="stat">
            <span className="stat-num">~<CountUp end={5} /> min</span>
            <span className="stat-label">Profile to PR</span>
          </div>
        </div>
      </div>
    </section>);

}

function HowItWorks() {
  return (
    <section id="how" data-screen-label="02 How it works">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <span className="eyebrow">How it works</span>
            <h2 style={{ marginTop: 18 }}>Three steps. No guesswork.</h2>
          </div>
          <p>Hook in. Profile. Merge the diff.</p>
        </div>

        <div className="steps">
          <div className="step reveal" data-delay="1">
            <span className="step-num">01 / PROFILE</span>
            <div className="step-icon">
              <div className="viz-profile">
                {[12, 28, 44, 60, 76, 92, 108, 124, 140, 156, 172, 188, 204, 220].map((x, i) => {
                  const heights = [22, 38, 30, 84, 46, 60, 28, 110, 72, 24, 50, 36, 90, 44];
                  const hot = i === 3 || i === 7 || i === 12;
                  return (
                    <div key={i} className={`bar ${hot ? 'hot' : ''}`}
                    style={{ left: x, height: heights[i] }} />);

                })}
              </div>
            </div>
            <h3>Profile on real GPUs</h3>
            <p>Bottlenecks surface in minutes — not after a 12-hour run dies.</p>
          </div>

          <div className="step reveal" data-delay="2">
            <span className="step-num">02 / REWRITE</span>
            <div className="step-icon">
              <div className="viz-rewrite">
                <div className="row-line">
                  <span className="from">AdamW(...)</span>
                  <span className="arr">→</span>
                  <span className="to">+ fused=True</span>
                </div>
                <div className="row-line">
                  <span className="from">model(x)</span>
                  <span className="arr">→</span>
                  <span className="to">+ autocast(bf16)</span>
                </div>
                <div className="row-line">
                  <span className="from">DataLoader(...)</span>
                  <span className="arr">→</span>
                  <span className="to">+ pin_memory</span>
                </div>
                <div className="row-line">
                  <span className="from">model = GPT(cfg)</span>
                  <span className="arr">→</span>
                  <span className="to">+ torch.compile</span>
                </div>
              </div>
            </div>
            <h3>Transparent rewrites</h3>
            <p>Reviewable diffs — fused optimizers, AMP, <span className="mono">torch.compile</span>. No black boxes.</p>
          </div>

          <div className="step reveal" data-delay="3">
            <span className="step-num">03 / MEASURE</span>
            <div className="step-icon">
              <div className="viz-measure">
                <div className="baseline">
                  <span className="label-w">baseline</span>
                  <span className="track"><span className="fill" /></span>
                  <span className="val">1.00×</span>
                </div>
                <div className="optimized">
                  <span className="label-w">profine</span>
                  <span className="track"><span className="fill" /></span>
                  <span className="val">8.51×</span>
                </div>
              </div>
            </div>
            <h3>Measured speedups</h3>
            <p>Every PR ships with a benchmark. If it isn't faster, we don't merge it.</p>
          </div>
        </div>
      </div>
    </section>);

}

function CodeDiff() {
  const ref = useRef(null);
  const [revealed, setRevealed] = useState(0);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let started = false;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !started) {
          started = true;
          // animate add lines in sequence
          const total = DIFF_NUMBERED.length;
          let i = 0;
          const tick = () => {
            i++;
            setRevealed(i);
            if (i < total) setTimeout(tick, 55);
          };
          tick();
        }
      });
    }, { threshold: 0.25 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  const adds = DIFF_NUMBERED.filter((l) => l.type === 'add').length;
  const dels = DIFF_NUMBERED.filter((l) => l.type === 'del').length;

  return (
    <section id="diff" data-screen-label="03 Rewrite">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <span className="eyebrow">The rewrite</span>
            <h2 style={{ marginTop: 18 }}>Every line, justified.</h2>
          </div>
          <p>A clean diff against your training script. Merge what you like.</p>
        </div>

        <div className="diff-wrap reveal" ref={ref}>
          <div className="diff-bar">
            <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
              <div className="dots">
                <span className="dot"></span><span className="dot"></span><span className="dot"></span>
              </div>
              <span className="file">profine/pull/142 — train.py</span>
            </div>
            <span className="badge">
              <span className="pulse"></span>
              <span>+{adds} −{dels} · 8.51× speedup</span>
            </span>
          </div>

          <div className="diff-body">
            {DIFF_NUMBERED.map((line, i) => {
              const visible = i < revealed;
              if (line.type === 'meta') {
                return (
                  <div key={i} className={`diff-line ctx ${visible ? 'appearing' : 'hidden'}`}>
                    <span className="ln"></span>
                    <span className="sign"></span>
                    <span className="code com">{line.text}</span>
                  </div>);

              }
              const sign = line.type === 'add' ? '+' : line.type === 'del' ? '−' : ' ';
              return (
                <div key={i} className={`diff-line ${line.type} ${visible ? 'appearing' : 'hidden'}`}>
                  <span className="ln">{line.ln}</span>
                  <span className="sign">{sign}</span>
                  <span className="code">{line.code}</span>
                </div>);

            })}
          </div>

          <div className="diff-foot">
            <div className="changes">
              <span className="plus">+{adds} additions</span>
              <span className="minus">−{dels} deletions</span>
              <span>profile-id 4f8a · A100 80GB</span>
            </div>
            <div>review → merge → measure</div>
          </div>
        </div>
      </div>
    </section>);

}

function Metrics() {
  const ref = useRef(null);
  const [active, setActive] = useState(false);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((es) => {
      es.forEach((e) => {if (e.isIntersecting) {setActive(true);io.unobserve(el);}});
    }, { threshold: 0.3 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  return (
    <section id="metrics" data-screen-label="04 Benchmarks">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <span className="eyebrow">Measured, not promised</span>
            <h2 style={{ marginTop: 18 }}>Real speedups on real code.</h2>
          </div>
          <p>Reproducible benchmark on Karpathy's minGPT (~20k★, unmodified).</p>
        </div>

        <div className="metrics-band reveal" ref={ref}>
          <div className="metrics-head">
            <span className="label">Workload</span>
            <span className="target">
              <b>minGPT</b> · char-level shakespeare · <span className="gpu mono">A100 80GB</span> · bf16
            </span>
          </div>

          <div className="metrics-grid">
            <MetricCell
              name="Training speedup"
              num={8.51}
              decimals={2}
              unit="×"
              baselineLabel="baseline"
              baselineVal="1.00×"
              baselineWidth="100%"
              profineVal="8.51×"
              profineWidth={active ? '100%' : '0%'}
              baselineWidthShown={active ? '12%' : '0%'} />
            
            <MetricCell
              name="Peak memory"
              num={-56}
              unit="%"
              baselineLabel="baseline"
              baselineVal="42.1 GB"
              baselineWidth="100%"
              profineVal="18.5 GB"
              profineWidth={active ? '44%' : '0%'}
              baselineWidthShown={active ? '100%' : '0%'} />
            
            <MetricCell
              name="GPU-hour cost"
              num={-88}
              unit="%"
              baselineLabel="baseline"
              baselineVal="$1.00"
              baselineWidth="100%"
              profineVal="$0.12"
              profineWidth={active ? '12%' : '0%'}
              baselineWidthShown={active ? '100%' : '0%'} />
            
          </div>

          <div className="metrics-foot">
            <span>Reproduce: <span className="mono">git clone github.com/karpathy/minGPT && profine optimize train.py</span></span>
            <span><a href="#github">Read the full report →</a></span>
          </div>
        </div>
      </div>
    </section>);

}

function MetricCell({ name, num, decimals = 0, unit, baselineLabel, baselineVal, profineVal, baselineWidthShown, profineWidth }) {
  return (
    <div className="metric-cell">
      <span className="name">{name}</span>
      <div className="big">
        <CountUp end={num} decimals={decimals} className="num" />
        <span className="unit">{unit}</span>
      </div>
      <div className="compare row-baseline">
        <span className="name-c">{baselineLabel}</span>
        <span className="track"><span className="fill" style={{ width: baselineWidthShown }} /></span>
        <span className="val">{baselineVal}</span>
      </div>
      <div className="compare row-profine" style={{ marginTop: 8 }}>
        <span className="name-c">profine</span>
        <span className="track"><span className="fill" style={{ width: profineWidth }} /></span>
        <span className="val">{profineVal}</span>
      </div>
    </div>);

}

function Flow() {
  const ref = useRef(null);
  const [active, setActive] = useState(false);
  const [mode, setMode] = useState('loop'); // 'loop' | 'manual'

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((es) => {
      es.forEach((e) => { if (e.isIntersecting) { setActive(true); io.unobserve(el); } });
    }, { threshold: 0.25 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  const stages = [
    { id: 'read',      label: 'read',      sub: 'parse training script', icon: <FlowIconRead /> },
    { id: 'profile',   label: 'profile',   sub: 'trace on real GPUs',    icon: <FlowIconProfile /> },
    { id: 'interpret', label: 'interpret', sub: 'rank bottlenecks',      icon: <FlowIconInterpret /> },
    { id: 'suggest',   label: 'suggest',   sub: 'propose rewrites',      icon: <FlowIconSuggest /> },
    { id: 'edit',      label: 'edit',      sub: 'open a clean PR',       icon: <FlowIconEdit /> },
    { id: 'benchmark', label: 'benchmark', sub: 'measure or revert',     icon: <FlowIconBenchmark /> },
  ];

  return (
    <section id="flow" data-screen-label="04 Pipeline">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <span className="eyebrow">The pipeline</span>
            <h2 style={{ marginTop: 18 }}>Six stages. One closed loop.</h2>
          </div>
          <p>From training script to measured speedup — each stage leaves a receipt.</p>
        </div>

        <div className={`flow-band reveal ${active ? 'lit' : ''} mode-${mode}`} ref={ref}>
          <div className="flow-mode" role="tablist" aria-label="Pipeline mode">
            <button role="tab" aria-selected={mode === 'loop'} className={mode === 'loop' ? 'on' : ''} onClick={() => setMode('loop')}>
              <span className="dot-loop" /> Loop <span className="mono tag">agentic</span>
            </button>
            <button role="tab" aria-selected={mode === 'manual'} className={mode === 'manual' ? 'on' : ''} onClick={() => setMode('manual')}>
              <span className="dot-manual" /> CLI <span className="mono tag">manual</span>
            </button>
          </div>

          <div className="flow-rail-wrap">
            <div className="flow-rail">
              <div className="rail-bg" />
              <div className="rail-fill" />
              <div className="rail-tokens">
                {[0,1,2,3,4,5,6,7].map((i) => (
                  <span key={i} className="tok" style={{ animationDelay: `${i * 0.6}s` }} />
                ))}
              </div>
            </div>

            <div className="flow-stages">
              {stages.map((s, i) => (
                <div key={s.id} className="flow-stage" style={{ '--i': i }}>
                  <div className="stage-node">
                    <span className="node-ring" />
                    <span className="node-core">{s.icon}</span>
                    <span className="node-num mono">{String(i + 1).padStart(2, '0')}</span>
                  </div>
                  <div className="stage-meta">
                    <span className="stage-label">{s.label}</span>
                    <span className="stage-sub">{s.sub}</span>
                  </div>
                </div>
              ))}
            </div>

            <svg className="flow-loopback" viewBox="0 0 1200 80" preserveAspectRatio="none" aria-hidden="true">
              <defs>
                <linearGradient id="lbGrad" x1="0" y1="0" x2="1" y2="0">
                  <stop offset="0%" stopColor="#00D1C7" stopOpacity="0" />
                  <stop offset="50%" stopColor="#00D1C7" stopOpacity="0.9" />
                  <stop offset="100%" stopColor="#00D1C7" stopOpacity="0" />
                </linearGradient>
              </defs>
              <path d="M 1180 10 C 1180 80, 20 80, 20 10" fill="none" stroke="url(#lbGrad)" strokeWidth="1.5" strokeDasharray="4 6" />
              <circle r="3.5" fill="#00D1C7">
                <animateMotion dur="3.6s" repeatCount="indefinite" path="M 1180 10 C 1180 80, 20 80, 20 10" />
              </circle>
            </svg>
          </div>

          <div className="flow-foot mono">
            {mode === 'loop' ? (
              <>
                <span><span className="dot-loop" /> Loop runs the cycle until your speedup target is hit or the budget burns out.</span>
                <span className="kbd">profine loop --target 4x --budget 30m</span>
              </>
            ) : (
              <>
                <span><span className="dot-manual" /> CLI hands you the diff. You review, merge, and re-run when you want.</span>
                <span className="kbd">profine optimize train.py</span>
              </>
            )}
          </div>
        </div>
      </div>
    </section>
  );
}

function FlowIconRead() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M6 3h9l4 4v14H6z" />
      <path d="M14 3v5h5" />
      <path d="M9 12h7M9 15h7M9 18h5" />
    </svg>
  );
}
function FlowIconProfile() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4">
      <rect x="4" y="13" width="3" height="7" />
      <rect x="9" y="9" width="3" height="11" />
      <rect x="14" y="5" width="3" height="15" className="hot-bar" />
      <rect x="19" y="11" width="3" height="9" />
    </svg>
  );
}
function FlowIconInterpret() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4">
      <circle cx="12" cy="12" r="3.5" />
      <path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M5 19l2-2M17 7l2-2" />
    </svg>
  );
}
function FlowIconSuggest() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M9 18h6" />
      <path d="M10 21h4" />
      <path d="M12 3a6 6 0 0 0-3.5 10.9c.5.4.8 1 .8 1.6V16h5.4v-.5c0-.6.3-1.2.8-1.6A6 6 0 0 0 12 3z" />
    </svg>
  );
}
function FlowIconEdit() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M5 7h6M5 12h10M5 17h6" />
      <path d="M14 17l3-3 3 3-3 3z" />
    </svg>
  );
}
function FlowIconBenchmark() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M4 18a8 8 0 0 1 16 0" />
      <path d="M12 18l4-6" />
      <circle cx="12" cy="18" r="1.2" fill="currentColor" stroke="none" />
    </svg>
  );
}

function Github() {
  const [copied, setCopied] = useState('');
  const copy = (txt, key) => {
    navigator.clipboard?.writeText(txt);
    setCopied(key);
    setTimeout(() => setCopied(''), 1400);
  };
  return (
    <section id="github" data-screen-label="06 GitHub">
      <div className="container">
        <div className="cta-band reveal">
          <span className="eyebrow" style={{ justifyContent: 'center', display: 'inline-flex' }}>OPEN SOURCE · MIT</span>
          <h2 style={{ marginTop: 18 }}>Two ways to ship it.</h2>
          <p>Same engine. Different leashes. Pick the one that matches your trust budget.</p>

          <div className="gh-grid">
            <article className="gh-card gh-loop">
              <header>
                <span className="gh-pill mono"><span className="dot-loop" /> agentic</span>
                <h3>Profine Loop</h3>
                <p>An agent runs the full cycle — read → profile → interpret → suggest → edit → benchmark — and re-runs until your speedup target lands. Walk away. Come back to a green PR.</p>
              </header>
              <div className="gh-cmd" onClick={() => copy('pip install profine-loop && profine loop train.py --target 4x', 'loop')}>
                <span className="prompt">$</span>
                <span className="cmd"><span className="cmd-dim">pip install</span> profine-loop</span>
                <span className="copy mono">{copied === 'loop' ? 'copied' : 'copy'}</span>
              </div>
              <ul className="gh-bullets">
                <li>Picks its own optimizations</li>
                <li>Self-rolls back regressions</li>
                <li>Best for nightly jobs</li>
              </ul>
              <a className="btn btn-primary gh-btn" href="https://github.com/profine-ai/loop" target="_blank" rel="noopener">
                <GhMark /> profine-ai/loop
                <span className="arrow">→</span>
              </a>
            </article>

            <article className="gh-card gh-cli">
              <header>
                <span className="gh-pill mono"><span className="dot-manual" /> manual</span>
                <h3>Profine CLI</h3>
                <p>One pass. One diff. You read it, you merge it, you measure it. No surprises in the dependency tree, no surprises in the PR.</p>
              </header>
              <div className="gh-cmd" onClick={() => copy('pip install profine && profine optimize train.py', 'cli')}>
                <span className="prompt">$</span>
                <span className="cmd"><span className="cmd-dim">pip install</span> profine</span>
                <span className="copy mono">{copied === 'cli' ? 'copied' : 'copy'}</span>
              </div>
              <ul className="gh-bullets">
                <li>One reviewable diff</li>
                <li>Zero runtime dependencies</li>
                <li>Best for production code</li>
              </ul>
              <a className="btn btn-ghost gh-btn" href="https://github.com/profine-ai/cli" target="_blank" rel="noopener">
                <GhMark /> profine-ai/cli
                <span className="arrow">→</span>
              </a>
            </article>
          </div>

          <div className="gh-foot mono">
            <span>★ 2.4k stars · MIT · py3.10+</span>
            <span>·</span>
            <span><a href="https://github.com/profine-ai" target="_blank" rel="noopener">github.com/profine-ai</a></span>
          </div>
        </div>
      </div>
    </section>
  );
}

function GhMark() {
  return (
    <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden="true">
      <path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.1.79-.25.79-.56v-2.18c-3.2.69-3.87-1.36-3.87-1.36-.52-1.32-1.27-1.67-1.27-1.67-1.04-.71.08-.69.08-.69 1.15.08 1.76 1.18 1.76 1.18 1.02 1.75 2.68 1.25 3.34.95.1-.74.4-1.25.73-1.54-2.55-.29-5.24-1.27-5.24-5.66 0-1.25.45-2.27 1.18-3.07-.12-.29-.51-1.45.11-3.03 0 0 .96-.31 3.15 1.17.91-.25 1.89-.38 2.86-.38s1.95.13 2.86.38c2.18-1.48 3.14-1.17 3.14-1.17.62 1.58.23 2.74.11 3.03.74.8 1.18 1.82 1.18 3.07 0 4.4-2.69 5.36-5.25 5.65.41.36.78 1.06.78 2.13v3.16c0 .31.21.66.79.55C20.21 21.39 23.5 17.08 23.5 12 23.5 5.65 18.35.5 12 .5z"/>
    </svg>
  );
}

function Footer() {
  return (
    <footer>
      <div className="container foot">
        <Brand />
        <div className="foot-links mono" style={{ fontSize: 12, letterSpacing: '0.04em' }}>
          <a href="#how">how it works</a>
          <a href="#flow">pipeline</a>
          <a href="#diff">rewrite</a>
          <a href="#metrics">benchmarks</a>
          <a href="#github">github</a>
        </div>
        <span className="mono" style={{ fontSize: 12, color: 'var(--text-faint)' }}>© 2026 Profine AI

        </span>
      </div>
    </footer>);

}

// ── Tweaks panel ─────────────────────────────────────────────────────
function ProfineTweaks({ tweaks, setTweak }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Headline" />
      <TweakText
        label="Pre"
        value={tweaks.headline_pre}
        onChange={(v) => setTweak('headline_pre', v)} />
      
      <TweakText
        label="Accent"
        value={tweaks.headline_accent}
        onChange={(v) => setTweak('headline_accent', v)} />
      
      <TweakText
        label="Subhead"
        value={tweaks.subhead}
        onChange={(v) => setTweak('subhead', v)} />
      

      <TweakSection label="Hero animation" />
      <TweakRadio
        label="Variant"
        value={tweaks.hero_variant}
        options={[
        { value: 'lattice', label: 'Lattice' },
        { value: 'tensor', label: 'Tensor' },
        { value: 'particles', label: 'Drift' }]
        }
        onChange={(v) => setTweak('hero_variant', v)} />
      

      <TweakSection label="Density" />
      <TweakRadio
        label="Spacing"
        value={tweaks.density}
        options={[
        { value: 'compact', label: 'Compact' },
        { value: 'comfortable', label: 'Comfy' }]
        }
        onChange={(v) => setTweak('density', v)} />
      
    </TweaksPanel>);

}

// ── App ──────────────────────────────────────────────────────────────
function App() {
  const [tweaks, setTweakState] = useTweaks(TWEAK_DEFAULTS);
  const setTweak = (k, v) => {
    if (typeof k === 'object') setTweakState(k);else
    setTweakState({ [k]: v });
  };

  useEffect(() => {
    document.documentElement.dataset.density = tweaks.density;
  }, [tweaks.density]);

  useEffect(() => {
    if (window.ProfineHero) window.ProfineHero.setVariant(tweaks.hero_variant);
  }, [tweaks.hero_variant]);

  useReveal();

  return (
    <>
      <Nav />
      <Hero tweaks={tweaks} />
      <HowItWorks />
      <CodeDiff />
      <Metrics />
      <Flow />
      <Github />
      <Footer />
      <ProfineTweaks tweaks={tweaks} setTweak={setTweak} />
    </>);

}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
