// File viewers — render each kind of document with its own UI

function Viewer({ fileId, identity, onClose, onScroll }) {
  const file = ROOM_FILES.find(f => f.id === fileId);
  const scrollRef = React.useRef(null);
  const [scrollPct, setScrollPct] = React.useState(0);
  const [page, setPage] = React.useState(1);
  const [elapsed, setElapsed] = React.useState(0);

  React.useEffect(() => {
    const t = setInterval(() => setElapsed(s => s + 1), 1000);
    return () => clearInterval(t);
  }, []);

  const handleScroll = (e) => {
    const el = e.currentTarget;
    const pct = Math.min(100, Math.round((el.scrollTop / Math.max(1, (el.scrollHeight - el.clientHeight))) * 100));
    setScrollPct(pct);
    if (onScroll) onScroll(pct);
  };

  if (!file) return null;
  const fmtTime = (s) => `${Math.floor(s/60)}m ${String(s%60).padStart(2,'0')}s`;

  return (
    <div style={{
      position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
      background: 'var(--bg)', zIndex: 100,
    }}>
      {/* Top toolbar */}
      <div className="viewer-toolbar" style={{
        height: 56, flexShrink: 0,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '0 24px',
        borderBottom: '1px solid var(--border)',
        background: 'var(--bg)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, minWidth: 0 }}>
          <button className="btn btn-ghost btn-sm" onClick={onClose}>← Room</button>
          <div className="viewer-meta-divider" style={{ width: 1, height: 18, background: 'var(--border)' }} />
          <span className="viewer-file-icon"><FileIcon kind={file.kind} size={22} /></span>
          <div style={{ minWidth: 0 }}>
            <div className="viewer-file-name" style={{ fontSize: 13, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{file.title || file.name}</div>
            <div className="mono viewer-file-meta" style={{ fontSize: 9, color: 'var(--text-tertiary)', letterSpacing: '0.08em', marginTop: 2 }}>
              {file.size} · {file.pages} {file.pages === 1 ? 'PAGE' : 'PAGES'} · {file.updated.toUpperCase()}
            </div>
          </div>
        </div>

        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <span className="mono viewer-meta-viewing" style={{ fontSize: 10, color: 'var(--text-tertiary)' }}>
            VIEWING_AS: {identity.email}
          </span>
          <div className="viewer-meta-divider" style={{ width: 1, height: 18, background: 'var(--border)' }} />
          <span className="mono viewer-meta-elapsed" style={{ fontSize: 10, color: 'var(--text-tertiary)' }}>
            ⏱ {fmtTime(elapsed)}
          </span>
          <span className="mono viewer-meta-scroll" style={{ fontSize: 10, color: 'var(--text-tertiary)' }}>
            ▼ {scrollPct}%
          </span>
          {file.pages > 1 && (
            <span className="viewer-pages"><PageStepper page={page} setPage={setPage} max={file.pages} /></span>
          )}
          <button className="btn btn-sm viewer-download">↓ Download</button>
        </div>
      </div>

      {/* Scrollable content */}
      <div ref={scrollRef} onScroll={handleScroll}
        style={{ flex: 1, overflow: 'auto', position: 'relative', background: 'var(--bg-elevated)' }}>
        <div style={
          file.kind === 'html'
            ? { position: 'relative', width: '100%', minHeight: '100%' }
            : { position: 'relative', maxWidth: 880, margin: '32px auto 80px', minHeight: 'calc(100% - 96px)' }
        }>
          <Watermark email={identity.email} />
          {file.kind === 'pdf' && <PdfBody file={file} page={page} />}
          {file.kind === 'html' && <HtmlBody file={file} />}
          {file.kind === 'xlsx' && <XlsxBody file={file} page={page} />}
          {file.kind === 'docx' && <DocxBody file={file} />}
          {file.kind === 'sol' && <SolBody file={file} />}
        </div>
      </div>
    </div>
  );
}

function PageStepper({ page, setPage, max }) {
  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', border: '1px solid var(--border)', height: 28 }}>
      <button onClick={() => setPage(Math.max(1, page - 1))}
        style={{ padding: '0 10px', height: 28, background: 'transparent', border: 'none', borderRight: '1px solid var(--border)', color: 'var(--text-secondary)' }}>
        ←
      </button>
      <span className="mono" style={{ fontSize: 10, padding: '0 10px', color: 'var(--text-secondary)' }}>
        {String(page).padStart(2,'0')} / {String(max).padStart(2,'0')}
      </span>
      <button onClick={() => setPage(Math.min(max, page + 1))}
        style={{ padding: '0 10px', height: 28, background: 'transparent', border: 'none', borderLeft: '1px solid var(--border)', color: 'var(--text-secondary)' }}>
        →
      </button>
    </div>
  );
}

// ── PDF: Pitch deck, audits ─────────────────────────
function PdfBody({ file, page }) {
  // Render different content depending on which PDF & page
  if (file.id === 'deck') return <DeckPage page={page} />;
  if (file.id === 'audit-tob') return <AuditPage source="Trail of Bits" page={page} />;
  if (file.id === 'audit-oz') return <AuditPage source="OpenZeppelin" page={page} />;
  return <DeckPage page={page} />;
}

const DECK_SLIDES = [
  { kind: 'cover', title: 'Arb Capital', sub: 'Series Seed · Q2 2026', tag: 'CONFIDENTIAL' },
  { kind: 'tag', label: 'PROBLEM', title: 'DeFi yield is opaque, fragmented, and unsafe for institutional capital.' },
  { kind: 'three', title: 'The opportunity', items: [
    { k: 'Stablecoin TVL', v: '$148B', d: 'Growing 18% YoY' },
    { k: 'Active vault standard', v: 'ERC-4626', d: '5,200+ deployments' },
    { k: 'Institutional gap', v: '< 4%', d: 'AUM in audited yield' },
  ]},
  { kind: 'tag', label: 'SOLUTION', title: 'Professionally managed ERC-4626 vaults with institutional risk controls.' },
  { kind: 'team', title: 'Team' },
  { kind: 'metrics', title: 'Traction' },
  { kind: 'ask', title: 'The ask' },
];

function DeckPage({ page }) {
  const slide = DECK_SLIDES[(page - 1) % DECK_SLIDES.length];

  return (
    <DocSheet pageNum={page} total={22} kind="DECK">
      {slide.kind === 'cover' && (
        <div style={{ height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 700, padding: 8 }}>
          <div className="section-num"><span>[ COVER ]</span><span className="div" /><span>2026.05</span></div>
          <div>
            <ArbLogo size={64} variant="gold-mono" />
            <h1 style={{ fontSize: 88, lineHeight: 1, letterSpacing: '-0.04em', fontWeight: 300, margin: '24px 0 16px' }}>
              Arb Capital.
            </h1>
            <h2 style={{ fontSize: 40, fontWeight: 300, letterSpacing: '-0.025em', color: 'var(--gold-dark)', margin: 0 }}>
              Real Alpha.
            </h2>
            <p style={{ fontSize: 16, color: 'var(--text-secondary)', marginTop: 32, maxWidth: 480, lineHeight: 1.6 }}>
              Institutional-grade ERC-4626 vaults. Built by ex-MakerDAO core engineers.
            </p>
          </div>
          <div className="mono" style={{ fontSize: 10, color: 'var(--text-tertiary)', letterSpacing: '0.14em' }}>
            SERIES SEED · CONFIDENTIAL · 2026
          </div>
        </div>
      )}
      {slide.kind === 'tag' && (
        <div style={{ minHeight: 700, display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 8 }}>
          <div className="section-num" style={{ marginBottom: 32 }}>
            <span>[ {String(page).padStart(2,'0')} ]</span><span className="div" /><span>{slide.label}</span>
          </div>
          <h2 style={{ fontSize: 56, lineHeight: 1.1, letterSpacing: '-0.03em', fontWeight: 300, margin: 0, maxWidth: 800 }}>
            {slide.title}
          </h2>
        </div>
      )}
      {slide.kind === 'three' && (
        <div style={{ minHeight: 700, padding: 8 }}>
          <div className="section-num" style={{ marginBottom: 32 }}>
            <span>[ {String(page).padStart(2,'0')} ]</span><span className="div" /><span>OPPORTUNITY</span>
          </div>
          <h2 style={{ fontSize: 36, fontWeight: 400, letterSpacing: '-0.02em', margin: '0 0 48px' }}>{slide.title}</h2>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 24 }}>
            {slide.items.map((it, i) => (
              <Brackets key={i} style={{ padding: 24, border: '1px solid var(--border)', minHeight: 200 }}>
                <div className="mono" style={{ fontSize: 10, letterSpacing: '0.14em', color: 'var(--text-tertiary)', marginBottom: 16 }}>
                  [ {String(i+1).padStart(2,'0')} ]
                </div>
                <div className="mono" style={{ fontSize: 10, letterSpacing: '0.12em', color: 'var(--text-secondary)', marginBottom: 12 }}>
                  {it.k}
                </div>
                <div style={{ fontSize: 44, letterSpacing: '-0.03em', fontWeight: 300 }}>{it.v}</div>
                <div style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 8 }}>{it.d}</div>
              </Brackets>
            ))}
          </div>
        </div>
      )}
      {slide.kind === 'team' && <TeamSlide page={page} />}
      {slide.kind === 'metrics' && <MetricsSlide page={page} />}
      {slide.kind === 'ask' && <AskSlide page={page} />}
    </DocSheet>
  );
}

