// NEXUS PLATFORM — Graph + Entities tabs
const { useState: useNxGrState, useMemo: useNxGrMemo } = React;
const Tng = window.ArbiterTokens;

function NexusGraph({ data }) {
  const nx = window.__nx;
  const [hovered, setHovered] = useNxGrState(null);
  const [matterFilter, setMatterFilter] = useNxGrState('All');

  const matters = useNxGrMemo(() => ['All', ...new Set(data.entities.map(e => e.matter))], [data]);
  const entities = data.entities.filter(e => matterFilter === 'All' || e.matter === matterFilter);
  const matterLinks = data.links.filter(l => matterFilter === 'All' || l.matter === matterFilter);

  const groups = {};
  entities.forEach(e => { (groups[e.type] = groups[e.type] || []).push(e); });
  const typeOrder = ['person', 'org', 'document', 'event', 'issue', 'artifact'];

  const hoveredLinks = hovered ? matterLinks.filter(l => l.from === hovered || l.to === hovered) : [];
  const connectedIds = new Set(hoveredLinks.flatMap(l => [l.from, l.to]));
  const entityById = useNxGrMemo(() => {
    const m = {}; data.entities.forEach(e => m[e.id] = e); return m;
  }, [data]);

  return (
    <div>
      {/* AI insight */}
      <div style={nx.card}>
        <div style={{ padding: '12px 16px', background: nx.fuchsiaBg, fontSize: '12px', color: Tng.color.text.secondary, lineHeight: 1.6, borderLeft: `3px solid ${nx.fuchsia}` }}>
          <div style={{ fontSize: '10px', fontWeight: 700, color: nx.fuchsia, textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '4px' }}>◆ Nexus AI — Graph Analysis</div>
          Central node: <b>James Harrington</b> (62 links) connects to every key entity — Meridian (CEO), Apex Ventures (sole director), the $14.2M wire total, and every core document. This hub-and-spoke pattern is the cleanest narrative for a jury. Secondary hub: Redstone Capital (88 links) as the plaintiff organizational anchor.
        </div>
      </div>

      {/* Filter */}
      <div style={{ display: 'flex', gap: '8px', marginBottom: '12px', alignItems: 'center' }}>
        <span style={{ fontSize: '10px', textTransform: 'uppercase', letterSpacing: '0.08em', color: Tng.color.text.tertiary, fontWeight: 600 }}>Filter</span>
        <select value={matterFilter} onChange={e => setMatterFilter(e.target.value)}
          style={{ padding: '4px 10px', fontSize: '11px', border: `1px solid ${Tng.color.border.light}`, borderRadius: '5px', background: Tng.color.bg.card, color: Tng.color.text.secondary }}>
          {matters.map(m => <option key={m} value={m}>{m === 'All' ? 'All matters' : m.length > 28 ? m.slice(0, 26) + '…' : m}</option>)}
        </select>
        <div style={{ flex: 1 }} />
        <span style={{ fontSize: '11px', color: Tng.color.text.tertiary }}>{entities.length} entities · {matterLinks.length} links</span>
      </div>

      {/* 6-column entity grid */}
      <div style={{ display: 'grid', gridTemplateColumns: `repeat(${typeOrder.length}, 1fr)`, gap: '10px', marginBottom: '16px' }}>
        {typeOrder.map(type => {
          const list = groups[type] || [];
          const ts = nx.typeStyle(type);
          return (
            <div key={type} style={{ ...nx.card, marginBottom: 0 }}>
              <div style={{ padding: '8px 12px', borderBottom: `1px solid ${Tng.color.border.light}`, display: 'flex', alignItems: 'center', gap: '6px', background: ts.bg }}>
                <span style={{ color: ts.color }}>{ts.icon}</span>
                <span style={{ fontSize: '10px', fontWeight: 700, color: ts.color, textTransform: 'uppercase', letterSpacing: '0.06em' }}>{ts.label}s</span>
                <span style={{ flex: 1 }} />
                <span style={{ fontSize: '10px', fontFamily: Tng.font.mono, color: ts.color }}>{list.length}</span>
              </div>
              {list.map(e => {
                const isHovered = hovered === e.id;
                const isConnected = connectedIds.has(e.id);
                const conn = hoveredLinks.find(l => l.from === e.id || l.to === e.id);
                const ls = conn ? nx.linkStyle(conn.type) : null;
                return (
                  <div key={e.id}
                    onMouseEnter={() => setHovered(e.id)}
                    onMouseLeave={() => setHovered(null)}
                    style={{ padding: '6px 10px', borderBottom: `1px solid ${Tng.color.border.light}`,
                      cursor: 'pointer', transition: 'all 0.15s',
                      background: isHovered ? ts.bg : isConnected ? Tng.color.bg.hover : 'transparent',
                      borderLeft: isConnected ? `3px solid ${ts.color}` : '3px solid transparent' }}>
                    <div style={{ fontSize: '11px', fontWeight: 600, color: isHovered ? ts.color : Tng.color.text.primary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.name}</div>
                    <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '2px', fontSize: '9px', color: Tng.color.text.tertiary }}>
                      <span>{e.linkCount} links</span>
                      {e.priority === 'key' && <span style={{ color: nx.crimson, fontWeight: 700 }}>KEY</span>}
                    </div>
                    {conn && !isHovered && (
                      <div style={{ fontSize: '9px', marginTop: '2px', color: ls.color, fontWeight: 700 }}>
                        {conn.from === e.id ? '→' : '←'} {ls.label}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          );
        })}
      </div>

      {/* Connection list */}
      <div style={nx.card}>
        <div style={nx.cardH}>
          <span>All connections — {matterLinks.length}</span>
          <span style={{ fontSize: '10px', color: Tng.color.text.tertiary }}>hover a card above to filter</span>
        </div>
        <div style={{ maxHeight: '280px', overflowY: 'auto' }}>
          {matterLinks.map(l => {
            const from = entityById[l.from];
            const to = entityById[l.to];
            if (!from || !to) return null;
            const isHighlighted = hovered && (l.from === hovered || l.to === hovered);
            const fromType = nx.typeStyle(from.type);
            const toType = nx.typeStyle(to.type);
            const ls = nx.linkStyle(l.type);
            return (
              <div key={l.id} style={{ padding: '6px 16px', borderBottom: `1px solid ${Tng.color.border.light}`, display: 'flex', alignItems: 'center', gap: '10px', fontSize: '11px', background: isHighlighted ? Tng.color.bg.hover : 'transparent', opacity: hovered && !isHighlighted ? 0.4 : 1 }}>
                <span style={{ fontFamily: Tng.font.mono, fontSize: '10px', color: Tng.color.text.tertiary, minWidth: '50px' }}>{l.id}</span>
                <span style={{ color: fromType.color, fontWeight: 700, minWidth: '180px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{fromType.icon} {from.name}</span>
                <span style={{ color: ls.color, fontStyle: 'italic', flex: 1, textAlign: 'center', fontWeight: 600 }}>— {ls.label} →</span>
                <span style={{ color: toType.color, fontWeight: 700, minWidth: '180px', textAlign: 'right', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{to.name} {toType.icon}</span>
                <div style={{ display: 'flex', gap: '2px', minWidth: '26px' }}>
                  {[1, 2, 3].map(w => (
                    <div key={w} style={{ width: '5px', height: '5px', borderRadius: '50%', background: w <= l.weight ? nx.fuchsia : Tng.color.border.light }} />
                  ))}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function NexusEntities({ data }) {
  const nx = window.__nx;
  const [q, setQ] = useNxGrState('');
  const [typeFilter, setTypeFilter] = useNxGrState('All');
  const [matterFilter, setMatterFilter] = useNxGrState('All');

  const stats = data.entityStats;
  const matters = useNxGrMemo(() => ['All', ...new Set(data.entities.map(e => e.matter))], [data]);
  const types = ['All', 'person', 'org', 'document', 'event', 'issue', 'artifact'];
  const filtered = data.entities.filter(e =>
    (typeFilter === 'All' || e.type === typeFilter) &&
    (matterFilter === 'All' || e.matter === matterFilter) &&
    (!q || e.name.toLowerCase().includes(q.toLowerCase()) || e.summary.toLowerCase().includes(q.toLowerCase()) || (e.aliases || []).some(a => a.toLowerCase().includes(q.toLowerCase())))
  );

  const totalIndexed = stats.byType.reduce((s, t) => s + t.total, 0);
  const totalLinked = stats.byType.reduce((s, t) => s + t.linked, 0);
  const totalOrphans = stats.byType.reduce((s, t) => s + t.orphans, 0);
  const linkedPct = ((totalLinked / totalIndexed) * 100).toFixed(1);
  const monthDelta = stats.growth[stats.growth.length - 1].delta;
  const monthDeltaPct = ((monthDelta / stats.growth[stats.growth.length - 2].count) * 100).toFixed(1);

  // Donut chart math — entity type distribution
  const donutSize = 160, donutStroke = 28, donutR = (donutSize - donutStroke) / 2;
  const donutCircum = 2 * Math.PI * donutR;
  let donutOffset = 0;
  const donutSegments = stats.byType.map(t => {
    const ts = nx.typeStyle(t.type);
    const len = (t.pctOfAll / 100) * donutCircum;
    const seg = { ...t, color: ts.color, icon: ts.icon, label: ts.label, offset: donutOffset, length: len };
    donutOffset += len;
    return seg;
  });

  // Sparkline points for growth
  const maxG = Math.max(...stats.growth.map(g => g.count));
  const minG = Math.min(...stats.growth.map(g => g.count));
  const spw = 320, sph = 60;
  const spPoints = stats.growth.map((g, i) => {
    const x = (i / (stats.growth.length - 1)) * spw;
    const y = sph - ((g.count - minG) / (maxG - minG)) * (sph - 4) - 2;
    return `${x},${y}`;
  }).join(' ');

  const priorityColor = (p) => p === 'key' ? { bg: 'rgba(194,48,48,0.08)', color: nx.crimson }
    : p === 'high' ? { bg: 'rgba(245,158,11,0.08)', color: nx.event }
    : p === 'medium' ? { bg: nx.fuchsiaBg, color: nx.fuchsia }
    : { bg: Tng.color.bg.secondary, color: Tng.color.text.secondary };

  return (
    <div>
      {/* ── TOP KPI STRIP ────────────────────────────────── */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: '12px', marginBottom: '16px' }}>
        <div style={nx.stat}>
          <span style={nx.statLabel}>Indexed entities</span>
          <span style={nx.statValue}>{totalIndexed.toLocaleString()}</span>
          <span style={{ ...nx.statDelta, color: nx.artifact }}>↑ {monthDelta} this month ({monthDeltaPct}%)</span>
        </div>
        <div style={nx.stat}>
          <span style={nx.statLabel}>Linked</span>
          <span style={{ ...nx.statValue, color: nx.fuchsia }}>{totalLinked.toLocaleString()}</span>
          <span style={{ ...nx.statDelta, color: Tng.color.text.tertiary }}>{linkedPct}% of indexed</span>
        </div>
        <div style={nx.stat}>
          <span style={nx.statLabel}>Active links</span>
          <span style={nx.statValue}>{data.kpis.linksActive.toLocaleString()}</span>
          <span style={{ ...nx.statDelta, color: Tng.color.text.tertiary }}>across all matters</span>
        </div>
        <div style={nx.stat}>
          <span style={nx.statLabel}>Key-priority</span>
          <span style={{ ...nx.statValue, color: nx.crimson }}>{stats.priority[0].count}</span>
          <span style={{ ...nx.statDelta, color: Tng.color.text.tertiary }}>{stats.priority[0].pct}% of catalog</span>
        </div>
        <div style={nx.stat}>
          <span style={nx.statLabel}>Orphans</span>
          <span style={{ ...nx.statValue, color: nx.event }}>{totalOrphans}</span>
          <span style={{ ...nx.statDelta, color: Tng.color.text.tertiary }}>&lt; 2 links each</span>
        </div>
        <div style={nx.stat}>
          <span style={nx.statLabel}>Pending canonical merge</span>
          <span style={{ ...nx.statValue, color: nx.fuchsia }}>{stats.aliases.pendingReview}</span>
          <span style={{ ...nx.statDelta, color: Tng.color.text.tertiary }}>{stats.aliases.ambiguousNames} ambiguous names</span>
        </div>
      </div>

      {/* ── DONUT + PRIORITY + LEADERBOARD ─────────────── */}
      <div style={{ display: 'grid', gridTemplateColumns: '1.1fr 1fr 1.6fr', gap: '14px', marginBottom: '16px' }}>
        {/* Donut chart — entity type distribution */}
        <div style={{ ...nx.card, marginBottom: 0 }}>
          <div style={nx.cardH}>Distribution by type</div>
          <div style={{ padding: '16px', display: 'flex', alignItems: 'center', gap: '16px' }}>
            <svg width={donutSize} height={donutSize} viewBox={`0 0 ${donutSize} ${donutSize}`}>
              <circle cx={donutSize / 2} cy={donutSize / 2} r={donutR} fill="none" stroke={Tng.color.border.light} strokeWidth={donutStroke} />
              {donutSegments.map(s => (
                <circle key={s.type}
                  cx={donutSize / 2} cy={donutSize / 2} r={donutR}
                  fill="none" stroke={s.color} strokeWidth={donutStroke}
                  strokeDasharray={`${s.length} ${donutCircum}`}
                  strokeDashoffset={-s.offset}
                  transform={`rotate(-90 ${donutSize / 2} ${donutSize / 2})`}
                  style={{ transition: 'stroke-width 0.15s' }} />
              ))}
              <text x={donutSize / 2} y={donutSize / 2 - 4} textAnchor="middle" fontSize="22" fontWeight="700" fill={Tng.color.text.primary} fontFamily={Tng.font.mono}>{(totalIndexed / 1000).toFixed(1)}K</text>
              <text x={donutSize / 2} y={donutSize / 2 + 16} textAnchor="middle" fontSize="10" fill={Tng.color.text.tertiary} letterSpacing="1.4">ENTITIES</text>
            </svg>
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '4px', fontSize: '11px' }}>
              {donutSegments.map(s => (
                <div key={s.type} style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
                  <span style={{ width: '8px', height: '8px', borderRadius: '50%', background: s.color }} />
                  <span style={{ color: Tng.color.text.primary, flex: 1, fontWeight: 500, textTransform: 'capitalize' }}>{s.label}</span>
                  <span style={{ fontFamily: Tng.font.mono, color: s.color, fontWeight: 700, minWidth: '36px', textAlign: 'right' }}>{s.total}</span>
                  <span style={{ fontFamily: Tng.font.mono, color: Tng.color.text.tertiary, minWidth: '36px', textAlign: 'right' }}>{s.pctOfAll}%</span>
                </div>
              ))}
            </div>
          </div>
        </div>

        {/* Priority + growth sparkline */}
        <div style={{ ...nx.card, marginBottom: 0 }}>
          <div style={nx.cardH}>Priority &amp; trend</div>
          <div style={{ padding: '14px 16px' }}>
            {stats.priority.map(p => {
              const pc = priorityColor(p.level);
              return (
                <div key={p.level} style={{ padding: '5px 0', borderBottom: `1px solid ${Tng.color.border.light}` }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '3px', fontSize: '12px' }}>
                    <span style={{ color: Tng.color.text.primary, fontWeight: 500, textTransform: 'capitalize' }}>{p.level}</span>
                    <span style={{ display: 'flex', gap: '8px' }}>
                      <span style={{ fontFamily: Tng.font.mono, color: pc.color, fontWeight: 700 }}>{p.count.toLocaleString()}</span>
                      <span style={{ fontFamily: Tng.font.mono, color: Tng.color.text.tertiary, minWidth: '36px', textAlign: 'right' }}>{p.pct}%</span>
                    </span>
                  </div>
                  <div style={{ height: '4px', background: Tng.color.border.light, borderRadius: '2px', overflow: 'hidden' }}>
                    <div style={{ width: `${p.pct}%`, height: '100%', background: pc.color }} />
                  </div>
                </div>
              );
            })}
            <div style={{ marginTop: '12px' }}>
              <div style={{ fontSize: '10px', fontWeight: 600, color: Tng.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '6px', display: 'flex', justifyContent: 'space-between' }}>
                <span>12-month growth</span>
                <span style={{ color: nx.fuchsia }}>{stats.growth[0].count.toLocaleString()} → {stats.growth[stats.growth.length - 1].count.toLocaleString()}</span>
              </div>
              <svg width={spw} height={sph} viewBox={`0 0 ${spw} ${sph}`} style={{ width: '100%', height: '60px' }}>
                <polyline fill={`${nx.fuchsia}22`} stroke="none" points={`0,${sph} ${spPoints} ${spw},${sph}`} />
                <polyline fill="none" stroke={nx.fuchsia} strokeWidth="2" points={spPoints} />
                {stats.growth.map((g, i) => {
                  const x = (i / (stats.growth.length - 1)) * spw;
                  const y = sph - ((g.count - minG) / (maxG - minG)) * (sph - 4) - 2;
                  return <circle key={i} cx={x} cy={y} r={i === stats.growth.length - 1 ? 3 : 1.5} fill={nx.fuchsia} />;
                })}
              </svg>
            </div>
          </div>
        </div>

        {/* Top connected entities leaderboard */}
        <div style={{ ...nx.card, marginBottom: 0 }}>
          <div style={nx.cardH}><span>Top-connected entities</span><span style={{ fontSize: '10px', color: Tng.color.text.tertiary }}>by inbound/outbound links</span></div>
          <div>
            {stats.topLinked.map((e, i) => {
              const ts = nx.typeStyle(e.type);
              const max = stats.topLinked[0].links;
              return (
                <div key={e.id} style={{ padding: '6px 16px', borderBottom: i < stats.topLinked.length - 1 ? `1px solid ${Tng.color.border.light}` : 'none', display: 'flex', alignItems: 'center', gap: '10px' }}>
                  <span style={{ fontFamily: Tng.font.mono, fontSize: '10px', color: Tng.color.text.tertiary, minWidth: '18px' }}>{i + 1}</span>
                  <span style={{ color: ts.color, fontSize: '12px' }}>{ts.icon}</span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: '12px', fontWeight: 600, color: Tng.color.text.primary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.name}</div>
                    <div style={{ fontSize: '10px', color: Tng.color.text.tertiary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.matter}</div>
                  </div>
                  <div style={{ width: '90px', height: '4px', background: Tng.color.border.light, borderRadius: '2px', overflow: 'hidden' }}>
                    <div style={{ width: `${(e.links / max) * 100}%`, height: '100%', background: ts.color }} />
                  </div>
                  <span style={{ fontFamily: Tng.font.mono, fontSize: '12px', color: nx.fuchsia, fontWeight: 700, minWidth: '30px', textAlign: 'right' }}>{e.links}</span>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* ── ORPHANS ALERT + ALIASES + MATTER COVERAGE ──── */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1.3fr', gap: '14px', marginBottom: '16px' }}>
        {/* Orphan entities alert */}
        <div style={{ ...nx.card, marginBottom: 0, borderLeft: `3px solid ${nx.event}` }}>
          <div style={{ ...nx.cardH, color: nx.event }}>! Orphan entities — {stats.orphans.total}</div>
          <div style={{ padding: '12px 16px' }}>
            <div style={{ fontSize: '11px', color: Tng.color.text.secondary, lineHeight: 1.55, marginBottom: '10px' }}>
              Entities indexed but with fewer than 2 active links. <b style={{ color: nx.event }}>{stats.orphans.highRelevanceOrphans}</b> are high-relevance documents awaiting canonicalization.
            </div>
            {Object.entries(stats.orphans.byType).map(([type, count]) => {
              const ts = nx.typeStyle(type);
              const pct = (count / stats.orphans.total) * 100;
              return (
                <div key={type} style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '3px 0', fontSize: '11px' }}>
                  <span style={{ color: ts.color }}>{ts.icon}</span>
                  <span style={{ color: Tng.color.text.primary, flex: 1, textTransform: 'capitalize' }}>{ts.label}s</span>
                  <div style={{ width: '60px', height: '4px', background: Tng.color.border.light, borderRadius: '2px', overflow: 'hidden' }}>
                    <div style={{ width: `${pct}%`, height: '100%', background: ts.color }} />
                  </div>
                  <span style={{ fontFamily: Tng.font.mono, color: ts.color, fontWeight: 700, minWidth: '34px', textAlign: 'right' }}>{count}</span>
                </div>
              );
            })}
            <button style={{ ...nx.btnSecondary, width: '100%', marginTop: '10px' }}>Run canonicalization batch →</button>
          </div>
        </div>

        {/* Alias & canonicalization */}
        <div style={{ ...nx.card, marginBottom: 0 }}>
          <div style={nx.cardH}>Alias &amp; canonicalization</div>
          <div style={{ padding: '12px 16px' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '12px' }}>
              <div>
                <div style={{ fontSize: '9px', color: Tng.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Aliases tracked</div>
                <div style={{ fontSize: '20px', fontWeight: 700, color: Tng.color.text.primary, fontFamily: Tng.font.mono }}>{stats.aliases.totalAliases.toLocaleString()}</div>
              </div>
              <div>
                <div style={{ fontSize: '9px', color: Tng.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Auto-merged</div>
                <div style={{ fontSize: '20px', fontWeight: 700, color: nx.artifact, fontFamily: Tng.font.mono }}>{stats.aliases.autoMerged}</div>
              </div>
              <div>
                <div style={{ fontSize: '9px', color: Tng.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Ambiguous</div>
                <div style={{ fontSize: '20px', fontWeight: 700, color: nx.event, fontFamily: Tng.font.mono }}>{stats.aliases.ambiguousNames}</div>
              </div>
              <div>
                <div style={{ fontSize: '9px', color: Tng.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Pending review</div>
                <div style={{ fontSize: '20px', fontWeight: 700, color: nx.crimson, fontFamily: Tng.font.mono }}>{stats.aliases.pendingReview}</div>
              </div>
            </div>
            <div style={{ fontSize: '11px', color: Tng.color.text.secondary, lineHeight: 1.55, padding: '8px 10px', background: nx.fuchsiaBg, borderRadius: '5px', borderLeft: `3px solid ${nx.fuchsia}` }}>
              ◆ AI fuzzy-matcher resolved <b>{stats.aliases.autoMerged}</b> duplicate entities this month. <b>{stats.aliases.pendingReview}</b> require human review.
            </div>
            <button style={{ ...nx.btnPrimary, width: '100%', marginTop: '10px' }}>Review pending merges →</button>
          </div>
        </div>

        {/* Matter coverage */}
        <div style={{ ...nx.card, marginBottom: 0 }}>
          <div style={nx.cardH}><span>Coverage by matter</span><span style={{ fontSize: '10px', color: Tng.color.text.tertiary }}>{stats.byMatter.length} matters</span></div>
          <div>
            {stats.byMatter.map((m, i) => {
              const max = Math.max(...stats.byMatter.map(x => x.total));
              const orphanPct = (m.orphans / m.total) * 100;
              return (
                <div key={m.matter} style={{ padding: '8px 16px', borderBottom: i < stats.byMatter.length - 1 ? `1px solid ${Tng.color.border.light}` : 'none' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px', fontSize: '12px' }}>
                    <span style={{ color: Tng.color.text.primary, fontWeight: 500, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{m.matter}</span>
                    <span style={{ display: 'flex', gap: '8px', fontFamily: Tng.font.mono, fontSize: '10px' }}>
                      <span style={{ color: Tng.color.text.secondary }}>{m.total.toLocaleString()}</span>
                      <span style={{ color: nx.crimson, fontWeight: 700 }}>{m.keyEntities} key</span>
                    </span>
                  </div>
                  <div style={{ display: 'flex', height: '6px', background: Tng.color.border.light, borderRadius: '3px', overflow: 'hidden' }}>
                    <div style={{ width: `${((m.linked - 0) / max) * 100}%`, background: nx.fuchsia }} />
                    <div style={{ width: `${(m.orphans / max) * 100}%`, background: nx.event }} />
                  </div>
                </div>
              );
            })}
            <div style={{ padding: '8px 16px', display: 'flex', gap: '12px', fontSize: '9px', color: Tng.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.06em' }}>
              <span><span style={{ display: 'inline-block', width: '8px', height: '8px', background: nx.fuchsia, borderRadius: '2px', marginRight: '4px' }} />Linked</span>
              <span><span style={{ display: 'inline-block', width: '8px', height: '8px', background: nx.event, borderRadius: '2px', marginRight: '4px' }} />Orphans</span>
            </div>
          </div>
        </div>
      </div>

      {/* ── RECENT ADDITIONS FEED ──────────────────────── */}
      <div style={{ ...nx.card }}>
        <div style={nx.cardH}><span>Recent additions</span><span style={{ fontSize: '10px', color: Tng.color.text.tertiary }}>last 10 · live sync</span></div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '0' }}>
          {stats.recent.map((r, i) => {
            const ts = nx.typeStyle(r.type);
            return (
              <div key={r.id} style={{ padding: '8px 16px', borderBottom: `1px solid ${Tng.color.border.light}`, borderRight: i % 2 === 0 ? `1px solid ${Tng.color.border.light}` : 'none', display: 'flex', alignItems: 'center', gap: '10px' }}>
                <span style={{ color: ts.color, fontSize: '13px' }}>{ts.icon}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: '12px', fontWeight: 600, color: Tng.color.text.primary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.name}</div>
                  <div style={{ fontSize: '10px', color: Tng.color.text.tertiary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.addedBy} · {r.matter}</div>
                </div>
                <span style={{ ...nx.tag, background: ts.bg, color: ts.color }}>{ts.label}</span>
                <span style={{ fontSize: '10px', color: Tng.color.text.tertiary, fontFamily: Tng.font.mono, minWidth: '70px', textAlign: 'right' }}>{r.addedAt}</span>
              </div>
            );
          })}
        </div>
      </div>

      {/* ── FULL CATALOG ───────────────────────────────── */}
      <div style={nx.card}>
        <div style={nx.cardH}>
          <span>Entity catalog — {filtered.length} of {data.entities.length} curated · {totalIndexed.toLocaleString()} in full index</span>
          <div style={{ display: 'flex', gap: '6px' }}>
            <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search entities…"
              style={{ padding: '3px 8px', fontSize: '11px', border: `1px solid ${Tng.color.border.light}`, borderRadius: '5px', background: Tng.color.bg.card, color: Tng.color.text.primary, minWidth: '220px', fontFamily: Tng.font.family }} />
            <select value={typeFilter} onChange={e => setTypeFilter(e.target.value)} style={{ padding: '3px 8px', fontSize: '11px', border: `1px solid ${Tng.color.border.light}`, borderRadius: '5px', background: Tng.color.bg.card, color: Tng.color.text.secondary }}>
              {types.map(t => <option key={t} value={t}>Type: {t}</option>)}
            </select>
            <select value={matterFilter} onChange={e => setMatterFilter(e.target.value)} style={{ padding: '3px 8px', fontSize: '11px', border: `1px solid ${Tng.color.border.light}`, borderRadius: '5px', background: Tng.color.bg.card, color: Tng.color.text.secondary }}>
              {matters.map(m => <option key={m} value={m}>Matter: {m === 'All' ? 'All' : m.length > 20 ? m.slice(0, 18) + '…' : m}</option>)}
            </select>
          </div>
        </div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead>
            <tr>
              <th style={nx.th}>ID</th>
              <th style={nx.th}>Type</th>
              <th style={nx.th}>Name</th>
              <th style={nx.th}>Summary</th>
              <th style={nx.th}>Matter</th>
              <th style={nx.th}>Date range</th>
              <th style={{ ...nx.th, textAlign: 'right' }}>Links</th>
              <th style={nx.th}>Priority</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(e => {
              const ts = nx.typeStyle(e.type);
              const pc = priorityColor(e.priority);
              return (
                <tr key={e.id}>
                  <td style={{ ...nx.td, fontFamily: Tng.font.mono, color: nx.fuchsia, fontWeight: 700, fontSize: '11px' }}>{e.id}</td>
                  <td style={nx.td}><span style={{ ...nx.tag, background: ts.bg, color: ts.color }}>{ts.icon} {ts.label}</span></td>
                  <td style={{ ...nx.td, fontWeight: 600, color: Tng.color.text.primary, maxWidth: '220px' }}>{e.name}</td>
                  <td style={{ ...nx.td, color: Tng.color.text.secondary, fontSize: '11px', maxWidth: '340px' }}>{e.summary}</td>
                  <td style={{ ...nx.td, color: Tng.color.text.secondary, fontSize: '11px', maxWidth: '170px' }}>{e.matter}</td>
                  <td style={{ ...nx.td, fontFamily: Tng.font.mono, fontSize: '11px', color: Tng.color.text.tertiary }}>{e.dateRange || '—'}</td>
                  <td style={{ ...nx.td, textAlign: 'right', fontFamily: Tng.font.mono, color: nx.fuchsia, fontWeight: 700 }}>{e.linkCount}</td>
                  <td style={nx.td}><span style={{ ...nx.tag, background: pc.bg, color: pc.color }}>{e.priority}</span></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

window.NexusGraph = NexusGraph;
window.NexusEntities = NexusEntities;
