/* BifferProxy homepage — main app */
const { useState, useEffect, useRef, useMemo } = React;

/* ---------- Icons (inline SVG, 1.5px stroke, lucide-style) ---------- */
const I = {
  user: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8"/></svg>,
  shield: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2 4 5v7c0 5 3.5 9 8 10 4.5-1 8-5 8-10V5l-8-3z"/></svg>,
  scan: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2M7 12h10"/></svg>,
  tag: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20.6 13.4 13.4 20.6a2 2 0 0 1-2.8 0l-8-8a2 2 0 0 1 0-2.8l7.2-7.2a2 2 0 0 1 1.4-.6H19a2 2 0 0 1 2 2v7.4a2 2 0 0 1-.6 1.4z"/><circle cx="15.5" cy="8.5" r="1.5"/></svg>,
  server: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="7" rx="1"/><rect x="3" y="13" width="18" height="7" rx="1"/><circle cx="7" cy="7.5" r="0.5"/><circle cx="7" cy="16.5" r="0.5"/></svg>,
  cpu: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><rect x="5" y="5" width="14" height="14" rx="2"/><rect x="9" y="9" width="6" height="6"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 9V5M19 15v4"/></svg>,
  log: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M4 6h16M4 10h16M4 14h10M4 18h8"/></svg>,
  globe: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3.5 3 14 0 18M12 3c-3 3.5-3 14 0 18"/></svg>,
  lock: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><rect x="4" y="10" width="16" height="10" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/></svg>,
  link: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M10 14a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1"/><path d="M14 10a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1"/></svg>,
  arrow: <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>,
  check: <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m20 6-11 11L4 12"/></svg>,
  play: <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>,
};
window.I = I;

/* ---------- Problem section ---------- */
const Problem = () => {
  useReveal();
  return (
    <section id="problem" data-screen-label="Home · Problem">
      <div className="container">
        <div className="reveal" style={{maxWidth: 760, marginBottom: 72}}>
          <div className="section-kicker">01 · The stakes</div>
          <h2 className="section-title">Your people are <span className="accent">already</span> pasting secrets into chatbots.</h2>
          <p className="section-lede">Every LLM request is an exfiltration vector. You can block the tools, or you can let them work — safely.</p>
        </div>
        <div className="problem-grid">
          <div className="stat-card glass reveal" style={{'--reveal-delay':'80ms'}}>
            <div>
              <div className="fig"><Counter to={1} />&nbsp;<span style={{color:'var(--ink-faint)'}}>in</span>&nbsp;<Counter to={3} /></div>
              <h3>Employees have pasted sensitive data into an LLM.</h3>
            </div>
            <p>Names, IBANs, M&A codenames, customer PII, internal URLs. The logs are elsewhere now.</p>
          </div>
          <div className="stat-card glass reveal" style={{'--reveal-delay':'160ms'}}>
            <div>
              <div className="fig">€<Counter to={35} /><span className="u">M</span></div>
              <h3>Maximum fine under the EU AI Act.</h3>
            </div>
            <p>7% of global turnover for prohibited processing. Your auditors are asking already.</p>
          </div>
          <div className="stat-card glass reveal" style={{'--reveal-delay':'240ms'}}>
            <div>
              <div className="fig alt">Prompts are memorized.<br/>Models leak.</div>
            </div>
            <p>Vendor policies shift. Logs are human-reviewed. Redaction at source is the only durable control.</p>
          </div>
        </div>
        <MotionPin style={{top: 40, right: 32}}>anim · counters tick on enter · 1400ms cubic-ease · stagger 80ms</MotionPin>
      </div>
    </section>
  );
};