function TeamSlide({ page }) {
  const team = [
    { name: 'Maya Strom', role: 'Founder, CEO', bg: 'Ex-MakerDAO core eng. Built Spark Protocol risk module.' },
    { name: 'David Reyes', role: 'CTO', bg: 'Ex-MakerDAO smart contracts. 6 years protocol security.' },
    { name: 'Asha Kim', role: 'Head of Risk', bg: 'Ex-Goldman quant. PhD financial math, MIT.' },
    { name: 'Tom Eisenhardt', role: 'Head of BD', bg: 'Ex-Coinbase Institutional. $2B+ in onboardings.' },
  ];
  return (
    <div style={{ minHeight: 700, padding: 8 }}>
      <div className="section-num" style={{ marginBottom: 32 }}>
        <span>[ {String(page).padStart(2,'0')} ]</span><span className="div" /><span>TEAM</span>
      </div>
      <h2 style={{ fontSize: 36, fontWeight: 400, letterSpacing: '-0.02em', margin: '0 0 48px' }}>Built by people who built MakerDAO.</h2>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
        {team.map(t => (
          <div key={t.name} style={{ borderTop: '1px solid var(--border)', paddingTop: 16, display: 'flex', gap: 16 }}>
            <div style={{ width: 56, height: 72, background: 'var(--bg-elevated)', flexShrink: 0,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontFamily: 'var(--font-mono)', fontSize: 22, color: 'var(--text-tertiary)' }}>
              {t.name.split(' ').map(n => n[0]).join('')}
            </div>
            <div>
              <div style={{ fontSize: 17 }}>{t.name}</div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--gold-dark)', letterSpacing: '0.1em', margin: '4px 0 10px' }}>{t.role.toUpperCase()}</div>
              <div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.6 }}>{t.bg}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function MetricsSlide({ page }) {
  const tvl = [3.2, 4.1, 5.8, 7.4, 9.1, 11.6, 14.2, 17.0, 19.4, 21.8, 23.2, 24.0];
  return (
    <div style={{ minHeight: 700, padding: 8 }}>
      <div className="section-num" style={{ marginBottom: 32 }}>
        <span>[ {String(page).padStart(2,'0')} ]</span><span className="div" /><span>TRACTION</span>
      </div>
      <h2 style={{ fontSize: 36, fontWeight: 400, letterSpacing: '-0.02em', margin: '0 0 32px' }}>$24M TVL. 12 months. Zero incidents.</h2>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 32 }}>
        <Brackets style={{ padding: 16, border: '1px solid var(--border)' }}>
          <div className="mono" style={{ fontSize: 10, color: 'var(--text-tertiary)', letterSpacing: '0.12em', marginBottom: 8 }}>TVL_GROWTH</div>
          <div style={{ fontSize: 28, letterSpacing: '-0.02em' }}>+650%</div>
          <div style={{ fontSize: 11, color: 'var(--success)', marginTop: 4, fontFamily: 'var(--font-mono)' }}>↑ 12mo</div>
        </Brackets>
        <Brackets style={{ padding: 16, border: '1px solid var(--border)' }}>
          <div className="mono" style={{ fontSize: 10, color: 'var(--text-tertiary)', letterSpacing: '0.12em', marginBottom: 8 }}>NET_APY_AVG</div>
          <div style={{ fontSize: 28, letterSpacing: '-0.02em' }}>8.21%</div>
          <div style={{ fontSize: 11, color: 'var(--text-secondary)', marginTop: 4, fontFamily: 'var(--font-mono)' }}>90d trailing</div>
        </Brackets>
        <Brackets style={{ padding: 16, border: '1px solid var(--border)' }}>
          <div className="mono" style={{ fontSize: 10, color: 'var(--text-tertiary)', letterSpacing: '0.12em', marginBottom: 8 }}>DEPOSITORS</div>
          <div style={{ fontSize: 28, letterSpacing: '-0.02em' }}>1,247</div>
          <div style={{ fontSize: 11, color: 'var(--success)', marginTop: 4, fontFamily: 'var(--font-mono)' }}>↑ 38 this wk</div>
        </Brackets>
        <Brackets style={{ padding: 16, border: '1px solid var(--border)' }}>
          <div className="mono" style={{ fontSize: 10, color: 'var(--text-tertiary)', letterSpacing: '0.12em', marginBottom: 8 }}>INCIDENTS</div>
          <div style={{ fontSize: 28, letterSpacing: '-0.02em' }}>0</div>
          <div style={{ fontSize: 11, color: 'var(--text-secondary)', marginTop: 4, fontFamily: 'var(--font-mono)' }}>since launch</div>
        </Brackets>
      </div>

      <Brackets style={{ padding: 24, border: '1px solid var(--border)' }}>
        <div className="mono" style={{ fontSize: 10, color: 'var(--text-tertiary)', letterSpacing: '0.12em', marginBottom: 16 }}>TVL_OVER_TIME // $M</div>
        <ChartTVL data={tvl} />
      </Brackets>
    </div>
  );
}

