// PERSONA PLATFORM — hub sub-platforms + pill sub-nav + CRM contact-perspective
// 6 hubs: Directory · Psychometrics · Network · Documents · CRM · Relationships
const { useState: usePnH, useMemo: usePnHMemo } = React;
const Tpnh = window.ArbiterTokens;

// ── Shared pill sub-nav ────────────────────────────────────────────────────
function PnSubNav({ views, active, onChange }) {
  const pn = window.__pn;
  return (
    <div style={{
      display: 'flex', gap: '4px', padding: '6px',
      background: Tpnh.color.bg.secondary,
      border: `1px solid ${Tpnh.color.border.light}`,
      borderRadius: '8px', marginBottom: '16px', flexWrap: 'wrap',
    }}>
      {views.map(v => {
        const isActive = active === v.id;
        return (
          <button key={v.id} onClick={() => onChange(v.id)} style={{
            padding: '6px 12px', fontSize: '11px',
            fontWeight: isActive ? 700 : 500,
            borderRadius: '6px', border: 'none', cursor: 'pointer',
            background: isActive ? pn.indigo : 'transparent',
            color: isActive ? '#fff' : Tpnh.color.text.secondary,
            display: 'inline-flex', alignItems: 'center', gap: '6px',
            transition: 'all 0.12s', fontFamily: Tpnh.font.family,
          }}>
            {v.label}
            {v.badge != null && (
              <span style={{
                fontSize: '10px', fontWeight: 700,
                padding: '1px 6px', borderRadius: '8px',
                background: isActive ? 'rgba(255,255,255,0.22)' : Tpnh.color.bg.card,
                color: isActive ? '#fff' : Tpnh.color.text.tertiary,
                fontFamily: Tpnh.font.mono,
              }}>{v.badge}</span>
            )}
          </button>
        );
      })}
    </div>
  );
}
window.PnSubNav = PnSubNav;

// Helper: small labeled stat block
function pnStat(pn, label, value, color) {
  return (
    <div style={pn.stat}>
      <div style={pn.statLabel}>{label}</div>
      <div style={{ ...pn.statValue, color: color || Tpnh.color.text.primary }}>{value}</div>
    </div>
  );
}

