// DISCOVERY PLATFORM — modals, drawers, and new hubs for the 18 opportunities
(function(){
const { useState, useMemo, useEffect } = React;
const T = window.ArbiterTokens;

// ── Modal shell ──────────────────────────────────────────────────────────
function DcModal({ title, subtitle, onClose, children, width = 720, footer }) {
  const dc = window.__dc;
  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.52)', zIndex: 1000,
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '40px',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width: width + 'px', maxWidth: '96vw', maxHeight: '92vh',
        background: T.color.bg.card, borderRadius: T.radius.lg,
        boxShadow: '0 24px 64px rgba(0,0,0,0.35)', display: 'flex', flexDirection: 'column', overflow: 'hidden',
      }}>
        <div style={{ padding: '14px 20px', borderBottom: `1px solid ${T.color.border.light}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div>
            <div style={{ fontSize: '14px', fontWeight: 700, color: T.color.text.primary }}>{title}</div>
            {subtitle && <div style={{ fontSize: '11px', color: T.color.text.tertiary, marginTop: '2px' }}>{subtitle}</div>}
          </div>
          <button onClick={onClose} style={{ border: 'none', background: 'transparent', cursor: 'pointer', fontSize: '16px', color: T.color.text.tertiary, padding: '4px 8px' }}><Icons.X size={11}/></button>
        </div>
        <div style={{ padding: '16px 20px', overflow: 'auto', flex: 1 }}>{children}</div>
        {footer && <div style={{ padding: '12px 20px', borderTop: `1px solid ${T.color.border.light}`, background: T.color.bg.secondary, display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>{footer}</div>}
      </div>
    </div>
  );
}

// Small helpers
const Field = ({ label, children, hint }) => (
  <label style={{ display: 'block', marginBottom: '10px' }}>
    <div style={{ fontSize: '10px', fontWeight: 600, color: T.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '4px' }}>{label}</div>
    {children}
    {hint && <div style={{ fontSize: '10px', color: T.color.text.tertiary, marginTop: '3px' }}>{hint}</div>}
  </label>
);
const inp = { width: '100%', padding: '7px 10px', border: `1px solid ${T.color.border.light}`, borderRadius: '6px', fontSize: '12px', fontFamily: T.font.family, boxSizing: 'border-box' };
const ta = { ...inp, fontFamily: T.font.family, resize: 'vertical', minHeight: '60px' };

// ── #1 Request Response Drawer ───────────────────────────────────────────
function DcRequestResponseDrawer({ request, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const data = store.state;
  const [picked, setPicked] = useState([]);
  const [customText, setCustomText] = useState('');
  const [filter, setFilter] = useState('');
  const lib = data.objectionsLibrary.filter(o => !filter || (o.code + ' ' + o.text).toLowerCase().includes(filter.toLowerCase()));
  const response = data.requestResponses.find(r => r.requestId === request.id);

  const toggle = (code) => setPicked(p => p.includes(code) ? p.filter(x => x !== code) : [...p, code]);
  const apply = () => {
    picked.forEach(code => store.addObjection(request.id, code));
    if (customText.trim()) store.addObjection(request.id, 'CUSTOM', customText.trim());
    setPicked([]); setCustomText('');
  };
  const markResponded = () => { store.markRequestResponded(request.id); onClose && onClose(); };

  return (
    <DcModal
      title={`${request.id} — ${request.type}`}
      subtitle={`${request.matter} · ${request.direction} · due ${request.due}`}
      onClose={onClose} width={860}
      footer={<>
        <button style={dc.btnSecondary} onClick={onClose}>Close</button>
        <button style={dc.btnPrimary} onClick={markResponded}>Mark Responded</button>
      </>}
    >
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px', color: T.color.text.secondary }}>Objections library</div>
          <input style={{ ...inp, marginBottom: '8px' }} placeholder="Filter…" value={filter} onChange={e => setFilter(e.target.value)} />
          <div style={{ maxHeight: '320px', overflow: 'auto', border: `1px solid ${T.color.border.light}`, borderRadius: '6px' }}>
            {lib.map(o => (
              <label key={o.id} style={{ display: 'flex', gap: '8px', padding: '8px 10px', borderBottom: `1px solid ${T.color.border.light}`, cursor: 'pointer', background: picked.includes(o.code) ? dc.cobaltBg : 'transparent' }}>
                <input type="checkbox" checked={picked.includes(o.code)} onChange={() => toggle(o.code)} />
                <div>
                  <div style={{ fontSize: '11px', fontWeight: 700 }}>{o.code}</div>
                  <div style={{ fontSize: '10px', color: T.color.text.tertiary }}>{o.basis}</div>
                  <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '2px' }}>{o.text}</div>
                </div>
              </label>
            ))}
          </div>
          <Field label="Custom objection text">
            <textarea style={ta} value={customText} onChange={e => setCustomText(e.target.value)} placeholder="Additional narrative for this request…" />
          </Field>
          <button style={dc.btnSecondary} onClick={apply} disabled={!picked.length && !customText.trim()}>Add {picked.length || ''} to response</button>
        </div>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px', color: T.color.text.secondary }}>Draft response ({response ? response.items.length : 0} items)</div>
          <div style={{ maxHeight: '380px', overflow: 'auto', border: `1px solid ${T.color.border.light}`, borderRadius: '6px', padding: '8px' }}>
            {(!response || !response.items.length) && <div role="status" style={{ fontSize: '11px', color: T.color.text.tertiary, padding: '8px' }}>No items yet — pick objections from the library.</div>}
            {response && response.items.map((it, i) => (
              <div key={it.id} style={{ padding: '8px', borderBottom: `1px solid ${T.color.border.light}` }}>
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span style={{ ...dc.tag, background: dc.cobaltBg, color: dc.cobalt }}>{i + 1}. {it.code}</span>
                  {it.basis && <span style={{ fontSize: '10px', color: T.color.text.tertiary }}>{it.basis}</span>}
                </div>
                <div style={{ fontSize: '11px', marginTop: '4px' }}>{it.text}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </DcModal>
  );
}

// ── #2 Meet-and-Confer Planner ───────────────────────────────────────────
function DcMeetConferPlannerModal({ matter, matterId, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const [form, setForm] = useState({ scheduled: '', opposingCounsel: '', agenda: '', attendees: 'M. Kirkland, L. Torres' });
  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const save = () => {
    store.scheduleMeetConfer({
      matter, matterId,
      scheduled: form.scheduled,
      opposingCounsel: form.opposingCounsel,
      attendees: form.attendees.split(',').map(s => s.trim()).filter(Boolean),
      agenda: form.agenda.split('\n').filter(Boolean),
    });
    onClose && onClose();
  };
  return (
    <DcModal title="Schedule meet-and-confer" subtitle={matter} onClose={onClose}
      footer={<><button style={dc.btnSecondary} onClick={onClose}>Cancel</button><button style={dc.btnPrimary} onClick={save} disabled={!form.scheduled}>Schedule</button></>}>
      <Field label="Date & time"><input style={inp} type="datetime-local" value={form.scheduled} onChange={e => upd('scheduled', e.target.value)} /></Field>
      <Field label="Opposing counsel"><input style={inp} value={form.opposingCounsel} onChange={e => upd('opposingCounsel', e.target.value)} placeholder="Firm — lead attorney" /></Field>
      <Field label="Our attendees"><input style={inp} value={form.attendees} onChange={e => upd('attendees', e.target.value)} /></Field>
      <Field label="Agenda (one item per line)" hint="Topics per FRCP 26(f) + local rules"><textarea style={{ ...ta, minHeight: '120px' }} value={form.agenda} onChange={e => upd('agenda', e.target.value)} placeholder={'ESI preservation scope\nSearch terms + sampling\nPrivilege protocol (FRE 502(d))\nProduction format'} /></Field>
    </DcModal>
  );
}

// ── #3 Proportionality Modal ─────────────────────────────────────────────
function DcProportionalityModal({ requestId, matter, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const [f, setF] = useState({ importance: 3, amount: 3, access: 3, resources: 3, benefit: 3, burden: 3 });
  const labels = {
    importance: 'Importance of issues',
    amount: 'Amount in controversy',
    access: 'Parties\' access to info',
    resources: 'Parties\' resources',
    benefit: 'Benefit of discovery',
    burden: 'Burden vs. benefit',
  };
  const avg = Math.round((Object.values(f).reduce((s, v) => s + v, 0) / 6) * 10) / 10;
  const verdict = avg >= 3.5 ? 'Proportional' : (avg >= 2.5 ? 'Mixed — narrow scope' : 'Disproportionate — object');
  const vColor = avg >= 3.5 ? dc.emerald : (avg >= 2.5 ? dc.amber : dc.crimson);
  const save = () => { store.scoreProportionality({ requestId, matter, factors: f }); onClose && onClose(); };

  return (
    <DcModal title="Proportionality assessment" subtitle={`FRCP 26(b)(1) 6-factor — ${matter || ''}`} onClose={onClose}
      footer={<><button style={dc.btnSecondary} onClick={onClose}>Cancel</button><button style={dc.btnPrimary} onClick={save}>Save assessment</button></>}>
      {Object.keys(f).map(k => (
        <div key={k} style={{ marginBottom: '14px' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
            <span style={{ fontSize: '12px', fontWeight: 600 }}>{labels[k]}</span>
            <span style={{ fontSize: '11px', fontFamily: T.font.mono, color: dc.cobalt, fontWeight: 700 }}>{f[k]}</span>
          </div>
          <input type="range" min="1" max="5" step="1" value={f[k]} onChange={e => setF({ ...f, [k]: +e.target.value })} style={{ width: '100%' }} />
        </div>
      ))}
      <div style={{ padding: '12px', background: dc.cobaltBg, borderRadius: '6px', marginTop: '12px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 600, color: T.color.text.secondary }}>Average score</div>
          <div style={{ fontSize: '28px', fontWeight: 700, fontFamily: T.font.mono, color: vColor }}>{avg}</div>
        </div>
        <div style={{ fontSize: '12px', fontWeight: 700, color: vColor }}>{verdict}</div>
      </div>
    </DcModal>
  );
}

// ── #4 Hold Composer + Ack Wall ──────────────────────────────────────────
function DcHoldComposerModal({ matter, matterId, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const data = store.state;
  const templates = data.holdTemplates;
  const [templateId, setTemplateId] = useState(templates[0] && templates[0].id);
  const [form, setForm] = useState({ scope: '', sources: 'Exchange, OneDrive, Teams', custodianCount: 0 });
  const tpl = templates.find(t => t.id === templateId);
  useEffect(() => { if (tpl) setForm(f => ({ ...f, scope: tpl.scopeTemplate || f.scope, sources: (tpl.sources || []).join(', ') || f.sources })); }, [templateId]);
  const save = () => {
    store.issueHold({
      matter, matterId,
      scope: form.scope,
      sources: form.sources.split(',').map(s => s.trim()).filter(Boolean),
      custodianCount: +form.custodianCount || 0,
      templateId,
    });
    onClose && onClose();
  };
  return (
    <DcModal title="Issue litigation hold" subtitle={matter} onClose={onClose}
      footer={<><button style={dc.btnSecondary} onClick={onClose}>Cancel</button><button style={dc.btnPrimary} onClick={save}>Issue hold</button></>}>
      <Field label="Template">
        <select style={inp} value={templateId || ''} onChange={e => setTemplateId(e.target.value)}>
          {templates.map(t => <option key={t.id} value={t.id}>{t.code} — {t.name}</option>)}
        </select>
      </Field>
      <Field label="Scope"><textarea style={ta} value={form.scope} onChange={e => setForm({ ...form, scope: e.target.value })} /></Field>
      <Field label="Sources (comma-separated)"><input style={inp} value={form.sources} onChange={e => setForm({ ...form, sources: e.target.value })} /></Field>
      <Field label="Custodian count"><input style={inp} type="number" value={form.custodianCount} onChange={e => setForm({ ...form, custodianCount: e.target.value })} /></Field>
    </DcModal>
  );
}

function DcHoldAckWall({ hold, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const acks = store.acksForHold(hold.id);
  const unacked = store.unackedCustodians(hold.id);
  const nudge = () => store.nudgeHold(hold.id, unacked.map(c => c.id));
  return (
    <DcModal title={`Ack wall — ${hold.id}`} subtitle={`${hold.matter} · ${hold.acknowledged}/${hold.custodianCount} (${hold.acknowledgedPct}%)`} onClose={onClose}
      footer={<><button style={dc.btnSecondary} onClick={onClose}>Close</button>{unacked.length > 0 && <button style={dc.btnPrimary} onClick={nudge}>Nudge {unacked.length}</button>}</>}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px', color: dc.emerald }}>Acknowledged ({acks.length})</div>
          {acks.length === 0 && <div style={{ fontSize: '11px', color: T.color.text.tertiary }}>None yet.</div>}
          {acks.map(a => {
            const c = store.state.custodians.find(x => x.id === a.custodianId);
            return (
              <div key={a.id} style={{ padding: '6px 8px', borderBottom: `1px solid ${T.color.border.light}`, fontSize: '11px', display: 'flex', justifyContent: 'space-between' }}>
                <span>{c ? c.name : a.custodianId}</span>
                <span style={{ color: T.color.text.tertiary, fontFamily: T.font.mono, fontSize: '10px' }}>{a.ackAt.slice(0, 10)}</span>
              </div>
            );
          })}
        </div>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px', color: dc.crimson }}>Pending ({unacked.length})</div>
          {unacked.length === 0 && <div style={{ fontSize: '11px', color: T.color.text.tertiary }}>All custodians acked.</div>}
          {unacked.map(c => (
            <div key={c.id} style={{ padding: '6px 8px', borderBottom: `1px solid ${T.color.border.light}`, fontSize: '11px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <span>{c.name}</span>
              <button style={{ ...dc.btnGhost, padding: '3px 8px' }} onClick={() => store.ackHold(hold.id, c.id, c.name)}>Ack on behalf</button>
            </div>
          ))}
        </div>
      </div>
    </DcModal>
  );
}

// ── #5 Interview Kit ─────────────────────────────────────────────────────
function DcInterviewKitModal({ custodian, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const [form, setForm] = useState({
    devicesInUse: 'Laptop (work), iPhone (work), iPhone (personal)',
    personalAccounts: 'Gmail (personal) — not work-related per custodian',
    collaboration: 'Teams, Slack (Enterprise Grid), Signal (work-adjacent)',
    byod: 'Yes — iPhone (personal) has some work texts',
    retention: 'Deletes email > 2y unless flagged',
    potentialSources: 'Exchange, OneDrive, Teams, personal iPhone (texts)',
    notes: '',
  });
  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const save = () => {
    store.logInterview({
      custodianId: custodian.id,
      custodianName: custodian.name,
      matter: custodian.matter,
      matterId: custodian.matterId,
      interviewer: 'M. Kirkland',
      ...form,
      potentialSources: form.potentialSources.split(',').map(s => s.trim()).filter(Boolean),
      devicesInUse: form.devicesInUse.split(',').map(s => s.trim()).filter(Boolean),
    });
    onClose && onClose();
  };
  return (
    <DcModal title={`Custodian interview — ${custodian.name}`} subtitle={`${custodian.role} · ${custodian.org}`} onClose={onClose}
      footer={<><button style={dc.btnSecondary} onClick={onClose}>Cancel</button><button style={dc.btnPrimary} onClick={save}>Log interview</button></>}>
      <Field label="Devices in use (comma)"><input style={inp} value={form.devicesInUse} onChange={e => upd('devicesInUse', e.target.value)} /></Field>
      <Field label="Personal accounts touching work"><input style={inp} value={form.personalAccounts} onChange={e => upd('personalAccounts', e.target.value)} /></Field>
      <Field label="Collaboration tools"><input style={inp} value={form.collaboration} onChange={e => upd('collaboration', e.target.value)} /></Field>
      <Field label="BYOD / off-channel"><input style={inp} value={form.byod} onChange={e => upd('byod', e.target.value)} /></Field>
      <Field label="Retention habits"><input style={inp} value={form.retention} onChange={e => upd('retention', e.target.value)} /></Field>
      <Field label="Potential sources (comma)"><input style={inp} value={form.potentialSources} onChange={e => upd('potentialSources', e.target.value)} /></Field>
      <Field label="Narrative notes"><textarea style={ta} value={form.notes} onChange={e => upd('notes', e.target.value)} /></Field>
    </DcModal>
  );
}

// ── #6 Collection Wizard ─────────────────────────────────────────────────
function DcCollectionWizardModal({ matter, matterId, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const [step, setStep] = useState(1);
  const [form, setForm] = useState({ custodian: '', sources: 'Exchange, OneDrive', vendor: 'Internal (Relativity One)', eta: '' });
  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const create = () => {
    const col = store.startCollection({
      custodian: form.custodian, matter,
      sources: form.sources.split(',').map(s => s.trim()).filter(Boolean),
      vendor: form.vendor, eta: form.eta,
    });
    store.addChainEvent({ collectionId: col.id, event: 'Collection job queued', actor: 'Collection Ops', hash: null });
    onClose && onClose();
  };
  return (
    <DcModal title="Start collection" subtitle={`Step ${step}/3 — ${matter}`} onClose={onClose}
      footer={<>
        {step > 1 && <button style={dc.btnSecondary} onClick={() => setStep(step - 1)}>Back</button>}
        {step < 3 && <button style={dc.btnPrimary} onClick={() => setStep(step + 1)}>Next</button>}
        {step === 3 && <button style={dc.btnPrimary} onClick={create}>Queue collection</button>}
      </>}>
      {step === 1 && (<>
        <Field label="Custodian"><input style={inp} value={form.custodian} onChange={e => upd('custodian', e.target.value)} placeholder="Name (role)" /></Field>
        <Field label="Sources (comma)"><input style={inp} value={form.sources} onChange={e => upd('sources', e.target.value)} /></Field>
      </>)}
      {step === 2 && (<>
        <Field label="Vendor / method">
          <select style={inp} value={form.vendor} onChange={e => upd('vendor', e.target.value)}>
            <option>Internal (Relativity One)</option><option>Lighthouse</option><option>Consilio</option><option>Cellebrite (mobile)</option>
          </select>
        </Field>
        <Field label="Target ETA"><input style={inp} type="date" value={form.eta} onChange={e => upd('eta', e.target.value)} /></Field>
      </>)}
      {step === 3 && (<div style={{ padding: '10px', background: dc.cobaltBg, borderRadius: '6px' }}>
        <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Review</div>
        <div style={{ fontSize: '11px', lineHeight: 1.7 }}>
          <div><b>Custodian:</b> {form.custodian}</div>
          <div><b>Sources:</b> {form.sources}</div>
          <div><b>Vendor:</b> {form.vendor}</div>
          <div><b>ETA:</b> {form.eta}</div>
        </div>
      </div>)}
    </DcModal>
  );
}

// ── #7 Chain of Custody Panel ────────────────────────────────────────────
function DcChainOfCustodyPanel({ collection, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const events = store.chainForCollection(collection.id);
  const [newEvent, setNewEvent] = useState({ event: '', actor: '', hash: '' });
  const add = () => {
    if (!newEvent.event) return;
    store.addChainEvent({ collectionId: collection.id, ...newEvent });
    setNewEvent({ event: '', actor: '', hash: '' });
  };
  return (
    <DcModal title={`Chain of custody — ${collection.id}`} subtitle={`${collection.matter} · ${collection.custodian}`} onClose={onClose}>
      <div style={{ marginBottom: '14px' }}>
        {events.length === 0 && <div role="status" style={{ fontSize: '11px', color: T.color.text.tertiary }}>No events recorded.</div>}
        {events.map(e => (
          <div key={e.id} style={{ padding: '8px 10px', borderLeft: `3px solid ${dc.cobalt}`, background: dc.cobaltBg, marginBottom: '6px', borderRadius: '4px' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <span style={{ fontSize: '11px', fontWeight: 700 }}>{e.event}</span>
              <span style={{ fontSize: '10px', color: T.color.text.tertiary, fontFamily: T.font.mono }}>{(e.at || '').slice(0, 19).replace('T', ' ')}</span>
            </div>
            {e.actor && <div style={{ fontSize: '10px', color: T.color.text.secondary }}>{e.actor}</div>}
            {e.hash && <div style={{ fontSize: '10px', fontFamily: T.font.mono, color: T.color.text.tertiary }}>SHA-256: {e.hash}</div>}
          </div>
        ))}
      </div>
      <div style={{ borderTop: `1px solid ${T.color.border.light}`, paddingTop: '12px' }}>
        <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Add event</div>
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '8px', marginBottom: '8px' }}>
          <input style={inp} placeholder="Event description" value={newEvent.event} onChange={e => setNewEvent({ ...newEvent, event: e.target.value })} />
          <input style={inp} placeholder="Actor" value={newEvent.actor} onChange={e => setNewEvent({ ...newEvent, actor: e.target.value })} />
        </div>
        <input style={{ ...inp, marginBottom: '8px', fontFamily: T.font.mono }} placeholder="SHA-256 hash (optional)" value={newEvent.hash} onChange={e => setNewEvent({ ...newEvent, hash: e.target.value })} />
        <button style={dc.btnPrimary} onClick={add}>Record event</button>
      </div>
    </DcModal>
  );
}

// ── #8 ECA Hub (new tab content) ─────────────────────────────────────────
function DcECAHub({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const matters = Array.from(new Set(data.searchTerms.map(t => t.matterId)));
  const [matterId, setMatterId] = useState(matters[0] || null);
  const [form, setForm] = useState({ term: '', hits: 0, families: 0 });
  const terms = data.searchTerms.filter(t => t.matterId === matterId);
  const summary = data.ecaSummaries.find(s => s.matterId === matterId);
  const add = () => {
    if (!form.term) return;
    store.addSearchTerm({ matterId, term: form.term, hits: +form.hits || 0, families: +form.families || 0 });
    setForm({ term: '', hits: 0, families: 0 });
  };
  const run = () => store.runECA(matterId);

  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={{ padding: '10px 16px', display: 'flex', gap: '10px', alignItems: 'center' }}>
          <span style={{ fontSize: '11px', fontWeight: 700 }}>Matter</span>
          <select style={{ ...inp, width: 'auto' }} value={matterId || ''} onChange={e => setMatterId(e.target.value)}>
            {matters.map(m => <option key={m} value={m}>{m}</option>)}
          </select>
          <button style={dc.btnPrimary} onClick={run}>Run ECA</button>
        </div>
      </div>
      <div style={dc.card}>
        <div style={dc.cardH}>Search terms</div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>Term</th><th style={dc.th}>Hits</th><th style={dc.th}>Families</th><th style={dc.th}>FP rate</th></tr></thead>
          <tbody>
            {terms.map(t => (
              <tr key={t.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{t.term}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{(t.hits || 0).toLocaleString()}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{(t.families || 0).toLocaleString()}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{t.falsePositivePct != null ? t.falsePositivePct + '%' : '—'}</td>
              </tr>
            ))}
            <tr>
              <td style={dc.td}><input style={inp} placeholder="e.g. pric* AND capac*" value={form.term} onChange={e => setForm({ ...form, term: e.target.value })} /></td>
              <td style={dc.td}><input style={inp} type="number" value={form.hits} onChange={e => setForm({ ...form, hits: e.target.value })} /></td>
              <td style={dc.td}><input style={inp} type="number" value={form.families} onChange={e => setForm({ ...form, families: e.target.value })} /></td>
              <td style={dc.td}><button style={dc.btnSecondary} onClick={add}>+ Add</button></td>
            </tr>
          </tbody>
        </table>
      </div>
      {summary && (
        <div style={dc.card}>
          <div style={dc.cardH}>ECA runs</div>
          <table style={{ width: '100%', borderCollapse: 'collapse' }}>
            <thead><tr><th style={dc.th}>At</th><th style={dc.th}>Terms</th><th style={dc.th}>Hits</th><th style={dc.th}>Families</th></tr></thead>
            <tbody>
              {summary.runs.map((r, i) => (
                <tr key={i}>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{r.at.slice(0, 19).replace('T', ' ')}</td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.termCount}</td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.hits.toLocaleString()}</td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.families.toLocaleString()}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ── #9 Processing Exception Queue ────────────────────────────────────────
function DcExceptionQueue({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const open = data.processingExceptions.filter(e => e.status !== 'Resolved');
  const resolved = data.processingExceptions.filter(e => e.status === 'Resolved');
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Exception queue — {open.length} open · {resolved.length} resolved</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>File</th><th style={dc.th}>Reason</th><th style={dc.th}>Matter</th><th style={dc.th}>Attempts</th><th style={dc.th}>Status</th><th style={dc.th}></th></tr></thead>
        <tbody>
          {[...open, ...resolved].map(e => (
            <tr key={e.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{e.id}</td>
              <td style={dc.td}>{e.fileName || e.file || '—'}</td>
              <td style={dc.td}>{e.reason}</td>
              <td style={dc.td}>{e.matter}</td>
              <td style={{ ...dc.td, textAlign: 'right', fontFamily: T.font.mono }}>{e.attempts || 0}</td>
              <td style={dc.td}><span style={{ ...dc.tag, background: e.status === 'Resolved' ? dc.emeraldBg : dc.amberBg, color: e.status === 'Resolved' ? dc.emerald : dc.amber }}>{e.status}</span></td>
              <td style={dc.td}>
                {e.status !== 'Resolved' && <>
                  <button style={dc.btnGhost} onClick={() => store.reprocessException(e.id)}>Reprocess</button>
                  <button style={dc.btnGhost} onClick={() => store.resolveException(e.id, 'Manual OCR')}>Mark resolved</button>
                </>}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// ── #10 Review Pane Modal (single-doc coding) ────────────────────────────
function DcReviewPaneModal({ doc, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const [c, setC] = useState(doc.codes || {});
  const toggle = (k) => setC(prev => ({ ...prev, [k]: !prev[k] }));
  const save = () => { store.codeDocument(doc.id, c); onClose && onClose(); };
  return (
    <DcModal title={`Review — ${doc.bates || doc.id}`} subtitle={doc.subject || ''} width={900} onClose={onClose}
      footer={<><button style={dc.btnSecondary} onClick={onClose}>Cancel</button><button style={dc.btnPrimary} onClick={save}>Save coding</button></>}>
      <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '16px' }}>
        <div>
          <div style={{ fontSize: '11px', color: T.color.text.tertiary, marginBottom: '6px' }}>
            From <b>{doc.from}</b> → {(doc.to || []).join(', ')} {doc.cc && doc.cc.length ? '· CC ' + doc.cc.join(', ') : ''} · {doc.date}
          </div>
          <div style={{ padding: '12px', border: `1px solid ${T.color.border.light}`, borderRadius: '6px', background: T.color.bg.secondary, fontSize: '12px', lineHeight: 1.6, whiteSpace: 'pre-wrap', minHeight: '220px' }}>
            {doc.preview || doc.body || '(no preview)'}
          </div>
        </div>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Coding</div>
          {['responsive', 'privileged', 'hot', 'confidential', 'redact'].map(k => (
            <label key={k} style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 8px', borderBottom: `1px solid ${T.color.border.light}`, fontSize: '12px' }}>
              <input type="checkbox" checked={!!c[k]} onChange={() => toggle(k)} />
              <span style={{ textTransform: 'capitalize' }}>{k}</span>
            </label>
          ))}
          <Field label="Issues (comma)">
            <input style={inp} value={(c.issues || []).join(', ')} onChange={e => setC({ ...c, issues: e.target.value.split(',').map(s => s.trim()).filter(Boolean) })} />
          </Field>
        </div>
      </div>
    </DcModal>
  );
}

// ── #11 Privilege Log Builder (hub) ──────────────────────────────────────
function DcPrivilegeLogBuilder({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const [filter, setFilter] = useState('');
  const [form, setForm] = useState({ matterId: '', bates: '', date: '', from: '', to: '', subject: '', basis: 'Attorney-Client', description: '' });
  const entries = data.privilegeEntries.filter(p => !filter || (p.bates + ' ' + p.subject + ' ' + p.from).toLowerCase().includes(filter.toLowerCase()));

  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const add = () => {
    if (!form.bates) return;
    store.addPrivEntry(form);
    setForm({ matterId: form.matterId, bates: '', date: '', from: '', to: '', subject: '', basis: 'Attorney-Client', description: '' });
  };

  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={dc.cardH}>New privilege log entry</div>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: '8px', marginBottom: '8px' }}>
            <input style={inp} placeholder="Matter ID" value={form.matterId} onChange={e => upd('matterId', e.target.value)} />
            <input style={inp} placeholder="Bates range" value={form.bates} onChange={e => upd('bates', e.target.value)} />
            <input style={inp} type="date" value={form.date} onChange={e => upd('date', e.target.value)} />
            <select style={inp} value={form.basis} onChange={e => upd('basis', e.target.value)}>
              <option>Attorney-Client</option><option>Work Product</option><option>Attorney-Client + Work Product</option><option>Joint Defense</option><option>Common Interest</option>
            </select>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: '8px', marginBottom: '8px' }}>
            <input style={inp} placeholder="From" value={form.from} onChange={e => upd('from', e.target.value)} />
            <input style={inp} placeholder="To" value={form.to} onChange={e => upd('to', e.target.value)} />
          </div>
          <input style={{ ...inp, marginBottom: '8px' }} placeholder="Subject" value={form.subject} onChange={e => upd('subject', e.target.value)} />
          <textarea style={ta} placeholder="Description of withheld content (enough to support claim without waiving)" value={form.description} onChange={e => upd('description', e.target.value)} />
          <div style={{ marginTop: '8px', textAlign: 'right' }}><button style={dc.btnPrimary} onClick={add}>Add entry</button></div>
        </div>
      </div>

      <div style={dc.card}>
        <div style={{ ...dc.cardH, gap: '8px' }}>
          <span>Log entries ({entries.length})</span>
          <input style={{ ...inp, width: '220px' }} placeholder="Filter…" value={filter} onChange={e => setFilter(e.target.value)} />
        </div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>Bates</th><th style={dc.th}>Date</th><th style={dc.th}>From</th><th style={dc.th}>To</th><th style={dc.th}>Basis</th><th style={dc.th}>Status</th><th style={dc.th}></th></tr></thead>
          <tbody>
            {entries.map(p => (
              <tr key={p.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{p.bates}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{p.date}</td>
                <td style={dc.td}>{p.from}</td>
                <td style={dc.td}>{p.to}</td>
                <td style={dc.td}><span style={{ ...dc.tag, background: dc.violetBg, color: dc.violet }}>{p.basis}</span></td>
                <td style={dc.td}>{p.status}</td>
                <td style={dc.td}>
                  {p.status !== 'Served' && <button style={dc.btnGhost} onClick={() => store.setPrivStatus(p.id, 'Served')}>Serve</button>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ── #12 TAR Validation Dashboard ─────────────────────────────────────────
function DcTARValidationDashboard({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const [modelId, setModelId] = useState(data.tarModels[0] && data.tarModels[0].id);
  const model = data.tarModels.find(m => m.id === modelId);
  const rounds = data.tarRounds.filter(r => r.modelId === modelId);
  const controls = data.tarControlSets.filter(c => c.modelId === modelId);
  const addRound = () => {
    if (!model) return;
    const last = rounds[0];
    const n = (last ? last.roundNumber || rounds.length : 0) + 1;
    store.runTARRound({
      modelId,
      roundNumber: n,
      docsSampled: 500,
      precision: Math.min(95, (model.precision || 70) + Math.random() * 2),
      recall: Math.min(97, (model.recall || 85) + Math.random() * 1),
      f1: Math.min(93, (model.f1 || 78) + Math.random() * 1.5),
    });
  };

  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={{ padding: '10px 16px', display: 'flex', gap: '10px', alignItems: 'center' }}>
          <span style={{ fontSize: '11px', fontWeight: 700 }}>Model</span>
          <select style={{ ...inp, width: 'auto' }} value={modelId} onChange={e => setModelId(e.target.value)}>
            {data.tarModels.map(m => <option key={m.id} value={m.id}>{m.id} — {m.matter}</option>)}
          </select>
          <button style={dc.btnPrimary} onClick={addRound}>Run validation round</button>
        </div>
      </div>

      {model && (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: '10px', marginBottom: '12px' }}>
          {[['Precision', model.precision, '%'], ['Recall', model.recall, '%'], ['F1', model.f1, ''], ['Rounds', model.trainingRounds, '']].map(([lbl, val, suf]) => (
            <div key={lbl} style={dc.stat}>
              <div style={dc.statLabel}>{lbl}</div>
              <div style={dc.statValue}>{val != null ? val + suf : '—'}</div>
            </div>
          ))}
        </div>
      )}

      <div style={dc.card}>
        <div style={dc.cardH}>Training rounds ({rounds.length})</div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>#</th><th style={dc.th}>Docs sampled</th><th style={dc.th}>Precision</th><th style={dc.th}>Recall</th><th style={dc.th}>F1</th><th style={dc.th}>At</th></tr></thead>
          <tbody>
            {rounds.map(r => (
              <tr key={r.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{r.roundNumber || '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.docsSampled || '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{r.precision != null ? Math.round(r.precision * 10) / 10 + '%' : '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{r.recall != null ? Math.round(r.recall * 10) / 10 + '%' : '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{r.f1 != null ? Math.round(r.f1 * 10) / 10 : '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{(r.runAt || '').slice(0, 10)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div style={dc.card}>
        <div style={dc.cardH}>Control sets — elusion testing ({controls.length})</div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Size</th><th style={dc.th}>Elusion rate</th><th style={dc.th}>Date</th></tr></thead>
          <tbody>
            {controls.map(c => (
              <tr key={c.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{c.id}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{c.size || '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{c.elusionRate != null ? c.elusionRate + '%' : '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{c.createdAt}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ── #13 Redaction Studio ─────────────────────────────────────────────────
function DcRedactionStudioModal({ doc, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const data = store.state;
  const [code, setCode] = useState(data.redactionReasons[0] && data.redactionReasons[0].code);
  const [reds, setReds] = useState(doc.redactions || []);
  const pii = data.piiDetections.filter(d => d.docId === doc.id && d.status !== 'Accepted');
  const add = () => {
    const r = store.addRedaction({ docId: doc.id, reasonCode: code });
    if (r) setReds([...reds, r]);
  };
  const accept = (id) => {
    store.acceptPiiDetection(id);
    setReds(store.state.reviewDocuments.find(d => d.id === doc.id).redactions || []);
  };
  return (
    <DcModal title={`Redaction studio — ${doc.bates || doc.id}`} onClose={onClose} width={820}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Apply redaction</div>
          <Field label="Reason code">
            <select style={inp} value={code} onChange={e => setCode(e.target.value)}>
              {data.redactionReasons.map(r => <option key={r.code} value={r.code}>{r.code} — {r.label}</option>)}
            </select>
          </Field>
          <button style={dc.btnPrimary} onClick={add}>+ Add redaction box</button>

          <div style={{ marginTop: '16px', fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>PII auto-detections ({pii.length})</div>
          {pii.length === 0 && <div style={{ fontSize: '11px', color: T.color.text.tertiary }}>None pending.</div>}
          {pii.map(p => (
            <div key={p.id} style={{ padding: '6px 8px', border: `1px solid ${T.color.border.light}`, borderRadius: '4px', marginBottom: '4px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <span style={{ fontSize: '11px' }}><b>{p.reasonCode}</b> — {p.snippet || p.preview}</span>
              <button style={dc.btnGhost} onClick={() => accept(p.id)}>Accept</button>
            </div>
          ))}
        </div>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Applied redactions ({reds.length})</div>
          {reds.map((r, i) => (
            <div key={r.id} style={{ padding: '6px 8px', borderBottom: `1px solid ${T.color.border.light}`, fontSize: '11px', display: 'flex', justifyContent: 'space-between' }}>
              <span>{i + 1}. <b>{r.reasonCode}</b> {r.reasonLabel && '— ' + r.reasonLabel}</span>
              <span style={{ color: T.color.text.tertiary, fontFamily: T.font.mono, fontSize: '10px' }}>{(r.at || '').slice(11, 19)}</span>
            </div>
          ))}
        </div>
      </div>
    </DcModal>
  );
}

// ── #14 Production Builder ───────────────────────────────────────────────
function DcProductionBuilderModal({ matter, matterId, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const scheme = store.state.batesSchemes.find(s => s.matterId === matterId);
  const [form, setForm] = useState({ docCount: 1000, volumeGB: 4.2, loadFormat: 'Relativity (OPT + DAT)', redactions: 0, privLog: true });
  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const build = () => {
    const p = store.buildProduction({ matter, matterId, ...form });
    setTimeout(() => store.shipProduction(p.id), 300);
    onClose && onClose();
  };
  return (
    <DcModal title="Build production" subtitle={matter} onClose={onClose}
      footer={<><button style={dc.btnSecondary} onClick={onClose}>Cancel</button><button style={dc.btnPrimary} onClick={build}>Build + ship</button></>}>
      {scheme && (
        <div style={{ padding: '10px', background: dc.cobaltBg, borderRadius: '6px', marginBottom: '12px', fontSize: '11px' }}>
          Bates scheme: <b>{scheme.prefix}-{String(scheme.nextNumber).padStart(scheme.pad, '0')}</b> → next. Stamps: {(scheme.confidentialityStamps || []).join(' / ') || '—'}
        </div>
      )}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px' }}>
        <Field label="Doc count"><input style={inp} type="number" value={form.docCount} onChange={e => upd('docCount', +e.target.value)} /></Field>
        <Field label="Volume (GB)"><input style={inp} type="number" step="0.1" value={form.volumeGB} onChange={e => upd('volumeGB', +e.target.value)} /></Field>
      </div>
      <Field label="Load format">
        <select style={inp} value={form.loadFormat} onChange={e => upd('loadFormat', e.target.value)}>
          <option>Relativity (OPT + DAT)</option><option>Concordance + Linked Native</option><option>Native + Load file</option>
        </select>
      </Field>
      <Field label="Redactions"><input style={inp} type="number" value={form.redactions} onChange={e => upd('redactions', +e.target.value)} /></Field>
      <label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '12px' }}>
        <input type="checkbox" checked={form.privLog} onChange={e => upd('privLog', e.target.checked)} /> Include privilege log
      </label>
    </DcModal>
  );
}

// ── #15 Deposition Binder Drawer ─────────────────────────────────────────
function DcDepoBinderDrawer({ depo, onClose }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const binder = store.getDepoBinder(depo.id);
  const [reload, setReload] = useState(0);
  const [item, setItem] = useState('');
  const addOutline = () => {
    if (!item) return;
    store.addDepoOutlineItem(depo.id, { topic: item });
    setItem(''); setReload(reload + 1);
  };
  return (
    <DcModal title={`Depo binder — ${depo.witness}`} subtitle={`${depo.matter} · ${depo.scheduled} · ${depo.location}`} onClose={onClose} width={820}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Outline ({binder.outline.length})</div>
          {binder.outline.map((o, i) => (
            <div key={o.id} style={{ padding: '6px 8px', borderBottom: `1px solid ${T.color.border.light}`, fontSize: '11px' }}>
              {i + 1}. {o.topic}
            </div>
          ))}
          <div style={{ marginTop: '8px', display: 'flex', gap: '6px' }}>
            <input style={inp} placeholder="Add topic…" value={item} onChange={e => setItem(e.target.value)} />
            <button style={dc.btnSecondary} onClick={addOutline}>Add</button>
          </div>
        </div>
        <div>
          <div style={{ fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Proposed exhibits ({binder.hotDocs.length})</div>
          {binder.hotDocs.length === 0 && <div style={{ fontSize: '11px', color: T.color.text.tertiary }}>Attach hot docs from Review → Depo.</div>}
          {binder.hotDocs.map(h => (
            <div key={h.id || h.bates} style={{ padding: '6px 8px', borderBottom: `1px solid ${T.color.border.light}`, fontSize: '11px' }}>
              <span style={{ ...dc.tag, background: dc.amberBg, color: dc.amber, marginRight: '6px' }}>Ex. {h.exhibitNumber}</span>
              <span style={{ fontFamily: T.font.mono }}>{h.bates || h.id}</span>
              {h.subject && <div style={{ color: T.color.text.tertiary, fontSize: '10px' }}>{h.subject}</div>}
            </div>
          ))}

          <div style={{ marginTop: '12px', fontSize: '11px', fontWeight: 700, marginBottom: '6px' }}>Prior statements ({(binder.priorStatements || []).length})</div>
          {(binder.priorStatements || []).length === 0 && <div style={{ fontSize: '11px', color: T.color.text.tertiary }}>None indexed.</div>}
          {(binder.priorStatements || []).map((p, i) => (
            <div key={i} style={{ padding: '4px 8px', fontSize: '11px', borderBottom: `1px solid ${T.color.border.light}` }}>
              <span style={{ fontFamily: T.font.mono }}>{p.source}</span> · {p.excerpt}
            </div>
          ))}
        </div>
      </div>
    </DcModal>
  );
}

// ── #16 Budget Hub ───────────────────────────────────────────────────────
function DcBudgetHub({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const summary = store.budgetSummary();
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: '10px', marginBottom: '12px' }}>
        <div style={dc.stat}><div style={dc.statLabel}>Allocated</div><div style={dc.statValue}>${(summary.allocated / 1_000_000).toFixed(2)}M</div></div>
        <div style={dc.stat}><div style={dc.statLabel}>Spent</div><div style={dc.statValue}>${(summary.spent / 1_000_000).toFixed(2)}M</div></div>
        <div style={dc.stat}><div style={dc.statLabel}>Forecast</div><div style={dc.statValue}>${(summary.forecast / 1_000_000).toFixed(2)}M</div></div>
        <div style={dc.stat}><div style={dc.statLabel}>Burn</div><div style={{ ...dc.statValue, color: summary.burnPct > 80 ? dc.crimson : dc.cobalt }}>{summary.burnPct}%</div></div>
      </div>

      <div style={dc.card}>
        <div style={dc.cardH}>By EDRM phase</div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>Phase</th><th style={dc.th}>Allocated</th><th style={dc.th}>Spent</th><th style={dc.th}>Forecast</th><th style={dc.th}>Variance</th><th style={dc.th}>Burn</th></tr></thead>
          <tbody>
            {data.budgetPhases.map(p => {
              const burn = p.allocated ? Math.round((p.spent / p.allocated) * 1000) / 10 : 0;
              const c = dc.edrmColor(p.phase);
              return (
                <tr key={p.phase}>
                  <td style={dc.td}><span style={{ ...dc.tag, background: c.bg, color: c.color }}>{p.phase}</span></td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(p.allocated / 1000).toFixed(0)}K</td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(p.spent / 1000).toFixed(0)}K</td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(p.forecast / 1000).toFixed(0)}K</td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right', color: p.variance < 0 ? dc.crimson : dc.emerald }}>{p.variance < 0 ? '-' : '+'}${Math.abs(p.variance / 1000).toFixed(0)}K</td>
                  <td style={dc.td}>
                    <div style={{ width: '80px', height: '6px', background: T.color.bg.secondary, borderRadius: '3px' }}>
                      <div style={{ width: Math.min(100, burn) + '%', height: '100%', background: burn > 100 ? dc.crimson : burn > 80 ? dc.amber : dc.cobalt, borderRadius: '3px' }} />
                    </div>
                    <span style={{ fontSize: '10px', fontFamily: T.font.mono, marginLeft: '6px' }}>{burn}%</span>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      <div style={dc.card}>
        <div style={dc.cardH}>Vendors</div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>Vendor</th><th style={dc.th}>Services</th><th style={dc.th}>Matters</th><th style={dc.th}>YTD</th><th style={dc.th}>MTD</th></tr></thead>
          <tbody>
            {data.vendors.map(v => (
              <tr key={v.id || v.name}>
                <td style={{ ...dc.td, fontWeight: 600 }}>{v.name}</td>
                <td style={dc.td}>{(v.services || [v.service]).filter(Boolean).join(', ')}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{v.activeMatters || v.matters || '—'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(((v.ytdSpend != null ? v.ytdSpend : v.committed) || 0) / 1000).toFixed(0)}K</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(((v.mtdSpend != null ? v.mtdSpend : v.spent) || 0) / 1000).toFixed(0)}K</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ── #17 Defensibility Timeline ───────────────────────────────────────────
function DcDefensibilityTimeline({ data }) {
  const dc = window.__dc;
  const matters = Array.from(new Set(data.defensibilityEvents.map(e => e.matter).filter(Boolean)));
  const [matter, setMatter] = useState(matters[0] || '');
  const events = data.defensibilityEvents.filter(e => !matter || e.matter === matter);
  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={{ padding: '10px 16px', display: 'flex', gap: '10px', alignItems: 'center' }}>
          <span style={{ fontSize: '11px', fontWeight: 700 }}>Matter</span>
          <select style={{ ...inp, width: 'auto' }} value={matter} onChange={e => setMatter(e.target.value)}>
            <option value="">All matters</option>
            {matters.map(m => <option key={m} value={m}>{m}</option>)}
          </select>
          <button style={dc.btnSecondary}>Export PDF</button>
        </div>
      </div>

      <div style={{ position: 'relative', paddingLeft: '24px' }}>
        <div style={{ position: 'absolute', left: '10px', top: 0, bottom: 0, width: '2px', background: dc.cobalt + '33' }} />
        {events.map(e => {
          const c = dc.edrmColor(e.phase || 'Process');
          const label = e.event || e.action;
          const when = (e.at || e.date || '').slice(0, 19).replace('T', ' ');
          const extra = e.evidence || e.artifact;
          return (
            <div key={e.id} style={{ position: 'relative', marginBottom: '12px' }}>
              <div style={{ position: 'absolute', left: '-18px', top: '8px', width: '10px', height: '10px', borderRadius: '50%', background: c.color, border: '2px solid #fff', boxShadow: `0 0 0 2px ${c.color}33` }} />
              <div style={{ padding: '10px 14px', background: T.color.bg.card, border: `1px solid ${T.color.border.light}`, borderRadius: '6px' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
                  <span style={{ fontSize: '12px', fontWeight: 700 }}>{label}</span>
                  <span style={{ fontSize: '10px', fontFamily: T.font.mono, color: T.color.text.tertiary }}>{when}</span>
                </div>
                <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
                  <span style={{ ...dc.tag, background: c.bg, color: c.color }}>{e.phase}</span>
                  {e.matter && <span style={{ fontSize: '10px', color: T.color.text.tertiary }}>{e.matter}</span>}
                  {e.actor && <span style={{ fontSize: '10px', color: T.color.text.tertiary }}>· {e.actor}</span>}
                </div>
                {extra && <div style={{ fontSize: '11px', marginTop: '4px', color: T.color.text.secondary, fontFamily: extra.startsWith('PROD') || extra.startsWith('HOLD') || extra.startsWith('BATCH') ? T.font.mono : T.font.family }}>{extra}</div>}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ── Tab stubs for standard tabs (simple list views) ──────────────────────
function DcRequestsTab({ data, onOpen, onPropScore, onMeetConfer }) {
  const dc = window.__dc;
  const [q, setQ] = useState('');
  const reqs = data.requests.filter(r => !q || (r.id + ' ' + r.matter + ' ' + r.type).toLowerCase().includes(q.toLowerCase()));
  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={{ padding: '10px 16px', display: 'flex', gap: '10px' }}>
          <input style={{ ...inp, flex: 1 }} placeholder="Filter requests…" value={q} onChange={e => setQ(e.target.value)} />
        </div>
      </div>
      <div style={dc.card}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Type</th><th style={dc.th}>Matter</th><th style={dc.th}>Direction</th><th style={dc.th}>Due</th><th style={dc.th}>Status</th><th style={dc.th}>Obj.</th><th style={dc.th}></th></tr></thead>
          <tbody>
            {reqs.map(r => {
              const sc = dc.statusColor(r.status);
              return (
                <tr key={r.id}>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 600 }}>{r.id}</td>
                  <td style={dc.td}>{r.type}</td>
                  <td style={dc.td}>{r.matter}</td>
                  <td style={dc.td}>{r.direction}</td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono }}>{r.due}</td>
                  <td style={dc.td}><span style={{ ...dc.tag, background: sc.bg, color: sc.color }}>{r.status}</span></td>
                  <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.objections || 0}</td>
                  <td style={dc.td}>
                    <button style={dc.btnGhost} onClick={() => onOpen && onOpen(r)}>Respond</button>
                    <button style={dc.btnGhost} onClick={() => onPropScore && onPropScore(r)}>Prop.</button>
                    <button style={dc.btnGhost} onClick={() => onMeetConfer && onMeetConfer(r)}>M&C</button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function DcHoldsTab({ data, onIssue, onAckWall }) {
  const dc = window.__dc;
  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={{ padding: '10px 16px' }}>
          <button style={dc.btnPrimary} onClick={onIssue}>+ Issue hold</button>
        </div>
      </div>
      <div style={dc.card}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>Hold</th><th style={dc.th}>Matter</th><th style={dc.th}>Issued</th><th style={dc.th}>Custodians</th><th style={dc.th}>Ack</th><th style={dc.th}>Status</th><th style={dc.th}></th></tr></thead>
          <tbody>
            {data.holds.map(h => (
              <tr key={h.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 600 }}>{h.id}</td>
                <td style={dc.td}>{h.matter}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{h.issuedDate}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{h.custodianCount}</td>
                <td style={dc.td}>
                  <span style={{ fontFamily: T.font.mono, fontSize: '11px' }}>{h.acknowledged}/{h.custodianCount}</span>
                  <div style={{ width: '60px', height: '4px', background: T.color.bg.secondary, borderRadius: '2px', marginTop: '3px' }}>
                    <div style={{ width: h.acknowledgedPct + '%', height: '100%', background: h.acknowledgedPct >= 100 ? dc.emerald : h.acknowledgedPct >= 80 ? dc.amber : dc.crimson, borderRadius: '2px' }} />
                  </div>
                </td>
                <td style={dc.td}><span style={{ ...dc.tag, background: h.status === 'Active' ? dc.cobaltBg : dc.slateBg, color: h.status === 'Active' ? dc.cobalt : dc.slate }}>{h.status}</span></td>
                <td style={dc.td}><button style={dc.btnGhost} onClick={() => onAckWall && onAckWall(h)}>Ack wall</button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function DcCustodiansAugmentedTab({ data, onInterview }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Custodians</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Name</th><th style={dc.th}>Role</th><th style={dc.th}>Matter</th><th style={dc.th}>Hold</th><th style={dc.th}>Interview</th><th style={dc.th}></th></tr></thead>
        <tbody>
          {data.custodians.map(c => {
            const iv = store.interviewForCustodian(c.id);
            return (
              <tr key={c.id}>
                <td style={{ ...dc.td, fontWeight: 600 }}>{c.name}</td>
                <td style={dc.td}>{c.role}</td>
                <td style={dc.td}>{c.matter}</td>
                <td style={dc.td}>{c.holdAcked ? <span style={{ ...dc.tag, background: dc.emeraldBg, color: dc.emerald }}>Acked</span> : <span style={{ ...dc.tag, background: dc.crimsonBg, color: dc.crimson }}>Pending</span>}</td>
                <td style={dc.td}>{iv ? <span style={{ fontSize: '10px', fontFamily: T.font.mono, color: T.color.text.tertiary }}>{iv.completedAt}</span> : <span style={{ fontSize: '10px', color: T.color.text.tertiary }}>—</span>}</td>
                <td style={dc.td}><button style={dc.btnGhost} onClick={() => onInterview && onInterview(c)}>{iv ? 'Re-interview' : 'Interview'}</button></td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function DcReviewQueueTab({ data, onOpenDoc, onRedact }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Review queue — sample documents</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Bates</th><th style={dc.th}>Subject</th><th style={dc.th}>From</th><th style={dc.th}>Date</th><th style={dc.th}>Codes</th><th style={dc.th}></th></tr></thead>
        <tbody>
          {data.reviewDocuments.map(d => {
            const codes = d.codes || {};
            return (
              <tr key={d.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 600 }}>{d.bates}</td>
                <td style={dc.td}>{d.subject}</td>
                <td style={dc.td}>{d.from}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{d.date}</td>
                <td style={dc.td}>
                  {codes.hot && <span style={{ ...dc.tag, background: dc.crimsonBg, color: dc.crimson, marginRight: '4px' }}>HOT</span>}
                  {codes.privileged && <span style={{ ...dc.tag, background: dc.violetBg, color: dc.violet, marginRight: '4px' }}>PRIV</span>}
                  {codes.responsive && <span style={{ ...dc.tag, background: dc.emeraldBg, color: dc.emerald, marginRight: '4px' }}>RESP</span>}
                </td>
                <td style={dc.td}>
                  <button style={dc.btnGhost} onClick={() => onOpenDoc && onOpenDoc(d)}>Code</button>
                  <button style={dc.btnGhost} onClick={() => onRedact && onRedact(d)}>Redact</button>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function DcProductionsAugmentedTab({ data, onBuild }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={{ padding: '10px 16px' }}>
          <button style={dc.btnPrimary} onClick={onBuild}>+ Build production</button>
        </div>
      </div>
      <div style={dc.card}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Matter</th><th style={dc.th}>Bates</th><th style={dc.th}>Docs</th><th style={dc.th}>GB</th><th style={dc.th}>Status</th><th style={dc.th}></th></tr></thead>
          <tbody>
            {data.productions.map(p => (
              <tr key={p.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 600 }}>{p.id}</td>
                <td style={dc.td}>{p.matter}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{p.batesRange}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{p.docCount.toLocaleString()}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{p.volumeGB}</td>
                <td style={dc.td}><span style={{ ...dc.tag, background: p.status === 'Sent' ? dc.emeraldBg : dc.cobaltBg, color: p.status === 'Sent' ? dc.emerald : dc.cobalt }}>{p.status}</span></td>
                <td style={dc.td}>
                  {p.status !== 'Sent' && <button style={dc.btnGhost} onClick={() => store.shipProduction(p.id)}>Ship</button>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function DcDepositionsAugmentedTab({ data, onBinder }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Witness</th><th style={dc.th}>Matter</th><th style={dc.th}>Scheduled</th><th style={dc.th}>Status</th><th style={dc.th}></th></tr></thead>
        <tbody>
          {data.depositions.map(d => (
            <tr key={d.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{d.id}</td>
              <td style={{ ...dc.td, fontWeight: 600 }}>{d.witness}</td>
              <td style={dc.td}>{d.matter}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{d.scheduled}</td>
              <td style={dc.td}>{d.status}</td>
              <td style={dc.td}><button style={dc.btnGhost} onClick={() => onBinder && onBinder(d)}>Binder</button></td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcCollectionsAugmentedTab({ data, onWizard, onChain }) {
  const dc = window.__dc;
  return (
    <div>
      <div style={{ ...dc.card, marginBottom: '12px' }}>
        <div style={{ padding: '10px 16px' }}>
          <button style={dc.btnPrimary} onClick={onWizard}>+ Start collection</button>
        </div>
      </div>
      <div style={dc.card}>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Custodian</th><th style={dc.th}>Matter</th><th style={dc.th}>Vendor</th><th style={dc.th}>Volume</th><th style={dc.th}>Status</th><th style={dc.th}>CoC</th></tr></thead>
          <tbody>
            {data.collections.map(c => (
              <tr key={c.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{c.id}</td>
                <td style={dc.td}>{c.custodian}</td>
                <td style={dc.td}>{c.matter}</td>
                <td style={dc.td}>{c.vendor}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{c.volumeGB ? c.volumeGB + ' GB' : '—'}</td>
                <td style={dc.td}>{c.status}</td>
                <td style={dc.td}><button style={dc.btnGhost} onClick={() => onChain && onChain(c)}>Chain</button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════════════════
// SUB-PLATFORM HUBS — multi-sub-tab pages for dense workflow areas
// ═════════════════════════════════════════════════════════════════════════

function DcSubTabs({ tabs, active, onChange }) {
  const dc = window.__dc;
  return (
    <div style={{ display: 'flex', gap: '0', borderRadius: '6px', border: `1px solid ${T.color.border.light}`, overflow: 'hidden', marginBottom: '12px', width: 'fit-content' }}>
      {tabs.map(t => (
        <button key={t.id} onClick={() => onChange(t.id)} style={{
          padding: '6px 14px', border: 'none', cursor: 'pointer', fontFamily: T.font.family,
          background: active === t.id ? dc.cobalt : T.color.bg.card,
          color: active === t.id ? '#fff' : T.color.text.secondary,
          fontSize: '11px', fontWeight: 600,
          borderRight: `1px solid ${T.color.border.light}`,
        }}>
          {t.label}{t.count != null ? ` (${t.count})` : ''}
        </button>
      ))}
    </div>
  );
}

// ── Shared list helpers ─────────────────────────────────────────────────
function DcObjectionsTab({ data }) {
  const dc = window.__dc;
  const [q, setQ] = useState('');
  const list = data.objectionsLibrary.filter(o => !q || (o.code + ' ' + o.text + ' ' + o.basis).toLowerCase().includes(q.toLowerCase()));
  return (
    <div style={dc.card}>
      <div style={{ ...dc.cardH, gap: '10px' }}>
        <span>Objections Library ({list.length})</span>
        <input style={{ ...inp, width: '260px' }} placeholder="Filter…" value={q} onChange={e => setQ(e.target.value)} />
      </div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Code</th><th style={dc.th}>Category</th><th style={dc.th}>Basis</th><th style={dc.th}>Canonical text</th></tr></thead>
        <tbody>
          {list.map(o => (
            <tr key={o.id}>
              <td style={{ ...dc.td, fontWeight: 700, fontFamily: T.font.mono }}>{o.code}</td>
              <td style={dc.td}><span style={{ ...dc.tag, background: dc.violetBg, color: dc.violet }}>{o.category}</span></td>
              <td style={{ ...dc.td, fontSize: '10px', color: T.color.text.tertiary }}>{o.basis}</td>
              <td style={dc.td}>{o.text}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcMeetConferTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Meet-and-Confer sessions ({data.meetConferSessions.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Matter</th><th style={dc.th}>Scheduled</th><th style={dc.th}>Opposing</th><th style={dc.th}>Status</th><th style={dc.th}>Outcomes</th></tr></thead>
        <tbody>
          {data.meetConferSessions.map(m => (
            <tr key={m.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{m.id}</td>
              <td style={dc.td}>{m.matter}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{(m.scheduled || '').slice(0, 16).replace('T', ' ')}</td>
              <td style={dc.td}>{m.opposingCounsel || '—'}</td>
              <td style={dc.td}><span style={{ ...dc.tag, background: m.status === 'Complete' ? dc.emeraldBg : dc.cobaltBg, color: m.status === 'Complete' ? dc.emerald : dc.cobalt }}>{m.status}</span></td>
              <td style={{ ...dc.td, fontSize: '10px', color: T.color.text.tertiary }}>{(m.outcomes || []).slice(0, 2).join(' · ') || '—'}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcProportionalityTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Proportionality assessments ({data.proportionalityAssessments.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Request</th><th style={dc.th}>Matter</th><th style={dc.th}>Avg</th><th style={dc.th}>Verdict</th><th style={dc.th}>Factors</th></tr></thead>
        <tbody>
          {data.proportionalityAssessments.map(p => {
            const vColor = p.avg >= 3.5 ? dc.emerald : p.avg >= 2.5 ? dc.amber : dc.crimson;
            return (
              <tr key={p.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{p.id}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{p.requestId || '—'}</td>
                <td style={dc.td}>{p.matter}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 700, color: vColor }}>{p.avg}</td>
                <td style={dc.td}><span style={{ ...dc.tag, background: vColor + '22', color: vColor }}>{p.verdict}</span></td>
                <td style={{ ...dc.td, fontSize: '10px', color: T.color.text.tertiary }}>
                  {Object.entries(p.factors || {}).map(([k, v]) => `${k.slice(0, 3)}:${v}`).join(' · ')}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function DcInterviewsTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Custodian interviews ({data.custodianInterviews.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Custodian</th><th style={dc.th}>Matter</th><th style={dc.th}>Date</th><th style={dc.th}>Interviewer</th><th style={dc.th}>Devices</th><th style={dc.th}>Sources</th></tr></thead>
        <tbody>
          {data.custodianInterviews.map(i => (
            <tr key={i.id}>
              <td style={{ ...dc.td, fontWeight: 600 }}>{i.custodianName || i.custodianId}</td>
              <td style={dc.td}>{i.matter}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{i.completedAt || i.date}</td>
              <td style={dc.td}>{i.interviewer}</td>
              <td style={{ ...dc.td, fontSize: '10px' }}>{(i.devicesInUse || []).slice(0, 3).join(', ') || '—'}</td>
              <td style={{ ...dc.td, fontSize: '10px' }}>{(i.potentialSources || []).join(', ') || '—'}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcSourcesTab({ data }) {
  const dc = window.__dc;
  const sourceIndex = {};
  data.custodians.forEach(c => (c.sources || []).forEach(s => {
    if (!sourceIndex[s]) sourceIndex[s] = { source: s, custodians: 0, volumeGB: 0, docCount: 0, matters: new Set() };
    sourceIndex[s].custodians += 1;
    sourceIndex[s].volumeGB += c.volumeGB || 0;
    sourceIndex[s].docCount += c.docCount || 0;
    sourceIndex[s].matters.add(c.matter);
  }));
  const rows = Object.values(sourceIndex).sort((a, b) => b.volumeGB - a.volumeGB);
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Sources & devices — coverage across custodians</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Source</th><th style={dc.th}>Custodians</th><th style={dc.th}>Volume</th><th style={dc.th}>Docs</th><th style={dc.th}>Matters</th></tr></thead>
        <tbody>
          {rows.map(r => (
            <tr key={r.source}>
              <td style={{ ...dc.td, fontWeight: 600 }}>{r.source}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.custodians}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.volumeGB.toFixed(1)} GB</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.docCount.toLocaleString()}</td>
              <td style={{ ...dc.td, fontSize: '10px' }}>{Array.from(r.matters).join(', ')}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcHoldTemplatesTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Hold templates ({data.holdTemplates.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Code</th><th style={dc.th}>Name</th><th style={dc.th}>Sources</th><th style={dc.th}>Scope template</th></tr></thead>
        <tbody>
          {data.holdTemplates.map(t => (
            <tr key={t.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 700 }}>{t.code}</td>
              <td style={{ ...dc.td, fontWeight: 600 }}>{t.name}</td>
              <td style={{ ...dc.td, fontSize: '10px' }}>{(t.sources || []).join(', ')}</td>
              <td style={{ ...dc.td, fontSize: '11px' }}>{t.scopeTemplate}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcHoldAcksTab({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Hold acknowledgments ({data.holdAcknowledgments.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Ack ID</th><th style={dc.th}>Hold</th><th style={dc.th}>Custodian</th><th style={dc.th}>Method</th><th style={dc.th}>At</th></tr></thead>
        <tbody>
          {data.holdAcknowledgments.map(a => {
            const c = store.state.custodians.find(x => x.id === a.custodianId);
            return (
              <tr key={a.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{a.id}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{a.holdId}</td>
                <td style={dc.td}>{c ? c.name : a.custodianId}</td>
                <td style={dc.td}>{a.method || 'Click-through'}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{(a.ackAt || '').slice(0, 19).replace('T', ' ')}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function DcChainOfCustodyTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Chain of custody ledger ({data.chainOfCustody.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Collection</th><th style={dc.th}>Event</th><th style={dc.th}>Actor</th><th style={dc.th}>At</th><th style={dc.th}>Hash (SHA-256)</th></tr></thead>
        <tbody>
          {data.chainOfCustody.map(e => (
            <tr key={e.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{e.collectionId}</td>
              <td style={dc.td}>{e.event}</td>
              <td style={dc.td}>{e.actor}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{(e.at || '').slice(0, 19).replace('T', ' ')}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{e.hash || '—'}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcVendorsTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Vendors ({data.vendors.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Vendor</th><th style={dc.th}>Services</th><th style={dc.th}>Matters</th><th style={dc.th}>Rate</th><th style={dc.th}>SLA</th><th style={dc.th}>YTD</th><th style={dc.th}>MTD</th></tr></thead>
        <tbody>
          {data.vendors.map(v => (
            <tr key={v.id || v.name}>
              <td style={{ ...dc.td, fontWeight: 600 }}>{v.name}</td>
              <td style={{ ...dc.td, fontSize: '10px' }}>{(v.services || [v.service]).filter(Boolean).join(', ')}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{v.activeMatters || v.matters || '—'}</td>
              <td style={{ ...dc.td, fontSize: '10px' }}>{v.rate || '—'}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{v.sla || '—'}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(((v.ytdSpend != null ? v.ytdSpend : v.committed) || 0) / 1000).toFixed(0)}K</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(((v.mtdSpend != null ? v.mtdSpend : v.spent) || 0) / 1000).toFixed(0)}K</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcReviewBatchesTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Review batches ({data.reviewBatches.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Batch</th><th style={dc.th}>Matter</th><th style={dc.th}>Team</th><th style={dc.th}>Progress</th><th style={dc.th}>Rate</th><th style={dc.th}>QC</th><th style={dc.th}>Hot %</th></tr></thead>
        <tbody>
          {data.reviewBatches.map(b => (
            <tr key={b.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 600 }}>{b.id}</td>
              <td style={dc.td}>{b.matter}</td>
              <td style={{ ...dc.td, fontSize: '11px' }}>{b.team}</td>
              <td style={dc.td}>
                <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                  <div style={{ width: '80px', height: '6px', background: T.color.bg.secondary, borderRadius: '3px' }}>
                    <div style={{ width: b.pct + '%', height: '100%', background: dc.cobalt, borderRadius: '3px' }} />
                  </div>
                  <span style={{ fontFamily: T.font.mono, fontSize: '10px' }}>{b.pct}%</span>
                </div>
                <div style={{ fontSize: '10px', color: T.color.text.tertiary, fontFamily: T.font.mono }}>{b.completed.toLocaleString()}/{b.assigned.toLocaleString()}</div>
              </td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{b.rate}/hr</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right', color: b.qcPass >= 97 ? dc.emerald : b.qcPass >= 94 ? dc.amber : dc.crimson }}>{b.qcPass}%</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{b.hotDocRate != null ? b.hotDocRate + '%' : '—'}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcReviewersTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Reviewers ({data.reviewers.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Name</th><th style={dc.th}>Role</th><th style={dc.th}>Matter</th><th style={dc.th}>Docs reviewed</th><th style={dc.th}>Rate</th><th style={dc.th}>QC pass</th><th style={dc.th}>Hot docs</th></tr></thead>
        <tbody>
          {data.reviewers.map(r => (
            <tr key={r.name}>
              <td style={{ ...dc.td, fontWeight: 600 }}>{r.name}</td>
              <td style={dc.td}>{r.role}</td>
              <td style={dc.td}>{r.matter}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.docsReviewed.toLocaleString()}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.rate}/hr</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right', color: r.qcPass >= 97 ? dc.emerald : dc.amber }}>{r.qcPass}%</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{r.hotDocs.toLocaleString()}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcClawbacksTab({ data }) {
  const dc = window.__dc;
  const clawbacks = (data.privilegeLog && data.privilegeLog.clawbacks) || [];
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Clawback notices ({clawbacks.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Matter</th><th style={dc.th}>Bates</th><th style={dc.th}>Reason</th><th style={dc.th}>Notified</th><th style={dc.th}>Ack</th></tr></thead>
        <tbody>
          {clawbacks.map(c => (
            <tr key={c.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{c.id}</td>
              <td style={dc.td}>{c.matter}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{c.bates}</td>
              <td style={dc.td}>{c.reason}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{c.notified}</td>
              <td style={dc.td}>{c.acknowledged ? <span style={{ ...dc.tag, background: dc.emeraldBg, color: dc.emerald }}>Ack {c.ackDate}</span> : <span style={{ ...dc.tag, background: dc.crimsonBg, color: dc.crimson }}>Pending</span>}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcBatesSchemesTab({ data }) {
  const dc = window.__dc;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Bates schemes ({data.batesSchemes.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Matter</th><th style={dc.th}>Prefix</th><th style={dc.th}>Pad</th><th style={dc.th}>Start</th><th style={dc.th}>Next</th><th style={dc.th}>Confidentiality</th></tr></thead>
        <tbody>
          {data.batesSchemes.map(s => (
            <tr key={s.id || s.matterId}>
              <td style={dc.td}>{s.matter || s.matterId}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontWeight: 700 }}>{s.prefix}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{s.pad}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{s.start || s.startNumber || 1}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right', fontWeight: 700, color: dc.cobalt }}>{s.nextNumber}</td>
              <td style={{ ...dc.td, fontSize: '10px' }}>{(s.confidentialityStamps || []).join(' / ') || '—'}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcReceivedProductionsTab({ data }) {
  const dc = window.__dc;
  const received = data.productions.filter(p => p.status === 'Received');
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Productions received from opposing ({received.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>ID</th><th style={dc.th}>Matter</th><th style={dc.th}>Bates</th><th style={dc.th}>Docs</th><th style={dc.th}>Format</th><th style={dc.th}>Received</th></tr></thead>
        <tbody>
          {received.map(p => (
            <tr key={p.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{p.id}</td>
              <td style={dc.td}>{p.matter}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, fontSize: '10px' }}>{p.batesRange}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{p.docCount.toLocaleString()}</td>
              <td style={{ ...dc.td, fontSize: '11px' }}>{p.loadFormat}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{p.sentDate}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcDepoBindersTab({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Deposition binders ({data.depoBinders.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Binder</th><th style={dc.th}>Witness</th><th style={dc.th}>Outline</th><th style={dc.th}>Exhibits</th><th style={dc.th}>Prior statements</th><th style={dc.th}>Exh. start</th></tr></thead>
        <tbody>
          {data.depoBinders.map(b => {
            const depo = store.state.depositions.find(d => d.id === b.depoId);
            return (
              <tr key={b.id}>
                <td style={{ ...dc.td, fontFamily: T.font.mono }}>{b.id}</td>
                <td style={{ ...dc.td, fontWeight: 600 }}>{depo ? depo.witness : b.depoId}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{(b.outline || []).length}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{(b.hotDocs || []).length}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{(b.priorStatements || []).length}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>Ex. {b.proposedExhibitStart}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function DcDesignationsTab({ data }) {
  const dc = window.__dc;
  const taken = data.depositions.filter(d => d.status === 'Taken');
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Designations — transcripts taken ({taken.length})</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Depo</th><th style={dc.th}>Witness</th><th style={dc.th}>Pages</th><th style={dc.th}>Our designations</th><th style={dc.th}>Opp. counter</th><th style={dc.th}>Exhibits</th></tr></thead>
        <tbody>
          {taken.map(d => (
            <tr key={d.id}>
              <td style={{ ...dc.td, fontFamily: T.font.mono }}>{d.id}</td>
              <td style={{ ...dc.td, fontWeight: 600 }}>{d.witness}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{d.transcriptPages || '—'}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{d.designationsOurs != null ? d.designationsOurs : '—'}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{d.designationsOpp != null ? d.designationsOpp : '—'}</td>
              <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{d.exhibits}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DcBudgetByMatterTab({ data }) {
  const dc = window.__dc;
  const store = window.DiscoveryStore;
  const matters = Array.from(new Set(store.state.requests.map(r => r.matter)));
  return (
    <div style={dc.card}>
      <div style={dc.cardH}>Budget by matter (estimate)</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr><th style={dc.th}>Matter</th><th style={dc.th}>Requests</th><th style={dc.th}>Holds</th><th style={dc.th}>Productions</th><th style={dc.th}>Allocated</th><th style={dc.th}>Spent (est)</th></tr></thead>
        <tbody>
          {matters.map(m => {
            const reqs = store.state.requests.filter(r => r.matter === m).length;
            const holds = store.state.holds.filter(h => h.matter === m).length;
            const prods = store.state.productions.filter(p => p.matter === m).length;
            const alloc = Math.round((data.kpis.budgetAllocated / matters.length));
            const spent = Math.round(alloc * (data.kpis.budgetBurnPct / 100));
            return (
              <tr key={m}>
                <td style={{ ...dc.td, fontWeight: 600 }}>{m}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{reqs}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{holds}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>{prods}</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(alloc / 1_000_000).toFixed(2)}M</td>
                <td style={{ ...dc.td, fontFamily: T.font.mono, textAlign: 'right' }}>${(spent / 1_000_000).toFixed(2)}M</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// ── Sub-platform hubs ───────────────────────────────────────────────────
function DcRequestsHub({ data, onOpen, onPropScore, onMeetConfer, onSchedulMC }) {
  const [sub, setSub] = useState('requests');
  const tabs = [
    { id: 'requests',        label: 'Requests',          count: data.requests.length },
    { id: 'objections',      label: 'Objections Library', count: data.objectionsLibrary.length },
    { id: 'meetconfer',      label: 'Meet-and-Confer',   count: data.meetConferSessions.length },
    { id: 'proportionality', label: 'Proportionality',   count: data.proportionalityAssessments.length },
  ];
  const dc = window.__dc;
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' }}>
        <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
        {sub === 'meetconfer' && <button style={dc.btnPrimary} onClick={onSchedulMC}>+ Schedule session</button>}
      </div>
      {sub === 'requests'        && <DcRequestsTab data={data} onOpen={onOpen} onPropScore={onPropScore} onMeetConfer={onMeetConfer} />}
      {sub === 'objections'      && <DcObjectionsTab data={data} />}
      {sub === 'meetconfer'      && <DcMeetConferTab data={data} />}
      {sub === 'proportionality' && <DcProportionalityTab data={data} />}
    </div>
  );
}

function DcCustodiansHub({ data, onInterview }) {
  const [sub, setSub] = useState('directory');
  const tabs = [
    { id: 'directory',  label: 'Directory',          count: data.custodians.length },
    { id: 'interviews', label: 'Interviews',         count: data.custodianInterviews.length },
    { id: 'sources',    label: 'Sources & Devices' },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'directory'  && <DcCustodiansAugmentedTab data={data} onInterview={onInterview} />}
      {sub === 'interviews' && <DcInterviewsTab data={data} />}
      {sub === 'sources'    && <DcSourcesTab data={data} />}
    </div>
  );
}

function DcHoldsHub({ data, onIssue, onAckWall }) {
  const [sub, setSub] = useState('active');
  const tabs = [
    { id: 'active',    label: 'Active',          count: data.holds.filter(h => h.status === 'Active').length },
    { id: 'templates', label: 'Templates',       count: data.holdTemplates.length },
    { id: 'acks',      label: 'Acknowledgments', count: data.holdAcknowledgments.length },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'active'    && <DcHoldsTab data={data} onIssue={onIssue} onAckWall={onAckWall} />}
      {sub === 'templates' && <DcHoldTemplatesTab data={data} />}
      {sub === 'acks'      && <DcHoldAcksTab data={data} />}
    </div>
  );
}

function DcCollectionsHub({ data, onWizard, onChain }) {
  const [sub, setSub] = useState('jobs');
  const tabs = [
    { id: 'jobs',    label: 'Jobs',             count: data.collections.length },
    { id: 'chain',   label: 'Chain of Custody', count: data.chainOfCustody.length },
    { id: 'vendors', label: 'Vendors',          count: data.vendors.length },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'jobs'    && <DcCollectionsAugmentedTab data={data} onWizard={onWizard} onChain={onChain} />}
      {sub === 'chain'   && <DcChainOfCustodyTab data={data} />}
      {sub === 'vendors' && <DcVendorsTab data={data} />}
    </div>
  );
}

function DcReviewHub({ data, onOpenDoc, onRedact }) {
  const [sub, setSub] = useState('queue');
  const tabs = [
    { id: 'queue',      label: 'Queue',      count: data.reviewDocuments.length },
    { id: 'batches',    label: 'Batches',    count: data.reviewBatches.length },
    { id: 'reviewers',  label: 'Reviewers',  count: data.reviewers.length },
    { id: 'clawbacks',  label: 'Clawbacks',  count: (data.privilegeLog && data.privilegeLog.clawbacks || []).length },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'queue'     && <DcReviewQueueTab data={data} onOpenDoc={onOpenDoc} onRedact={onRedact} />}
      {sub === 'batches'   && <DcReviewBatchesTab data={data} />}
      {sub === 'reviewers' && <DcReviewersTab data={data} />}
      {sub === 'clawbacks' && <DcClawbacksTab data={data} />}
    </div>
  );
}

function DcProductionsHub({ data, onBuild }) {
  const [sub, setSub] = useState('outbound');
  const outbound = data.productions.filter(p => p.status !== 'Received').length;
  const received = data.productions.filter(p => p.status === 'Received').length;
  const tabs = [
    { id: 'outbound', label: 'Outbound',      count: outbound },
    { id: 'bates',    label: 'Bates Schemes', count: data.batesSchemes.length },
    { id: 'received', label: 'Received',      count: received },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'outbound' && <DcProductionsAugmentedTab data={data} onBuild={onBuild} />}
      {sub === 'bates'    && <DcBatesSchemesTab data={data} />}
      {sub === 'received' && <DcReceivedProductionsTab data={data} />}
    </div>
  );
}

function DcDepositionsHub({ data, onBinder }) {
  const [sub, setSub] = useState('schedule');
  const taken = data.depositions.filter(d => d.status === 'Taken').length;
  const tabs = [
    { id: 'schedule',     label: 'Schedule',     count: data.depositions.length },
    { id: 'binders',      label: 'Binders',      count: data.depoBinders.length },
    { id: 'designations', label: 'Designations', count: taken },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'schedule'     && <DcDepositionsAugmentedTab data={data} onBinder={onBinder} />}
      {sub === 'binders'      && <DcDepoBindersTab data={data} />}
      {sub === 'designations' && <DcDesignationsTab data={data} />}
    </div>
  );
}

function DcBudgetHubWrapper({ data }) {
  const [sub, setSub] = useState('phases');
  const tabs = [
    { id: 'phases',  label: 'By Phase',  count: data.budgetPhases.length },
    { id: 'vendors', label: 'Vendors',   count: data.vendors.length },
    { id: 'matters', label: 'By Matter' },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'phases'  && <DcBudgetHub data={data} />}
      {sub === 'vendors' && <DcVendorsTab data={data} />}
      {sub === 'matters' && <DcBudgetByMatterTab data={data} />}
    </div>
  );
}

// ── GROUP HUBS (consolidated top-level) ────────────────────────────────
function DcPreservationHub({ data, onInterview, onIssue, onAckWall }) {
  const [sub, setSub] = useState('custodians');
  const tabs = [
    { id: 'custodians', label: 'Custodians', count: data.custodians.length },
    { id: 'holds',      label: 'Legal Holds', count: data.holds.length },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'custodians' && <DcCustodiansHub data={data} onInterview={onInterview} />}
      {sub === 'holds'      && <DcHoldsHub data={data} onIssue={onIssue} onAckWall={onAckWall} />}
    </div>
  );
}

function DcCollectionHub({ data, onWizard, onChain }) {
  const [sub, setSub] = useState('collections');
  const tabs = [
    { id: 'collections', label: 'Collections', count: data.collections.length },
    { id: 'eca',         label: 'Early Case Assessment' },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'collections' && <DcCollectionsHub data={data} onWizard={onWizard} onChain={onChain} />}
      {sub === 'eca'         && <DcECAHub data={data} />}
    </div>
  );
}

function DcReviewAnalyzeHub({ data, onOpenDoc, onRedact }) {
  const [sub, setSub] = useState('processing');
  const tabs = [
    { id: 'processing', label: 'Processing' },
    { id: 'review',     label: 'Review',    count: data.reviewDocuments ? data.reviewDocuments.length : 0 },
    { id: 'privilege',  label: 'Privilege', count: data.privilegeEntries ? data.privilegeEntries.length : 0 },
    { id: 'tar',        label: 'TAR',       count: data.tarRounds ? data.tarRounds.length : 0 },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'processing' && <>
        <DiscoveryProcessing data={data} />
        <DcExceptionQueue data={data} />
      </>}
      {sub === 'review'    && <DcReviewHub data={data} onOpenDoc={onOpenDoc} onRedact={onRedact} />}
      {sub === 'privilege' && <DcPrivilegeLogBuilder data={data} />}
      {sub === 'tar'       && <>
        <DiscoveryTAR data={data} />
        <DcTARValidationDashboard data={data} />
      </>}
    </div>
  );
}

function DcTrialHub({ data, onBinder }) {
  const [sub, setSub] = useState('depositions');
  const tabs = [
    { id: 'depositions', label: 'Depositions', count: data.depositions.length },
    { id: 'disputes',    label: 'Disputes',    count: data.disputes ? data.disputes.length : 0 },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'depositions' && <DcDepositionsHub data={data} onBinder={onBinder} />}
      {sub === 'disputes'    && <DiscoveryDisputes data={data} />}
    </div>
  );
}

function DcOpsHub({ data }) {
  const [sub, setSub] = useState('budget');
  const tabs = [
    { id: 'budget',        label: 'Budget' },
    { id: 'defensibility', label: 'Defensibility', count: data.defensibilityEvents ? data.defensibilityEvents.length : 0 },
    { id: 'activity',      label: 'Activity' },
  ];
  return (
    <div>
      <DcSubTabs tabs={tabs} active={sub} onChange={setSub} />
      {sub === 'budget'        && <DcBudgetHubWrapper data={data} />}
      {sub === 'defensibility' && <DcDefensibilityTimeline data={data} />}
      {sub === 'activity'      && <DiscoveryActivity data={data} />}
    </div>
  );
}

// ── Expose on window ─────────────────────────────────────────────────────
window.DcModal                       = DcModal;
window.DcRequestResponseDrawer       = DcRequestResponseDrawer;
window.DcMeetConferPlannerModal      = DcMeetConferPlannerModal;
window.DcProportionalityModal        = DcProportionalityModal;
window.DcHoldComposerModal           = DcHoldComposerModal;
window.DcHoldAckWall                 = DcHoldAckWall;
window.DcInterviewKitModal           = DcInterviewKitModal;
window.DcCollectionWizardModal       = DcCollectionWizardModal;
window.DcChainOfCustodyPanel         = DcChainOfCustodyPanel;
window.DcECAHub                      = DcECAHub;
window.DcExceptionQueue              = DcExceptionQueue;
window.DcReviewPaneModal             = DcReviewPaneModal;
window.DcPrivilegeLogBuilder         = DcPrivilegeLogBuilder;
window.DcTARValidationDashboard      = DcTARValidationDashboard;
window.DcRedactionStudioModal        = DcRedactionStudioModal;
window.DcProductionBuilderModal      = DcProductionBuilderModal;
window.DcDepoBinderDrawer            = DcDepoBinderDrawer;
window.DcBudgetHub                   = DcBudgetHub;
window.DcDefensibilityTimeline       = DcDefensibilityTimeline;
window.DcRequestsTab                 = DcRequestsTab;
window.DcHoldsTab                    = DcHoldsTab;
window.DcCustodiansAugmentedTab      = DcCustodiansAugmentedTab;
window.DcReviewQueueTab              = DcReviewQueueTab;
window.DcProductionsAugmentedTab     = DcProductionsAugmentedTab;
window.DcDepositionsAugmentedTab     = DcDepositionsAugmentedTab;
window.DcCollectionsAugmentedTab     = DcCollectionsAugmentedTab;

// Sub-tab list views
window.DcSubTabs                     = DcSubTabs;
window.DcObjectionsTab               = DcObjectionsTab;
window.DcMeetConferTab               = DcMeetConferTab;
window.DcProportionalityTab          = DcProportionalityTab;
window.DcInterviewsTab               = DcInterviewsTab;
window.DcSourcesTab                  = DcSourcesTab;
window.DcHoldTemplatesTab            = DcHoldTemplatesTab;
window.DcHoldAcksTab                 = DcHoldAcksTab;
window.DcChainOfCustodyTab           = DcChainOfCustodyTab;
window.DcVendorsTab                  = DcVendorsTab;
window.DcReviewBatchesTab            = DcReviewBatchesTab;
window.DcReviewersTab                = DcReviewersTab;
window.DcClawbacksTab                = DcClawbacksTab;
window.DcBatesSchemesTab             = DcBatesSchemesTab;
window.DcReceivedProductionsTab      = DcReceivedProductionsTab;
window.DcDepoBindersTab              = DcDepoBindersTab;
window.DcDesignationsTab             = DcDesignationsTab;
window.DcBudgetByMatterTab           = DcBudgetByMatterTab;

// Sub-platform hubs
window.DcRequestsHub                 = DcRequestsHub;
window.DcCustodiansHub               = DcCustodiansHub;
window.DcHoldsHub                    = DcHoldsHub;
window.DcCollectionsHub              = DcCollectionsHub;
window.DcReviewHub                   = DcReviewHub;
window.DcProductionsHub              = DcProductionsHub;
window.DcDepositionsHub              = DcDepositionsHub;
window.DcBudgetHubWrapper            = DcBudgetHubWrapper;

// Consolidated group hubs (top-level 8-tab layout)
window.DcPreservationHub             = DcPreservationHub;
window.DcCollectionHub               = DcCollectionHub;
window.DcReviewAnalyzeHub            = DcReviewAnalyzeHub;
window.DcTrialHub                    = DcTrialHub;
window.DcOpsHub                      = DcOpsHub;

})();
