// ============================================================
//   LayoutAttention — the "Action needed" plan, realized.
//
//   Product law: Action needed ROUTES attention. Filters help you
//   INSPECT candidates. Filters do not define what needs attention.
//
//   IA:
//     [ Your candidates ]  [ AI working · N ]      ← two tabs
//
//     Your candidates (default):
//       All / Applied / Sourced            Filters ▾
//       ───────────────────────────────────────────
//       ACTION NEEDED   live unhandled triggers, urgency-sorted
//       ALL CANDIDATES  the funnel/list — filterable, sortable
//
//     AI working: the machine room / trust surface. Sourcing +
//       screening pool. Anything that needs a human GRADUATES into
//       Action needed — you never have to open this tab to find work.
//
//   Action needed is an unhandled-event log, not a smarter Engaged.
//   A candidate appears only on a specific trigger, with a reason and
//   a recommended next action. One dominant reason per row, by the
//   precedence ladder below. Source affects PRIORITY, not membership.
//
//   Rows are navigation only — clicking opens the detail panel, which
//   owns stage changes + actions.
//
//   Reuses globals from LayoutSurfaces.jsx: STAGES, QUALIFIED_TO_COLUMN,
//   AI_STAGES, AI_STATUS.
// ============================================================
const { color: AT } = window.FF;

// ============================================================
//   ACTION NEEDED — spec (kept in lockstep with the discovery note)
//
//   Contains candidates with a LIVE, UNHANDLED, HUMAN-BLOCKING event.
//   Every item carries: trigger timestamp · specific reason · recommended
//   next action · clear condition · expiry/snooze path. (The clear, expiry
//   and snooze affordances live in the detail panel — out of scope for
//   these read-only rows.)
//
//   "Handled" = reply sent · call logged · note added · scheduled ·
//   advanced · rejected · snoozed · dismissed · or a deliberate review
//   decision. Opening the profile does NOT count.
//
//   Clearing is TEAM-WIDE in v1: if anyone on the account handles it, it
//   clears for everyone. "Human-owned" means STAGE-owned, not assignee-
//   owned — there's no assignment concept yet.
//
//   The ladder is PRECEDENCE: if multiple triggers match, show the highest.
//   `sort` orders WITHIN a rung only and never gates membership.
// ============================================================
const AT_FLOOR = 4.0;                                   // job's quality floor (shared by rank 2 + 3)
const AT_HUMAN = new Set(['engaged', 'review', 'interview']);  // human-owned stages
const AT_STALE_N = 4;                                   // days of no-touch before "stale"

// Rung 1 is one tier ("waiting on a human") with three flavors — same
// urgency, but a specific row label + action so a scheduling failure never
// reads as "the candidate is waiting on us."
const AT_WAIT_LABEL  = { candidate:'Waiting on us', system:'Needs your help', decision:'Decision needed' };
const AT_WAIT_ACTION = { candidate:'Reply',         system:'Resolve',        decision:'Decide' };

