// Slate — Alternative Investments + Structured Products screens.
// Each is a tabbed page sized for the way an RM actually works through these books.

const { Icons, fmt, ALT_DEALS, ALT_THESES, ALT_STRATEGY_MIX, ALT_JCURVE,
        ALT_CASHFLOW, ALT_UNFUNDED_LADDER,
        SP_RFQ, SP_QUOTES, SP_TEMPLATES, SP_BOOK, SP_CALENDAR,
        HOUSEHOLD, Charts } = window.Slate;

// ============ Alternative Investments ============
function AltsScreen({ navigate }) {
  const [tab, setTab] = React.useState('deals');
  return (
    <div className="page">
      <div className="page-header">
        <div>
          <div className="eyebrow">Curated · matched to Marchetti IPS &amp; theses</div>
          <h1 className="serif">Alternative Investments</h1>
          <p className="text-2 mt-8" style={{ maxWidth: 640 }}>
            Deal flow filtered against the household IPS, current allocation drift, and stated theses.
            Fit score blends sponsor track record, IPS fit, vintage timing, and diversification.
          </p>
        </div>
        <span className="tag accent">Alts target 13% · actual 12.2%</span>
      </div>

      <div className="tabs">
        <button className={tab==='deals'?'active':''} onClick={()=>setTab('deals')}>Deal flow ({ALT_DEALS.length})</button>
        <button className={tab==='strategy'?'active':''} onClick={()=>setTab('strategy')}>Strategy mix</button>
        <button className={tab==='holdings'?'active':''} onClick={()=>setTab('holdings')}>Holdings</button>
        <button className={tab==='pacing'?'active':''} onClick={()=>setTab('pacing')}>Pacing plan</button>
        <button className={tab==='cashflow'?'active':''} onClick={()=>setTab('cashflow')}>Cashflow plan</button>
      </div>

      {tab === 'deals'    && <AltsDealFlowTab/>}
      {tab === 'strategy' && <AltsStrategyMixTab/>}
      {tab === 'holdings' && <AltsHoldingsTab/>}
      {tab === 'pacing'   && <AltsPacingTab/>}
      {tab === 'cashflow' && <AltsCashflowTab/>}
    </div>
  );
}

// Deal flow — thesis chips + sorted-by-fit cards with fit-score breakdown.
function AltsDealFlowTab() {
  const [activeTheses, setActiveTheses] = React.useState(() => ALT_THESES.map(t => t.key));
  const [strategyFilter, setStrategyFilter] = React.useState('all');

  const toggleThesis = key => {
    setActiveTheses(s => s.includes(key) ? s.filter(x => x !== key) : [...s, key]);
  };

  const STRATS = [
    ['all', 'All strategies'],
    ['buyout', 'Buyout'],
    ['credit', 'Credit'],
    ['real_assets', 'Real Assets'],
    ['venture', 'Venture'],
    ['secondaries', 'Secondaries'],
  ];

  let deals = ALT_DEALS.slice();
  if (strategyFilter !== 'all') deals = deals.filter(d => d.strategyKey === strategyFilter);
  deals = deals.filter(d => activeTheses.includes(d.thesisKey));
  deals.sort((a, b) => b.fitScore - a.fitScore);

  return (
    <div>
      <div className="mb-16">
        <div className="label" style={{ marginBottom: 8 }}>Active theses · click to toggle</div>
        <div className="chips">
          {ALT_THESES.map(t => {
            const on = activeTheses.includes(t.key);
            return (
              <span key={t.key} className={`thesis-tag ${on ? 'on' : ''}`} onClick={() => toggleThesis(t.key)}>
                {on ? '✓ ' : ''}{t.label}
              </span>
            );
          })}
        </div>
      </div>

      <div className="row gap-12 mb-16" style={{ flexWrap:'wrap', alignItems:'center' }}>
        <div className="seg">
          {STRATS.map(([k, l]) => (
            <button key={k} className={strategyFilter===k?'active':''} onClick={()=>setStrategyFilter(k)}>{l}</button>
          ))}
        </div>
        <div className="spacer"/>
        <span className="text-3" style={{ fontSize: 12 }}>{deals.length} offerings · sorted by fit</span>
      </div>

      <div className="grid-2" style={{ gap: 20 }}>
        {deals.map(d => <DealCard key={d.id} d={d}/>)}
        {deals.length === 0 && (
          <div className="card" style={{ padding: 28, gridColumn:'1 / -1', textAlign:'center', color:'var(--ink-3)' }}>
            No deals match the active theses. Toggle more chips above.
          </div>
        )}
      </div>
    </div>
  );
}