function ChartTVL({ data }) {
  const w = 800, h = 200, pad = 12;
  const max = Math.max(...data) * 1.1;
  const step = (w - pad * 2) / (data.length - 1);
  const pts = data.map((d, i) => `${pad + i * step},${h - pad - (d / max) * (h - pad * 2)}`);
  const areaPts = `${pad},${h - pad} ${pts.join(' ')} ${pad + (data.length - 1) * step},${h - pad}`;
  return (
    <svg width="100%" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ display: 'block' }}>
      <polygon points={areaPts} fill="rgba(212,175,55,0.12)" />
      <polyline points={pts.join(' ')} fill="none" stroke="#D4AF37" strokeWidth="1.5" />
      {data.map((d, i) => (
        <circle key={i} cx={pad + i * step} cy={h - pad - (d / max) * (h - pad * 2)} r="2" fill="#D4AF37" />
      ))}
      {/* Y axis ticks */}
      {[0, 0.5, 1].map(t => (
        <line key={t} x1={pad} x2={w - pad} y1={h - pad - t * (h - pad * 2)} y2={h - pad - t * (h - pad * 2)} stroke="var(--border)" strokeDasharray="2 4" />
      ))}
    </svg>
  );
}

function AskSlide({ page }) {
  return (
    <div style={{ minHeight: 700, padding: 8, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
      <div className="section-num" style={{ marginBottom: 32 }}>
        <span>[ {String(page).padStart(2,'0')} ]</span><span className="div" /><span>THE_ASK</span>
      </div>
      <div style={{ fontSize: 15, color: 'var(--text-secondary)', marginBottom: 16 }}>Series Seed · SAFE post-money</div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 24, marginBottom: 48 }}>
        <span style={{ fontSize: 96, letterSpacing: '-0.04em', fontWeight: 300, lineHeight: 1 }}>$4M</span>
        <span style={{ fontSize: 22, color: 'var(--text-secondary)' }}>raise on a</span>
        <span style={{ fontSize: 56, letterSpacing: '-0.03em', fontWeight: 300, color: 'var(--gold-dark)' }}>$20M</span>
        <span style={{ fontSize: 22, color: 'var(--text-secondary)' }}>cap.</span>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 20 }}>
        <UseRow pct={45} label="Engineering" />
        <UseRow pct={30} label="Risk & audits" />
        <UseRow pct={25} label="GTM & ops" />
      </div>
    </div>
  );
}