// One dominant reason per candidate, by precedence. `sort` is ascending,
// WITHIN a rung only:
//   1 waiting  → longest wait first   (−waitAge)
//   2 inbound  → most recent first    (appliedAge) — recency is SORT, not membership
//   3 screened → highest score first  (−score)
//   4 stale    → most overdue first   (−staleDays)
function atTrigger(c) {
  // Handled clears the item outright — a deliberate handling action (reply,
  // call, note, schedule, advance, reject, dismiss, review decision). A new
  // event would re-trigger; opening the profile never counts.
  if (c.handled) return null;
  // 1 — candidate OR system is waiting on a human
  if (AT_HUMAN.has(c.stage) && c.waitingOnUs) {
    const kind = c.waitKind || 'candidate';
    return { rank:1, cat: AT_WAIT_LABEL[kind] || AT_WAIT_LABEL.candidate, reason: c.waitReason || 'Replied — respond now', action: AT_WAIT_ACTION[kind] || 'Reply', sort: -(c.waitAge || 0), age: c.waitAge ? `${c.waitAge}h` : null };
  }
  // 2 — new qualified inbound application, not yet handled (still in 'new').
  //     Membership = applied + clears floor + unhandled. Age ONLY sorts it —
  //     an aged-but-unhandled applicant falls lower, never falls out.
  if (c.stage === 'new' && c.source === 'applied' && (c.score || 0) >= AT_FLOOR)
    return { rank:2, cat:'New application', reason:'New qualified applicant — review & reach out', action:'Review', sort: (c.appliedAge || 0), age: c.appliedAge ? `${c.appliedAge}h` : null };
  // 3 — AI finished screening / newly qualified, awaiting human review
  if (c.stage === 'review')
    return { rank:3, cat:'Screened', reason:'Screened & scored — ready for your review', action:'Review', sort: -(c.score || 0), age: c.screenedAge ? `${c.screenedAge}h` : null };
  // 4 — stale after human ownership (already in a human-owned stage, no touch in N days)
  if (AT_HUMAN.has(c.stage) && (c.staleDays || 0) >= AT_STALE_N)
    return { rank:4, cat:'Stale', reason:`No touch in ${c.staleDays} days — follow up`, action:'Follow up', sort: -(c.staleDays || 0), age: `${c.staleDays}d` };
  return null;
}

// trigger category → accent color. The three rung-1 flavors share one
// (critical) color — same tier, different label.
const AT_CAT = {
  'Waiting on us':   AT.critical[600],
  'Needs your help': AT.critical[600],
  'Decision needed': AT.critical[600],
  'New application': AT.inform[600],
  'Screened':        AT.caution[700],
  'Stale':           AT.shade[600],
};

const atInitials = (name) => name.split(' ').map(s => s[0]).slice(0, 2).join('');