function DealCard({ d }) {
  const fitParts = [
    ['Sponsor track',    d.fit.sponsor,        30],
    ['IPS fit',          d.fit.ips,            35],
    ['Vintage timing',   d.fit.vintage,        20],
    ['Diversification',  d.fit.diversification,15],
  ];
  const thesisLabel = (ALT_THESES.find(t => t.key === d.thesisKey) || {}).label;

  return (
    <div className="card" style={{ padding: 24, display:'flex', flexDirection:'column', gap: 14 }}>
      <div className="row" style={{ justifyContent:'space-between', alignItems:'flex-start', gap: 16 }}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div className="eyebrow">{d.sponsor}</div>
          <div className="serif" style={{ fontSize: 22, fontWeight: 600, marginTop: 2, lineHeight: 1.15, textWrap: 'balance' }}>{d.name}</div>
          <div className="text-3" style={{ fontSize: 12, marginTop: 6 }}>{d.strategy} · vintage {d.vintage}</div>
          {thesisLabel && <span className="tag accent" style={{ marginTop: 8 }}>thesis · {thesisLabel}</span>}
        </div>
        <div title="Fit score 0–100 — sum of sponsor track (/30), IPS fit (/35), vintage timing (/20), diversification (/15). Green at ≥85." style={{ textAlign:'right', minWidth: 90, cursor:'help' }}>
          <div className="label">Fit score</div>
          <div className="num" style={{ fontSize: 30, color: d.fitScore >= 85 ? 'var(--pos)' : 'var(--ink)' }}>{d.fitScore}</div>
          <div className="bar-track" style={{ width: 90, marginTop: 4 }}>
            <div className="bar-fill" style={{ width: d.fitScore + '%', background: d.fitScore >= 85 ? 'var(--pos)' : 'var(--ink-3)' }}/>
          </div>
        </div>
      </div>

      <div className="stack stack-2" style={{ paddingTop: 4 }}>
        {fitParts.map(([label, score, max]) => (
          <div key={label} className="row" style={{ alignItems:'center', gap: 10, fontSize: 11.5 }}>
            <span style={{ width: 110, color: 'var(--ink-3)' }}>{label}</span>
            <div className="bar-track" style={{ flex: 1, height: 4 }}>
              <div className="bar-fill" style={{ width: ((score / max) * 100) + '%' }}/>
            </div>
            <span className="num" style={{ width: 38, textAlign: 'right', color: 'var(--ink-2)' }}>{score}/{max}</span>
          </div>
        ))}
      </div>

      <div className="grid-4" style={{ gap: 12 }}>
        <div title="Target IRR — the annualized return the GP is targeting (range)." style={{ cursor:'help' }}><div className="label">Target IRR</div><div className="num" style={{ fontSize: 14 }}>{d.target}</div></div>
        <div title="Fund life — how long capital is locked up (years + possible extension)." style={{ cursor:'help' }}><div className="label">Term</div><div className="num" style={{ fontSize: 14 }}>{d.term}</div></div>
        <div title="Minimum LP commitment to enter the fund." style={{ cursor:'help' }}><div className="label">Min</div><div className="num" style={{ fontSize: 14 }}>{fmt.money(d.minimum, {compact:true})}</div></div>
        <div title="Annual management fee (% of committed capital) / carried interest (GP's share of profits, typically above an 8% hurdle)." style={{ cursor:'help' }}><div className="label">Mgmt / Carry</div><div className="num" style={{ fontSize: 14 }}>{d.mgmt}% / {d.carry}%</div></div>
      </div>

      <div className="margin-note" style={{ fontSize: 13 }}>
        <div className="label" style={{ color:'var(--accent)' }}>Why it fits</div>
        <div style={{ marginTop: 2 }}>{d.why}</div>
      </div>

      <div className="row" style={{ justifyContent:'space-between', alignItems:'center', gap: 12, borderTop:'1px dashed var(--rule-2)', paddingTop: 12, flexWrap:'wrap' }}>
        <div className="text-3" style={{ fontSize: 11.5, display:'flex', flexWrap:'wrap', gap: 10, alignItems:'center' }}>
          <span className={`tag ${d.status === 'Limited' ? 'warn' : ''}`} title={d.status === 'Limited' ? 'Subscription nearly full — closing soon.' : 'Currently accepting new commitments.'} style={{ cursor:'help' }}>{d.status}</span>
          <span title="Final date to commit. Wires happen later via capital calls." style={{ cursor:'help' }}>Closes {d.closeDate}</span>
          <span>·</span>
          <span title="Capital raised so far / target fund size." style={{ cursor:'help' }}>{d.commitments}</span>
          <span>·</span>
          <span title="Share of fund committed by the GP from their own money — alignment indicator." style={{ cursor:'help' }}>GP commit {d.gpCommit}</span>
          {d.coInvest && <span className="tag" title="GP allows direct deal-level investment alongside the fund — often fee-free, attractive for larger LPs." style={{ borderColor:'var(--accent)', color:'var(--accent)', cursor:'help' }}>co-invest</span>}
        </div>
        <div className="row gap-8" style={{ flex: '0 0 auto' }}>
          <button className="btn ghost sm">Brief</button>
          <button className="btn sm">Pitch to client</button>
        </div>
      </div>
    </div>
  );
}