function UseRow({ pct, label }) {
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
        <span className="mono" style={{ fontSize: 10, letterSpacing: '0.12em', color: 'var(--text-secondary)' }}>{label.toUpperCase()}</span>
        <span className="mono" style={{ fontSize: 10, color: 'var(--gold-dark)' }}>{pct}%</span>
      </div>
      <div className="bar bar-gold"><i style={{ width: `${pct}%` }} /></div>
    </div>
  );
}

// ── Audit PDF ───────────────────────────────────────
function AuditPage({ source, page }) {
  return (
    <DocSheet pageNum={page} total={48} kind={source.toUpperCase()}>
      <div className="section-num" style={{ marginBottom: 16 }}>
        <span>[ AUDIT_REPORT ]</span><span className="div" /><span>{source.toUpperCase()}</span>
      </div>
      <h1 style={{ fontSize: 32, fontWeight: 400, letterSpacing: '-0.02em', margin: '0 0 12px' }}>
        ArbVault Smart Contract Security Review
      </h1>
      <p style={{ fontSize: 14, color: 'var(--text-secondary)', marginBottom: 32 }}>
        Conducted by {source}. February — March 2026. Scope: ArbVault.sol v2.0, 1,847 lines.
      </p>

      <div style={{ borderTop: '1px solid var(--border)', borderBottom: '1px solid var(--border)', padding: '20px 0', marginBottom: 32 }}>
        <div className="mono" style={{ fontSize: 10, letterSpacing: '0.14em', color: 'var(--text-tertiary)', marginBottom: 16 }}>EXECUTIVE_SUMMARY</div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 24 }}>
          <SeverityCount label="CRITICAL" count={0} />
          <SeverityCount label="HIGH" count={0} />
          <SeverityCount label="MEDIUM" count={2} resolved />
          <SeverityCount label="LOW" count={5} resolved />
        </div>
      </div>

      <h3 style={{ fontSize: 18, fontWeight: 500, marginBottom: 12 }}>Findings</h3>
      <FindingRow id="ATB-01" sev="MEDIUM" status="RESOLVED" title="Reentrancy guard ordering in withdraw()" />
      <FindingRow id="ATB-02" sev="MEDIUM" status="RESOLVED" title="Oracle staleness check missing TWAP fallback" />
      <FindingRow id="ATB-03" sev="LOW" status="RESOLVED" title="Event emission missing for fee parameter updates" />
      <FindingRow id="ATB-04" sev="LOW" status="RESOLVED" title="Inconsistent natspec on _harvest()" />
      <FindingRow id="ATB-05" sev="LOW" status="ACK" title="Centralization: pause guardian role" />

      <p style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.7, marginTop: 32 }}>
        All medium-severity findings were addressed prior to mainnet deployment. Low-severity findings ATB-03 and ATB-04 were patched in v2.0.1. ATB-05 is acknowledged as an intentional design choice; the pause guardian role is held by a 3-of-5 multisig with public membership.
      </p>
    </DocSheet>
  );
}