function SourceChip({ source }) {
  const applied = source === 'applied';
  const c = applied ? AT.inform : AT.copilot;
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap:4, flex:'none',
      padding:'1px 7px', borderRadius:9999, fontSize:10, fontWeight:700,
      background: applied ? c[50] : 'transparent',
      color: applied ? c[700] : AT.shade[600],
      border: applied ? `1px solid ${c[50]}` : `1px solid ${AT.tint[100]}`,
    }}>
      {applied ? 'Applied' : '⚡ Sourced'}
    </span>
  );
}
function AttnRow({ c, t, on, onSelect, muted }) {
  const accent = AT_CAT[t.cat] || AT.shade[600];
  return (
    <div onClick={() => onSelect?.(c.id)} style={{
      position:'relative', padding:'12px 18px 12px 16px', borderBottom:`1px solid ${AT.tint[80]}`, cursor:'pointer',
      background: on ? AT.highlight[50] + '66' : (muted ? 'transparent' : '#fff'), display:'flex', alignItems:'center', gap:12,
    }}>
      {on && <div style={{ position:'absolute', left:0, top:0, bottom:0, width:3, background: AT.highlight[500] }}/>}
      <span style={{ width:34, height:34, borderRadius:'50%', background: AT.tint[60], color: AT.shade[820], display:'flex', alignItems:'center', justifyContent:'center', fontSize:12, fontWeight:700, flex:'none', opacity: muted ? 0.75 : 1 }}>{atInitials(c.name)}</span>
      <div style={{ flex:1, minWidth:0 }}>
        <div style={{ display:'flex', alignItems:'center', gap:7, marginBottom:3 }}>
          <span style={{ fontSize:14, fontWeight:700, color: AT.shade[880], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.name}</span>
          <span style={{ fontSize:10.5, color: AT.primary[700], fontWeight:700, flex:'none' }}>★{c.score}</span>
          <SourceChip source={c.source}/>
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:7, minWidth:0 }}>
          <span style={{ flex:'none', fontSize:9.5, fontWeight:800, letterSpacing:'.04em', textTransform:'uppercase', color: accent }}>{t.cat}</span>
          <span style={{ flex:'none', width:3, height:3, borderRadius:'50%', background: AT.tint[100] }}/>
          <span style={{ fontSize:12.5, color: AT.shade[820], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{t.reason}</span>
        </div>
      </div>
      {/* Wait-age: the cost is accruing, and that's the point. */}
      {t.age && (
        <span title="Waiting on a human" style={{
          flex:'none', fontSize:11, fontWeight:700, fontVariantNumeric:'tabular-nums',
          color: t.rank === 1 ? AT.critical[600] : AT.shade[600], minWidth:26, textAlign:'right',
        }}>{t.age}</span>
      )}
      <span style={{ flex:'none', fontSize:11, fontWeight:700, color: AT.shade[800] }}>{t.action} →</span>
    </div>
  );
}

function LayoutAttention({ candidates, selectedId, onSelect }) {
  const [tab, setTab]               = React.useState('mine');   // 'mine' | 'ai'
  const f = useFilterBar();
  const [openStages, setOpenStages] = React.useState(() => new Set(STAGES.map(s => s.key)));
  const [foldOpen, setFoldOpen]       = React.useState(false);  // reveal action items outside the source filter
  const [closedOpen, setClosedOpen]   = React.useState(false);  // the off-ramp, collapsed by default
  // Handling drains the queue. The model is an unhandled-event log, so the
  // demo has to show items LEAVING — a static list reads as a saved filter.
  const [handled, setHandled] = React.useState({});
  const [toast, setToast]     = React.useState(null);
  const handle = (id, t) => {
    const c = candidates.find(x => x.id === id);
    setHandled(h => ({ ...h, [id]: true }));
    setToast(`${(c ? c.name.split(' ')[0] : 'Candidate')} — ${t.action.toLowerCase()} logged`);
    window.clearTimeout(handle._t);
    handle._t = window.setTimeout(() => setToast(null), 2400);
  };

  // The source filter scopes the map (All candidates) AND the queue — but for
  // the queue it FOLDS, never hides: items outside the current source drop into
  // a collapsible group, always one tap from full view. (Product law: a filter
  // must never silently suppress attention.) Stage / My / Unread / Sort are
  // map-only inspection filters. (Name search lives in the app header.)
  const visible = (c) => f.matchSource(c);
  const otherSource = f.source === 'applied' ? 'AI Sourced' : 'Applicant';   // what the fold reveals

  // ---- ACTION NEEDED queue ----
  const sortItems = (arr) => arr.slice().sort((a, b) => a.t.rank - b.t.rank || a.t.sort - b.t.sort || (b.c.score || 0) - (a.c.score || 0));
  const allItems    = candidates.filter(c => !handled[c.id]).map(c => ({ c, t: atTrigger(c) })).filter(x => x.t);
  const visItems    = sortItems(allItems.filter(x => visible(x.c)));
  const foldedItems = sortItems(allItems.filter(x => !visible(x.c)));   // outside the source filter
  const trigIds     = new Set(allItems.map(x => x.c.id));   // lens pills in the funnel

  // ---- ALL CANDIDATES (the funnel / map) ----
  const funnelPool = candidates.filter(c =>
    visible(c) && f.matchSecondary(c) && QUALIFIED_TO_COLUMN[c.stage]);
  const groups = STAGES.map(s => ({
    ...s,
    members: funnelPool.filter(c => QUALIFIED_TO_COLUMN[c.stage] === s.key).slice().sort(f.sortFn),
  }));
  // The off-ramp — a separate state family below the funnel, source-scoped.
  const closedPool = candidates.filter(c => c.stage === 'closed' && visible(c) && f.matchSecondary(c));

  // ---- AI WORKING tab (machine room) ----
  // Only what the AI is still handling on its own. Anyone who's fired an
  // Action-needed trigger has GRADUATED out — they live in the queue now, not
  // here. No dual-presence: AI working means "not yours yet."
  const aiAll     = candidates.filter(c => AI_STAGES.has(c.stage) && !trigIds.has(c.id));
  const aiVisible = aiAll.filter(visible);

  const toggleStage  = (k) => setOpenStages(s => { const n = new Set(s); n.has(k) ? n.delete(k) : n.add(k); return n; });
  const splitLabel = (members) => {
    const a = members.filter(m => m.source === 'applied').length;
    return `${a} applied · ${members.length - a} sourced`;
  };

  return (
    <section data-screen-label="Candidates" style={{ flex:'none', width:460, borderRight:`1px solid ${AT.tint[80]}`, display:'flex', flexDirection:'column', minHeight:'100vh', background:'#fff' }}>
      <style>{`.ff-stagehd:hover{background:${AT.tint[20]}}`}</style>

      {/* ── Tabs: Your candidates · AI working ── */}
      <div style={{ display:'flex', gap:18, padding:'12px 18px 0' }}>
        <TabBtn on={tab === 'mine'} onClick={() => setTab('mine')} label="Your candidates" />
        <TabBtn on={tab === 'ai'}   onClick={() => setTab('ai')}
          label={<span>AI working <span style={{ color: AT.copilot[700], fontWeight:800 }}>· {aiAll.length}</span></span>}
          accent={AT.copilot[600]} dot />
      </div>
      <div style={{ borderBottom:`1px solid ${AT.tint[80]}` }}/>

      {tab === 'ai' ? (
        <AIWorkingTab list={aiVisible} total={aiAll.length} selectedId={selectedId} onSelect={onSelect} />
      ) : (
        <React.Fragment>
          <FilterBar f={f}/>

          <div style={{ flex:1, overflow:'auto', borderTop:`1px solid ${AT.tint[80]}` }}>
            {/* Receipt for the drain — makes "handled" legible. */}
            {toast && (
              <div style={{
                margin:'10px 18px 0', padding:'9px 12px', borderRadius:8, background: AT.shade[880], color:'#fff',
                fontSize:12.5, fontWeight:600, display:'flex', alignItems:'center', gap:8, animation:'at-toast .18s ease',
              }}>
                <style>{`@keyframes at-toast{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}`}</style>
                <span style={{ color: AT.primary[300] || AT.primary[500] }}>✓</span>{toast}
              </div>
            )}

            {/* ─────────── ACTION NEEDED ─────────── */}
            <div style={{ padding:'12px 18px 8px', background: AT.primary[50] + '55' }}>
              <div style={{ display:'flex', alignItems:'baseline', gap:8 }}>
                <span style={{ fontSize:13, fontWeight:800, color: AT.primary[600], textTransform:'uppercase', letterSpacing:'.04em' }}>Action needed</span>
                <span style={{ fontSize:11, fontWeight:800, color:'#fff', background: AT.primary[600], borderRadius:9999, padding:'1px 8px' }}>{visItems.length}</span>
              </div>
            </div>

            {visItems.length === 0 && foldedItems.length === 0 && (
              <div style={{ padding:'44px 24px', textAlign:'center' }}>
                <div style={{
                  width:44, height:44, margin:'0 auto 12px', borderRadius:'50%',
                  background: AT.primary[50], color: AT.primary[600],
                  display:'flex', alignItems:'center', justifyContent:'center', fontSize:20, fontWeight:800,
                }}>✓</div>
                <div style={{ fontSize:15, fontWeight:800, color: AT.shade[880], marginBottom:3 }}>Nothing needs you right now.</div>
                <div style={{ fontSize:12.5, color: AT.shade[600], lineHeight:1.5 }}>
                  You cleared it. New replies, applications and<br/>completed screenings land here as they happen.
                </div>
              </div>
            )}
            {visItems.length === 0 && foldedItems.length > 0 && (
              <div style={{ padding:'18px 24px 4px', textAlign:'center', color: AT.shade[600], fontSize:12.5 }}>
                No {source} action items right now.
              </div>
            )}
            {visItems.map(({ c, t }) => (
              <AttnRow key={c.id} c={c} t={t} on={c.id === selectedId} onSelect={onSelect} />
            ))}

            {/* fold-don't-hide: action items outside the source filter, one tap from full view */}
            {foldedItems.length > 0 && (
              <div style={{ borderBottom:`1px solid ${AT.tint[80]}`, background: AT.tint[20] + '55' }}>
                <button onClick={() => setFoldOpen(o => !o)} aria-expanded={foldOpen} style={{
                  width:'100%', textAlign:'left', display:'flex', alignItems:'center', gap:7,
                  padding:'10px 18px', background:'transparent', border:0, cursor:'pointer',
                  fontSize:11.5, fontWeight:700, color: AT.primary[700],
                }}>
                  <span style={{ fontSize:14, lineHeight:1, width:12, display:'inline-block' }}>{foldOpen ? '–' : '+'}</span>
                  {foldOpen
                    ? `Hide ${foldedItems.length} ${otherSource} action item${foldedItems.length > 1 ? 's' : ''}`
                    : `Show ${foldedItems.length} ${otherSource} action item${foldedItems.length > 1 ? 's' : ''} outside your filter`}
                </button>
                {foldOpen && foldedItems.map(({ c, t }) => (
                  <AttnRow key={c.id} c={c} t={t} on={c.id === selectedId} onSelect={onSelect} muted />
                ))}
              </div>
            )}

            {/* ─────────── ALL CANDIDATES (the funnel / map) ─────────── */}
            <div style={{ padding:'14px 18px 7px', background:'#fff', borderTop:`1px solid ${AT.tint[80]}` }}>
              <div style={{ display:'flex', alignItems:'baseline', gap:8 }}>
                <span style={{ fontSize:13, fontWeight:800, color: AT.shade[820], textTransform:'uppercase', letterSpacing:'.04em' }}>All candidates</span>
                <span style={{ fontSize:11, fontWeight:700, color: AT.shade[600] }}>{funnelPool.length}</span>
                {f.active && <span style={{ fontSize:10.5, color: AT.shade[800], fontWeight:600 }}>· filtered</span>}
              </div>
            </div>

            {groups.map(stage => {
              const open = openStages.has(stage.key);
              return (
                <div key={stage.key}>
                  <button onClick={() => toggleStage(stage.key)} className="ff-stagehd" style={{
                    width:'100%', textAlign:'left', display:'flex', alignItems:'center', gap:9,
                    padding:'11px 18px', background:'transparent', border:0, borderBottom:`1px solid ${AT.tint[60]}`, cursor:'pointer', transition:'background .12s',
                  }}>
                    <span style={{ width:16, height:16, flex:'none', display:'inline-flex', alignItems:'center', justifyContent:'center', borderRadius:4, background: AT.tint[40], color: AT.shade[700], fontSize:12, fontWeight:700, transition:'transform .15s', transform: open ? 'rotate(90deg)' : 'none' }}>›</span>
                    <span style={{ fontSize:11.5, fontWeight:800, letterSpacing:'.04em', textTransform:'uppercase', color: AT.shade[820] }}>{stage.label}</span>
                    <span style={{ fontSize:11, fontWeight:700, color: AT.shade[600], fontVariantNumeric:'tabular-nums' }}>{stage.members.length}</span>
                    {stage.members.length > 0 && <span style={{ fontSize:10.5, color: AT.shade[600] }}>· {splitLabel(stage.members)}</span>}
                  </button>
                  {open && stage.members.map(c => {
                    const on = c.id === selectedId, flag = trigIds.has(c.id);
                    return (
                      <div key={c.id} onClick={() => onSelect?.(c.id)} style={{
                        position:'relative', padding:'9px 18px 9px 30px', borderBottom:`1px solid ${AT.tint[80]}`, cursor:'pointer',
                        background: on ? AT.highlight[50] + '66' : '#fff', display:'flex', alignItems:'center', gap:10,
                      }}>
                        {on && <div style={{ position:'absolute', left:0, top:0, bottom:0, width:3, background: AT.highlight[500] }}/>}
                        <span style={{ width:26, height:26, borderRadius:'50%', background: AT.tint[40], color: AT.shade[700], display:'flex', alignItems:'center', justifyContent:'center', fontSize:10.5, fontWeight:700, flex:'none' }}>{atInitials(c.name)}</span>
                        <div style={{ flex:1, minWidth:0 }}>
                          <div style={{ display:'flex', alignItems:'center', gap:6 }}>
                            <span style={{ fontSize:13.5, fontWeight:700, color: AT.shade[880], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.name}</span>
                            <SourceChip source={c.source}/>
                          </div>
                          <div style={{ fontSize:11.5, color: AT.shade[700], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.role} · {(c.loc||'').split(',')[0]}</div>
                        </div>
                        {flag && (
                          <span title="Also in Action needed" style={{ display:'inline-flex', alignItems:'center', gap:5, flex:'none', padding:'2px 8px 2px 6px', borderRadius:9999, background: AT.primary[50], color: AT.primary[700], fontSize:10.5, fontWeight:700 }}>
                            <span style={{ width:6, height:6, borderRadius:'50%', background: AT.primary[500] }}/>Action needed
                          </span>
                        )}
                      </div>
                    );
                  })}
                  {open && !stage.members.length && <div style={{ padding:'9px 30px', fontSize:11.5, color: AT.shade[600], fontStyle:'italic' }}>Empty</div>}
                </div>
              );
            })}

            {/* CLOSED — the off-ramp, below Hired, collapsed + quiet */}
            <ClosedSection list={closedPool} open={closedOpen} onToggle={() => setClosedOpen(o => !o)} selectedId={selectedId} onSelect={onSelect} />
          </div>
        </React.Fragment>
      )}
    </section>
  );
}

function TabBtn({ on, onClick, label, accent, dot }) {
  const c = accent || AT.primary[600];
  return (
    <button onClick={onClick} style={{
      display:'inline-flex', alignItems:'center', gap:6, padding:'6px 0 12px', background:'transparent',
      border:0, borderBottom:`2px solid ${on ? c : 'transparent'}`, cursor:'pointer',
      fontSize:14, fontWeight:800, color: on ? AT.shade[880] : AT.shade[600], marginBottom:-1,
    }}>
      {dot && <span className="ai-dot" style={{ width:7, height:7, flex:'none' }}/>}
      {label}
    </button>
  );
}
function ClosedSection({ list, open, onToggle, selectedId, onSelect }) {
  if (!list.length) return null;
  const rej = list.filter(c => c.closedReason === 'rejected').length;
  const ni  = list.length - rej;
  return (
    <div style={{ borderTop:`6px solid ${AT.tint[20]}` }}>
      <button onClick={onToggle} aria-expanded={open} className="ff-stagehd" style={{
        width:'100%', textAlign:'left', display:'flex', alignItems:'center', gap:9,
        padding:'11px 18px', background:'transparent', border:0, borderBottom:`1px solid ${AT.tint[60]}`, cursor:'pointer', transition:'background .12s',
      }}>
        <span style={{ width:16, height:16, flex:'none', display:'inline-flex', alignItems:'center', justifyContent:'center', borderRadius:4, background: AT.tint[40], color: AT.shade[600], fontSize:12, fontWeight:700, transition:'transform .15s', transform: open ? 'rotate(90deg)' : 'none' }}>›</span>
        <span style={{ fontSize:11.5, fontWeight:800, letterSpacing:'.04em', textTransform:'uppercase', color: AT.shade[600] }}>Closed</span>
        <span style={{ fontSize:11, fontWeight:700, color: AT.shade[600], fontVariantNumeric:'tabular-nums' }}>{list.length}</span>
        <span style={{ fontSize:10.5, color: AT.shade[600] }}>· {rej} rejected · {ni} not interested</span>
      </button>
      {open && list.map(c => {
        const on = c.id === selectedId, r = AT_CLOSED[c.closedReason] || { label:'Closed', c: AT.shade[600] };
        return (
          <div key={c.id} onClick={() => onSelect?.(c.id)} style={{
            position:'relative', padding:'9px 18px 9px 30px', borderBottom:`1px solid ${AT.tint[60]}`, cursor:'pointer',
            background: on ? AT.highlight[50] + '66' : AT.tint[20] + '66', display:'flex', alignItems:'center', gap:10,
          }}>
            {on && <div style={{ position:'absolute', left:0, top:0, bottom:0, width:3, background: AT.highlight[500] }}/>}
            <span style={{ width:26, height:26, borderRadius:'50%', background: AT.tint[40], color: AT.shade[600], display:'flex', alignItems:'center', justifyContent:'center', fontSize:10.5, fontWeight:700, flex:'none', opacity:.8 }}>{atInitials(c.name)}</span>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ display:'flex', alignItems:'center', gap:6 }}>
                <span style={{ fontSize:13, fontWeight:600, color: AT.shade[700], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.name}</span>
                <SourceChip source={c.source}/>
              </div>
              <div style={{ fontSize:11.5, color: AT.shade[600], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.role} · {(c.loc||'').split(',')[0]}</div>
            </div>
            <span style={{ flex:'none', padding:'2px 8px', borderRadius:9999, border:`1px solid ${AT.tint[100]}`, color: r.c, fontSize:10, fontWeight:700 }}>{r.label}</span>
          </div>
        );
      })}
    </div>
  );
}

// AI working tab — the machine room / trust surface. De-emphasized rows.
// Everyone here is still being handled by the AI with no human action needed;
// the moment one needs a human it graduates OUT into Action needed, so you
// never have to dig here for work.
function AIWorkingTab({ list, total, selectedId, onSelect }) {
  return (
    <div style={{ flex:1, overflow:'auto' }}>
      <div style={{ padding:'12px 18px', background: AT.copilot[50] + '55', borderBottom:`1px solid ${AT.tint[60]}` }}>
        <div style={{ fontSize:12, color: AT.shade[700], lineHeight:1.45 }}>
          The AI is sourcing &amp; screening <strong style={{ color: AT.shade[880] }}>{total}</strong> candidates on its own. The moment one needs a human it moves to <strong style={{ color: AT.primary[700] }}>Action needed</strong> — so this tab only holds what the AI is still handling. You don’t have to work it.
        </div>
      </div>
      {list.length === 0 && (
        <div style={{ padding:'40px 24px', textAlign:'center', fontSize:13, color: AT.shade[600] }}>No candidates match.</div>
      )}
      {list.map(c => {
        const st = AI_STATUS[c.stage] || { label:'In progress', c: AT.shade[600] };
        const on = c.id === selectedId;
        return (
          <div key={c.id} onClick={() => onSelect?.(c.id)} style={{
            position:'relative', padding:'9px 18px', borderBottom:`1px solid ${AT.tint[60]}`, cursor:'pointer',
            background: on ? AT.highlight[50] + '66' : '#fff', display:'flex', alignItems:'center', gap:10,
          }}>
            {on && <div style={{ position:'absolute', left:0, top:0, bottom:0, width:3, background: AT.highlight[500] }}/>}
            <span style={{ width:26, height:26, borderRadius:'50%', background: AT.tint[40], color: AT.shade[700], display:'flex', alignItems:'center', justifyContent:'center', fontSize:10.5, fontWeight:700, flex:'none' }}>{atInitials(c.name)}</span>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ fontSize:13, fontWeight:600, color: AT.shade[820], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.name}</div>
              <div style={{ fontSize:11.5, color: AT.shade[600], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.role} · {(c.loc||'').split(',')[0]}</div>
            </div>
            <span style={{ display:'inline-flex', alignItems:'center', gap:5, flex:'none', fontSize:10.5, fontWeight:700, color: st.c }}>
              <span style={{ width:6, height:6, borderRadius:'50%', background: st.c }}/>{st.label}
            </span>
          </div>
        );
      })}
    </div>
  );
}

Object.assign(window, { LayoutAttention });