/* ---------- How it works — horizontal scroll ---------- */
const FLOW = [
  { icn: I.user,   kind: '',       label: 'USER / AGENT',      title: 'Employee or agent',  desc: 'Sends a normal request to any OpenAI-compatible endpoint.', lat: 'client · <1 ms' },
  { icn: I.shield, kind: 'accent', label: 'BIFFERPROXY',       title: 'The proxy intercepts', desc: 'Deployed inside your perimeter. Nothing leaves yet.',          lat: 'intake · 2 ms' },
  { icn: I.scan,   kind: '',       label: 'DETECT',            title: 'Regex + NER scan',     desc: 'Two-layer detector finds 11 entity types with confidence scores.', lat: '6–14 ms' },
  { icn: I.tag,    kind: 'accent', label: 'PSEUDONYMIZE',      title: 'Replace spans with tokens', desc: 'Deterministic per session. Same entity → same token.',     lat: '<1 ms' },
  { icn: I.cpu,    kind: '',       label: 'UPSTREAM LLM',      title: 'Sent to the model',    desc: 'OpenAI, Anthropic, Mistral, Gemini, Bedrock, Azure — unchanged API.', lat: '80–200 ms' },
  { icn: I.shield, kind: 'accent', label: 'DE-PSEUDONYMIZE',   title: 'Restore tokens inline',desc: 'Session-aware reverse map. Tokens swap back to originals.', lat: '<1 ms' },
  { icn: I.user,   kind: '',       label: 'USER / AGENT',      title: 'Clean response',       desc: 'Your client sees exactly what it expected. Plus an audit entry.', lat: 'delivered · invisible' },
];