function SeverityCount({ label, count, resolved }) {
  const color = label === 'CRITICAL' ? 'var(--error)' :
    label === 'HIGH' ? 'var(--error)' :
    label === 'MEDIUM' ? 'var(--warning)' : 'var(--text-secondary)';
  return (
    <div>
      <div className="mono" style={{ fontSize: 9, letterSpacing: '0.14em', color: 'var(--text-tertiary)', marginBottom: 8 }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
        <span style={{ fontSize: 32, letterSpacing: '-0.02em', color }}>{count}</span>
        {resolved && count > 0 && (
          <span className="mono" style={{ fontSize: 9, color: 'var(--success)', letterSpacing: '0.1em' }}>✓ RESOLVED</span>
        )}
      </div>
    </div>
  );
}

function FindingRow({ id, sev, status, title }) {
  const sevColor = sev === 'MEDIUM' ? 'var(--warning)' : sev === 'HIGH' ? 'var(--error)' : 'var(--text-tertiary)';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '14px 0', borderBottom: '1px solid var(--border)' }}>
      <span className="mono" style={{ fontSize: 11, color: 'var(--text-tertiary)', width: 70 }}>{id}</span>
      <span className="badge" style={{ borderColor: sevColor, color: sevColor, width: 78, justifyContent: 'center' }}>{sev}</span>
      <span style={{ fontSize: 13, flex: 1 }}>{title}</span>
      <span className="mono" style={{ fontSize: 10, color: status === 'RESOLVED' ? 'var(--success)' : 'var(--text-tertiary)', letterSpacing: '0.08em' }}>
        {status === 'RESOLVED' ? '✓ ' : '• '}{status}
      </span>
    </div>
  );
}

// ── Document sheet wrapper ────────────────────────
function DocSheet({ children, pageNum, total, kind }) {
  return (
    <div className="doc-sheet" style={{
      background: 'var(--bg-card)',
      border: '1px solid var(--border)',
      padding: 56,
      minHeight: 800,
      position: 'relative',
      boxShadow: '0 1px 0 rgba(0,0,0,0.04)',
    }}>
      {children}
      <div style={{
        position: 'absolute', bottom: 16, left: 56, right: 56,
        display: 'flex', justifyContent: 'space-between',
        fontFamily: 'var(--font-mono)', fontSize: 9, color: 'var(--text-tertiary)',
        letterSpacing: '0.14em',
        paddingTop: 12, borderTop: '1px solid var(--border)',
      }}>
        <span>ARB_CAPITAL · {kind}</span>
        <span>{String(pageNum).padStart(2,'0')} / {String(total).padStart(2,'0')}</span>
      </div>
    </div>
  );
}

// ── HTML memo ───────────────────────────────────────
function HtmlBody({ file }) {
  // Live HTML hosted on R2 — render in a sandboxed iframe.
  // Watermark overlay sits in the parent (added by Viewer) and stays above the iframe.
  if (file.url) {
    return (
      <div style={{ background: 'var(--bg-card)', position: 'relative', overflow: 'hidden', height: 'calc(100vh - 56px)' }}>
        <iframe
          className="viewer-iframe"
          src={file.url}
          title={file.title || file.name}
          style={{ width: '100%', height: '100%', minHeight: 600, border: 'none', display: 'block', background: 'white' }}
        />
      </div>
    );
  }
  return (
    <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border)', padding: 56, position: 'relative' }}>
      <div className="mono" style={{ fontSize: 9, color: 'var(--text-tertiary)', letterSpacing: '0.14em', marginBottom: 8 }}>
        MEMO · INTERACTIVE_HTML
      </div>
      <h1 style={{ fontSize: 36, fontWeight: 400, letterSpacing: '-0.025em', margin: '0 0 12px' }}>
        Vault Architecture
      </h1>
      <p style={{ fontSize: 15, color: 'var(--text-secondary)', marginBottom: 32 }}>
        How Arb Capital structures yield generation. ERC-4626 mechanics, oracle stack, liquidation flow.
      </p>

      <hr className="hr" />

      <h2 style={{ fontSize: 22, fontWeight: 500, margin: '32px 0 12px' }}>1. Vault primitive</h2>
      <p style={{ fontSize: 15, color: 'var(--text-secondary)', lineHeight: 1.8, marginBottom: 16 }}>
        Each Arb Capital strategy is deployed as an ERC-4626 vault — a standardized tokenization of yield-bearing positions. Depositors mint shares; the vault holds the underlying assets and routes them to the active strategy.
      </p>

      <Brackets style={{ background: 'var(--bg)', padding: 20, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.6, marginBottom: 24 }}>
        <div style={{ color: 'var(--gold-dark)' }}>// ArbVault.sol — interface</div>
        <div>function deposit(uint256 assets, address receiver) → uint256 shares;</div>
        <div>function withdraw(uint256 assets, address receiver, address owner) → uint256 shares;</div>
        <div>function totalAssets() → uint256;</div>
        <div>function convertToShares(uint256 assets) → uint256 shares;</div>
      </Brackets>

      <h2 style={{ fontSize: 22, fontWeight: 500, margin: '32px 0 12px' }}>2. Oracle stack</h2>
      <p style={{ fontSize: 15, color: 'var(--text-secondary)', lineHeight: 1.8, marginBottom: 24 }}>
        Pricing is sourced from a three-tier oracle: Chainlink primary, Uniswap v3 TWAP fallback, and a heartbeat staleness check. If Chainlink stops updating, the vault auto-escalates to TWAP. If both fail, deposits and withdrawals freeze.
      </p>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 32 }}>
        <OracleNode tier="01" name="Chainlink" status="primary" />
        <OracleNode tier="02" name="Uniswap V3 TWAP" status="fallback" />
        <OracleNode tier="03" name="Heartbeat freeze" status="emergency" />
      </div>

      <h2 style={{ fontSize: 22, fontWeight: 500, margin: '32px 0 12px' }}>3. Risk parameters</h2>
      <table className="tbl" style={{ marginBottom: 32 }}>
        <thead><tr><th>Parameter</th><th>Value</th><th>Set by</th><th>Cooldown</th></tr></thead>
        <tbody>
          <tr><td>Max LTV</td><td>72%</td><td>Risk multisig</td><td>72h</td></tr>
          <tr><td>Liquidation threshold</td><td>78%</td><td>Risk multisig</td><td>72h</td></tr>
          <tr><td>Performance fee</td><td>10%</td><td>Governance</td><td>7d</td></tr>
          <tr><td>Pause guardian</td><td>3-of-5</td><td>Multisig</td><td>0h</td></tr>
        </tbody>
      </table>

      <h2 style={{ fontSize: 22, fontWeight: 500, margin: '32px 0 12px' }}>4. Liquidation flow</h2>
      <ol style={{ fontSize: 15, color: 'var(--text-secondary)', lineHeight: 1.9, paddingLeft: 20 }}>
        <li>Position health check on every block.</li>
        <li>If health factor &lt; 1.0, liquidator may seize collateral at 5% discount.</li>
        <li>Bad debt socialized across vault if liquidator can't fully cover.</li>
        <li>Insurance fund (3% of TVL) absorbs first-loss tranche.</li>
      </ol>
    </div>
  );
}