// ── Directory sub-views ────────────────────────────────────────────────────
function PnDirByType({ data, onSelectPerson }) {
  const pn = window.__pn;
  const groups = {};
  data.people.forEach(p => { (groups[p.type] = groups[p.type] || []).push(p); });
  return (
    <div>
      {Object.entries(groups).map(([type, list]) => {
        const tc = pn.typeColor(type);
        return (
          <div key={type} style={pn.card}>
            <div style={pn.cardH}>
              <span><span style={{ ...pn.tag, background: tc.bg, color: tc.color, marginRight: '8px' }}>{type}</span>{list.length} profile{list.length === 1 ? '' : 's'}</span>
            </div>
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <thead><tr>
                <th style={pn.th}>Name</th><th style={pn.th}>Organization</th>
                <th style={pn.th}>Status</th><th style={pn.th}>Risk</th>
                <th style={pn.th}>Updated</th>
              </tr></thead>
              <tbody>
                {list.map(p => {
                  const rc = pn.riskColor(p.risk);
                  return (
                    <tr key={p.id} style={{ cursor: 'pointer' }}
                      onClick={() => onSelectPerson && onSelectPerson(p.id)}
                      onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                      onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                      <td style={{ ...pn.td, fontWeight: 700 }}>{p.name}</td>
                      <td style={pn.td}>{p.organization}</td>
                      <td style={pn.td}>{p.status}</td>
                      <td style={pn.td}><span style={{ ...pn.tag, background: rc.bg, color: rc.color }}>{p.risk}</span></td>
                      <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px', color: Tpnh.color.text.tertiary }}>{p.lastUpdated}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        );
      })}
    </div>
  );
}
window.PnDirByType = PnDirByType;

function PnDirByRisk({ data, onSelectPerson }) {
  const pn = window.__pn;
  const order = ['Critical','High','Medium','Low'];
  const groups = {};
  data.people.forEach(p => { (groups[p.risk] = groups[p.risk] || []).push(p); });
  return (
    <div>
      {order.filter(r => groups[r]).map(risk => {
        const rc = pn.riskColor(risk);
        return (
          <div key={risk} style={pn.card}>
            <div style={pn.cardH}>
              <span><span style={{ ...pn.tag, background: rc.bg, color: rc.color, marginRight: '8px' }}>{risk}</span>{groups[risk].length} profile{groups[risk].length === 1 ? '' : 's'}</span>
            </div>
            <div style={{ padding: '4px 16px 12px' }}>
              {groups[risk].map(p => (
                <div key={p.id} onClick={() => onSelectPerson && onSelectPerson(p.id)}
                  style={{ padding: '8px 0', borderBottom: `1px solid ${Tpnh.color.border.light}`, cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                  <div>
                    <div style={{ fontSize: '13px', fontWeight: 700, color: Tpnh.color.text.primary }}>{p.name}</div>
                    <div style={{ fontSize: '11px', color: Tpnh.color.text.tertiary }}>{p.type} · {p.organization}</div>
                  </div>
                  <div style={{ fontSize: '11px', color: Tpnh.color.text.tertiary, fontFamily: Tpnh.font.mono }}>{p.status}</div>
                </div>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}
window.PnDirByRisk = PnDirByRisk;

function PnDirByOrg({ data, onSelectPerson }) {
  const pn = window.__pn;
  const orgs = {};
  data.people.forEach(p => { (orgs[p.organization] = orgs[p.organization] || []).push(p); });
  return (
    <div>
      {Object.entries(orgs).map(([org, list]) => (
        <div key={org} style={pn.card}>
          <div style={pn.cardH}>
            <span style={{ fontSize: '13px', fontWeight: 700, color: Tpnh.color.text.primary }}>{org}</span>
            <span style={{ fontSize: '11px', color: Tpnh.color.text.tertiary, fontFamily: Tpnh.font.mono }}>{list.length} contact{list.length === 1 ? '' : 's'}</span>
          </div>
          <div style={{ padding: '4px 16px 12px' }}>
            {list.map(p => {
              const tc = pn.typeColor(p.type);
              return (
                <div key={p.id} onClick={() => onSelectPerson && onSelectPerson(p.id)}
                  style={{ padding: '8px 0', borderBottom: `1px solid ${Tpnh.color.border.light}`, cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '12px' }}>
                  <div>
                    <div style={{ fontSize: '13px', fontWeight: 700, color: Tpnh.color.text.primary }}>{p.name}</div>
                    <div style={{ fontSize: '11px', color: Tpnh.color.text.tertiary }}>{p.title}</div>
                  </div>
                  <span style={{ ...pn.tag, background: tc.bg, color: tc.color }}>{p.type}</span>
                </div>
              );
            })}
          </div>
        </div>
      ))}
    </div>
  );
}
window.PnDirByOrg = PnDirByOrg;

function PnDirRecent({ data, onSelectPerson }) {
  const pn = window.__pn;
  const sorted = [...data.people].sort((a, b) => (b.lastUpdated || '').localeCompare(a.lastUpdated || ''));
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>Recently updated — {sorted.length} profiles</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Name</th><th style={pn.th}>Type</th>
          <th style={pn.th}>Organization</th><th style={pn.th}>Last Updated</th>
        </tr></thead>
        <tbody>
          {sorted.map(p => {
            const tc = pn.typeColor(p.type);
            return (
              <tr key={p.id} style={{ cursor: 'pointer' }}
                onClick={() => onSelectPerson && onSelectPerson(p.id)}
                onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                <td style={{ ...pn.td, fontWeight: 700 }}>{p.name}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: tc.bg, color: tc.color }}>{p.type}</span></td>
                <td style={pn.td}>{p.organization}</td>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px', color: Tpnh.color.text.secondary }}>{p.lastUpdated}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnDirRecent = PnDirRecent;

// ── Psychometrics sub-views ────────────────────────────────────────────────
function PnPsychOcean({ data, onSelectPerson }) {
  const pn = window.__pn;
  const assessed = data.people.filter(p => p.psych);
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>OCEAN — {assessed.length} assessed</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Name</th>
          {pn.oceanTraits.map(t => <th key={t.key} style={{ ...pn.th, textAlign: 'center' }}>{t.label.slice(0, 4)}</th>)}
        </tr></thead>
        <tbody>
          {assessed.map(p => (
            <tr key={p.id} style={{ cursor: 'pointer' }} onClick={() => onSelectPerson && onSelectPerson(p.id)}
              onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
              onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
              <td style={{ ...pn.td, fontWeight: 700 }}>{p.name}</td>
              {pn.oceanTraits.map(t => {
                const v = p.psych.ocean[t.key];
                return (
                  <td key={t.key} style={{ ...pn.td, textAlign: 'center' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '8px', justifyContent: 'center' }}>
                      <div style={{ width: '60px', height: '6px', background: Tpnh.color.bg.secondary, borderRadius: '3px', overflow: 'hidden' }}>
                        <div style={{ width: `${v}%`, height: '100%', background: t.color }} />
                      </div>
                      <span style={{ fontFamily: Tpnh.font.mono, fontSize: '11px', fontWeight: 700, color: t.color, minWidth: '22px' }}>{v}</span>
                    </div>
                  </td>
                );
              })}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
window.PnPsychOcean = PnPsychOcean;

function PnPsychVulnerabilities({ data, onSelectPerson }) {
  const pn = window.__pn;
  const assessed = data.people.filter(p => p.psych && p.psych.vulnerabilities);
  const freq = {};
  assessed.forEach(p => p.psych.vulnerabilities.forEach(v => { freq[v] = (freq[v] || 0) + 1; }));
  const ranked = Object.entries(freq).sort((a,b) => b[1] - a[1]);
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.3fr', gap: '16px' }}>
      <div style={pn.card}>
        <div style={pn.cardH}>Top vulnerability themes</div>
        <div style={{ padding: '8px 16px 16px' }}>
          {ranked.map(([v, n]) => (
            <div key={v} style={{ padding: '8px 0', borderBottom: `1px solid ${Tpnh.color.border.light}` }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
                <span style={{ fontSize: '12px', fontWeight: 600, color: Tpnh.color.text.primary }}>{v}</span>
                <span style={{ fontSize: '11px', fontWeight: 700, color: pn.crimson, fontFamily: Tpnh.font.mono }}>{n}</span>
              </div>
              <div style={{ width: '100%', height: '4px', background: Tpnh.color.bg.secondary, borderRadius: '2px', overflow: 'hidden' }}>
                <div style={{ width: `${(n / assessed.length) * 100}%`, height: '100%', background: pn.crimson }} />
              </div>
            </div>
          ))}
        </div>
      </div>
      <div style={pn.card}>
        <div style={pn.cardH}>By subject — {assessed.length} assessed</div>
        <div style={{ padding: '8px 16px 16px' }}>
          {assessed.map(p => (
            <div key={p.id} onClick={() => onSelectPerson && onSelectPerson(p.id)}
              style={{ padding: '10px 0', borderBottom: `1px solid ${Tpnh.color.border.light}`, cursor: 'pointer' }}>
              <div style={{ fontSize: '12px', fontWeight: 700, color: Tpnh.color.text.primary, marginBottom: '4px' }}>{p.name}</div>
              <div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}>
                {p.psych.vulnerabilities.map(v => (
                  <span key={v} style={{ ...pn.tag, background: pn.crimsonBg, color: pn.crimson }}>{v}</span>
                ))}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
window.PnPsychVulnerabilities = PnPsychVulnerabilities;

function PnPsychAssessments({ data, onSelectPerson }) {
  const pn = window.__pn;
  const [modal, setModal] = React.useState(false);
  const list = data.people.filter(p => p.psych).sort((a,b) => (b.psych.assessedDate || '').localeCompare(a.psych.assessedDate || ''));
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>
        <span>Assessment log — {list.length} records</span>
        <button style={pn.btnPrimary} onClick={() => setModal(true)}>+ Order assessment</button>
      </div>
      {window.PnAssessmentModal && <window.PnAssessmentModal open={modal} onClose={() => setModal(false)} />}
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Subject</th><th style={pn.th}>Type</th>
          <th style={pn.th}>Assessed By</th><th style={pn.th}>Date</th>
          <th style={pn.th}>Status</th>
        </tr></thead>
        <tbody>
          {list.map(p => {
            const tc = pn.typeColor(p.type);
            return (
              <tr key={p.id} style={{ cursor: 'pointer' }} onClick={() => onSelectPerson && onSelectPerson(p.id)}
                onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                <td style={{ ...pn.td, fontWeight: 700 }}>{p.name}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: tc.bg, color: tc.color }}>{p.type}</span></td>
                <td style={{ ...pn.td, fontSize: '11px', color: Tpnh.color.text.secondary }}>{p.psych.assessedBy}</td>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px' }}>{p.psych.assessedDate}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: pn.emeraldBg, color: pn.emerald }}>Complete</span></td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnPsychAssessments = PnPsychAssessments;

// ── Network sub-views ──────────────────────────────────────────────────────
function PnNetAssociations({ data, onSelectPerson }) {
  const pn = window.__pn;
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>Association edges — {data.associations.length} links</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Source</th><th style={pn.th}>Relationship</th>
          <th style={pn.th}>Target</th><th style={pn.th}>Detail</th>
        </tr></thead>
        <tbody>
          {data.associations.map((a, i) => {
            const src = data.people.find(p => p.id === a.source);
            const tgt = data.people.find(p => p.id === a.target);
            return (
              <tr key={i}>
                <td style={{ ...pn.td, fontWeight: 700, cursor: 'pointer', color: pn.indigo }}
                  onClick={() => src && onSelectPerson && onSelectPerson(src.id)}>{src ? src.name : a.source}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: pn.indigoBg, color: pn.indigo }}>{a.type}</span></td>
                <td style={{ ...pn.td, fontWeight: 700, cursor: 'pointer', color: pn.indigo }}
                  onClick={() => tgt && onSelectPerson && onSelectPerson(tgt.id)}>{tgt ? tgt.name : a.target}</td>
                <td style={{ ...pn.td, fontSize: '11px', color: Tpnh.color.text.secondary, lineHeight: 1.5 }}>{a.detail}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnNetAssociations = PnNetAssociations;

function PnNetKeyRelationships({ data, onSelectPerson }) {
  const pn = window.__pn;
  const degree = {};
  data.associations.forEach(a => { degree[a.source] = (degree[a.source] || 0) + 1; degree[a.target] = (degree[a.target] || 0) + 1; });
  const ranked = data.people.map(p => ({ ...p, deg: degree[p.id] || 0 })).sort((a,b) => b.deg - a.deg);
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>Most connected — degree centrality</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Rank</th><th style={pn.th}>Name</th>
          <th style={pn.th}>Type</th><th style={pn.th}>Connections</th>
        </tr></thead>
        <tbody>
          {ranked.map((p, i) => {
            const tc = pn.typeColor(p.type);
            return (
              <tr key={p.id} style={{ cursor: 'pointer' }} onClick={() => onSelectPerson && onSelectPerson(p.id)}
                onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, color: Tpnh.color.text.tertiary }}>#{i+1}</td>
                <td style={{ ...pn.td, fontWeight: 700 }}>{p.name}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: tc.bg, color: tc.color }}>{p.type}</span></td>
                <td style={{ ...pn.td, fontWeight: 700, fontFamily: Tpnh.font.mono, color: pn.indigo }}>{p.deg}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnNetKeyRelationships = PnNetKeyRelationships;

// ── Documents sub-views ────────────────────────────────────────────────────
function PnDocsByType({ data }) {
  const pn = window.__pn;
  const colors = { Legal: pn.indigo, Investigative: pn.violet, 'Grand Jury': pn.crimson, Intelligence: pn.amber, 'Court Order': pn.emerald, Pleading: pn.teal };
  const groups = {};
  data.documents.forEach(d => { (groups[d.type] = groups[d.type] || []).push(d); });
  return (
    <div>
      {Object.entries(groups).map(([type, list]) => {
        const c = colors[type] || pn.slate;
        return (
          <div key={type} style={pn.card}>
            <div style={pn.cardH}>
              <span><span style={{ ...pn.tag, background: `${c}18`, color: c, marginRight: '8px' }}>{type}</span>{list.length} document{list.length === 1 ? '' : 's'}</span>
            </div>
            <div style={{ padding: '4px 16px 12px' }}>
              {list.map(d => {
                const person = data.people.find(p => p.id === d.personId);
                return (
                  <div key={d.id} style={{ padding: '8px 0', borderBottom: `1px solid ${Tpnh.color.border.light}`, display: 'flex', justifyContent: 'space-between' }}>
                    <div>
                      <div style={{ fontSize: '12px', fontWeight: 700, color: Tpnh.color.text.primary }}>{d.title}</div>
                      <div style={{ fontSize: '11px', color: Tpnh.color.text.tertiary }}>{person && person.name}</div>
                    </div>
                    <div style={{ fontSize: '11px', color: Tpnh.color.text.tertiary, fontFamily: Tpnh.font.mono }}>{d.date}</div>
                  </div>
                );
              })}
            </div>
          </div>
        );
      })}
    </div>
  );
}
window.PnDocsByType = PnDocsByType;

function PnDocsRecent({ data }) {
  const pn = window.__pn;
  const colors = { Legal: pn.indigo, Investigative: pn.violet, 'Grand Jury': pn.crimson, Intelligence: pn.amber, 'Court Order': pn.emerald, Pleading: pn.teal };
  const sorted = [...data.documents].sort((a,b) => (b.date || '').localeCompare(a.date || ''));
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>Recent documents — latest {sorted.length}</div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Title</th><th style={pn.th}>Subject</th>
          <th style={pn.th}>Type</th><th style={pn.th}>Date</th>
        </tr></thead>
        <tbody>
          {sorted.map(d => {
            const person = data.people.find(p => p.id === d.personId);
            const c = colors[d.type] || pn.slate;
            return (
              <tr key={d.id}>
                <td style={{ ...pn.td, fontWeight: 700 }}>{d.title}</td>
                <td style={{ ...pn.td, fontSize: '11px' }}>{person && person.name}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: `${c}18`, color: c }}>{d.type}</span></td>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px', color: Tpnh.color.text.secondary }}>{d.date}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnDocsRecent = PnDocsRecent;

// ── CRM sub-views ──────────────────────────────────────────────────────────
function PnCrmPipeline({ data, onSelectPerson }) {
  const pn = window.__pn;
  const stages = data.crmPipeline;
  const byStage = {};
  stages.forEach(s => { byStage[s.key] = []; });
  data.people.forEach(p => {
    const crm = data.crm[p.id];
    if (crm && byStage[crm.stage]) byStage[crm.stage].push({ ...p, crm });
  });
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: `repeat(${stages.length}, minmax(180px, 1fr))`, gap: '12px', overflowX: 'auto' }}>
        {stages.map(s => {
          const list = byStage[s.key] || [];
          const totalValue = list.reduce((a, p) => a + (p.crm.valueEstimate || 0), 0);
          return (
            <div key={s.key} style={{ background: Tpnh.color.bg.card, border: `1px solid ${Tpnh.color.border.light}`, borderRadius: '8px', display: 'flex', flexDirection: 'column' }}>
              <div style={{ padding: '10px 12px', borderBottom: `1px solid ${Tpnh.color.border.light}`, background: Tpnh.color.bg.secondary, borderRadius: '8px 8px 0 0' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                  <span style={{ fontSize: '11px', fontWeight: 700, color: s.color, textTransform: 'uppercase', letterSpacing: '0.08em' }}>{s.label}</span>
                  <span style={{ fontSize: '11px', fontWeight: 700, color: Tpnh.color.text.tertiary, fontFamily: Tpnh.font.mono }}>{list.length}</span>
                </div>
                {totalValue > 0 && (
                  <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, marginTop: '4px', fontFamily: Tpnh.font.mono }}>
                    ${Math.round(totalValue/1000)}k
                  </div>
                )}
              </div>
              <div style={{ padding: '8px', display: 'flex', flexDirection: 'column', gap: '6px', minHeight: '80px' }}>
                {list.map(p => {
                  const tc = pn.typeColor(p.type);
                  return (
                    <div key={p.id} onClick={() => onSelectPerson && onSelectPerson(p.id)}
                      style={{ padding: '8px 10px', background: Tpnh.color.bg.card, border: `1px solid ${Tpnh.color.border.light}`, borderLeft: `3px solid ${s.color}`, borderRadius: '6px', cursor: 'pointer' }}>
                      <div style={{ fontSize: '12px', fontWeight: 700, color: Tpnh.color.text.primary }}>{p.name}</div>
                      <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, marginBottom: '4px' }}>{p.organization}</div>
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                        <span style={{ ...pn.tag, background: tc.bg, color: tc.color, fontSize: '9px' }}>{p.type}</span>
                        {p.crm.valueEstimate > 0 && (
                          <span style={{ fontSize: '10px', fontWeight: 700, color: pn.emerald, fontFamily: Tpnh.font.mono }}>${Math.round(p.crm.valueEstimate/1000)}k</span>
                        )}
                      </div>
                      <div style={{ fontSize: '9px', color: Tpnh.color.text.tertiary, marginTop: '4px', fontFamily: Tpnh.font.mono }}>Next: {p.crm.nextTouch}</div>
                    </div>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}
window.PnCrmPipeline = PnCrmPipeline;

function PnCrmCommunications({ data, onSelectPerson }) {
  const pn = window.__pn;
  const channelColor = { Email: pn.indigo, Phone: pn.emerald, Meeting: pn.violet, 'In-person': pn.teal, Chambers: pn.slate, Event: pn.amber };
  const sentiColor = { Positive: pn.emerald, Neutral: pn.slate, Concerned: pn.amber, Stressed: pn.crimson };
  const sorted = [...data.crmComms].sort((a,b) => (b.when || '').localeCompare(a.when || ''));
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>
        <span>Communication log — {sorted.length} touchpoints</span>
        <button style={pn.btnPrimary}>+ Log interaction</button>
      </div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>When</th>
          <th style={pn.th}>Contact</th>
          <th style={pn.th}>Channel</th>
          <th style={pn.th}>Subject</th>
          <th style={pn.th}>Owner</th>
          <th style={pn.th}>Sentiment</th>
        </tr></thead>
        <tbody>
          {sorted.map(c => {
            const p = data.people.find(x => x.id === c.personId);
            const cc = channelColor[c.channel] || pn.slate;
            const sc = sentiColor[c.sentiment] || pn.slate;
            return (
              <tr key={c.id} style={{ cursor: 'pointer' }} onClick={() => p && onSelectPerson && onSelectPerson(p.id)}
                onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px', whiteSpace: 'nowrap' }}>{c.when}</td>
                <td style={{ ...pn.td, fontWeight: 700 }}>{p ? p.name : '—'}</td>
                <td style={pn.td}>
                  <span style={{ ...pn.tag, background: `${cc}18`, color: cc }}>
                    {c.direction === 'Inbound' ? '← ' : '→ '}{c.channel}
                  </span>
                </td>
                <td style={{ ...pn.td, fontSize: '12px' }}>
                  <div style={{ fontWeight: 600 }}>{c.subject}</div>
                  <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, marginTop: '2px', lineHeight: 1.4, maxWidth: '420px' }}>{c.summary}</div>
                </td>
                <td style={{ ...pn.td, fontSize: '11px', color: Tpnh.color.text.secondary }}>{c.owner}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: `${sc}18`, color: sc }}>{c.sentiment}</span></td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnCrmCommunications = PnCrmCommunications;

function PnCrmTasks({ data, onSelectPerson }) {
  const pn = window.__pn;
  const prioColor = { Critical: pn.crimson, High: pn.orange, Medium: pn.amber, Low: pn.slate };
  const statusColor = { Open: pn.indigo, Overdue: pn.crimson, Completed: pn.emerald };
  const sorted = [...data.crmTasks].sort((a,b) => {
    const rank = { Overdue: 0, Open: 1, Completed: 2 };
    return (rank[a.status] - rank[b.status]) || (a.due || '').localeCompare(b.due || '');
  });
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>
        <span>Follow-up tasks — {sorted.filter(t => t.status !== 'Completed').length} open</span>
        <button style={pn.btnPrimary}>+ New task</button>
      </div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Status</th>
          <th style={pn.th}>Title</th>
          <th style={pn.th}>Contact</th>
          <th style={pn.th}>Due</th>
          <th style={pn.th}>Priority</th>
          <th style={pn.th}>Owner</th>
        </tr></thead>
        <tbody>
          {sorted.map(t => {
            const p = data.people.find(x => x.id === t.personId);
            const pc = prioColor[t.priority] || pn.slate;
            const sc = statusColor[t.status] || pn.slate;
            return (
              <tr key={t.id} style={{ cursor: 'pointer' }} onClick={() => p && onSelectPerson && onSelectPerson(p.id)}
                onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                <td style={pn.td}><span style={{ ...pn.tag, background: `${sc}18`, color: sc }}>{t.status}</span></td>
                <td style={{ ...pn.td, fontWeight: 700 }}>
                  <div>{t.title}</div>
                  <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, marginTop: '2px', fontWeight: 500 }}>{t.type}</div>
                </td>
                <td style={{ ...pn.td, fontSize: '12px' }}>{p ? p.name : '—'}</td>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px', whiteSpace: 'nowrap', color: t.status === 'Overdue' ? pn.crimson : Tpnh.color.text.secondary, fontWeight: t.status === 'Overdue' ? 700 : 500 }}>{t.due}</td>
                <td style={pn.td}><span style={{ ...pn.tag, background: `${pc}18`, color: pc }}>{t.priority}</span></td>
                <td style={{ ...pn.td, fontSize: '11px', color: Tpnh.color.text.secondary }}>{t.owner}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnCrmTasks = PnCrmTasks;

function PnCrmAccounts({ data, onSelectPerson }) {
  const pn = window.__pn;
  const tierColor = { Key: pn.crimson, Strategic: pn.indigo, Referral: pn.teal, Bench: pn.emerald };
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '10px', marginBottom: '16px' }}>
        {pnStat(pn, 'Accounts',       data.crmAccounts.length, pn.indigo)}
        {pnStat(pn, 'Open A/R',       '$' + Math.round(data.crmAccounts.reduce((a,x) => a + x.openArMoney, 0)/1000) + 'k', pn.amber)}
        {pnStat(pn, 'YTD Billed',     '$' + Math.round(data.crmAccounts.reduce((a,x) => a + x.ytdBilled, 0)/1000) + 'k', pn.emerald)}
        {pnStat(pn, 'Active Matters', data.crmAccounts.reduce((a,x) => a + x.matters, 0), pn.violet)}
      </div>
      <div style={pn.card}>
        <div style={pn.cardH}>
          <span>Accounts — {data.crmAccounts.length} organizations</span>
          <button style={pn.btnPrimary}>+ New account</button>
        </div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={pn.th}>Account</th>
            <th style={pn.th}>Industry</th>
            <th style={pn.th}>Tier</th>
            <th style={pn.th}>Contacts</th>
            <th style={pn.th}>Matters</th>
            <th style={pn.th}>Open A/R</th>
            <th style={pn.th}>YTD Billed</th>
            <th style={pn.th}>Owner</th>
          </tr></thead>
          <tbody>
            {data.crmAccounts.map(a => {
              const tc = tierColor[a.tier] || pn.slate;
              return (
                <tr key={a.id} style={{ cursor: 'pointer' }}
                  onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                  onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                  <td style={{ ...pn.td, fontWeight: 700 }}>
                    <div>{a.name}</div>
                    <div style={{ fontSize: '10px', color: pn.indigo, fontFamily: Tpnh.font.mono, marginTop: '2px' }}>{a.id}</div>
                  </td>
                  <td style={{ ...pn.td, fontSize: '11px' }}>{a.industry}</td>
                  <td style={pn.td}><span style={{ ...pn.tag, background: `${tc}18`, color: tc }}>{a.tier}</span></td>
                  <td style={pn.td}>
                    <div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}>
                      {a.peopleIds.map(pid => {
                        const p = data.people.find(x => x.id === pid);
                        if (!p) return null;
                        return (
                          <span key={pid} onClick={(e) => { e.stopPropagation(); onSelectPerson && onSelectPerson(pid); }}
                            style={{ ...pn.tag, background: pn.indigoBg, color: pn.indigo, cursor: 'pointer' }}>
                            {p.name.split(' ').slice(-1)[0]}
                          </span>
                        );
                      })}
                    </div>
                  </td>
                  <td style={{ ...pn.td, fontWeight: 700, fontFamily: Tpnh.font.mono, color: pn.indigo }}>{a.matters}</td>
                  <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontWeight: 700, color: a.openArMoney > 0 ? pn.amber : Tpnh.color.text.tertiary }}>
                    {a.openArMoney > 0 ? '$' + Math.round(a.openArMoney/1000) + 'k' : '—'}
                  </td>
                  <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontWeight: 700, color: a.ytdBilled > 0 ? pn.emerald : Tpnh.color.text.tertiary }}>
                    {a.ytdBilled > 0 ? '$' + Math.round(a.ytdBilled/1000) + 'k' : '—'}
                  </td>
                  <td style={{ ...pn.td, fontSize: '11px', color: Tpnh.color.text.secondary }}>{a.owner}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}
window.PnCrmAccounts = PnCrmAccounts;

function PnCrmEngagement({ data, onSelectPerson }) {
  const pn = window.__pn;
  const stageColor = {};
  data.crmPipeline.forEach(s => { stageColor[s.key] = s.color; });
  const list = data.people.filter(p => data.crm[p.id]).map(p => ({ ...p, crm: data.crm[p.id] })).sort((a,b) => b.crm.engagement - a.crm.engagement);
  const today = '2026-04-21';
  const daysSince = (d) => {
    if (!d) return null;
    const a = new Date(today), b = new Date(d);
    return Math.round((a - b) / 86400000);
  };
  return (
    <div style={pn.card}>
      <div style={pn.cardH}>
        <span>Engagement scoreboard — {list.length} contacts</span>
        <span style={{ fontSize: '11px', color: Tpnh.color.text.tertiary, fontFamily: Tpnh.font.mono }}>Avg {Math.round(list.reduce((a,p) => a + p.crm.engagement, 0)/list.length)} / 100</span>
      </div>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead><tr>
          <th style={pn.th}>Contact</th>
          <th style={pn.th}>Stage</th>
          <th style={pn.th}>Engagement</th>
          <th style={pn.th}>Last Contact</th>
          <th style={pn.th}>Cadence</th>
          <th style={pn.th}>Value</th>
          <th style={pn.th}>Owner</th>
        </tr></thead>
        <tbody>
          {list.map(p => {
            const stage = data.crmPipeline.find(s => s.key === p.crm.stage);
            const since = daysSince(p.crm.lastContact);
            const overdue = since != null && since > p.crm.cadenceDays;
            const engColor = p.crm.engagement >= 75 ? pn.emerald : p.crm.engagement >= 50 ? pn.indigo : p.crm.engagement >= 30 ? pn.amber : pn.crimson;
            return (
              <tr key={p.id} style={{ cursor: 'pointer' }} onClick={() => onSelectPerson && onSelectPerson(p.id)}
                onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                <td style={{ ...pn.td, fontWeight: 700 }}>
                  <div>{p.name}</div>
                  <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, marginTop: '2px', fontWeight: 500 }}>{p.organization}</div>
                </td>
                <td style={pn.td}>{stage && <span style={{ ...pn.tag, background: `${stage.color}18`, color: stage.color }}>{stage.label}</span>}</td>
                <td style={pn.td}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                    <div style={{ width: '80px', height: '6px', background: Tpnh.color.bg.secondary, borderRadius: '3px', overflow: 'hidden' }}>
                      <div style={{ width: `${p.crm.engagement}%`, height: '100%', background: engColor }} />
                    </div>
                    <span style={{ fontSize: '11px', fontWeight: 700, color: engColor, fontFamily: Tpnh.font.mono, minWidth: '24px' }}>{p.crm.engagement}</span>
                  </div>
                </td>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px' }}>
                  {p.crm.lastContact}
                  {since != null && <div style={{ fontSize: '10px', color: overdue ? pn.crimson : Tpnh.color.text.tertiary, fontWeight: overdue ? 700 : 500 }}>{since}d ago</div>}
                </td>
                <td style={{ ...pn.td, fontSize: '11px', color: Tpnh.color.text.secondary }}>{p.crm.cadenceDays}d</td>
                <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontWeight: 700, color: p.crm.valueEstimate > 0 ? pn.emerald : Tpnh.color.text.tertiary }}>
                  {p.crm.valueEstimate > 0 ? '$' + Math.round(p.crm.valueEstimate/1000) + 'k' : '—'}
                </td>
                <td style={{ ...pn.td, fontSize: '11px', color: Tpnh.color.text.secondary }}>{p.crm.owner}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}
window.PnCrmEngagement = PnCrmEngagement;

function PnCrmOverview({ data, onSelectPerson }) {
  const pn = window.__pn;
  const k = data.crmKpis;
  const overdueTasks = data.crmTasks.filter(t => t.status === 'Overdue');
  const recentComms = [...data.crmComms].sort((a,b) => (b.when||'').localeCompare(a.when||'')).slice(0, 5);
  const channelColor = { Email: pn.indigo, Phone: pn.emerald, Meeting: pn.violet, 'In-person': pn.teal, Chambers: pn.slate, Event: pn.amber };
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: '10px', marginBottom: '16px' }}>
        {pnStat(pn, 'Open Pipeline',   k.openPipeline,      pn.indigo)}
        {pnStat(pn, 'MTD Touches',     k.mtdTouches,        pn.violet)}
        {pnStat(pn, 'Avg Engagement',  k.avgEngagement,     pn.emerald)}
        {pnStat(pn, 'Due Follow-ups',  k.dueFollowUps,      pn.crimson)}
        {pnStat(pn, 'Referrals YTD',   k.referralsYtd,      pn.teal)}
        {pnStat(pn, 'Active Accounts', k.activeAccounts,    pn.amber)}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.25fr', gap: '16px' }}>
        <div style={pn.card}>
          <div style={pn.cardH}>
            <span>Overdue & urgent — {overdueTasks.length} tasks</span>
          </div>
          <div style={{ padding: '8px 16px 16px' }}>
            {overdueTasks.length === 0 && <div style={{ fontSize: '12px', color: Tpnh.color.text.tertiary, padding: '10px 0' }}>No overdue tasks.</div>}
            {overdueTasks.map(t => {
              const p = data.people.find(x => x.id === t.personId);
              return (
                <div key={t.id} onClick={() => p && onSelectPerson && onSelectPerson(p.id)}
                  style={{ padding: '10px 0', borderBottom: `1px solid ${Tpnh.color.border.light}`, cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                  <div>
                    <div style={{ fontSize: '12px', fontWeight: 700, color: Tpnh.color.text.primary }}>{t.title}</div>
                    <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, marginTop: '2px' }}>{p && p.name} · {t.owner}</div>
                  </div>
                  <div style={{ fontSize: '11px', color: pn.crimson, fontFamily: Tpnh.font.mono, fontWeight: 700 }}>{t.due}</div>
                </div>
              );
            })}
          </div>
        </div>
        <div style={pn.card}>
          <div style={pn.cardH}>
            <span>Recent touchpoints</span>
          </div>
          <div style={{ padding: '8px 16px 16px' }}>
            {recentComms.map(c => {
              const p = data.people.find(x => x.id === c.personId);
              const cc = channelColor[c.channel] || pn.slate;
              return (
                <div key={c.id} onClick={() => p && onSelectPerson && onSelectPerson(p.id)}
                  style={{ padding: '10px 0', borderBottom: `1px solid ${Tpnh.color.border.light}`, cursor: 'pointer' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '2px' }}>
                    <span style={{ fontSize: '12px', fontWeight: 700, color: Tpnh.color.text.primary }}>{p ? p.name : '—'}</span>
                    <span style={{ ...pn.tag, background: `${cc}18`, color: cc }}>{c.direction === 'Inbound' ? '← ' : '→ '}{c.channel}</span>
                  </div>
                  <div style={{ fontSize: '11px', color: Tpnh.color.text.secondary }}>{c.subject}</div>
                  <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, fontFamily: Tpnh.font.mono, marginTop: '2px' }}>{c.when}</div>
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}
window.PnCrmOverview = PnCrmOverview;

// ── Hub wrappers ───────────────────────────────────────────────────────────
function PnDirectoryHub({ data, onSelectPerson }) {
  const [sub, setSub] = usePnH('all');
  const views = [
    { id: 'all',    label: 'All contacts', badge: data.people.length },
    { id: 'type',   label: 'By type' },
    { id: 'risk',   label: 'By risk' },
    { id: 'org',    label: 'By organization' },
    { id: 'recent', label: 'Recent' },
    { id: 'saved',  label: 'Saved views',   badge: (data.savedViews || []).length },
  ];
  return (
    <div>
      <PnSubNav views={views} active={sub} onChange={setSub} />
      {sub === 'all'    && <PersonaDirectoryTab data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'type'   && <PnDirByType data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'risk'   && <PnDirByRisk data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'org'    && <PnDirByOrg data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'recent' && <PnDirRecent data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'saved'  && window.PnSavedViewsPanel && <window.PnSavedViewsPanel onApply={() => setSub('all')} />}
    </div>
  );
}
window.PnDirectoryHub = PnDirectoryHub;

function PnPsychHub({ data, onSelectPerson }) {
  const [sub, setSub] = usePnH('overview');
  const assessed = data.people.filter(p => p.psych).length;
  const views = [
    { id: 'overview',   label: 'Overview',        badge: assessed },
    { id: 'ocean',      label: 'OCEAN' },
    { id: 'vulns',      label: 'Vulnerabilities' },
    { id: 'assess',     label: 'Assessments' },
    { id: 'cohorts',    label: 'Cohorts',         badge: (data.cohorts || []).length },
  ];
  return (
    <div>
      <PnSubNav views={views} active={sub} onChange={setSub} />
      {sub === 'overview' && <PersonaPsychTab data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'ocean'    && <PnPsychOcean data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'vulns'    && <PnPsychVulnerabilities data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'assess'   && <PnPsychAssessments data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'cohorts'  && window.PnCohortsPanel && <window.PnCohortsPanel onSelectPerson={onSelectPerson} />}
    </div>
  );
}
window.PnPsychHub = PnPsychHub;

function PnNetworkHub({ data, onSelectPerson }) {
  const pn = window.__pn;
  const [sub, setSub] = usePnH('graph');
  const views = [
    { id: 'graph',      label: 'Graph' },
    { id: 'edges',      label: 'Associations', badge: data.associations.length },
    { id: 'key',        label: 'Key relationships' },
    { id: 'centrality', label: 'Centrality' },
    { id: 'conflicts',  label: 'Conflicts',     badge: (data.conflicts || []).filter(c => c.status === 'Active').length },
  ];
  return (
    <div>
      <PnSubNav views={views} active={sub} onChange={setSub} />
      {sub === 'graph' && (
        <div style={{ ...pn.card, marginBottom: 0 }}>
          <div style={pn.cardH}>Network Association Map</div>
          <div style={{ padding: '60px 24px', textAlign: 'center', color: Tpnh.color.text.tertiary }}>
            <div style={{ width: '48px', height: '48px', margin: '0 auto 12px', opacity: 0.35 }}>
              {window.Icons && <window.Icons.Nexus size={48} color={pn.indigo} strokeWidth={1.25} />}
            </div>
            <div style={{ fontSize: '14px', fontWeight: 600, color: Tpnh.color.text.secondary, marginBottom: '6px' }}>Graph Visualization</div>
            <div style={{ fontSize: '12px', marginBottom: '24px' }}>{data.associations.length} association edges across {data.people.length} profiles.</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, auto)', gap: '8px', maxWidth: '500px', margin: '0 auto' }}>
              {data.associations.map((a, i) => {
                const src = data.people.find(p => p.id === a.source);
                const tgt = data.people.find(p => p.id === a.target);
                if (!src || !tgt) return null;
                return (
                  <div key={i} style={{ padding: '10px 14px', background: Tpnh.color.bg.secondary, borderRadius: '6px', border: `1px solid ${Tpnh.color.border.light}`, textAlign: 'left' }}>
                    <div style={{ fontSize: '11px', fontWeight: 700, color: Tpnh.color.text.primary }}>{src.name}</div>
                    <div style={{ fontSize: '10px', color: pn.indigo, fontWeight: 600, margin: '2px 0' }}>→ {a.type}</div>
                    <div style={{ fontSize: '11px', fontWeight: 700, color: Tpnh.color.text.primary }}>{tgt.name}</div>
                    <div style={{ fontSize: '10px', color: Tpnh.color.text.tertiary, marginTop: '4px', lineHeight: 1.4 }}>{a.detail}</div>
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      )}
      {sub === 'edges'      && <PnNetAssociations data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'key'        && <PnNetKeyRelationships data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'centrality' && window.PnCentralityPanel && <window.PnCentralityPanel onSelectPerson={onSelectPerson} />}
      {sub === 'conflicts'  && window.PnConflictsPanel  && <window.PnConflictsPanel />}
    </div>
  );
}
window.PnNetworkHub = PnNetworkHub;

function PnDocumentsHub({ data }) {
  const pn = window.__pn;
  const [sub, setSub] = usePnH('all');
  const views = [
    { id: 'all',    label: 'All documents', badge: data.documents.length },
    { id: 'type',   label: 'By type' },
    { id: 'recent', label: 'Recent' },
  ];
  const allDocs = data.documents;
  const typeColors = { Legal: pn.indigo, Investigative: pn.violet, 'Grand Jury': pn.crimson, Intelligence: pn.amber, 'Court Order': pn.emerald, Pleading: pn.teal };
  return (
    <div>
      <PnSubNav views={views} active={sub} onChange={setSub} />
      {sub === 'all' && (
        <div style={{ ...pn.card, marginBottom: 0 }}>
          <div style={pn.cardH}>
            <span>Linked Documents — {allDocs.length} records</span>
            <button style={pn.btnPrimary}>+ Link document</button>
          </div>
          <table style={{ width: '100%', borderCollapse: 'collapse' }}>
            <thead><tr>
              <th style={pn.th}>Doc ID</th>
              <th style={pn.th}>Title</th>
              <th style={pn.th}>Subject</th>
              <th style={pn.th}>Type</th>
              <th style={pn.th}>Date</th>
            </tr></thead>
            <tbody>
              {allDocs.map(d => {
                const person = data.people.find(p => p.id === d.personId);
                const c = typeColors[d.type] || pn.slate;
                return (
                  <tr key={d.id} style={{ cursor: 'pointer' }}
                    onMouseOver={e => e.currentTarget.style.background = Tpnh.color.bg.secondary}
                    onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                    <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, color: pn.indigo, fontWeight: 700, fontSize: '11px' }}>{d.id}</td>
                    <td style={{ ...pn.td, fontWeight: 600, maxWidth: '320px' }}>{d.title}</td>
                    <td style={pn.td}>
                      {person && <span style={{ ...pn.tag, background: pn.typeColor(person.type).bg, color: pn.typeColor(person.type).color }}>{person.name}</span>}
                    </td>
                    <td style={pn.td}><span style={{ ...pn.tag, background: `${c}18`, color: c }}>{d.type}</span></td>
                    <td style={{ ...pn.td, fontFamily: Tpnh.font.mono, fontSize: '11px', color: Tpnh.color.text.secondary }}>{d.date}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
      {sub === 'type'   && <PnDocsByType data={data} />}
      {sub === 'recent' && <PnDocsRecent data={data} />}
    </div>
  );
}
window.PnDocumentsHub = PnDocumentsHub;

function PnCrmHub({ data, onSelectPerson }) {
  const pn = window.__pn;
  const [sub, setSub] = usePnH('overview');
  const [tpOpen, setTpOpen] = React.useState(false);
  const [taskOpen, setTaskOpen] = React.useState(false);
  const open = data.crmTasks.filter(t => t.status !== 'Completed').length;
  const views = [
    { id: 'overview', label: 'Overview' },
    { id: 'pipeline', label: 'Pipeline',       badge: Object.keys(data.crm).length },
    { id: 'comms',    label: 'Communications', badge: data.crmComms.length },
    { id: 'tasks',    label: 'Tasks',          badge: open },
    { id: 'accounts', label: 'Accounts',       badge: data.crmAccounts.length },
    { id: 'engage',   label: 'Engagement' },
    { id: 'audit',    label: 'Audit',          badge: (data.auditLog || []).length },
  ];
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px', gap: '8px' }}>
        <PnSubNav views={views} active={sub} onChange={setSub} />
        <div style={{ display: 'flex', gap: '6px', flexShrink: 0 }}>
          <button style={pn.btnSecondary} onClick={() => setTpOpen(true)}> Log touchpoint</button>
          <button style={pn.btnPrimary}   onClick={() => setTaskOpen(true)}>+ New task</button>
        </div>
      </div>
      {window.PnTouchpointModal && <window.PnTouchpointModal open={tpOpen}   onClose={() => setTpOpen(false)} />}
      {window.PnTaskModal       && <window.PnTaskModal       open={taskOpen} onClose={() => setTaskOpen(false)} />}
      {sub === 'overview' && <PnCrmOverview       data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'pipeline' && <PnCrmPipeline       data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'comms'    && <PnCrmCommunications data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'tasks'    && <PnCrmTasks          data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'accounts' && <PnCrmAccounts       data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'engage'   && <PnCrmEngagement     data={data} onSelectPerson={onSelectPerson} />}
      {sub === 'audit'    && window.PnAuditTimeline && <window.PnAuditTimeline limit={40} />}
    </div>
  );
}
window.PnCrmHub = PnCrmHub;
