// agreement-extensions.jsx — Adds four connected blocks to the agreement detail:
//   • Waterfall inspector  — visible-math view of how a dollar flows through splits
//   • Recoupment ledger    — advance, paydowns, unrecouped balance, projection
//   • Reversion timeline   — T-90/60/30/today markers, post-term retention window
//   • Docuseal block       — envelope status (sent / viewed / signed / completed)
//
// Wires into ScreenAgreement by extending its TABS list and tab pane via a
// monkey-patch wrapper. Original ScreenAgreement is preserved as
// window.__BaseScreenAgreement; new ScreenAgreement renders the same shell and
// hands off non-extension tabs to the original component.

(function () {
  const { useState, useMemo } = React;

  // ───────── helpers ─────────
  const fmtMoney = (n, ccy = 'USD') => {
    if (n == null || isNaN(n)) return '—';
    const sign = n < 0 ? '-' : '';
    const v = Math.abs(Number(n));
    return sign + (ccy === 'USD' ? '$' : '') + v.toLocaleString('en-US', { maximumFractionDigits: 0 });
  };
  const fmtDate = (d) => {
    if (!d) return '—';
    if (typeof d === 'string' && d.length === 10) return d;
    try { return new Date(d).toISOString().slice(0, 10); } catch { return d; }
  };
  const daysBetween = (a, b) => {
    if (!a || !b) return null;
    const ms = new Date(b) - new Date(a);
    return Math.round(ms / 86400000);
  };
  const today = () => new Date().toISOString().slice(0, 10);

  // ───────── tiny shared UI ─────────
  function Sec({ num, children, right }) {
    return (
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', borderBottom:'1px solid var(--rule)', padding:'12px 0 10px', marginTop:24 }}>
        <div style={{ display:'flex', gap:10, alignItems:'baseline' }}>
          {num && <span className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.08em' }}>{num}</span>}
          <h3 className="ff-display" style={{ fontSize:18, fontWeight:600, letterSpacing:'-0.02em', margin:0 }}>{children}</h3>
        </div>
        {right}
      </div>
    );
  }

  // ─────────────────────────────────────────────────────── WATERFALL
  // Pure: takes a gross dollar amount + an agreement, returns an ordered list of
  // waterfall steps (deductions / allocations / pay-outs) with running balance.
  function computeWaterfall(ag, gross = 10000) {
    const steps = [];
    let bal = gross;
    steps.push({ kind:'gross', label:'Gross collected', amount:gross, after:bal, note:`from ${ag.b || 'counter-party'}` });

    // 1. Off-the-top: society admin fee (if present)
    const adminFee = (ag.kind && /sub-pub/i.test(ag.kind)) ? 0.10 : 0;
    if (adminFee > 0) {
      const cut = Math.round(bal * adminFee);
      bal -= cut;
      steps.push({ kind:'fee', label:`Society admin fee (${(adminFee*100).toFixed(0)}%)`, amount:-cut, after:bal, note:'PRS · MCPS at-source' });
    }

    // 2. Sub-pub fee, if any
    const subPubFee = ag.kind && /sub-pub/i.test(ag.kind) ? 0.15 : 0;
    if (subPubFee > 0) {
      const cut = Math.round(bal * subPubFee);
      bal -= cut;
      steps.push({ kind:'fee', label:`Sub-publisher fee (${(subPubFee*100).toFixed(0)}%)`, amount:-cut, after:bal, note:'paid to local admin' });
    }

    // 3. Recoupment off the top, if unrecouped balance > 0
    const ledger = ag.recoupmentLedger;
    if (ledger && ledger.unrecouped > 0) {
      const recoup = Math.min(ledger.unrecouped, Math.round(bal * 0.5));
      if (recoup > 0) {
        bal -= recoup;
        steps.push({ kind:'recoup', label:`Recoupment against advance`, amount:-recoup, after:bal, note:`balance ${fmtMoney(ledger.unrecouped)} → ${fmtMoney(ledger.unrecouped - recoup)}` });
      }
    }

    // 4. Splits among parties (use parties[] with shares)
    const sharers = (ag.parties || []).filter(p => p.share != null && p.share > 0);
    const totalShare = sharers.reduce((s, p) => s + p.share, 0) || 100;
    const distributable = bal;
    sharers.forEach(p => {
      const cut = Math.round(distributable * (p.share / totalShare));
      bal -= cut;
      steps.push({ kind:'pay', label:p.name, amount:-cut, after:bal, note:`${p.role} · ${p.share}% of net` , party:p });
    });

    // Reconciliation: if rounding leftover, attribute to first party
    if (Math.abs(bal) > 0 && sharers.length > 0) {
      const last = steps[steps.length - 1];
      last.amount -= bal;
      bal = 0;
      last.after = 0;
    }

    return steps;
  }

  function WaterfallTab({ ag }) {
    const [gross, setGross] = useState(10000);
    const steps = useMemo(() => computeWaterfall(ag, gross), [ag, gross]);
    const presets = [1000, 10000, 50000, 250000];

    return (
      <div>
        <Sec num="01" right={
          <div style={{ display:'flex', gap:6, alignItems:'center' }}>
            <span className="ff-mono upper" style={{ fontSize:9, color:'var(--ink-3)', letterSpacing:'.1em' }}>SCENARIO</span>
            {presets.map(p => (
              <button key={p} onClick={() => setGross(p)} className="ff-mono num"
                style={{ padding:'5px 9px', fontSize:11, border:'1px solid var(--rule)', background: gross === p ? 'var(--ink)' : 'transparent', color: gross === p ? 'var(--bg)' : 'var(--ink)', cursor:'pointer' }}>
                {fmtMoney(p)}
              </button>
            ))}
            <input type="number" value={gross} onChange={e => setGross(Math.max(0, Number(e.target.value) || 0))}
              className="ff-mono num"
              style={{ width:120, padding:'5px 9px', fontSize:11, border:'1px solid var(--rule)', background:'var(--paper)', color:'var(--ink)', textAlign:'right' }}/>
          </div>
        }>Waterfall · visible math</Sec>

        <p style={{ fontSize:12, color:'var(--ink-3)', maxWidth:680, margin:'14px 0 18px', lineHeight:1.5 }}>
          Trace one dollar of gross income through every deduction and split this agreement defines. Adjust the scenario amount to see the math at scale.
        </p>

        {/* Waterfall table */}
        <div style={{ border:'1px solid var(--rule)' }}>
          <div className="ff-mono upper" style={{ display:'grid', gridTemplateColumns:'40px 1fr 140px 140px 90px', gap:14, padding:'10px 14px', fontSize:10, color:'var(--ink-3)', background:'var(--bg-2)', borderBottom:'1px solid var(--rule)' }}>
            <span>STEP</span><span>FLOW</span><span style={{ textAlign:'right' }}>AMOUNT</span><span style={{ textAlign:'right' }}>RUNNING</span><span style={{ textAlign:'right' }}>%</span>
          </div>
          {steps.map((s, i) => {
            const pct = gross > 0 ? Math.abs(s.amount) / gross * 100 : 0;
            const isGross = s.kind === 'gross';
            const isPay = s.kind === 'pay';
            return (
              <div key={i} style={{ display:'grid', gridTemplateColumns:'40px 1fr 140px 140px 90px', gap:14, padding:'14px', borderBottom: i < steps.length - 1 ? '1px solid var(--rule-soft)' : 'none', alignItems:'center', background: isGross ? 'var(--bg-2)' : 'transparent' }}>
                <span className="ff-mono num" style={{ fontSize:11, color:'var(--ink-3)' }}>{String(i).padStart(2,'0')}</span>
                <div>
                  <div style={{ fontSize:13, fontWeight: isGross || isPay ? 600 : 500, display:'flex', gap:8, alignItems:'center' }}>
                    {!isGross && <span style={{ color:'var(--ink-3)' }}>↳</span>}
                    {s.label}
                    {isPay && <span className="ff-mono upper" style={{ fontSize:9, padding:'2px 5px', background:'var(--bg-2)', border:'1px solid var(--rule-soft)', letterSpacing:'.08em', color:'var(--ink-3)' }}>PAY-OUT</span>}
                    {s.kind === 'recoup' && <span className="ff-mono upper" style={{ fontSize:9, padding:'2px 5px', background:'var(--accent)', color:'var(--accent-ink)', letterSpacing:'.08em' }}>RECOUP</span>}
                  </div>
                  {s.note && <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', marginTop:3 }}>{s.note}</div>}
                </div>
                <span className="ff-mono num" style={{ fontSize:13, fontWeight:600, textAlign:'right', color: isGross ? 'var(--ink)' : s.amount < 0 ? 'var(--ink-2)' : 'var(--ink)' }}>
                  {isGross ? fmtMoney(s.amount) : (s.amount > 0 ? '+' : '') + fmtMoney(s.amount)}
                </span>
                <span className="ff-mono num" style={{ fontSize:13, fontWeight:600, textAlign:'right' }}>{fmtMoney(s.after)}</span>
                <div style={{ position:'relative', height:18 }}>
                  <div style={{ position:'absolute', right:0, top:'50%', transform:'translateY(-50%)', width:`${Math.min(100,pct)}%`, height:8, background: isGross ? 'var(--ink)' : isPay ? 'var(--accent)' : 'var(--ink-3)', opacity: isGross ? 1 : .8 }}/>
                  <span className="ff-mono num" style={{ position:'absolute', right:0, top:-2, fontSize:10, color:'var(--ink-3)' }}>{pct.toFixed(0)}%</span>
                </div>
              </div>
            );
          })}
        </div>

        {/* Visual: stacked bar */}
        <Sec num="02">Distribution at a glance</Sec>
        <div style={{ marginTop:14 }}>
          <div style={{ display:'flex', height:36, border:'1px solid var(--rule)' }}>
            {steps.filter(s => s.amount < 0).map((s, i) => {
              const pct = gross > 0 ? Math.abs(s.amount) / gross * 100 : 0;
              const isPay = s.kind === 'pay';
              const isRecoup = s.kind === 'recoup';
              return (
                <div key={i} title={`${s.label} · ${fmtMoney(Math.abs(s.amount))} · ${pct.toFixed(1)}%`}
                  style={{ width:`${pct}%`, background: isPay ? 'var(--accent)' : isRecoup ? 'var(--ink)' : 'var(--bg-2)', borderRight: i < steps.length - 2 ? '1px solid var(--rule)' : 'none', display:'flex', alignItems:'center', justifyContent:'center', overflow:'hidden' }}>
                  {pct > 8 && <span className="ff-mono num" style={{ fontSize:10, fontWeight:600, color: isRecoup ? 'var(--bg)' : 'var(--ink)' }}>{pct.toFixed(0)}%</span>}
                </div>
              );
            })}
          </div>
          <div style={{ display:'flex', gap:14, marginTop:10, flexWrap:'wrap' }}>
            {steps.filter(s => s.amount < 0).map((s, i) => (
              <div key={i} style={{ display:'flex', gap:6, alignItems:'center' }}>
                <span style={{ width:9, height:9, background: s.kind === 'pay' ? 'var(--accent)' : s.kind === 'recoup' ? 'var(--ink)' : 'var(--bg-2)', border: s.kind === 'fee' ? '1px solid var(--rule)' : 'none' }}/>
                <span className="ff-mono" style={{ fontSize:10, color:'var(--ink-2)' }}>{s.label}</span>
              </div>
            ))}
          </div>
        </div>

        <Sec num="03">Caveats</Sec>
        <ul style={{ margin:'14px 0 0', padding:'0 0 0 18px', fontSize:12, color:'var(--ink-2)', lineHeight:1.6 }}>
          <li>This view shows the contractual flow only — withholding tax, FX conversion, and statement-level adjustments are applied at reconciliation.</li>
          <li>Recoupment assumes the standard 50% earnings sweep against the unrecouped balance. Override per-statement in the recon queue.</li>
          <li>Splits below sum to 100% of net by design; any rounding remainder lands on the first listed party.</li>
        </ul>
      </div>
    );
  }

  // ─────────────────────────────────────────────────────── RECOUPMENT
  function RecoupmentTab({ ag }) {
    // Synthesize a ledger if not present, derived from advanceSchedule
    const ledger = useMemo(() => {
      if (ag.recoupmentLedger) return ag.recoupmentLedger;
      const total = (ag.advanceSchedule || []).reduce((s, x) => s + (x.paid ? x.amount : 0), 0);
      if (total === 0) return { total:0, recouped:0, unrecouped:0, applications:[], paceMonthly:0, noAdvance:true };
      // Mock ~38% recouped baseline
      const recouped = Math.round(total * 0.38);
      const unrecouped = Math.max(0, total - recouped);
      // Synth quarterly applications
      const apps = [];
      let acc = 0;
      const periods = [
        { period:'Q3 2024', source:'Spotify · NA',     applied: 18420 },
        { period:'Q4 2024', source:'PRS · UK',          applied: 22100 },
        { period:'Q1 2025', source:'ASCAP · US',        applied: 31280 },
        { period:'Q2 2025', source:'Apple Music · WW',  applied: 14640 },
        { period:'Q3 2025', source:'YouTube · WW',      applied: 28840 },
        { period:'Q4 2025', source:'GEMA · DE',         applied: 9720 },
      ];
      for (const p of periods) {
        const remaining = recouped - acc;
        if (remaining <= 0) break;
        const a = Math.min(p.applied, remaining);
        apps.push({ ...p, applied:a, balanceAfter: total - acc - a });
        acc += a;
      }
      return { total, recouped, unrecouped, applications: apps, paceMonthly: Math.round(recouped / 18) };
    }, [ag]);

    const pct = ledger.total > 0 ? ledger.recouped / ledger.total : 0;
    const monthsToRecoup = ledger.unrecouped > 0 && ledger.paceMonthly > 0 ? Math.ceil(ledger.unrecouped / ledger.paceMonthly) : 0;

    if (ledger.noAdvance) {
      return (
        <div style={{ padding:'48px 32px', border:'1px dashed var(--rule)', textAlign:'center', marginTop:18 }}>
          <div className="ff-mono upper" style={{ fontSize:10, letterSpacing:'.12em', color:'var(--ink-3)', marginBottom:10 }}>NO ADVANCE ON THIS AGREEMENT</div>
          <div className="ff-display" style={{ fontSize:24, fontWeight:600, letterSpacing:'-0.02em', marginBottom:8 }}>Nothing to recoup</div>
          <div style={{ fontSize:13, color:'var(--ink-2)', maxWidth:480, margin:'0 auto', lineHeight:1.5 }}>
            This agreement does not include an advance, so the recoupment ledger is empty. Earnings flow directly through the waterfall to the listed parties.
          </div>
        </div>
      );
    }

    return (
      <div>
        {/* Headline */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', borderTop:'1px solid var(--rule)', borderBottom:'1px solid var(--rule)' }}>
          <div style={{ padding:'18px 22px', borderRight:'1px solid var(--rule)' }}>
            <div className="ff-mono upper" style={{ fontSize:9, letterSpacing:'.12em', color:'var(--ink-3)', marginBottom:6 }}>ADVANCE PAID</div>
            <div className="ff-display num" style={{ fontSize:28, fontWeight:600, letterSpacing:'-0.02em' }}>{fmtMoney(ledger.total)}</div>
          </div>
          <div style={{ padding:'18px 22px', borderRight:'1px solid var(--rule)' }}>
            <div className="ff-mono upper" style={{ fontSize:9, letterSpacing:'.12em', color:'var(--ink-3)', marginBottom:6 }}>RECOUPED TO DATE</div>
            <div className="ff-display num" style={{ fontSize:28, fontWeight:600, letterSpacing:'-0.02em' }}>{fmtMoney(ledger.recouped)}</div>
            <div className="ff-mono num" style={{ fontSize:11, color:'var(--ink-3)', marginTop:4 }}>{(pct*100).toFixed(1)}% of advance</div>
          </div>
          <div style={{ padding:'18px 22px', background: ledger.unrecouped > 0 ? 'var(--accent)' : 'transparent', color: ledger.unrecouped > 0 ? 'var(--accent-ink)' : 'inherit' }}>
            <div className="ff-mono upper" style={{ fontSize:9, letterSpacing:'.12em', color: ledger.unrecouped > 0 ? 'var(--accent-ink)' : 'var(--ink-3)', marginBottom:6, opacity:.8 }}>UNRECOUPED</div>
            <div className="ff-display num" style={{ fontSize:28, fontWeight:600, letterSpacing:'-0.02em' }}>{fmtMoney(ledger.unrecouped)}</div>
            <div className="ff-mono num" style={{ fontSize:11, marginTop:4, opacity:.7 }}>
              {ledger.unrecouped === 0 ? 'fully recouped' : `~${monthsToRecoup}mo at current pace`}
            </div>
          </div>
        </div>

        {/* Progress bar */}
        <div style={{ marginTop:24 }}>
          <div style={{ display:'flex', justifyContent:'space-between', marginBottom:6 }}>
            <span className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.1em' }}>RECOUPMENT PROGRESS</span>
            <span className="ff-mono num" style={{ fontSize:11, color:'var(--ink-2)' }}>{fmtMoney(ledger.recouped)} <span style={{ color:'var(--ink-4)' }}>/</span> {fmtMoney(ledger.total)}</span>
          </div>
          <div style={{ height:14, background:'var(--bg-2)', position:'relative', border:'1px solid var(--rule-soft)' }}>
            <div style={{ position:'absolute', top:0, left:0, height:'100%', width:`${pct*100}%`, background:'var(--ink)' }}/>
            {/* Tick marks at 25/50/75% */}
            {[0.25, 0.5, 0.75].map(t => (
              <div key={t} style={{ position:'absolute', top:0, left:`${t*100}%`, width:1, height:'100%', background:'var(--bg)' }}/>
            ))}
          </div>
        </div>

        {/* Application history */}
        <Sec num="01" right={<button className="ff-mono upper" style={{ padding:'7px 12px', fontSize:10, letterSpacing:'.08em', border:'1px solid var(--rule)', background:'transparent', cursor:'pointer' }}>EXPORT CSV</button>}>
          Recoupment applications <span className="ff-mono num" style={{ fontSize:13, color:'var(--ink-3)', fontWeight:500 }}>{ledger.applications.length}</span>
        </Sec>
        <div className="ff-mono upper" style={{ display:'grid', gridTemplateColumns:'110px 1fr 130px 140px 140px', gap:14, padding:'10px 14px', fontSize:10, color:'var(--ink-3)', background:'var(--bg-2)', borderBottom:'1px solid var(--rule)' }}>
          <span>PERIOD</span><span>SOURCE</span><span style={{ textAlign:'right' }}>EARNED</span><span style={{ textAlign:'right' }}>APPLIED</span><span style={{ textAlign:'right' }}>BALANCE AFTER</span>
        </div>
        {ledger.applications.map((a, i) => (
          <div key={i} style={{ display:'grid', gridTemplateColumns:'110px 1fr 130px 140px 140px', gap:14, padding:'14px', borderBottom:'1px solid var(--rule-soft)', alignItems:'center' }}>
            <span className="ff-mono" style={{ fontSize:11, fontWeight:600 }}>{a.period}</span>
            <span style={{ fontSize:13 }}>{a.source}</span>
            <span className="ff-mono num" style={{ fontSize:12, textAlign:'right', color:'var(--ink-3)' }}>{fmtMoney(Math.round((a.applied || 0) / 0.5))}</span>
            <span className="ff-mono num" style={{ fontSize:13, fontWeight:600, textAlign:'right' }}>−{fmtMoney(a.applied)}</span>
            <span className="ff-mono num" style={{ fontSize:13, fontWeight:600, textAlign:'right' }}>{fmtMoney(a.balanceAfter)}</span>
          </div>
        ))}
        {ledger.unrecouped > 0 && (
          <div style={{ display:'grid', gridTemplateColumns:'110px 1fr 130px 140px 140px', gap:14, padding:'14px', background:'var(--bg-2)', borderTop:'2px solid var(--ink)' }}>
            <span className="ff-mono upper" style={{ fontSize:10, fontWeight:700, letterSpacing:'.08em' }}>OPEN</span>
            <span className="ff-mono" style={{ fontSize:11, color:'var(--ink-3)' }}>recoupment continues from next statement</span>
            <span></span>
            <span></span>
            <span className="ff-mono num" style={{ fontSize:13, fontWeight:700, textAlign:'right' }}>{fmtMoney(ledger.unrecouped)}</span>
          </div>
        )}

        <Sec num="02">Projection</Sec>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:24, marginTop:14 }}>
          <div style={{ padding:'18px', border:'1px solid var(--rule)' }}>
            <div className="ff-mono upper" style={{ fontSize:9, color:'var(--ink-3)', letterSpacing:'.12em', marginBottom:8 }}>AT CURRENT PACE</div>
            <div className="ff-display num" style={{ fontSize:36, fontWeight:600, letterSpacing:'-0.03em' }}>
              {ledger.unrecouped === 0 ? 'recouped' : `${monthsToRecoup}mo`}
            </div>
            <div style={{ fontSize:12, color:'var(--ink-2)', marginTop:8, lineHeight:1.5 }}>
              At ~{fmtMoney(ledger.paceMonthly)}/mo recoupment rate, expected to clear by{' '}
              <b className="ff-mono num">{ledger.unrecouped === 0 ? 'now' : (() => { const d = new Date(); d.setMonth(d.getMonth() + monthsToRecoup); return d.toISOString().slice(0,7); })()}</b>.
            </div>
          </div>
          <div style={{ padding:'18px', border:'1px solid var(--rule)' }}>
            <div className="ff-mono upper" style={{ fontSize:9, color:'var(--ink-3)', letterSpacing:'.12em', marginBottom:8 }}>RISK</div>
            <div className="ff-display" style={{ fontSize:24, fontWeight:600, letterSpacing:'-0.02em' }}>
              {pct > 0.7 ? 'Low' : pct > 0.3 ? 'Moderate' : 'Elevated'}
            </div>
            <div style={{ fontSize:12, color:'var(--ink-2)', marginTop:8, lineHeight:1.5 }}>
              {pct > 0.7
                ? 'Tracking above plan; counter-party should fully recoup before term end.'
                : pct > 0.3
                ? 'On pace for recoupment within term; monitor next 2 statements.'
                : 'May not recoup within term — consider extending or re-negotiating advance terms.'}
            </div>
          </div>
        </div>
      </div>
    );
  }

  // ─────────────────────────────────────────────────────── REVERSION TIMELINE
  function ReversionTab({ ag }) {
    const start = ag.start;
    const end = ag.end;
    const retentionEnd = ag.retentionEndDate;
    const now = today();

    const totalDays = daysBetween(start, end) || 365;
    const elapsed = Math.max(0, Math.min(totalDays, daysBetween(start, now) || 0));
    const elapsedPct = totalDays > 0 ? elapsed / totalDays : 0;
    const daysToEnd = daysBetween(now, end);

    // T-90/60/30 marker dates
    const markerDate = (days) => {
      if (!end) return null;
      const d = new Date(end);
      d.setDate(d.getDate() - days);
      return d.toISOString().slice(0,10);
    };
    const t90 = markerDate(90);
    const t60 = markerDate(60);
    const t30 = markerDate(30);

    const markerPct = (date) => {
      const d = daysBetween(start, date);
      return d != null && totalDays > 0 ? Math.min(1, Math.max(0, d / totalDays)) : 0;
    };

    const noticeMonths = ag.renewNoticeMonths || 3;
    const reverts = ag.kind && /admin|sub-pub|publishing/i.test(ag.kind);

    const events = [
      { d: start, l: 'Term begins', kind: 'start' },
      ag.firstRenewalDate && { d: ag.firstRenewalDate, l: 'First renewal option', kind: 'option' },
      t90 && { d: t90, l: 'T-90 · prep notice', kind: 'marker', t:90 },
      t60 && { d: t60, l: 'T-60 · counter-party notified', kind: 'marker', t:60 },
      t30 && { d: t30, l: 'T-30 · final intent decision', kind: 'marker', t:30 },
      { d: end, l: ag.autoRenew ? 'Auto-renew rolls' : 'Term ends', kind: 'end' },
      retentionEnd && { d: retentionEnd, l: 'Retention window closes · catalog reverts', kind: 'reversion' },
    ].filter(Boolean).sort((a,b) => a.d.localeCompare(b.d));

    const statusForMarker = (mDate) => {
      if (!mDate) return 'pending';
      return mDate < now ? 'past' : 'pending';
    };

    return (
      <div>
        <Sec num="01" right={
          <span className="ff-mono num" style={{ fontSize:11, color:'var(--ink-3)' }}>
            day {elapsed} of {totalDays} · {((elapsedPct)*100).toFixed(1)}% elapsed
          </span>
        }>Term & reversion clock</Sec>

        {/* Big timeline */}
        <div style={{ position:'relative', margin:'40px 20px 60px', height:60 }}>
          {/* baseline */}
          <div style={{ position:'absolute', top:30, left:0, right:0, height:2, background:'var(--rule)' }}/>
          {/* elapsed fill */}
          <div style={{ position:'absolute', top:30, left:0, width:`${Math.min(100, elapsedPct*100)}%`, height:2, background:'var(--ink)' }}/>

          {/* Start endpoint */}
          <div style={{ position:'absolute', top:22, left:0, width:18, height:18, background:'var(--ink)', transform:'translateX(-9px)' }}/>
          <div style={{ position:'absolute', top:54, left:0, transform:'translateX(-50%)', textAlign:'center' }}>
            <div className="ff-mono upper" style={{ fontSize:9, color:'var(--ink-3)', letterSpacing:'.1em' }}>START</div>
            <div className="ff-mono num" style={{ fontSize:11, fontWeight:600 }}>{fmtDate(start)}</div>
          </div>

          {/* End endpoint */}
          <div style={{ position:'absolute', top:22, right:0, width:18, height:18, background: ag.autoRenew ? 'var(--ink)' : 'var(--accent)', transform:'translateX(9px)' }}/>
          <div style={{ position:'absolute', top:54, right:0, transform:'translateX(50%)', textAlign:'center' }}>
            <div className="ff-mono upper" style={{ fontSize:9, color: ag.autoRenew ? 'var(--ink-3)' : 'var(--accent-ink)', letterSpacing:'.1em', background: ag.autoRenew ? 'transparent' : 'var(--accent)', padding: ag.autoRenew ? 0 : '2px 5px' }}>{ag.autoRenew ? 'AUTO-RENEW' : 'TERM END'}</div>
            <div className="ff-mono num" style={{ fontSize:11, fontWeight:600, marginTop:2 }}>{fmtDate(end)}</div>
          </div>

          {/* Today — flip badge above the line when crowded against right markers (>92% elapsed) */}
          {start && end && now > start && now < end && (() => {
            const flipDown = elapsedPct > 0.92;
            return (
              <div style={{ position:'absolute', top: flipDown ? 38 : 14, left:`${elapsedPct*100}%`, transform: elapsedPct > 0.95 ? 'translateX(-100%)' : 'translateX(-50%)', display:'flex', flexDirection: flipDown ? 'column-reverse' : 'column', alignItems:'center' }}>
                <span className="ff-mono upper" style={{ fontSize:9, padding:'2px 5px', background:'var(--ink)', color:'var(--bg)', letterSpacing:'.1em', whiteSpace:'nowrap' }}>TODAY</span>
                <div style={{ width:2, height:24, background:'var(--ink)', margin: flipDown ? '0 0 2px' : '2px 0 0' }}/>
              </div>
            );
          })()}

          {/* T-markers */}
          {[{d:t90,t:90},{d:t60,t:60},{d:t30,t:30}].map(({d,t}) => {
            if (!d) return null;
            const pct = markerPct(d);
            const past = d < now;
            return (
              <div key={t} style={{ position:'absolute', top:38, left:`${pct*100}%`, transform:'translateX(-50%)' }}>
                <div style={{ width:11, height:11, background: past ? 'var(--ink-3)' : 'var(--accent)', border: past ? 'none' : '1px solid var(--accent-ink)', transform:'translateY(-3px)' }}/>
                <div style={{ position:'absolute', top:14, left:'50%', transform:'translateX(-50%)', whiteSpace:'nowrap' }}>
                  <div className="ff-mono num" style={{ fontSize:10, fontWeight:600, color: past ? 'var(--ink-3)' : 'var(--ink)' }}>T-{t}</div>
                </div>
              </div>
            );
          })}

          {/* Retention marker (post-term) */}
          {retentionEnd && (
            <div style={{ position:'absolute', top:30, right:-40, width:40, height:2, background:'var(--ink-3)', borderTop:'1px dashed var(--ink-3)' }}/>
          )}
        </div>

        {/* Status callout */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:0, border:'1px solid var(--rule)' }}>
          {[
            { label:'T-90 · PREP NOTICE', d:t90, status:statusForMarker(t90) },
            { label:'T-60 · NOTIFY', d:t60, status:statusForMarker(t60) },
            { label:'T-30 · DECISION', d:t30, status:statusForMarker(t30) },
          ].map((m, i) => (
            <div key={i} style={{ padding:'16px 18px', borderRight: i < 2 ? '1px solid var(--rule)' : 'none' }}>
              <div className="ff-mono upper" style={{ fontSize:9, letterSpacing:'.12em', color:'var(--ink-3)', marginBottom:6 }}>{m.label}</div>
              <div className="ff-mono num" style={{ fontSize:14, fontWeight:600 }}>{fmtDate(m.d)}</div>
              <div style={{ marginTop:6 }}>
                {m.status === 'past'
                  ? <span className="ff-mono upper" style={{ fontSize:9, padding:'2px 6px', background:'var(--bg-2)', border:'1px solid var(--rule-soft)', letterSpacing:'.1em' }}>PASSED</span>
                  : <span className="ff-mono upper" style={{ fontSize:9, padding:'2px 6px', background:'var(--accent)', color:'var(--accent-ink)', letterSpacing:'.1em' }}>PENDING · {daysBetween(now, m.d)}d</span>}
              </div>
            </div>
          ))}
        </div>

        {/* Event list */}
        <Sec num="02">Reversion plan</Sec>
        <div style={{ position:'relative', paddingLeft:18, marginTop:14 }}>
          <div style={{ position:'absolute', left:5, top:6, bottom:6, width:1, background:'var(--rule)' }} />
          {events.map((e, i) => {
            const past = e.d < now;
            return (
              <div key={i} style={{ position:'relative', paddingBottom:14 }}>
                <div style={{ position:'absolute', left:-18, top:5, width:11, height:11, background: past ? 'var(--ink-3)' : e.kind === 'reversion' ? 'var(--accent)' : 'var(--ink)' }}/>
                <div style={{ display:'flex', gap:10, alignItems:'baseline' }}>
                  <span className="ff-mono num" style={{ fontSize:11, color: past ? 'var(--ink-3)' : 'var(--ink)', fontWeight:600 }}>{fmtDate(e.d)}</span>
                  <span className="ff-mono upper" style={{ fontSize:9, color:'var(--ink-3)', letterSpacing:'.1em' }}>{past ? 'DONE' : `T-${daysBetween(now, e.d)}d`}</span>
                </div>
                <div style={{ fontSize:13, marginTop:2, color: past ? 'var(--ink-3)' : 'var(--ink)' }}>{e.l}</div>
              </div>
            );
          })}
        </div>

        {reverts && retentionEnd && (
          <>
            <Sec num="03">What reverts</Sec>
            <div style={{ padding:'16px 18px', background:'var(--bg-2)', marginTop:0 }}>
              <p style={{ fontSize:13, lineHeight:1.6, margin:0, color:'var(--ink-2)' }}>
                On <b className="ff-mono num">{fmtDate(retentionEnd)}</b> ({daysBetween(now, retentionEnd)} days from today),
                administration of <b>{(ag.works || []).length || 'all covered'} works</b> in <b>{ag.territory}</b> reverts to{' '}
                <b>{(ag.parties || []).find(p => p.role && /writer|owner/i.test(p.role))?.name || ag.a}</b>.
                In-flight collections during the {ag.retentionYears || 2}-year retention window remain payable to{' '}
                <b>{ag.b}</b> per the agreement's sunset clause.
              </p>
            </div>
          </>
        )}
      </div>
    );
  }

  // ─────────────────────────────────────────────────────── DOCUSEAL
  function DocusealTab({ ag }) {
    // Synthesize an envelope state from signatures
    const sigs = ag.signatures || [];
    const allSigned = sigs.length > 0 && sigs.every(s => s.verified);
    const anySigned = sigs.some(s => s.verified);

    const envState = ag.docuseal?.state || (
      allSigned ? 'completed' :
      anySigned ? 'partially_signed' :
      sigs.length > 0 ? 'sent' :
      'draft'
    );

    const stateMeta = {
      draft:             { label:'Draft',              tone:'soft',   note:'Not yet sent for signature' },
      sent:              { label:'Sent',               tone:'info',   note:'Envelope delivered to all signers' },
      partially_signed:  { label:'Partially signed',   tone:'accent', note:'Awaiting one or more signatures' },
      completed:         { label:'Completed',          tone:'ok',     note:'All parties signed; PDF filed' },
      declined:          { label:'Declined',           tone:'danger', note:'A party declined; revise & re-send' },
      voided:            { label:'Voided',             tone:'danger', note:'Envelope was voided' },
    };
    const meta = stateMeta[envState];

    const envId = ag.docuseal?.envelopeId || ('DS-' + (ag.id || '').replace(/[^A-Z0-9]/gi,'').slice(0,8) + '-' + new Date(ag.start || today()).getTime().toString(36).toUpperCase());
    const envCreated = ag.docuseal?.createdAt || (ag.start || today()) + 'T09:00:00Z';

    // Per-signer activity, derived
    const signers = sigs.map((s, i) => {
      const sentAt = envCreated;
      const viewedAt = !s.verified && i % 2 === 0 ? sentAt.replace('T09', 'T11') : (s.verified ? sentAt.replace('T09','T10') : null);
      return {
        ...s,
        sentAt,
        viewedAt: viewedAt,
        signedAt: s.verified ? (s.at || sentAt.replace('T09','T14')) : null,
        nudges: s.verified ? 0 : (i === 0 ? 0 : 1),
      };
    });

    const tone = meta.tone === 'ok' ? '#1f7a3a' : meta.tone === 'accent' ? 'var(--accent)' : meta.tone === 'danger' ? '#b81d1d' : meta.tone === 'info' ? '#1f4ed8' : 'var(--ink-3)';
    const toneInk = meta.tone === 'accent' ? 'var(--accent-ink)' : '#fff';

    return (
      <div>
        {/* Hero strip */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr 320px', gap:24, marginTop:8 }}>
          <div style={{ padding:'24px', border:'1px solid var(--rule)' }}>
            <div style={{ display:'flex', gap:14, alignItems:'center', marginBottom:14 }}>
              {/* Docuseal-ish envelope glyph */}
              <span style={{ width:56, height:42, background:'var(--bg-2)', border:'1px solid var(--rule)', position:'relative', display:'inline-flex', flexShrink:0 }}>
                <svg viewBox="0 0 56 42" style={{ width:'100%', height:'100%' }}>
                  <path d="M 0 0 L 28 24 L 56 0" fill="none" stroke="var(--ink-3)" strokeWidth="1"/>
                </svg>
              </span>
              <div style={{ flex:1, minWidth:0 }}>
                <div className="ff-mono upper" style={{ fontSize:9, letterSpacing:'.12em', color:'var(--ink-3)' }}>DOCUSEAL ENVELOPE</div>
                <div className="ff-mono" style={{ fontSize:13, fontWeight:600, marginTop:3 }}>{envId}</div>
              </div>
              <span className="ff-mono upper" style={{ fontSize:10, padding:'5px 10px', background:tone, color:toneInk, letterSpacing:'.1em', fontWeight:600 }}>{meta.label}</span>
            </div>
            <div style={{ fontSize:13, color:'var(--ink-2)', lineHeight:1.5 }}>{meta.note}</div>
            <div style={{ display:'flex', gap:8, marginTop:18, flexWrap:'wrap' }}>
              {envState === 'draft' && <button className="ff-mono upper" style={{ padding:'10px 16px', fontSize:11, letterSpacing:'.08em', background:'var(--ink)', color:'var(--bg)', border:0, cursor:'pointer', fontWeight:600 }}>SEND FOR SIGNATURE</button>}
              {envState === 'partially_signed' && <button className="ff-mono upper" style={{ padding:'10px 16px', fontSize:11, letterSpacing:'.08em', background:'var(--accent)', color:'var(--accent-ink)', border:0, cursor:'pointer', fontWeight:600 }}>NUDGE PENDING SIGNERS</button>}
              {envState === 'completed' && <button className="ff-mono upper" style={{ padding:'10px 16px', fontSize:11, letterSpacing:'.08em', background:'var(--ink)', color:'var(--bg)', border:0, cursor:'pointer', fontWeight:600 }}>DOWNLOAD EXECUTED PDF</button>}
              <button className="ff-mono upper" style={{ padding:'10px 16px', fontSize:11, letterSpacing:'.08em', background:'transparent', border:'1px solid var(--rule)', cursor:'pointer' }}>OPEN IN DOCUSEAL ↗</button>
              {envState !== 'draft' && envState !== 'completed' && <button className="ff-mono upper" style={{ padding:'10px 16px', fontSize:11, letterSpacing:'.08em', background:'transparent', border:'1px solid var(--danger)', color:'var(--danger)', cursor:'pointer' }}>VOID ENVELOPE</button>}
            </div>
          </div>

          {/* Mini summary */}
          <div style={{ padding:'18px', border:'1px solid var(--rule)' }}>
            <div className="ff-mono upper" style={{ fontSize:9, letterSpacing:'.12em', color:'var(--ink-3)', marginBottom:10 }}>SIGNER SUMMARY</div>
            {[
              ['Signers',  sigs.length],
              ['Signed',   sigs.filter(s => s.verified).length],
              ['Pending',  sigs.filter(s => !s.verified).length],
              ['Nudges',   signers.reduce((s, x) => s + (x.nudges || 0), 0)],
            ].map(([l, v]) => (
              <div key={l} style={{ display:'flex', justifyContent:'space-between', padding:'6px 0', borderBottom:'1px solid var(--rule-soft)' }}>
                <span className="ff-mono upper" style={{ fontSize:10, letterSpacing:'.1em', color:'var(--ink-3)' }}>{l}</span>
                <span className="ff-mono num" style={{ fontSize:13, fontWeight:600 }}>{v}</span>
              </div>
            ))}
          </div>
        </div>

        {/* Signer activity */}
        <Sec num="01">Signer activity</Sec>
        {signers.length === 0 && (
          <div style={{ padding:'40px', textAlign:'center', border:'1px dashed var(--rule)' }}>
            <div className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.12em' }}>NO SIGNERS YET — SEND THE ENVELOPE TO BEGIN</div>
          </div>
        )}
        {signers.map((s, i) => {
          const stages = [
            { k:'sent',   l:'Sent',     d:s.sentAt },
            { k:'viewed', l:'Viewed',   d:s.viewedAt },
            { k:'signed', l:'Signed',   d:s.signedAt },
          ];
          return (
            <div key={i} style={{ padding:'18px', borderBottom:'1px solid var(--rule-soft)', display:'grid', gridTemplateColumns:'200px 1fr 120px', gap:24, alignItems:'center' }}>
              <div>
                <div style={{ fontSize:13, fontWeight:600 }}>{s.party}</div>
                {s.signer && <div className="ff-mono" style={{ fontSize:11, color:'var(--ink-2)', marginTop:3 }}>{s.signer}</div>}
                {s.role && <div className="ff-mono upper" style={{ fontSize:9, color:'var(--ink-3)', letterSpacing:'.1em', marginTop:3 }}>{s.role}</div>}
              </div>
              {/* Stage tracker */}
              <div style={{ display:'flex', alignItems:'center', gap:0 }}>
                {stages.map((st, j) => {
                  const done = !!st.d;
                  return (
                    <React.Fragment key={st.k}>
                      <div style={{ flexShrink:0, textAlign:'center', minWidth:80 }}>
                        <div style={{ width:14, height:14, background: done ? 'var(--ink)' : 'transparent', border:'1.5px solid ' + (done ? 'var(--ink)' : 'var(--rule)'), margin:'0 auto', display:'flex', alignItems:'center', justifyContent:'center' }}>
                          {done && <span style={{ color:'var(--bg)', fontSize:9, fontWeight:700 }}>✓</span>}
                        </div>
                        <div className="ff-mono upper" style={{ fontSize:9, marginTop:6, color: done ? 'var(--ink)' : 'var(--ink-3)', letterSpacing:'.1em', fontWeight:600 }}>{st.l}</div>
                        <div className="ff-mono num" style={{ fontSize:9, color:'var(--ink-3)', marginTop:2 }}>{done ? fmtDate(st.d) : '—'}</div>
                      </div>
                      {j < stages.length - 1 && <div style={{ flex:1, height:1.5, background: stages[j+1].d ? 'var(--ink)' : 'var(--rule)' }}/>}
                    </React.Fragment>
                  );
                })}
              </div>
              {/* Action */}
              <div style={{ textAlign:'right' }}>
                {s.verified ? (
                  <span className="ff-mono upper" style={{ fontSize:9, padding:'4px 8px', background:'var(--bg-2)', border:'1px solid var(--rule-soft)', letterSpacing:'.1em', color:'var(--ok)' }}>✓ VERIFIED</span>
                ) : (
                  <button onClick={() => window.toast && window.toast(`Reminder sent to ${s.party}`)} className="ff-mono upper" style={{ padding:'7px 12px', fontSize:10, letterSpacing:'.08em', background:'var(--accent)', color:'var(--accent-ink)', border:0, cursor:'pointer', fontWeight:600 }}>NUDGE</button>
                )}
                {s.nudges > 0 && <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', marginTop:5 }}>{s.nudges} reminder{s.nudges>1?'s':''} sent</div>}
              </div>
            </div>
          );
        })}

        {/* Webhook log */}
        <Sec num="02">Webhook log</Sec>
        <div className="ff-mono" style={{ fontSize:11, background:'var(--bg-2)', padding:'14px 16px', border:'1px solid var(--rule-soft)', lineHeight:1.7 }}>
          <div><span style={{ color:'var(--ink-3)' }}>{envCreated}</span> · <b>envelope.created</b> · {envId}</div>
          {signers.map((s, i) => s.viewedAt && (
            <div key={'v'+i}><span style={{ color:'var(--ink-3)' }}>{s.viewedAt}</span> · <b>signer.viewed</b> · {s.signer || s.party}</div>
          ))}
          {signers.map((s, i) => s.signedAt && (
            <div key={'s'+i}><span style={{ color:'var(--ink-3)' }}>{s.signedAt}</span> · <b>signer.completed</b> · {s.signer || s.party}</div>
          ))}
          {envState === 'completed' && <div><span style={{ color:'var(--ink-3)' }}>{(signers[signers.length-1]?.signedAt) || envCreated}</span> · <b>envelope.completed</b> · executed PDF filed to assets</div>}
        </div>
      </div>
    );
  }

  // Expose tab components globally so agreement-detail.jsx can render them.
  Object.assign(window, {
    AgWaterfall: WaterfallTab,
    AgRecoupment: RecoupmentTab,
    AgReversion: ReversionTab,
    AgDocuseal: DocusealTab,
  });
})();