function OracleNode({ tier, name, status }) {
  return (
    <Brackets style={{ padding: 16, border: '1px solid var(--border)' }}>
      <div className="mono" style={{ fontSize: 9, letterSpacing: '0.14em', color: 'var(--text-tertiary)', marginBottom: 8 }}>
        TIER_{tier}
      </div>
      <div style={{ fontSize: 16, marginBottom: 8 }}>{name}</div>
      <span className={`badge b-${status === 'primary' ? 'success' : status === 'fallback' ? 'gold' : 'warning'}`}>{status.toUpperCase()}</span>
    </Brackets>
  );
}

// ── XLSX viewer ─────────────────────────────────────
function XlsxBody({ file, page }) {
  const sheets = ['Summary', 'Returns', 'Sensitivities', 'Fees', 'Vault_USDC', 'Vault_ETH', 'Assumptions'];
  const sheet = sheets[(page - 1) % sheets.length];
  return (
    <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border)' }}>
      {/* Tabs */}
      <div style={{ display: 'flex', borderBottom: '1px solid var(--border)', overflow: 'auto' }}>
        {sheets.map((s, i) => (
          <div key={s} style={{
            padding: '10px 14px',
            fontFamily: 'var(--font-mono)', fontSize: 11,
            background: s === sheet ? 'var(--bg-card)' : 'var(--bg-elevated)',
            borderRight: '1px solid var(--border)',
            borderTop: s === sheet ? `2px solid var(--gold)` : '2px solid transparent',
            color: s === sheet ? 'var(--text-primary)' : 'var(--text-secondary)',
            whiteSpace: 'nowrap',
          }}>{s}</div>
        ))}
      </div>

      {/* Cell grid */}
      <div style={{ overflow: 'auto', padding: 0 }}>
        {sheet === 'Returns' || sheet === 'Summary' ? <ReturnsTable /> : <SensitivityTable sheet={sheet} />}
      </div>
    </div>
  );
}