// Strategy mix — actual vs target across the alts sleeve, plus vintage diversification.
function AltsStrategyMixTab() {
  const totalActualMv = ALT_STRATEGY_MIX.reduce((a, s) => a + s.mvActual, 0);
  return (
    <div className="grid-2">
      <div className="card" style={{ padding: 28 }}>
        <h3 className="serif" style={{ margin: 0, fontSize: 18 }}>Sub-strategy targets</h3>
        <div className="text-3" style={{ fontSize: 12 }}>Within the 13% alts sleeve. Bar = actual; tick = IPS sub-target.</div>
        <div className="stack stack-3 mt-16">
          {ALT_STRATEGY_MIX.map(s => (
            <div key={s.key}>
              <div className="row" style={{ justifyContent:'space-between' }}>
                <span style={{ fontSize: 13 }}>{s.label}</span>
                <span className="num" style={{ fontSize: 13 }}>
                  {s.actual.toFixed(0)}% <span className="text-3" style={{ fontSize: 11, marginLeft: 6 }}>tgt {s.target}%</span>
                </span>
              </div>
              <div className="bar-track with-target mt-8">
                <div className={`bar-fill ${Math.abs(s.actual - s.target) > 15 ? 'neg' : ''}`} style={{ width: Math.min(100, s.actual) + '%' }}/>
                <div className="target" style={{ left: s.target + '%' }}/>
              </div>
              <div className="text-3 mt-8" style={{ fontSize: 11 }}>{fmt.money(s.mvActual, { compact: true })} committed</div>
            </div>
          ))}
        </div>
      </div>

      <div className="stack stack-3" style={{ gap: 24 }}>
        <div className="card" style={{ padding: 24 }}>
          <div className="label">Alts sleeve · committed</div>
          <div className="num" style={{ fontSize: 32, marginTop: 4 }}>{fmt.money(totalActualMv, { compact: true })}</div>
          <div className="text-3" style={{ fontSize: 12 }}>Pine Ridge II only · 100% Buyout</div>
          <hr className="divider dashed" style={{ margin: '16px 0' }}/>
          <div className="margin-note" style={{ fontSize: 13 }}>
            <div className="label" style={{ color:'var(--accent)' }}>Concentration risk</div>
            <div style={{ marginTop: 2 }}>
              All alts capital is in a single Buyout fund. The pacing plan begins diversifying into Credit, Real Assets, and Secondaries — see Pacing plan tab.
            </div>
          </div>
        </div>

        <div className="card" style={{ padding: 24 }}>
          <h3 className="serif" style={{ margin: 0, fontSize: 16 }}>Vintage diversification</h3>
          <div className="text-3" style={{ fontSize: 12 }}>Commitments by vintage year (existing + planned).</div>
          <div className="row gap-16 mt-8" style={{ flexWrap:'wrap', fontSize: 11, color:'var(--ink-3)' }}>
            <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:8, background:'var(--ink)' }}/> existing commitment</span>
            <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:8, background:'var(--ink-3)' }}/> planned (pacing plan)</span>
          </div>
          <div className="stack stack-2 mt-16">
            {[
              { y: 2019, mv: 10000000, kind: 'existing' },
              { y: 2026, mv: 7500000,  kind: 'planned'  },
              { y: 2027, mv: 7500000,  kind: 'planned'  },
            ].map(v => (
              <div key={v.y} className="row" style={{ alignItems:'center', gap: 10, fontSize: 13 }}>
                <span className="mono" style={{ width: 50 }}>{v.y}</span>
                <div className="bar-track" style={{ flex: 1 }}>
                  <div className="bar-fill" style={{ width: ((v.mv / 12000000) * 100) + '%', background: v.kind === 'existing' ? 'var(--ink)' : 'var(--ink-3)' }}/>
                </div>
                <span className="num" style={{ width: 60, textAlign:'right' }}>{fmt.money(v.mv, { compact: true })}</span>
                <span className="tag">{v.kind}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// Holdings — existing alt commitments. Today: Pine Ridge II only.
function AltsHoldingsTab() {
  const stats = [
    { label: 'Commitment',          value: '$10.0M', tip: 'Total amount pledged to the fund. Drawn over time via capital calls.' },
    { label: 'Called',              value: '$8.4M', sub: '84%', tip: 'Capital actually wired so far. Remainder ($1.6M) called over Q3 2026.' },
    { label: 'Distributions (DPI)', value: '$3.1M', sub: '0.37×', tip: 'Distributions to Paid-In. Cash returned ÷ cash contributed. 0.37× = $0.37 back per $1 in.' },
    { label: 'NAV (RVPI)',          value: '$8.4M', sub: '1.00×', tip: 'Residual Value to Paid-In. Current fund value ÷ cash contributed. Still in the fund (unrealized).' },
    { label: 'Total value (TVPI)',  value: '$11.5M', sub: '1.37×', good: true, tip: 'Total Value to Paid-In = DPI + RVPI. Realized + unrealized return multiple.' },
    { label: 'Net IRR',             value: '14.8%',  good: true, tip: 'Internal rate of return — annualized return accounting for the timing of every cashflow, net of fees.' },
  ];
  return (
    <div className="card" style={{ padding: 28 }}>
      <div className="row" style={{ justifyContent:'space-between', alignItems:'flex-start', gap: 16 }}>
        <div>
          <h3 className="serif" style={{ margin: 0, fontSize: 18 }}>Pine Ridge Opportunities II — LP</h3>
          <div className="text-3" style={{ fontSize: 12 }}>JPM Private · Marchetti Holding LLC · 2019 vintage · Buyout</div>
        </div>
        <span className="tag pos">Active · in distribution</span>
      </div>

      <div className="grid-3 mt-16" style={{ gap: 8 }}>
        {stats.map(s => (
          <div key={s.label} title={s.tip} style={{ borderTop:'1px dashed var(--rule-2)', paddingTop: 8, cursor: s.tip ? 'help' : 'default' }}>
            <div className="label">{s.label}</div>
            <div className="num" style={{ fontSize: 22, color: s.good ? 'var(--pos)' : 'var(--ink)' }}>{s.value}</div>
            {s.sub && <div className="text-3" style={{ fontSize: 11, color: s.good ? 'var(--pos)' : 'var(--ink-3)' }}>{s.sub}</div>}
          </div>
        ))}
      </div>

      <hr className="divider dashed" style={{ margin: '24px 0' }}/>
      <h4 className="serif" style={{ margin: 0, fontSize: 15 }}>J-curve · cumulative cashflows</h4>
      <div className="text-3" style={{ fontSize: 12 }}>
        Cumulative dollars in vs. out since inception. Quarter labels along the x-axis.
      </div>
      <div className="mt-16">
        <Charts.JCurve data={ALT_JCURVE} height={200}/>
      </div>
      <div className="row gap-16 mt-12" style={{ flexWrap:'wrap', fontSize: 11.5, color:'var(--ink-3)' }}>
        <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:2, background:'var(--ink)' }}/> Total value · NAV + distributions (upside)</span>
        <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:0, borderTop:'1.4px dashed var(--neg)' }}/> Capital called · cumulative, plotted negative</span>
      </div>

      <hr className="divider dashed" style={{ margin: '24px 0' }}/>
      <h4 className="serif" style={{ margin: 0, fontSize: 15 }}>Capital call schedule (projected)</h4>
      <div className="stack stack-2 mt-12" style={{ fontSize: 13 }}>
        {[['Q3 2026','$1.6M','Final call — operating'],['Q1 2027','$0','Distribution expected'],['Q4 2027','$0','Distribution expected — exit']].map(([d,a,n]) => (
          <div key={d} className="row" style={{ justifyContent:'space-between', borderBottom:'1px dashed var(--rule-2)', paddingBottom: 8 }}>
            <span className="mono" style={{ fontSize: 12, width: 90 }}>{d}</span>
            <span className="num" style={{ width: 60 }}>{a}</span>
            <span className="text-3" style={{ flex: 1, textAlign:'right' }}>{n}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// Pacing plan — the 18-month commitment schedule with timeline visual.
function AltsPacingTab() {
  const plan = [
    { q:'Q3 2026', commit:5000000, deal:'Pine Ridge IV',           strategy:'Buyout',     pace:'On track' },
    { q:'Q4 2026', commit:2500000, deal:'Atlas Direct Lending VII',strategy:'Credit',     pace:'On track' },
    { q:'Q1 2027', commit:5000000, deal:'Northwind Climate Infra', strategy:'Real Assets',pace:'Discussion' },
    { q:'Q2 2027', commit:2500000, deal:'Helios Secondaries 2026', strategy:'Secondaries',pace:'Discussion' },
  ];
  const totalCommit = plan.reduce((a, p) => a + p.commit, 0);

  return (
    <div className="card" style={{ padding: 24 }}>
      <div className="row" style={{ justifyContent:'space-between', alignItems:'flex-start', gap: 16 }}>
        <div>
          <h3 className="serif" style={{ margin: 0, fontSize: 18 }}>Capital deployment plan · 18 months</h3>
          <div className="text-3" style={{ fontSize: 12 }}>Bring the alts sleeve from 12.2% → 13.0% IPS target while diversifying away from a single Buyout vintage.</div>
        </div>
        <div style={{ textAlign:'right' }}>
          <div className="label">Total committed</div>
          <div className="num" style={{ fontSize: 24 }}>{fmt.money(totalCommit, { compact: true })}</div>
        </div>
      </div>

      <div className="row gap-16 mt-12" style={{ flexWrap:'wrap', fontSize: 11.5, color:'var(--ink-3)' }}>
        <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:10, height:10, borderRadius:'50%', background:'var(--pos)' }}/> On track · committed</span>
        <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:10, height:10, borderRadius:'50%', background:'var(--warn)' }}/> Discussion · not yet committed</span>
      </div>

      {/* timeline bar */}
      <div className="mt-16" style={{ position:'relative', height: 64 }}>
        <div style={{ position:'absolute', top: 26, left: 0, right: 0, height: 2, background: 'var(--rule)' }}/>
        {plan.map((p, i) => (
          <div key={p.q} style={{ position:'absolute', left: ((i + 0.5) / plan.length * 100) + '%', transform:'translateX(-50%)', textAlign:'center' }}>
            <div style={{ width: 14, height: 14, borderRadius: '50%', background: p.pace === 'On track' ? 'var(--pos)' : 'var(--warn)', margin: '20px auto 0', border: '2px solid var(--surface)', boxShadow:'0 0 0 1px var(--rule-2)' }}/>
            <div className="mono" style={{ fontSize: 11, marginTop: 6 }}>{p.q}</div>
            <div className="num" style={{ fontSize: 11 }}>{fmt.money(p.commit, { compact: true })}</div>
          </div>
        ))}
      </div>

      <hr className="divider dashed" style={{ margin: '8px 0 16px' }}/>

      <div className="stack stack-3">
        {plan.map(p => (
          <div key={p.q} className="row" style={{ justifyContent:'space-between', alignItems:'center', borderBottom:'1px dashed var(--rule-2)', paddingBottom: 12, gap: 12, flexWrap:'wrap' }}>
            <span className="mono" style={{ fontSize: 13, width: 80 }}>{p.q}</span>
            <span className="num" style={{ width: 80 }}>{fmt.money(p.commit, { compact: true })}</span>
            <span style={{ flex: 1, fontWeight: 500, minWidth: 160 }}>{p.deal}</span>
            <span className="tag">{p.strategy}</span>
            <span className={`tag ${p.pace==='On track' ? 'pos' : 'warn'}`}>{p.pace}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// Cashflow plan — projects capital calls and distributions for next 12 quarters,
// then maps the unfunded commitment onto a duration-matched Treasury ladder.
function AltsCashflowTab() {
  const totalCommitted = 25000000;       // $10M Pine Ridge II + $15M pacing plan
  const totalCalled    = 8400000;
  const totalUnfunded  = totalCommitted - totalCalled;

  const ladderTotal    = ALT_UNFUNDED_LADDER.reduce((a,r)=>a+r.amount, 0);
  const weightedYield  = ALT_UNFUNDED_LADDER.reduce((a,r)=>a+r.amount*r.yield, 0) / ladderTotal;
  const ladderIncome   = ladderTotal * weightedYield / 100;
  const mmfBlendedRate = 4.50; // assumed avg MMF over horizon (Fed cut path)
  const mmfIncome      = ladderTotal * mmfBlendedRate / 100;
  const incomeLift     = ladderIncome - mmfIncome;

  return (
    <div>
      <div className="kpis">
        <div className="kpi" title="Sum of all alt-fund commitments — both wired and still to come." style={{ cursor:'help' }}>
          <span className="label">Total committed</span>
          <span className="v lg">{fmt.money(totalCommitted, {compact:true})}</span>
          <span className="text-3" style={{ fontSize: 12 }}>existing $10M + pacing $15M</span>
        </div>
        <div className="kpi" title="Capital actually wired to GPs to date." style={{ cursor:'help' }}>
          <span className="label">Already called</span>
          <span className="v lg">{fmt.money(totalCalled, {compact:true})}</span>
        </div>
        <div className="kpi" title="Committed but not yet called — the household has promised to wire this when GPs request it. Doesn't have to sit in overnight cash." style={{ cursor:'help' }}>
          <span className="label">Unfunded commitment</span>
          <span className="v lg">{fmt.money(totalUnfunded, {compact:true})}</span>
          <span className="text-3" style={{ fontSize: 12 }}>drawn 2026–2030</span>
        </div>
      </div>
      <div className="text-3 mt-12" style={{ fontSize: 12 }}>
        This tab focuses on the alts treasury workflow — call/distribution rhythm and the unfunded commitment ladder. For full household income vs. outflows across all sources, see Household → Cashflow.
      </div>

      <div className="section">
        <h2 className="serif">Capital calls vs. distributions · next 12 quarters</h2>
        <div className="sub">Drives how much liquidity is needed when. Bars below the line are wires out; bars above are cash coming in.</div>
        <div className="card mt-12" style={{ padding: 16 }}>
          <Charts.CashflowBars data={ALT_CASHFLOW} height={220}/>
          <div className="row gap-16 mt-12" style={{ flexWrap:'wrap', fontSize: 11.5, color:'var(--ink-3)' }}>
            <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:10, background:'var(--neg)', opacity:0.85 }}/> Capital calls (cash out)</span>
            <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:10, background:'var(--pos)', opacity:0.85 }}/> Distributions (cash in)</span>
          </div>
        </div>
        <div className="table-wrap mt-16">
          <table className="tbl">
            <thead>
              <tr>
                <th title="Quarter the cashflow occurs.">Quarter</th>
                <th className="num" title="Capital wired to GPs in this quarter (negative = out).">Calls</th>
                <th className="num" title="Cash returned from GPs in this quarter.">Distributions</th>
                <th className="num" title="Calls + distributions for the quarter.">Net</th>
                <th title="Which funds drive this quarter's flow.">Drivers</th>
              </tr>
            </thead>
            <tbody>
              {ALT_CASHFLOW.map(c => {
                const net = c.calls + c.dist;
                return (
                  <tr key={c.q}>
                    <td className="mono" style={{ fontSize: 12 }}>{c.q}</td>
                    <td className="num" style={{ color: c.calls < 0 ? 'var(--neg)' : 'var(--ink-3)' }}>{c.calls ? fmt.money(c.calls, {compact:true}) : '—'}</td>
                    <td className="num" style={{ color: c.dist > 0 ? 'var(--pos)' : 'var(--ink-3)' }}>{c.dist ? '+' + fmt.money(c.dist, {compact:true}) : '—'}</td>
                    <td className="num" style={{ fontWeight: 600, color: net < 0 ? 'var(--neg)' : net > 0 ? 'var(--pos)' : 'var(--ink-3)' }}>{net ? (net > 0 ? '+' : '') + fmt.money(net, {compact:true}) : '—'}</td>
                    <td className="text-3" style={{ fontSize: 12 }}>{c.notes}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      <div className="section grid-3-2">
        <div>
          <h2 className="serif">Unfunded commitment ladder</h2>
          <div className="sub">Earmark each tranche to instruments maturing near the expected call. Locks in yield on the medium-term sleeve while staying liquid for the imminent calls.</div>
          <div className="card mt-12" style={{ padding: 0, overflow:'hidden' }}>
            {/* stacked bar showing tranche split */}
            <div className="row" style={{ height: 14, background:'var(--rule)' }}>
              {ALT_UNFUNDED_LADDER.map((r, i) => (
                <div key={r.bucket} title={r.bucket + ' · ' + fmt.money(r.amount, {compact:true})}
                  style={{
                    width: ((r.amount / ladderTotal) * 100) + '%',
                    background: ['var(--ink)', 'var(--ink-2)', 'var(--ink-3)', 'var(--ink-4)'][i],
                    borderRight: i < ALT_UNFUNDED_LADDER.length - 1 ? '1px solid var(--surface)' : 'none',
                  }}/>
              ))}
            </div>
            <table className="tbl" style={{ marginTop: 0 }}>
              <thead>
                <tr>
                  <th title="Time to expected use of the cash.">Bucket</th>
                  <th className="num" title="Amount earmarked to this maturity bucket.">Amount</th>
                  <th title="Indicative instrument the cash should sit in.">Instrument</th>
                  <th className="num" title="Indicative yield at current curve.">Yield</th>
                  <th title="Which calls this tranche covers.">Covers</th>
                </tr>
              </thead>
              <tbody>
                {ALT_UNFUNDED_LADDER.map((r, i) => (
                  <tr key={r.bucket}>
                    <td><span className="dot" style={{ background: ['var(--ink)', 'var(--ink-2)', 'var(--ink-3)', 'var(--ink-4)'][i] }}/> {r.bucket}</td>
                    <td className="num">{fmt.money(r.amount, {compact:true})}</td>
                    <td className="text-3" style={{ fontSize: 12 }}>{r.instrument}</td>
                    <td className="num">{r.yield.toFixed(2)}%</td>
                    <td className="text-3" style={{ fontSize: 11.5 }}>{r.covers}</td>
                  </tr>
                ))}
                <tr style={{ fontWeight: 600 }}>
                  <td>Total / blended</td>
                  <td className="num">{fmt.money(ladderTotal, {compact:true})}</td>
                  <td className="text-3" style={{ fontSize: 12 }}>weighted by amount</td>
                  <td className="num">{weightedYield.toFixed(2)}%</td>
                  <td className="text-3" style={{ fontSize: 11.5 }}>full unfunded sleeve</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>

        <div className="stack stack-3" style={{ gap: 16 }}>
          <div className="card" style={{ padding: 20 }}>
            <div className="label">Ladder vs all-MMF baseline</div>
            <div className="num" style={{ fontSize: 28, color:'var(--pos)', marginTop: 4 }}>+{fmt.money(incomeLift, {compact:true})}/yr</div>
            <div className="text-3" style={{ fontSize: 12, marginTop: 4 }}>
              Ladder earns ~{weightedYield.toFixed(2)}% × {fmt.money(ladderTotal, {compact:true})} = {fmt.money(ladderIncome, {compact:true})}/yr.
              Baseline ({mmfBlendedRate.toFixed(1)}% projected MMF avg over the call horizon) earns {fmt.money(mmfIncome, {compact:true})}/yr.
            </div>
            <hr className="divider dashed" style={{ margin:'14px 0' }}/>
            <div className="text-3" style={{ fontSize: 11.5 }}>
              Today's MMF (5.18%) earns slightly more in the short run; the ladder hedges the Fed-cut path and locks in income across the entire 36-month draw window.
            </div>
          </div>

          <div className="margin-note" style={{ fontSize: 13 }}>
            <div className="label" style={{ color:'var(--accent)' }}>Why this matters</div>
            <div style={{ marginTop: 4 }}>
              An LP with $16.6M of unfunded commitments doesn't need $16.6M sitting in overnight cash. The GP gives ~10 business days notice for calls — long enough to mature short-dated paper. Matching maturity to expected use is standard institutional treasury practice.
            </div>
          </div>

          <div className="margin-note" style={{ fontSize: 13 }}>
            <div className="label" style={{ color:'var(--ink-3)' }}>Forecast caveat</div>
            <div style={{ marginTop: 4 }}>
              Calls follow industry-typical drawdown patterns (timing variance ±1–2 quarters). Distributions are GP estimates and depend on actual exit events; expect material variance.
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ============ Structured Products ============
function StructuredScreen({ navigate }) {
  const [tab, setTab] = React.useState('rfq');
  return (
    <div className="page">
      <div className="page-header">
        <div>
          <div className="eyebrow">Multi-issuer RFQ · live</div>
          <h1 className="serif">Structured Products</h1>
          <p className="text-2 mt-8" style={{ maxWidth: 640 }}>
            Quote one trade across {SP_QUOTES.length} dealers in parallel. Slate normalizes terms so the comparison is apples-to-apples,
            tracks issuer fill quality, and watches the existing book's barriers and observation calendar.
          </p>
        </div>
        <span className="tag warn">Live RFQ · 8 of 10 returned</span>
      </div>

      <div className="tabs">
        <button className={tab==='rfq'?'active':''} onClick={()=>setTab('rfq')}>Active RFQ</button>
        <button className={tab==='book'?'active':''} onClick={()=>setTab('book')}>Book ({SP_BOOK.length})</button>
        <button className={tab==='calendar'?'active':''} onClick={()=>setTab('calendar')}>Calendar</button>
        <button className={tab==='templates'?'active':''} onClick={()=>setTab('templates')}>Templates</button>
      </div>

      {tab === 'rfq'       && <RfqTab/>}
      {tab === 'book'      && <BookTab/>}
      {tab === 'calendar'  && <CalendarTab/>}
      {tab === 'templates' && <TemplatesTab/>}
    </div>
  );
}

// ---- RFQ tab — trade ticket + payoff diagram + responses table ----
function RfqTab() {
  const sortedQuotes = SP_QUOTES.slice().sort((a, b) => (b.coupon || -1) - (a.coupon || -1));
  const live = sortedQuotes.filter(q => !q.pending);
  const minCoupon = Math.min(...live.map(q => q.coupon));
  const maxCoupon = Math.max(...live.map(q => q.coupon));

  return (
    <div>
      <div className="grid-2" style={{ gap: 20 }}>
        <div className="card" style={{ padding: 24 }}>
          <div className="row" style={{ justifyContent:'space-between', alignItems:'flex-start', gap: 24 }}>
            <div style={{ minWidth: 0, flex: 1 }}>
              <div className="label">Trade ticket · {SP_RFQ.id}</div>
              <div className="serif" style={{ fontSize: 22, fontWeight: 600, marginTop: 2, lineHeight: 1.2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{SP_RFQ.type}</div>
              <div className="text-3" style={{ fontSize: 13, marginTop: 8 }}>Underlier: <span className="mono">{SP_RFQ.underlier}</span></div>
            </div>
            <div title="Notional — headline trade size. The amount of principal the trade is sized against." style={{ textAlign:'right', flex: '0 0 auto', cursor:'help' }}>
              <div className="label">Notional</div>
              <div className="num" style={{ fontSize: 26 }}>{fmt.money(SP_RFQ.notional, {compact:true})}</div>
            </div>
          </div>
          <div className="grid-4 mt-16">
            <div title="Tenor — time to maturity of the note." style={{ cursor:'help' }}><div className="label">Tenor</div><div className="num" style={{ fontSize: 14 }}>{SP_RFQ.tenor}</div></div>
            <div title="Observation — how often the underlier level is checked (for coupons, autocalls, barrier breaches)." style={{ cursor:'help' }}><div className="label">Observation</div><div className="num" style={{ fontSize: 14 }}>{SP_RFQ.observation}</div></div>
            <div title="Protection — downside cushion. Soft barriers only matter at maturity; European = checked at scheduled dates only (vs American = continuously)." style={{ cursor:'help' }}><div className="label">Protection</div><div className="num" style={{ fontSize: 14 }}>{SP_RFQ.protection}</div></div>
            <div title="When the RFQ was sent to dealers." style={{ cursor:'help' }}><div className="label">Sent</div><div className="num" style={{ fontSize: 14 }}>{SP_RFQ.sentAt}</div></div>
          </div>
        </div>

        <div className="card" style={{ padding: 24 }}>
          <h4 className="serif" style={{ margin: 0, fontSize: 16 }}>Payoff · per annum</h4>
          <div className="text-3" style={{ fontSize: 12 }}>
            Worst-of phoenix memory. Coupon paid quarterly when worst-of ≥ 65% of initial.
            Soft barrier observed at maturity.
          </div>
          <div className="mt-12">
            <Charts.PayoffDiagram shape="phoenix" barrierPct={65} coupon={11.4} height={180} label="best quote 11.40%"/>
          </div>
          <div className="row gap-12 mt-12" style={{ flexWrap:'wrap', fontSize: 11.5, color:'var(--ink-3)' }}>
            <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:2, background:'var(--ink)' }}/> Payoff</span>
            <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:0, borderTop:'2px dashed var(--neg)' }}/> 65% soft barrier</span>
            <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:0, borderTop:'1px dashed var(--ink-4)' }}/> Spot 100%</span>
          </div>
        </div>
      </div>

      <div className="section">
        <div className="row" style={{ justifyContent:'space-between', alignItems:'baseline', gap: 16, flexWrap: 'wrap', marginBottom: 4 }}>
          <h2 className="serif" style={{ whiteSpace: 'nowrap', margin: 0 }}>Issuer responses</h2>
          <span className="text-3" style={{ fontSize: 12 }}>Sorted by coupon · ★ marks best-in-class</span>
        </div>
        <div className="sub">"vs best" bar shows where each issuer's coupon sits between the lowest and highest live quote.</div>
        <div className="table-wrap mt-12">
          <table className="tbl rfq-tbl">
            <thead>
              <tr>
                <th title="The bank issuing the note. You take on this issuer's credit risk for the term.">Issuer</th>
                <th title="Issuer credit rating from S&amp;P / Moody's / Fitch. Higher is safer.">Rating</th>
                <th className="num" title="Annualized income rate the issuer is offering, paid contingent on barrier conditions.">Coupon</th>
                <th title="Where this issuer's coupon sits between the lowest and highest live quote.">vs best</th>
                <th title="Barrier level + observation type. Lower % = more loss before protection kicks in. European = checked only at maturity; American = continuous.">Barrier</th>
                <th className="num" title="Mark-to-market on day 1 — the note's fair value at issue, as % of par. The gap from 100 is the embedded fee.">MTM Day-1</th>
                <th title="Time the issuer's quote came back.">Returned</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {sortedQuotes.map(q => {
                const range = maxCoupon - minCoupon || 1;
                const widthPct = q.coupon ? ((q.coupon - minCoupon) / range) * 100 : 0;
                const isBest = q.best === 'coupon';
                const winnerLabel = q.best === 'coupon' ? 'best coupon' : q.best === 'protection' ? 'best protection' : null;
                return (
                  <tr key={q.issuer} className={`${q.pending ? 'pending' : ''} ${isBest ? 'best' : ''}`}>
                    <td>
                      <b>{q.issuer}</b>
                      {winnerLabel && <span className="winner-tag">★ {winnerLabel}</span>}
                    </td>
                    <td className="text-3">{q.rating}</td>
                    <td className="num" style={{ fontWeight: isBest ? 600 : 400 }}>{q.coupon ? q.coupon.toFixed(2) + '%' : '—'}</td>
                    <td>
                      {q.coupon ? (
                        <div className={`sparkbar ${isBest ? 'win' : ''}`} style={{ width: 100 }}>
                          <div style={{ width: Math.max(6, widthPct) + '%' }}/>
                        </div>
                      ) : <span className="text-3">—</span>}
                    </td>
                    <td className="text-3" style={{ fontSize: 12 }}>{q.barrier}</td>
                    <td className="num">{q.mtmDay1 ? q.mtmDay1.toFixed(2) : '—'}</td>
                    <td className="mono" style={{ fontSize: 12, color: q.pending ? 'var(--warn)' : 'var(--ink-3)' }}>{q.returnedAt}</td>
                    <td>{!q.pending && <button className="btn ghost sm">Select</button>}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      <div className="action-bar">
        <button className="btn ghost">Save RFQ</button>
        <button className="btn">Re-quote</button>
        <button className="btn primary">Execute with JPM <span dangerouslySetInnerHTML={{__html: Icons.arrow}}/></button>
      </div>
    </div>
  );
}

// ---- Book tab — existing notes with barrier proximity ----
function BookTab() {
  const totalMtm = SP_BOOK.reduce((a, n) => a + n.mtm, 0);
  const totalNotional = SP_BOOK.reduce((a, n) => a + n.notional, 0);
  const couponYtd = SP_BOOK.reduce((a, n) => a + n.couponCollected, 0);
  return (
    <div>
      <div className="kpis">
        <div className="kpi" title="Number of structured notes the household currently holds." style={{ cursor:'help' }}><span className="label">Notes outstanding</span><span className="v lg">{SP_BOOK.length}</span></div>
        <div className="kpi" title="Sum of headline trade sizes across the book." style={{ cursor:'help' }}><span className="label">Notional</span><span className="v lg">{fmt.money(totalNotional, { compact: true })}</span></div>
        <div className="kpi" title="Mark-to-market — current value of the book if sold today on the secondary market." style={{ cursor:'help' }}><span className="label">Mark-to-market</span><span className="v lg">{fmt.money(totalMtm, { compact: true })}</span></div>
        <div className="kpi" title="Coupon income collected this calendar year across the book." style={{ cursor:'help' }}><span className="label">Coupon ytd</span><span className="v lg" style={{ color:'var(--pos)' }}>+{fmt.money(couponYtd, { compact: true })}</span></div>
      </div>
      <div className="grid-2 mt-24" style={{ gap: 20 }}>
        {SP_BOOK.map(n => <BookNoteCard key={n.id} n={n}/>)}
      </div>
    </div>
  );
}

function BookNoteCard({ n }) {
  // Render an underlier-vs-barrier line. Span 50% to 130% of initial.
  const minPct = 50, maxPct = 130;
  const span = maxPct - minPct;
  const barrierLeft = ((n.barrierPct - minPct) / span) * 100;
  const spotLeft    = ((n.spotPct    - minPct) / span) * 100;
  const distance = (n.spotPct - n.barrierPct).toFixed(1);
  const inDanger = n.spotPct - n.barrierPct < 10;
  return (
    <div className="card" style={{ padding: 24 }}>
      <div className="row" style={{ justifyContent:'space-between', alignItems:'flex-start', gap: 12 }}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div className="eyebrow">{n.issuer} · {n.underlier}</div>
          <div className="serif" style={{ fontSize: 18, fontWeight: 600, marginTop: 4, lineHeight: 1.2, textWrap:'balance' }}>{n.name}</div>
          <div className="text-3" style={{ fontSize: 12, marginTop: 4 }}>Issued {n.issued} · Maturity {n.maturity}</div>
        </div>
        <div title="Mark-to-market: current value vs. issue price. Positive = note is worth more than what was paid." style={{ flex: '0 0 auto', textAlign:'right', cursor:'help' }}>
          <div className="label">MTM</div>
          <div className="num" style={{ fontSize: 22, color: n.pnlPct >= 0 ? 'var(--pos)' : 'var(--neg)' }}>{(n.pnlPct >= 0 ? '+' : '') + n.pnlPct.toFixed(1)}%</div>
          <div className="text-3" style={{ fontSize: 11 }}>{fmt.money(n.mtm, { compact: true })}</div>
        </div>
      </div>

      <div className="grid-4 mt-16" style={{ gap: 12 }}>
        <div title="Headline size of this trade at issue." style={{ cursor:'help' }}><div className="label">Notional</div><div className="num" style={{ fontSize: 14 }}>{fmt.money(n.notional, { compact: true })}</div></div>
        <div title="Annualized coupon rate. Some shapes (e.g. boosters) pay no coupon." style={{ cursor:'help' }}><div className="label">Coupon</div><div className="num" style={{ fontSize: 14 }}>{n.coupon ? n.coupon.toFixed(1) + '%' : '—'}</div></div>
        <div title="Total coupon paid since issue." style={{ cursor:'help' }}><div className="label">Collected</div><div className="num" style={{ fontSize: 14 }}>{n.couponCollected ? fmt.money(n.couponCollected, { compact: true }) : '—'}</div></div>
        <div title="Barrier level + type. Hard = locked in the moment it's breached. Soft = only matters at maturity." style={{ cursor:'help' }}><div className="label">Barrier</div><div className="num" style={{ fontSize: 14 }}>{n.barrierPct}% · {n.barrierType}</div></div>
      </div>

      <div className="mt-16">
        <div className="row" style={{ justifyContent:'space-between', alignItems:'baseline', marginBottom: 6 }}>
          <span className="label">Underlier vs barrier</span>
          <span className="text-3" style={{ fontSize: 10.5 }}>scale 50% → 130% of initial spot</span>
        </div>
        <div style={{ position:'relative', height: 32 }}>
          <div style={{ position:'absolute', left: 0, right: 0, top: 13, height: 4, background: 'var(--rule)', borderRadius: 99 }}/>
          <div style={{ position:'absolute', left: barrierLeft + '%', top: 6, bottom: 6, width: 2, background: 'var(--neg)' }}/>
          <div style={{ position:'absolute', left: barrierLeft + '%', top: -2, fontSize: 9, color: 'var(--neg)', fontFamily: 'var(--font-mono)', transform: 'translateX(-50%)' }}>{n.barrierPct}%</div>
          <div style={{ position:'absolute', left: spotLeft + '%', top: 8, width: 14, height: 14, borderRadius: '50%', background: inDanger ? 'var(--neg)' : 'var(--pos)', border: '2px solid var(--surface)', boxShadow:'0 0 0 1px var(--rule-2)', transform: 'translateX(-50%)' }}/>
          <div style={{ position:'absolute', left: spotLeft + '%', bottom: -1, fontSize: 9, color: inDanger ? 'var(--neg)' : 'var(--pos)', fontFamily: 'var(--font-mono)', transform: 'translateX(-50%)' }}>{n.spotPct.toFixed(1)}%</div>
        </div>
        <div className="row gap-12 mt-8" style={{ flexWrap:'wrap', fontSize: 10.5, color:'var(--ink-3)' }}>
          <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:2, height:10, background:'var(--neg)' }}/> barrier</span>
          <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:9, height:9, borderRadius:'50%', background:'var(--pos)' }}/> spot · safe</span>
          <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:9, height:9, borderRadius:'50%', background:'var(--neg)' }}/> spot · within 10pp of barrier</span>
        </div>
        <div className="text-3 mt-8" style={{ fontSize: 11.5 }}>{Number(distance) >= 0 ? `+${distance}pp above barrier` : `${distance}pp through barrier`}</div>
      </div>

      <hr className="divider dashed" style={{ margin: '16px 0 12px' }}/>
      <div className="row" style={{ justifyContent:'space-between', alignItems:'center' }}>
        <div className="text-3" style={{ fontSize: 12 }}>Next: {n.nextEvent}</div>
        <button className="btn ghost sm">Open ticket</button>
      </div>
    </div>
  );
}

// ---- Calendar tab — observations / autocalls / coupons / maturities ----
function CalendarTab() {
  const events = SP_CALENDAR.slice().sort((a, b) => a.date.localeCompare(b.date));
  const buckets = {};
  for (const e of events) {
    const month = e.date.slice(0, 7);
    (buckets[month] = buckets[month] || []).push(e);
  }
  const monthLabel = m => {
    const [y, mm] = m.split('-');
    return new Date(Number(y), Number(mm) - 1, 1).toLocaleString('en-US', { month: 'long', year: 'numeric' });
  };
  const KIND_TAG = {
    observation:  { tag: 'tag',        label: 'observation' },
    autocall_obs: { tag: 'tag accent', label: 'autocall obs' },
    coupon:       { tag: 'tag pos',    label: 'coupon' },
    maturity:     { tag: 'tag warn',   label: 'maturity' },
    trade_date:   { tag: 'tag accent', label: 'trade date' },
  };
  return (
    <div className="stack stack-3" style={{ gap: 20 }}>
      <div className="card" style={{ padding: 16 }}>
        <div className="text-3" style={{ fontSize: 12 }}>{events.length} upcoming events across {SP_BOOK.length} held notes + 1 active RFQ.</div>
        <div className="row gap-12 mt-12" style={{ flexWrap:'wrap' }}>
          <span className="tag">observation · scheduled level check</span>
          <span className="tag accent">autocall obs · may redeem early</span>
          <span className="tag pos">coupon · cash payment</span>
          <span className="tag warn">maturity · final settlement</span>
          <span className="tag accent">trade date · RFQ execution window</span>
        </div>
      </div>
      {Object.keys(buckets).map(m => (
        <div key={m} className="card" style={{ padding: 24 }}>
          <h3 className="serif" style={{ margin: 0, fontSize: 16 }}>{monthLabel(m)}</h3>
          <div className="stack stack-2 mt-12">
            {buckets[m].map((e, i) => {
              const note = e.noteId ? SP_BOOK.find(b => b.id === e.noteId) : null;
              const kind = KIND_TAG[e.kind] || KIND_TAG.observation;
              return (
                <div key={i} className="row" style={{ alignItems:'center', gap: 12, borderBottom:'1px dashed var(--rule-2)', paddingBottom: 8, flexWrap:'wrap' }}>
                  <span className="mono" style={{ fontSize: 12, width: 100, color: 'var(--ink-3)' }}>{e.date}</span>
                  <span className={kind.tag} style={{ minWidth: 110, justifyContent: 'center' }}>{kind.label}</span>
                  <span style={{ flex: 1, minWidth: 220, fontSize: 13 }}>{e.label}</span>
                  {note && <span className="text-3" style={{ fontSize: 11.5 }}>{note.issuer} · {note.underlier}</span>}
                </div>
              );
            })}
          </div>
        </div>
      ))}
    </div>
  );
}

// ---- Templates tab — strategy menu with mini payoff diagrams ----
function TemplatesTab() {
  return (
    <div>
      <div className="row gap-16 mb-16" style={{ flexWrap:'wrap', alignItems:'center', fontSize: 11.5, color:'var(--ink-3)' }}>
        <span className="text-3" style={{ fontSize: 12 }}>Each diagram: payoff (% of notional) at maturity vs. underlier performance from −50% to +50%.</span>
        <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:2, background:'var(--ink)' }}/> Payoff</span>
        <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:0, borderTop:'1.2px dashed var(--neg)' }}/> Barrier / floor</span>
        <span className="row gap-8" style={{ alignItems:'center' }}><span style={{ width:14, height:0, borderTop:'1px dashed var(--ink-4)' }}/> Spot 100% (par)</span>
      </div>
      <div className="grid-2" style={{ gap: 20 }}>
      {SP_TEMPLATES.map(t => {
        const barrierPct = parseInt(t.protection, 10) || 65;
        const coupon = (t.coupon === '—') ? 0 : parseFloat(String(t.coupon).replace('%','')) || 8;
        return (
          <div key={t.id} className="card" style={{ padding: 24 }}>
            <div className="eyebrow">{t.tenor} · {t.protection}</div>
            <div className="serif" style={{ fontSize: 20, fontWeight: 600, marginTop: 2 }}>{t.name}</div>
            <p className="text-2" style={{ fontSize: 13, marginTop: 8 }}>{t.use}</p>
            <div className="mt-16">
              <Charts.PayoffDiagram shape={t.shape} barrierPct={barrierPct} coupon={coupon} height={140}/>
            </div>
            <div className="row gap-16 mt-12">
              <div title="Estimated annualized coupon if this template were sent to RFQ today. Final terms set by issuer pricing." style={{ cursor:'help' }}><div className="label">Indicative coupon</div><div className="num" style={{ fontSize: 18 }}>{t.coupon}</div></div>
              <div title="Downside protection level. Hard = locks in the moment it's breached; soft = only matters at maturity." style={{ cursor:'help' }}><div className="label">Protection</div><div className="num" style={{ fontSize: 18 }}>{t.protection}</div></div>
            </div>
            <button className="btn sm mt-16">Send to RFQ</button>
          </div>
        );
      })}
      </div>
    </div>
  );
}

window.Slate.AltsStructured = { AltsScreen, StructuredScreen };