const Flow = () => {
  const secRef = useRef(null);
  const trackRef = useRef(null);
  const [progress, setProgress] = useState(0);
  const [maxShift, setMaxShift] = useState(0);

  useEffect(() => {
    const sec = secRef.current;
    const track = trackRef.current;
    if (!sec || !track) return;

    const recalc = () => {
      const w = track.scrollWidth;
      const viewW = window.innerWidth;
      setMaxShift(Math.max(0, w - viewW + 64));
    };
    recalc();
    window.addEventListener('resize', recalc);

    const onScroll = () => {
      const r = sec.getBoundingClientRect();
      const vh = window.innerHeight;
      // progress: 0 when top enters, 1 when bottom sub-viewport approaches
      const total = r.height - vh;
      if (total <= 0) return;
      const scrolled = Math.min(total, Math.max(0, -r.top));
      setProgress(scrolled / total);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', recalc); };
  }, []);

  const shift = -progress * maxShift;
  const pct = Math.round(progress * 100);

  return (
    <section ref={secRef} className="flow-sec" id="how" data-screen-label="Home · How it works"
             style={{height: '340vh', padding: 0}}>
      <div className="flow-sticky">
        <div className="flow-head">
          <div className="section-kicker">02 · How it works</div>
          <h2 className="section-title" style={{maxWidth: 820}}>
            A single hop between your clients and <span className="accent">any</span> LLM.
          </h2>
          <p className="section-lede">Scroll to walk through one round-trip. Every node runs on your infra. No data ever reaches a third-party model in the clear.</p>
        </div>

        <div className="flow-track" ref={trackRef} style={{transform: `translateX(${shift}px)`}}>
          {FLOW.map((n, i) => (
            <React.Fragment key={i}>
              <div className="flow-node glass spotlight">
                <div className="idx">0{i+1} — {n.label}</div>
                <div className={'icn ' + (n.kind || '')}>{n.icn}</div>
                <h3>{n.title}</h3>
                <p>{n.desc}</p>
                <div className="lat">latency · <b>{n.lat}</b></div>
              </div>
              {i < FLOW.length - 1 && (
                <div className="flow-connector">
                  <span className="dot" style={{'--dot': `${Math.min(100, Math.max(0, (progress * FLOW.length - i) * 100))}%`}}></span>
                </div>
              )}
            </React.Fragment>
          ))}
        </div>

        <div className="flow-progress">
          <span className="hint">request</span>
          <div className="bar"><div className="fill" style={{'--p': `${pct}%`}}></div></div>
          <span className="hint tnum">{pct.toString().padStart(2,'0')}% · node {Math.min(FLOW.length, 1+Math.floor(progress*FLOW.length))}/{FLOW.length}</span>
        </div>

        <MotionPin style={{top: 20, right: 32}}>anim · section pins 340vh · track translates X · data packets flow on scroll</MotionPin>
      </div>
    </section>
  );
};

/* ---------- Side-by-side demo ---------- */
const SAMPLES = {
  legal: {
    left: `Team — attached is the draft SPA for the acquisition of Corvex Medical by Helios Diagnostics, target close 18 June 2026.
Key contacts: Marie Dupont (Helios Legal, marie.dupont@helios.eu, +33 6 12 34 56 78) and Ahmed El-Sayed at Corvex (a.elsayed@corvex-med.com).
Wire the signing escrow — €18,400,000 — to IBAN FR7630001007941234567890185 by Thursday. The data room is at https://vdr.helios.eu/corvex-2026.`,
    entities: [
      ['Corvex Medical','[ORG_1]','ORGANIZATION'],
      ['Helios Diagnostics','[ORG_2]','ORGANIZATION'],
      ['18 June 2026','[DATE_1]','DATE_TIME'],
      ['Marie Dupont','[PERSON_1]','PERSON'],
      ['marie.dupont@helios.eu','[EMAIL_1]','EMAIL_ADDRESS'],
      ['+33 6 12 34 56 78','[PHONE_1]','PHONE_NUMBER'],
      ['Ahmed El-Sayed','[PERSON_2]','PERSON'],
      ['Corvex','[ORG_1]','ORGANIZATION'],
      ['a.elsayed@corvex-med.com','[EMAIL_2]','EMAIL_ADDRESS'],
      ['€18,400,000','[AMOUNT_1]','DATE_TIME'],
      ['FR7630001007941234567890185','[IBAN_1]','CREDIT_CARD'],
      ['Thursday','[DATE_2]','DATE_TIME'],
      ['https://vdr.helios.eu/corvex-2026','[URL_1]','IP_ADDRESS'],
    ],
  },
  engineering: {
    left: `Pinning incident INC-4821. The auth-edge pod on 10.44.17.22 is flapping since 03:14 UTC.
Owner is Priya Rao (priya.rao@stellar.ai). Customer impacted: Banque Nordique, contract BN-2026-Q2.
Rollback candidate: commit a7f3d2c on branch release/6.4. ETA for green dashboard 06:30 UTC.`,
    entities: [
      ['INC-4821','[CASE_1]','CREDIT_CARD'],
      ['10.44.17.22','[IP_1]','IP_ADDRESS'],
      ['03:14 UTC','[DATE_1]','DATE_TIME'],
      ['Priya Rao','[PERSON_1]','PERSON'],
      ['priya.rao@stellar.ai','[EMAIL_1]','EMAIL_ADDRESS'],
      ['Banque Nordique','[ORG_1]','ORGANIZATION'],
      ['BN-2026-Q2','[CASE_2]','CREDIT_CARD'],
      ['a7f3d2c','[HASH_1]','IP_ADDRESS'],
      ['06:30 UTC','[DATE_2]','DATE_TIME'],
    ],
  },
  finance: {
    left: `Q2 close — flagging three receivables over 60 days:
• Aether Biosciences (PO 4771): €842,000, contact cfo@aether-bio.fr, owner Léa Martin.
• Northwind Polymers: $1.2M, 401 Pine St, Austin TX, contact accounting@nwpoly.com.
• Delta Freight GmbH: €310,500, contact r.wagner@delta-freight.de, phone +49 30 4455 6677.
Board review Friday 14:00 CET.`,
    entities: [
      ['Aether Biosciences','[ORG_1]','ORGANIZATION'],
      ['4771','[CASE_1]','CREDIT_CARD'],
      ['€842,000','[AMOUNT_1]','DATE_TIME'],
      ['cfo@aether-bio.fr','[EMAIL_1]','EMAIL_ADDRESS'],
      ['Léa Martin','[PERSON_1]','PERSON'],
      ['Northwind Polymers','[ORG_2]','ORGANIZATION'],
      ['$1.2M','[AMOUNT_2]','DATE_TIME'],
      ['401 Pine St, Austin TX','[LOCATION_1]','LOCATION'],
      ['accounting@nwpoly.com','[EMAIL_2]','EMAIL_ADDRESS'],
      ['Delta Freight GmbH','[ORG_3]','ORGANIZATION'],
      ['€310,500','[AMOUNT_3]','DATE_TIME'],
      ['r.wagner@delta-freight.de','[EMAIL_3]','EMAIL_ADDRESS'],
      ['+49 30 4455 6677','[PHONE_1]','PHONE_NUMBER'],
      ['Friday 14:00 CET','[DATE_1]','DATE_TIME'],
    ],
  },
};

function renderWithEntities(text, entities, showTokens) {
  // find all spans, non-overlapping, keep leftmost
  const hits = [];
  for (const [orig, tok, type] of entities) {
    let i = 0;
    while (true) {
      const idx = text.indexOf(orig, i);
      if (idx < 0) break;
      hits.push({ start: idx, end: idx + orig.length, orig, tok, type });
      i = idx + orig.length;
    }
  }
  hits.sort((a,b) => a.start - b.start || (b.end - b.start) - (a.end - a.start));
  const picked = [];
  let last = -1;
  for (const h of hits) if (h.start >= last) { picked.push(h); last = h.end; }
  const out = [];
  let cur = 0;
  picked.forEach((h, i) => {
    if (h.start > cur) out.push(<span key={'t'+i}>{text.slice(cur, h.start)}</span>);
    if (showTokens) out.push(<Tag key={'s'+i} type={h.type}>{h.tok}</Tag>);
    else out.push(<span key={'s'+i}>{h.orig}</span>);
    cur = h.end;
  });
  if (cur < text.length) out.push(<span key="end">{text.slice(cur)}</span>);
  return out;
}

const SideBySide = () => {
  const [which, setWhich] = useState('legal');
  useReveal();
  const sample = SAMPLES[which];
  return (
    <section id="compare" data-screen-label="Home · Side-by-side">
      <div className="container">
        <div className="reveal" style={{maxWidth: 780, marginBottom: 40}}>
          <div className="section-kicker">03 · Visible proof</div>
          <h2 className="section-title">What you sent vs. <span className="accent">what the model saw.</span></h2>
          <p className="section-lede">Tokens are deterministic within a session — so the model can reason about them — and meaningless outside of it. Flip through real prompts.</p>
        </div>

        <div className="sbs-toggle reveal">
          {[['legal','Legal & M&A'],['engineering','R&D · Engineering'],['finance','Finance · Strategy']].map(([k,l]) => (
            <button key={k} className={which===k?'on':''} onClick={() => setWhich(k)}>{l}</button>
          ))}
        </div>

        <div className="sbs-grid">
          <div className="sbs-panel glass reveal">
            <div className="sbs-head">
              <div className="label"><span className="d"></span>What you sent</div>
              <div className="meta">origin · localhost:7081</div>
            </div>
            <div className="sbs-body">{renderWithEntities(sample.left, sample.entities, false)}</div>
            <div className="sbs-foot"><span>POST /v1/chat/completions</span><span>raw · 0 redactions</span></div>
          </div>
          <div className="sbs-panel glass reveal" style={{'--reveal-delay':'100ms'}}>
            <div className="sbs-head redact">
              <div className="label"><span className="d"></span>What the LLM saw</div>
              <div className="meta">→ gpt-5 · tls</div>
            </div>
            <div className="sbs-body">{renderWithEntities(sample.left, sample.entities, true)}</div>
            <div className="sbs-foot"><span>POST /v1/chat/completions</span><span className="tnum">{sample.entities.length} entities · 0 PII leaked</span></div>
          </div>
        </div>

        <div className="reveal" style={{marginTop: 16, display: 'flex', alignItems: 'center', gap: 12, color: 'var(--ink-muted)', fontFamily: 'var(--font-mono)', fontSize: 12}}>
          <span style={{color: 'var(--ink-faint)'}}>↻</span>
          Same token on the way back — response arrives de-pseudonymized, your client sees the originals.
        </div>
        <MotionPin style={{top: 40, right: 32}}>interactive · toggle example · tokens morph 260ms</MotionPin>
      </div>
    </section>
  );
};

/* ---------- Feature grid ---------- */
const AuditStream = () => {
  const rows = [
    ['02:14:07','redact','[PERSON_3]','0.96'],
    ['02:14:07','redact','[EMAIL_2]','1.00'],
    ['02:14:09','detect','IBAN','1.00'],
    ['02:14:11','restore','[PERSON_3]','ok'],
    ['02:14:14','redact','[ORG_1]','0.88'],
    ['02:14:18','restore','[EMAIL_2]','ok'],
    ['02:14:21','redact','[PHONE_1]','0.98'],
    ['02:14:24','detect','CREDIT_CARD','1.00'],
  ];
  return (
    <div className="audit-mini">
      <div className="stream">
        {[...rows, ...rows].map((r, i) => (
          <div key={i} className="row mono">
            <span className="t">{r[0]}</span>
            <span className="e">{r[1]}</span>
            <span style={{flex:1, color:'var(--ink-muted)'}}>{r[2]}</span>
            <span className="n">{r[3]}</span>
          </div>
        ))}
      </div>
    </div>
  );
};

const FEATURES = [
  { icn: I.link, title: 'Works with any LLM', desc: 'Drop-in OpenAI-compatible endpoint. Swap the hostname, keep the SDK.',
    viz: (
      <div className="vendor-marquee">
        <span className="vendor-chip openai"><span className="sw"/>openai</span>
        <span className="vendor-chip anthropic"><span className="sw"/>anthropic</span>
        <span className="vendor-chip mistral"><span className="sw"/>mistral</span>
        <span className="vendor-chip google"><span className="sw"/>gemini</span>
        <span className="vendor-chip azure"><span className="sw"/>azure</span>
        <span className="vendor-chip bedrock"><span className="sw"/>bedrock</span>
      </div>
    ) },
  { icn: I.server, title: 'Self-hosted, always', desc: 'Ships as a Rust binary or container. Runs in your VPC, on-prem, or air-gapped.',
    viz: (
      <div className="perimeter">
        <span className="box">client</span>
        <span className="arr">—</span>
        <span className="box in">biffer</span>
        <span className="arr">—</span>
        <span className="box in">egress</span>
        <span className="arr">⋮</span>
        <span className="box">vendor</span>
      </div>
    ) },
  { icn: I.scan, title: 'Two-layer detection', desc: 'Regex for format-bound entities, ONNX NER for prose. Tunable per policy.',
    viz: (
      <div style={{display:'flex', flexDirection:'column', gap:6}}>
        <div style={{display:'flex', gap:8, fontSize:10.5}}>
          <span style={{color:'var(--kin)'}}>REGEX</span>
          <span style={{color:'var(--ink-muted)'}}>email · iban · phone · card · ip · url · ssn</span>
        </div>
        <div style={{display:'flex', gap:8, fontSize:10.5}}>
          <span style={{color:'var(--tsuru)'}}>NER&nbsp;&nbsp;</span>
          <span style={{color:'var(--ink-muted)'}}>person · organization · location · date</span>
        </div>
        <div style={{display:'flex', gap:8, fontSize:10.5, color:'var(--ink-faint)'}}>
          <span>conf</span>
          <span style={{flex:1, height:4, background:'var(--surface-border)', borderRadius:2, overflow:'hidden', alignSelf:'center'}}>
            <span style={{display:'block', height:'100%', width:'94%', background:'var(--kin)'}}></span>
          </span>
          <span className="tnum">0.94</span>
        </div>
      </div>
    ) },
  { icn: I.tag, title: 'Session-aware tokens', desc: 'Same entity resolves to the same token across a session — so the model can still reason.',
    viz: (
      <div style={{display:'flex', flexDirection:'column', gap:6}}>
        <div style={{display:'flex', alignItems:'center', gap:8, fontSize:11}}>
          <span style={{color:'var(--ink-muted)'}}>Marie Dupont</span>
          <span style={{color:'var(--ink-faint)'}}>→</span>
          <Tag type="PERSON">[PERSON_1]</Tag>
        </div>
        <div style={{display:'flex', alignItems:'center', gap:8, fontSize:11}}>
          <span style={{color:'var(--ink-muted)'}}>M. Dupont</span>
          <span style={{color:'var(--ink-faint)'}}>→</span>
          <Tag type="PERSON">[PERSON_1]</Tag>
        </div>
        <div style={{display:'flex', alignItems:'center', gap:8, fontSize:11}}>
          <span style={{color:'var(--ink-muted)'}}>marie@acme.eu</span>
          <span style={{color:'var(--ink-faint)'}}>→</span>
          <Tag type="EMAIL_ADDRESS">[EMAIL_1]</Tag>
        </div>
      </div>
    ) },
  { icn: I.log, title: 'Tamper-evident audit', desc: 'Every detection, every restore, every prompt hash — append-only and SIEM-shaped.',
    viz: <AuditStream/> },
  { icn: I.globe, title: 'Multilingual NER', desc: 'English and French ship now. German, Spanish, Italian, Dutch in eval.',
    viz: (
      <div style={{display:'flex', gap:8, flexWrap:'wrap', alignItems:'center'}}>
        <span className="vendor-chip" style={{color:'var(--ink)'}}><span className="sw" style={{background:'var(--kin)'}}/>EN · shipping</span>
        <span className="vendor-chip" style={{color:'var(--ink)'}}><span className="sw" style={{background:'var(--kin)'}}/>FR · shipping</span>
        <span className="vendor-chip"><span className="sw" style={{background:'var(--tsuru)'}}/>DE · eval</span>
        <span className="vendor-chip"><span className="sw" style={{background:'var(--tsuru)'}}/>ES · eval</span>
        <span className="vendor-chip" style={{opacity:0.5}}><span className="sw"/>IT · roadmap</span>
        <span className="vendor-chip" style={{opacity:0.5}}><span className="sw"/>NL · roadmap</span>
      </div>
    ) },
];

const Features = () => {
  useReveal();
  return (
    <section id="features" data-screen-label="Home · Features">
      <div className="container">
        <div className="reveal" style={{maxWidth: 780, marginBottom: 64}}>
          <div className="section-kicker">04 · Platform</div>
          <h2 className="section-title">Six mechanics. <span className="accent">No magic.</span></h2>
          <p className="section-lede">Each is independently verifiable, independently disableable, independently auditable. Your CISO can reason about the whole surface in an hour.</p>
        </div>
        <div className="feat-grid">
          {FEATURES.map((f, i) => (
            <FeatCard key={i} f={f} delay={i*60}/>
          ))}
        </div>
        <MotionPin style={{top: 40, right: 32}}>hover · cursor spotlight gold 14% · reveals stagger 60ms</MotionPin>
      </div>
    </section>
  );
};
const FeatCard = ({ f, delay }) => {
  const ref = useRef(null);
  useSpotlight(ref);
  return (
    <div ref={ref} className="feat-card glass spotlight reveal" style={{'--reveal-delay':`${delay}ms`}}>
      <div className="ficn">{f.icn}</div>
      <h3>{f.title}</h3>
      <p>{f.desc}</p>
      <div className="viz">{f.viz}</div>
    </div>
  );
};

/* ---------- Compliance band ---------- */
const Compliance = () => {
  useReveal();
  return (
    <div className="compliance" id="compliance" data-screen-label="Home · Compliance">
      <div className="container reveal">
        <div className="comp-row">
          <span className="comp-mark">GDPR</span>
          <span className="comp-mark">EU AI Act</span>
          <span className="comp-mark">HIPAA</span>
          <span className="comp-mark">SOC 2<span className="note">in progress</span></span>
          <span className="comp-mark">ISO 27001<span className="note">roadmap</span></span>
          <span className="comp-mark">NIS2</span>
        </div>
        <p className="comp-tag">Designed to meet the controls your auditors already ask for.</p>
      </div>
    </div>
  );
};

/* ---------- Use cases ---------- */
const UseCases = () => {
  useReveal();
  const cases = [
    { kind: 'Legal & M&A', title: 'Redact before review.', body: 'Draft memos, due-diligence Qs, and summarisations on deal docs — without dropping counterparty names, IBANs, or closing dates into someone else\'s log.',
      samples: ['[ORG_1]','[PERSON_2]','[AMOUNT_1]','[DATE_2]','[IBAN_1]'], tags: ['PERSON','ORGANIZATION','DATE_TIME','CREDIT_CARD','CREDIT_CARD']},
    { kind: 'R&D · Engineering', title: 'Debug with context.', body: 'Paste stack traces, incident tickets, customer names — let the model help without tattooing your internal topology onto a training corpus.',
      samples: ['[IP_1]','[HASH_1]','[PERSON_1]','[ORG_2]','[CASE_1]'], tags: ['IP_ADDRESS','IP_ADDRESS','PERSON','ORGANIZATION','CREDIT_CARD']},
    { kind: 'Finance · Strategy', title: 'Analyze without leaking.', body: 'Forecasts, receivables, tender responses — keep counterparty and figure intact to you, opaque to the vendor.',
      samples: ['[AMOUNT_1]','[EMAIL_1]','[ORG_3]','[DATE_1]','[PHONE_1]'], tags: ['DATE_TIME','EMAIL_ADDRESS','ORGANIZATION','DATE_TIME','PHONE_NUMBER']},
  ];
  return (
    <section id="use-cases" data-screen-label="Home · Use cases">
      <div className="container">
        <div className="reveal" style={{maxWidth: 780, marginBottom: 64}}>
          <div className="section-kicker">05 · Use cases</div>
          <h2 className="section-title">Three teams. <span className="accent">Same proxy.</span></h2>
        </div>
        <div className="uc-grid">
          {cases.map((c,i) => (
            <UCCard key={i} c={c} delay={i*80}/>
          ))}
        </div>
      </div>
    </section>
  );
};
const UCCard = ({c, delay}) => {
  const ref = useRef(null);
  useSpotlight(ref);
  return (
    <div ref={ref} className="uc-card glass spotlight reveal" style={{'--reveal-delay':`${delay}ms`}}>
      <div className="kind">{c.kind}</div>
      <h3>{c.title}</h3>
      <p>{c.body}</p>
      <div className="samples">
        {c.samples.map((s,i) => <Tag key={i} type={c.tags[i]}>{s}</Tag>)}
      </div>
    </div>
  );
};

/* ---------- Closing CTA ---------- */
const ClosingCTA = () => (
  <section className="close-cta" data-screen-label="Home · Closing">
    <div className="container-narrow" style={{position:'relative', zIndex:1}}>
      <h2>Stop leaking.<br/><span className="accent">Ship faster.</span></h2>
      <div className="cta-row" style={{justifyContent:'center'}}>
        <a href="contact.html" className="btn-pill primary btn-lg">Book a demo <span className="arrow">→</span></a>
        <a href="how-it-works.html" className="btn-pill secondary btn-lg">See the flow</a>
      </div>
      <p className="sub">30-minute demo. No slides. Your prompts, our proxy, live on a screen share.</p>
    </div>
  </section>
);

/* ---------- HERO ---------- */
const Hero = () => {
  useReveal();
  return (
    <section className="hero-sec" data-screen-label="Home · Hero">
      <div className="grid-bg"></div>
      <div className="container">
        <div className="hero-grid">
          <div className="hero-copy">
            <div className="eyebrow"><span className="dot"></span>LIVE · 2026 · v0.6.4</div>
            <h1 className="mega">
              <span className="mega-line">Use any LLM.</span>
              <span className="mega-line accent">Leak nothing.</span>
            </h1>
            <p className="lede">
              BifferProxy is the self-hosted proxy that pseudonymizes sensitive data
              before it ever reaches a third-party model — then restores it on the way back.
              Transparent to your code. Auditable end-to-end.
            </p>
            <div className="cta-row">
              <a href="contact.html" className="btn-pill primary btn-lg">Book a demo <span className="arrow">→</span></a>
              <a href="#how" className="btn-pill secondary btn-lg">See how it works</a>
            </div>
            <div className="trust-row">
              <span className="trust-tag">GDPR<span className="dim">ready</span></span>
              <span className="trust-tag">EU AI Act<span className="dim">Art. 10</span></span>
              <span className="trust-tag">SOC 2<span className="dim">in progress</span></span>
              <span className="trust-tag">self-hosted<span className="dim">always</span></span>
              <span className="trust-tag">EN · FR<span className="dim">shipping</span></span>
            </div>
          </div>
          <div className="reveal" style={{'--reveal-delay': '120ms', position:'relative'}}>
            <HeroDemo/>
            <MotionPin style={{top: -18, left: 12}}>storyboard · 8s loop · type → redact → send → stream back → restore</MotionPin>
          </div>
        </div>
      </div>
    </section>
  );
};

/* ---------- Motion pin toggle (replaced by Tweaks panel — kept as inert placeholder) ---------- */
const MotionToggle = () => null;
window.MotionToggle = MotionToggle;

/* ---------- App ---------- */
const Home = () => (
  <>
    <Nav active="home"/>
    <Hero/>
    <Problem/>
    <Flow/>
    <SideBySide/>
    <Features/>
    <Compliance/>
    <UseCases/>
    <ClosingCTA/>
    <Footer/>
    <MotionToggle/>
  </>
);

window.Home = Home;
if (!window.__BIFFER_NO_AUTOMOUNT) {
  ReactDOM.createRoot(document.getElementById('root')).render(<Home/>);
}