function ReturnsTable() {
  const years = ['2026', '2027', '2028', '2029', '2030'];
  const scenarios = [
    { label: 'Base', tvl: [24, 80, 220, 480, 850], apy: [8.2, 7.8, 7.4, 7.0, 6.6], rev: [0.5, 1.6, 4.2, 8.6, 14.3] },
    { label: 'Bear', tvl: [24, 45, 90, 160, 240], apy: [8.2, 6.5, 5.8, 5.2, 4.8], rev: [0.5, 0.8, 1.6, 2.6, 3.4] },
    { label: 'Bull', tvl: [24, 140, 480, 1200, 2400], apy: [8.2, 8.4, 8.6, 8.8, 8.9], rev: [0.5, 2.8, 9.6, 24, 48] },
  ];
  return (
    <div style={{ minWidth: 700 }}>
      {/* Spreadsheet header bar */}
      <div style={{ display: 'flex', background: 'var(--bg-elevated)', borderBottom: '1px solid var(--border)', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text-tertiary)', letterSpacing: '0.06em' }}>
        <div style={{ width: 32, padding: '4px 0', textAlign: 'center', borderRight: '1px solid var(--border)' }}>·</div>
        {['A', 'B', 'C', 'D', 'E', 'F', 'G'].map(c => (
          <div key={c} style={{ flex: 1, padding: '4px 8px', borderRight: '1px solid var(--border)' }}>{c}</div>
        ))}
      </div>

      <SheetRow rowNum="1" cells={['SCENARIO', 'METRIC', ...years]} bold />
      {scenarios.map((s, si) => (
        <React.Fragment key={s.label}>
          <SheetRow rowNum={si * 3 + 2} cells={[s.label.toUpperCase(), 'TVL ($M)', ...s.tvl.map(v => v.toFixed(0))]} highlight={si === 0} />
          <SheetRow rowNum={si * 3 + 3} cells={['', 'Net APY (%)', ...s.apy.map(v => v.toFixed(2))]} highlight={si === 0} />
          <SheetRow rowNum={si * 3 + 4} cells={['', 'Revenue ($M)', ...s.rev.map(v => v.toFixed(2))]} highlight={si === 0} />
        </React.Fragment>
      ))}

      <SheetRow rowNum="11" cells={['', '', '', '', '', '', '']} />
      <SheetRow rowNum="12" cells={['SUMMARY', '5Y_REV_BASE', '$', '29.2M', '', '', '']} bold />
      <SheetRow rowNum="13" cells={['', '5Y_REV_BULL', '$', '93.0M', '', '', '']} />
      <SheetRow rowNum="14" cells={['', '5Y_REV_BEAR', '$', '8.9M', '', '', '']} />
    </div>
  );
}

function SheetRow({ rowNum, cells, bold, highlight }) {
  return (
    <div style={{
      display: 'flex', borderBottom: '1px solid var(--border)',
      background: highlight ? 'rgba(212,175,55,0.04)' : 'transparent',
    }}>
      <div style={{ width: 32, padding: '8px 0', textAlign: 'center', borderRight: '1px solid var(--border)',
        background: 'var(--bg-elevated)', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text-tertiary)' }}>{rowNum}</div>
      {cells.map((c, i) => (
        <div key={i} style={{
          flex: 1, padding: '8px 10px', borderRight: '1px solid var(--border)',
          fontFamily: i > 0 ? 'var(--font-mono)' : 'var(--font-sans)', fontSize: 12,
          fontWeight: bold ? 600 : 400, color: bold ? 'var(--text-primary)' : 'var(--text-secondary)',
        }}>{c}</div>
      ))}
    </div>
  );
}

function SensitivityTable({ sheet }) {
  const apyDeltas = [-3, -2, -1, 0, 1, 2, 3];
  const tvlDeltas = ['-50%', '-25%', '0%', '+25%', '+50%', '+100%'];
  // Base 5y rev = 29.2M
  const calc = (apy, tvl) => {
    const tvlMult = { '-50%': 0.5, '-25%': 0.75, '0%': 1, '+25%': 1.25, '+50%': 1.5, '+100%': 2 }[tvl];
    return (29.2 * (1 + apy / 8.2) * tvlMult).toFixed(1);
  };
  return (
    <div style={{ minWidth: 700 }}>
      <SheetRow rowNum="1" cells={['SENSITIVITY', '5Y_REV ($M)', ...apyDeltas.map(d => `APY ${d > 0 ? '+' : ''}${d}%`)]} bold />
      {tvlDeltas.map((tvl, ri) => (
        <SheetRow key={tvl} rowNum={ri + 2}
          cells={['TVL_Δ', tvl, ...apyDeltas.map(apy => `$${calc(apy, tvl)}`)]}
          highlight={tvl === '0%'} />
      ))}
    </div>
  );
}

// ── DOCX (term sheet) ───────────────────────────────
function DocxBody({ file }) {
  return (
    <div style={{ background: '#fff', border: '1px solid var(--border)', padding: 72, fontFamily: 'Georgia, serif', position: 'relative', minHeight: 900 }}>
      <div style={{ textAlign: 'center', marginBottom: 36, paddingBottom: 24, borderBottom: '2px solid #0D0D0D' }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.18em', marginBottom: 8 }}>CONFIDENTIAL — DRAFT</div>
        <h1 style={{ fontSize: 22, margin: 0, fontWeight: 700, letterSpacing: '0.04em' }}>ARB CAPITAL, INC.</h1>
        <h2 style={{ fontSize: 16, margin: '4px 0 0', fontWeight: 400, fontStyle: 'italic' }}>Term Sheet — Series Seed Financing</h2>
      </div>
      <p style={{ fontSize: 13, lineHeight: 1.8, color: '#222' }}>
        This non-binding term sheet outlines the proposed terms for an investment in Arb Capital, Inc. ("Company") by participating investors. This term sheet is for discussion purposes only and shall not constitute a binding agreement.
      </p>

      <TermRow term="Issuer" value="Arb Capital, Inc., a Delaware corporation" />
      <TermRow term="Round" value="Series Seed (SAFE — post-money)" />
      <TermRow term="Target Raise" value="$4,000,000" />
      <TermRow term="Valuation Cap" value="$20,000,000 (post-money)" />
      <TermRow term="Discount" value="20% (in lieu of cap, if elected)" />
      <TermRow term="Most Favored Nation" value="Yes — through equity round" />
      <TermRow term="Pro Rata Rights" value="2x participation cap, Series A and Series B" />
      <TermRow term="Information Rights" value="Quarterly financials; annual audited statements above $5M raise" />
      <TermRow term="Lead Investor" value="[ TBD ]" />
      <TermRow term="Use of Proceeds" value="Engineering (45%) · Risk & audits (30%) · GTM & operations (25%)" />
      <TermRow term="Closing" value="Rolling closes through Q3 2026" />

      <p style={{ fontSize: 11, color: '#666', lineHeight: 1.7, marginTop: 36, fontStyle: 'italic' }}>
        This term sheet is non-binding except for the confidentiality provisions herein. Final terms are subject to definitive documentation and customary diligence.
      </p>
    </div>
  );
}

function TermRow({ term, value }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '180px 1fr', gap: 24, padding: '14px 0', borderBottom: '1px solid #eee' }}>
      <span style={{ fontSize: 13, fontWeight: 700, color: '#0D0D0D' }}>{term}</span>
      <span style={{ fontSize: 13, color: '#222' }}>{value}</span>
    </div>
  );
}

// ── Solidity source viewer ─────────────────────────
function SolBody({ file }) {
  const lines = [
    { t: 'comment', s: '// SPDX-License-Identifier: BUSL-1.1' },
    { t: 'pragma', s: 'pragma solidity 0.8.24;' },
    { t: 'blank', s: '' },
    { t: 'import', s: 'import { ERC4626 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";' },
    { t: 'import', s: 'import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";' },
    { t: 'import', s: 'import { IOracle } from "./interfaces/IOracle.sol";' },
    { t: 'blank', s: '' },
    { t: 'comment', s: '/// @title  ArbVault — institutional-grade ERC-4626 yield vault' },
    { t: 'comment', s: '/// @author Arb Capital — engineering@arbcapital.xyz' },
    { t: 'comment', s: '/// @notice Audited by Trail of Bits & OpenZeppelin (V2 — March 2026)' },
    { t: 'contract', s: 'contract ArbVault is ERC4626, ReentrancyGuard {' },
    { t: 'blank', s: '' },
    { t: 'indent', s: '    IOracle public immutable oracle;' },
    { t: 'indent', s: '    address public riskMultisig;' },
    { t: 'indent', s: '    uint256 public maxLTV     = 7200;  // 72.00%' },
    { t: 'indent', s: '    uint256 public liqThresh  = 7800;  // 78.00%' },
    { t: 'indent', s: '    uint256 public perfFee    = 1000;  // 10.00%' },
    { t: 'blank', s: '' },
    { t: 'event', s: '    event Deposit(address indexed sender, uint256 assets, uint256 shares);' },
    { t: 'event', s: '    event Harvest(uint256 yield, uint256 fee, uint256 timestamp);' },
    { t: 'blank', s: '' },
    { t: 'fn', s: '    function deposit(uint256 assets, address receiver)' },
    { t: 'fn', s: '        public override nonReentrant returns (uint256 shares)' },
    { t: 'fn', s: '    {' },
    { t: 'fn', s: '        require(!paused(), "ArbVault: paused");' },
    { t: 'fn', s: '        shares = previewDeposit(assets);' },
    { t: 'fn', s: '        _deposit(_msgSender(), receiver, assets, shares);' },
    { t: 'fn', s: '        emit Deposit(_msgSender(), assets, shares);' },
    { t: 'fn', s: '    }' },
    { t: 'blank', s: '' },
    { t: 'fn', s: '    function _harvest() internal returns (uint256 yield) {' },
    { t: 'fn', s: '        // … strategy-specific yield realization' },
    { t: 'fn', s: '        uint256 fee = (yield * perfFee) / 10000;' },
    { t: 'fn', s: '        emit Harvest(yield, fee, block.timestamp);' },
    { t: 'fn', s: '    }' },
    { t: 'contract', s: '}' },
  ];

  return (
    <div style={{ background: '#0D0D0D', color: '#F5F5F0', fontFamily: 'var(--font-mono)', fontSize: 12, lineHeight: 1.7, position: 'relative' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '14px 20px', borderBottom: '1px solid rgba(255,255,255,0.1)' }}>
        <span style={{ fontSize: 11, letterSpacing: '0.12em', color: 'rgba(245,245,240,0.6)' }}>ArbVault.sol</span>
        <span style={{ fontSize: 10, letterSpacing: '0.12em', color: '#D4AF37' }}>✓ VERIFIED · 0x7A2f…E3c4</span>
      </div>
      <div style={{ padding: '20px 0' }}>
        {lines.map((l, i) => (
          <div key={i} style={{ display: 'flex', padding: '0 20px' }}>
            <span style={{ width: 36, textAlign: 'right', marginRight: 16, color: 'rgba(245,245,240,0.25)' }}>{i + 1}</span>
            <span style={{ color: colorFor(l.t) }}>{l.s || '\u00A0'}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function colorFor(t) {
  return ({
    comment: 'rgba(245,245,240,0.4)',
    pragma: '#D4AF37',
    import: '#A3A39E',
    contract: '#E6C44A',
    event: '#5B21B6',
    fn: '#F5F5F0',
    indent: '#A3A39E',
  })[t] || '#F5F5F0';
}

Object.assign(window, { Viewer });
