// Middle "Candidates" column — owns the four layout variations.
const { color: CC, font: CF, shadow: CS } = window.FF;

/* ============================================================
   ROOT
   ============================================================ */
function CandidatesColumn({ candidates, selectedId, onSelect, layout, vocab, aiActivity, receiptTone, focusOnly, selectedJobId }) {
  return (
    <section data-screen-label="Candidates column" style={{
      flex:'none', width: layout === 'split' ? 720 : 460,
      background: '#fff', borderRight: `1px solid ${CC.tint[80]}`,
      display:'flex', flexDirection:'column', minHeight:'100vh',
    }}>
      {/* The checkbox is hover-revealed in production: it eases in from the
          left into a reserved gutter, so the row content never reflows. */}
      <style>{`
        .ff-crow .ff-cbx{
          width:0; margin-right:0; opacity:0; transform:translateX(-6px);
          flex:none; pointer-events:none;
          transition:width .16s ease, margin-right .16s ease, opacity .14s ease, transform .16s ease;
        }
        .ff-crow:hover .ff-cbx,
        .ff-crow .ff-cbx:focus-visible,
        .ff-crow .ff-cbx:checked{
          width:14px; margin-right:8px; opacity:1; transform:none; pointer-events:auto;
        }
      `}</style>
      {/* Header: "Candidates" + Upload + Search */}
      <CandidatesHeader/>

      {/* AI Activity */}
      {aiActivity === 'strip' && <AIActivityStrip/>}
      {aiActivity === 'panel' && <AIActivityPanel/>}

      {/* Body varies by layout */}
      {layout === 'current' && <LayoutCurrent candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'badges'  && <LayoutBadges  candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'lanes'   && <LayoutLanes   candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'split'   && <LayoutSplit   candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'workspace' && <LayoutWorkspace candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'match'     && <LayoutMatch     candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'campaign'  && <LayoutCampaign  candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'segment'   && <LayoutSegment   candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'surfaces'  && <LayoutSurfaces  candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'attention' && <LayoutAttention candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'focus'     && <LayoutFocus     candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab} focusOnly={focusOnly}/>}
      {layout === 'activity'  && <LayoutActivity  candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'stacked'   && <LayoutStacked   candidates={candidates} selectedId={selectedId} onSelect={onSelect} vocab={vocab}/>}
      {layout === 'receipt'   && <LayoutReceipt   candidates={candidates} selectedId={selectedId} onSelect={onSelect} tone={receiptTone}/>}
      {layout === 'sourcefirst' && <LayoutSourceFirst candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'intent'    && <LayoutIntent    candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'autorank'  && <LayoutAutoRank  candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'sealed'    && <LayoutSealed    candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
      {layout === 'handoff'   && <LayoutHandoff   candidates={candidates} selectedId={selectedId} onSelect={onSelect}/>}
    </section>
  );
}

function CandidatesHeader(){
  return (
    <div style={{ padding:'18px 20px 14px', display:'flex', alignItems:'center', justifyContent:'space-between', borderBottom:`1px solid ${CC.tint[80]}` }}>
      <div style={{ display:'flex', alignItems:'center', gap:8 }}>
        <button style={{ background:'transparent', border:0, padding:4, cursor:'pointer' }}>
          <img src="assets/icons/chevron-left.svg" width={16} height={16}/>
        </button>
        <h2 style={{ margin:0, fontSize:18, fontWeight:800, color: CC.shade[880], letterSpacing:'-.01em' }}>Candidates</h2>
      </div>
      <div style={{ display:'flex', alignItems:'center', gap:18 }}>
        <button style={{ display:'inline-flex', alignItems:'center', gap:6, background:'transparent', border:0, color: CC.shade[820], fontSize:13, fontWeight:600, cursor:'pointer' }}>
          Upload <img src="assets/icons/users-plus.svg" width={16} height={16}/>
        </button>
        <button style={{ display:'inline-flex', alignItems:'center', gap:6, background:'transparent', border:0, color: CC.shade[820], fontSize:13, fontWeight:600, cursor:'pointer' }}>
          Search <img src="assets/icons/search-20.svg" width={16} height={16}/>
        </button>
      </div>
    </div>
  );
}

/* ============================================================
   AI ACTIVITY
   ============================================================ */
function AIActivityStrip(){
  const a = window.__AI_ACTIVITY__.thisWeek;
  return (
    <div style={{
      padding:'10px 18px', background:'linear-gradient(90deg,#F5E6FF 0%, #ECEAFD 100%)',
      borderBottom:`1px solid ${CC.copilot[50]}`, display:'flex', alignItems:'center', gap:14
    }}>
      <img src="assets/icons/lightning-20.svg" width={16} height={16}/>
      <div style={{ fontSize:12, color: CC.copilot[800], lineHeight:1.4 }}>
        <span style={{ fontWeight:700 }}>Your AI recruiter this week:</span>{' '}
        <strong style={{ color: CC.copilot[800] }}>{a.sourced}</strong> candidates sourced
        <span style={{ opacity:.4, margin:'0 6px' }}>·</span>
        <strong>{a.messaged}</strong> messaged
        <span style={{ opacity:.4, margin:'0 6px' }}>·</span>
        <strong>{a.replied}</strong> replied
        <span style={{ opacity:.4, margin:'0 6px' }}>·</span>
        <strong>{a.scheduled}</strong> interviews booked
      </div>
    </div>
  );
}

function AIActivityPanel(){
  const a = window.__AI_ACTIVITY__;
  const KIND_ICON = {
    sourced:   { bg: CC.copilot[50],   fg: CC.copilot[700],  icon: 'users-plus' },
    messaged:  { bg: CC.inform[50],    fg: CC.inform[700],   icon: 'megaphone' },
    replied:   { bg: CC.primary[50],   fg: CC.primary[600],  icon: 'warm-candidate-20' },
    scheduled: { bg: CC.highlight[50], fg: CC.highlight[700], icon: 'star-filled-highlight' },
  };
  return (
    <div style={{ borderBottom:`1px solid ${CC.tint[80]}`, background: CC.tint[20] }}>
      <div style={{ padding:'14px 18px 8px', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
          <span style={{
            width:24, height:24, borderRadius:6, display:'inline-flex', alignItems:'center', justifyContent:'center',
            background: 'linear-gradient(270deg,#5f30d1 0%,#ae35f7 66%)'
          }}>
            <img src="assets/icons/lightning-20.svg" width={12} height={12} style={{ filter:'brightness(0) invert(1)' }}/>
          </span>
          <span style={{ fontSize:13, fontWeight:700, color: CC.shade[880] }}>Your AI recruiter is working</span>
        </div>
        <span style={{ fontSize:11, color: CC.shade[700] }}>This week</span>
      </div>
      <div style={{ display:'grid', gridTemplateColumns:'repeat(4,1fr)', gap:8, padding:'0 18px 12px' }}>
        {[
          ['Sourced', a.thisWeek.sourced, CC.copilot[700]],
          ['Messaged', a.thisWeek.messaged, CC.inform[700]],
          ['Replied', a.thisWeek.replied, CC.primary[600]],
          ['Booked', a.thisWeek.scheduled, CC.highlight[700]],
        ].map(([l,n,col]) => (
          <div key={l} style={{ background:'#fff', borderRadius:8, padding:'8px 10px', border:`1px solid ${CC.tint[80]}` }}>
            <div style={{ fontSize:18, fontWeight:800, color: col, lineHeight:1.1 }}>{n}</div>
            <div style={{ fontSize:11, color: CC.shade[700], marginTop:1 }}>{l}</div>
          </div>
        ))}
      </div>
      <div style={{ padding:'4px 18px 12px', display:'flex', flexDirection:'column', gap:4, maxHeight:120, overflow:'auto' }}>
        {a.recent.slice(0,3).map((r,i) => {
          const k = KIND_ICON[r.kind];
          return (
            <div key={i} style={{ display:'flex', alignItems:'center', gap:8, fontSize:12, color: CC.shade[820] }}>
              <span style={{ width:18, height:18, borderRadius:4, background:k.bg, display:'inline-flex', alignItems:'center', justifyContent:'center', flex:'none' }}>
                <img src={`assets/icons/${k.icon}.svg`} width={10} height={10}/>
              </span>
              <span style={{ flex:1, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{r.text}</span>
              <span style={{ fontSize:11, color: CC.shade[600], flex:'none' }}>{r.t}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ============================================================
   LAYOUT A — CURRENT (status quo, the screenshot)
   ============================================================ */
function LayoutCurrent({ candidates, selectedId, onSelect, vocab }) {
  const [stage, setStage] = React.useState('sourcing');
  const v = window.FFLIB.vocab(vocab);
  // When vocab is non-default, the first two tabs are relabeled with the
  // source vocabulary so even "just rename" feels meaningfully different.
  const sourcingLabel = vocab === 'applied-sourced' ? 'Sourcing' : v.sourced;
  const newLabel      = vocab === 'applied-sourced' ? 'New'      : v.applied;
  const tabs = [
    { k:'sourcing', label: sourcingLabel, n: candidates.filter(c=>c.stage==='sourcing').length },
    { k:'new',      label: newLabel,      n: candidates.filter(c=>c.stage==='new').length },
    { k:'engaged',  label:'Engaged',      n: candidates.filter(c=>c.stage==='engaged').length },
    { k:'review',   label:'Review',       n: candidates.filter(c=>c.stage==='review').length },
    { k:'interview',label:'Interview',    n: candidates.filter(c=>c.stage==='interview').length },
  ];
  const list = candidates.filter(c => c.stage === stage);
  return (
    <React.Fragment>
      <UploadBanner/>
      <TabRow tabs={tabs} active={stage} onChange={setStage}/>
      <SortRow/>
      <CandidateList items={list} selectedId={selectedId} onSelect={onSelect} showSourceBadge={false} vocab={vocab}/>
    </React.Fragment>
  );
}

function UploadBanner(){
  return (
    <div style={{ margin:'14px 16px 0', padding:'12px 14px', background: CC.copilot[50], borderRadius:10, display:'flex', alignItems:'flex-start', gap:10, position:'relative' }}>
      <img src="assets/icons/users-plus.svg" width={20} height={20} style={{ flex:'none', marginTop:2 }}/>
      <div style={{ flex:1, fontSize:12, color: CC.shade[820], lineHeight:1.4 }}>
        <div style={{ fontWeight:700, color: CC.shade[880], marginBottom:2 }}>Already have resumes for this job?</div>
        Upload them and let your AI recruiter handle the next steps.<br/>
        <a href="#" style={{ color: CC.copilot[700], fontWeight:600 }} onClick={e=>e.preventDefault()}>Upload candidates &gt;</a>
      </div>
      <button style={{ background:'transparent', border:0, color: CC.shade[600], cursor:'pointer', fontSize:18, padding:0, lineHeight:1 }}>×</button>
    </div>
  );
}

// Matches the shipped segmented control: counts inline in the label, the
// active segment a solid Black Blue pill, a Copilot bolt on Sourcing, and the
// right-hand chevron that affords the horizontal scroll.
function TabRow({ tabs, active, onChange }){
  return (
    <div style={{ padding:'14px 16px 0', display:'flex', alignItems:'center', gap:6, position:'relative' }}>
      <div style={{ display:'flex', gap:6, overflowX:'auto', flexWrap:'nowrap', flex:1, scrollbarWidth:'none' }}>
        {tabs.map(t => {
          const on = t.k === active;
          return (
            <button key={t.k} onClick={()=>onChange(t.k)} style={{
              display:'inline-flex', alignItems:'center', gap:6, padding:'6px 13px',
              background: on ? CC.shade[880] : '#fff',
              border: `1px solid ${on ? CC.shade[880] : CC.tint[100]}`,
              color: on ? '#fff' : CC.shade[820],
              borderRadius:9999, fontSize:13, fontWeight:600, cursor:'pointer', whiteSpace:'nowrap',
            }}>
              {t.k === 'sourcing' && (
                <span style={{
                  width:16, height:16, borderRadius:'50%', flex:'none',
                  display:'inline-flex', alignItems:'center', justifyContent:'center',
                  background: on ? 'rgba(255,255,255,.18)' : CC.copilot[50],
                }}>
                  <img src="assets/icons/lightning-20.svg" width={10} height={10}
                       style={{ filter: on ? 'brightness(0) invert(1)' : 'none' }}/>
                </span>
              )}
              {t.label}{t.n ? <span style={{ fontWeight:800 }}>{t.n}</span> : null}
            </button>
          );
        })}
      </div>
      <span aria-hidden style={{
        flex:'none', width:22, height:22, borderRadius:'50%', background:'#fff',
        border:`1px solid ${CC.tint[100]}`, display:'inline-flex', alignItems:'center',
        justifyContent:'center', fontSize:12, color: CC.shade[700],
      }}>›</span>
    </div>
  );
}

function SortRow(){
  return (
    <div style={{ padding:'12px 16px 8px', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
      <div style={{ display:'flex', alignItems:'center', gap:8 }}>
        <input type="checkbox" style={{ width:16, height:16 }}/>
        <img src="assets/icons/chevron-down.svg" width={14} height={14}/>
      </div>
      <div style={{ display:'flex', alignItems:'center', gap:10 }}>
        <button style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'5px 10px', background: CC.tint[20], border:`1px solid ${CC.tint[80]}`, borderRadius:6, fontSize:12, fontWeight:500, color: CC.shade[820], cursor:'pointer' }}>
          Most recent conversations
          <img src="assets/icons/chevron-down.svg" width={12} height={12}/>
        </button>
        <img src="assets/icons/filter-lines-20.svg" width={16} height={16}/>
      </div>
    </div>
  );
}

/* ============================================================
   LAYOUT B — BADGES (current + source pill on every row)
   ============================================================ */
function LayoutBadges({ candidates, selectedId, onSelect, vocab }) {
  const v = window.FFLIB.vocab(vocab);
  const [stage, setStage] = React.useState('sourcing');
  const [sourceFilter, setSourceFilter] = React.useState('all'); // 'all' | 'applied' | 'sourced'
  const tabs = [
    { k:'sourcing', label:'Sourcing', n: candidates.filter(c=>c.stage==='sourcing').length },
    { k:'new',      label:'New',      n: candidates.filter(c=>c.stage==='new').length },
    { k:'engaged',  label:'Engaged',  n: candidates.filter(c=>c.stage==='engaged').length },
    { k:'review',   label:'Review',   n: candidates.filter(c=>c.stage==='review').length },
    { k:'interview',label:'Interview',n: candidates.filter(c=>c.stage==='interview').length },
  ];
  let list = candidates.filter(c => c.stage === stage);
  if (sourceFilter !== 'all') list = list.filter(c => c.source === sourceFilter);

  const sChip = (key, label, color) => {
    const on = sourceFilter === key;
    return (
      <button key={key} onClick={()=>setSourceFilter(key)} style={{
        display:'inline-flex', alignItems:'center', gap:6, padding:'4px 10px',
        background: on ? color.bg : '#fff',
        border: `1px solid ${on ? color.fg : CC.tint[100]}`,
        color: on ? color.fg : CC.shade[820],
        borderRadius:9999, fontSize:12, fontWeight:600, cursor:'pointer',
      }}>
        {key !== 'all' && <span style={{ width:6, height:6, borderRadius:'50%', background: color.fg }}/>}
        {label}
      </button>
    );
  };

  return (
    <React.Fragment>
      <UploadBanner/>
      <TabRow tabs={tabs} active={stage} onChange={setStage}/>
      <div style={{ padding:'10px 16px 0', display:'flex', alignItems:'center', gap:6 }}>
        <span style={{ fontSize:11, color: CC.shade[700], fontWeight:600, textTransform:'uppercase', letterSpacing:'.06em', marginRight:4 }}>Source</span>
        {sChip('all',      'All',      { bg: CC.tint[40], fg: CC.shade[820] })}
        {sChip('applied',  v.applied,  { bg: CC.inform[50], fg: CC.inform[700] })}
        {sChip('sourced',  v.sourced,  { bg: CC.copilot[50], fg: CC.copilot[700] })}
      </div>
      <SortRow/>
      <CandidateList items={list} selectedId={selectedId} onSelect={onSelect} showSourceBadge={true} vocab={vocab}/>
    </React.Fragment>
  );
}

/* ============================================================
   LAYOUT C — LANES (Applied / Sourced as top-level)
   ============================================================ */
function LayoutLanes({ candidates, selectedId, onSelect, vocab }) {
  const v = window.FFLIB.vocab(vocab);
  const [lane, setLane] = React.useState('sourced'); // sourced first to match screenshot intent
  // funnel stages within each lane
  const stagesForLane = lane === 'applied'
    ? [ {k:'new',label:'New'}, {k:'engaged',label:'Engaged'}, {k:'review',label:'Review'}, {k:'interview',label:'Interview'} ]
    : [ {k:'sourcing',label:'Sourcing'}, {k:'engaged',label:'Engaged'}, {k:'review',label:'Review'}, {k:'interview',label:'Interview'} ];
  const [stage, setStage] = React.useState(stagesForLane[0].k);
  React.useEffect(()=>{ setStage(stagesForLane[0].k); /* eslint-disable-next-line */ }, [lane]);

  const appliedTotal = candidates.filter(c=>c.source==='applied').length;
  const sourcedTotal = candidates.filter(c=>c.source==='sourced').length;
  const tabs = stagesForLane.map(s => ({
    ...s,
    n: candidates.filter(c => c.source === lane && c.stage === s.k).length,
  }));
  const list = candidates.filter(c => c.source === lane && c.stage === stage);

  return (
    <React.Fragment>
      {/* Lane switcher — the headline */}
      <div style={{ padding:'16px 16px 0' }}>
        <div style={{ display:'flex', gap:0, background: CC.tint[20], borderRadius:12, padding:4, border:`1px solid ${CC.tint[80]}` }}>
          <LaneTab
            active={lane==='applied'} onClick={()=>setLane('applied')}
            title={v.appliedLong} subtitle="They applied to your job"
            count={appliedTotal} color={CC.inform}
            iconBg={CC.inform[50]} icon="users-plus"
          />
          <LaneTab
            active={lane==='sourced'} onClick={()=>setLane('sourced')}
            title={v.sourcedLong} subtitle="Your AI recruiter found them"
            count={sourcedTotal} color={CC.copilot}
            iconBg={CC.copilot[50]} icon="lightning-20"
          />
        </div>
      </div>
      <TabRow tabs={tabs} active={stage} onChange={setStage}/>
      <SortRow/>
      <CandidateList items={list} selectedId={selectedId} onSelect={onSelect} showSourceBadge={false} vocab={vocab}/>
    </React.Fragment>
  );
}

function LaneTab({ active, onClick, title, subtitle, count, color, iconBg, icon }){
  return (
    <button onClick={onClick} style={{
      flex:1, display:'flex', alignItems:'center', gap:10, padding:'10px 12px',
      background: active ? '#fff' : 'transparent',
      border: active ? `1px solid ${color[500]}` : '1px solid transparent',
      borderRadius:10, cursor:'pointer', textAlign:'left',
      boxShadow: active ? '0 1px 3px rgba(13,10,44,.08)' : 'none',
    }}>
      <span style={{ width:32, height:32, borderRadius:8, background: iconBg, display:'inline-flex', alignItems:'center', justifyContent:'center', flex:'none' }}>
        <img src={`assets/icons/${icon}.svg`} width={16} height={16} style={{ filter: active ? '' : 'opacity(.65)' }}/>
      </span>
      <div style={{ flex:1, minWidth:0 }}>
        <div style={{ display:'flex', alignItems:'baseline', gap:6 }}>
          <span style={{ fontSize:14, fontWeight:700, color: active ? color[700] : CC.shade[820] }}>{title}</span>
          <span style={{ fontSize:13, fontWeight:700, color: active ? color[600] : CC.shade[700] }}>{count}</span>
        </div>
        <div style={{ fontSize:11, color: CC.shade[700], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{subtitle}</div>
      </div>
    </button>
  );
}

/* ============================================================
   LAYOUT D — SPLIT (side-by-side: applied | sourced)
   ============================================================ */
function LayoutSplit({ candidates, selectedId, onSelect, vocab }) {
  const v = window.FFLIB.vocab(vocab);
  return (
    <div style={{ flex:1, display:'flex', minHeight:0 }}>
      <SplitPane
        title={v.appliedLong}
        subtitle="They applied to your job"
        color={CC.inform}
        iconBg={CC.inform[50]} icon="users-plus"
        stages={[
          { k:'new',     label:'New' },
          { k:'engaged', label:'Engaged' },
          { k:'review',  label:'Review' },
        ]}
        defaultStage="new"
        items={candidates.filter(c=>c.source==='applied')}
        selectedId={selectedId} onSelect={onSelect}
      />
      <div style={{ width:1, background: CC.tint[80] }}/>
      <SplitPane
        title={v.sourcedLong}
        subtitle="Your AI recruiter found them"
        color={CC.copilot}
        iconBg={CC.copilot[50]} icon="lightning-20"
        stages={[
          { k:'sourcing', label:'Sourcing' },
          { k:'engaged',  label:'Engaged' },
          { k:'review',   label:'Review' },
        ]}
        defaultStage="sourcing"
        items={candidates.filter(c=>c.source==='sourced')}
        selectedId={selectedId} onSelect={onSelect}
      />
    </div>
  );
}

function SplitPane({ title, subtitle, color, iconBg, icon, stages, defaultStage, items, selectedId, onSelect }) {
  const [stage, setStage] = React.useState(defaultStage);
  const counts = Object.fromEntries(stages.map(s => [s.k, items.filter(i => i.stage === s.k).length]));
  const list = items.filter(i => i.stage === stage);
  return (
    <div style={{ flex:1, display:'flex', flexDirection:'column', minWidth:0 }}>
      <div style={{ padding:'14px 16px 10px', background: '#fff', borderBottom:`1px solid ${CC.tint[80]}` }}>
        <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
          <span style={{ width:24, height:24, borderRadius:6, background: iconBg, display:'inline-flex', alignItems:'center', justifyContent:'center', flex:'none' }}>
            <img src={`assets/icons/${icon}.svg`} width={13} height={13}/>
          </span>
          <div style={{ flex:1, minWidth:0 }}>
            <div style={{ fontSize:14, fontWeight:700, color: color[700], lineHeight:1.2 }}>{title}</div>
            <div style={{ fontSize:11, color: CC.shade[700] }}>{subtitle}</div>
          </div>
          <div style={{ fontSize:18, fontWeight:800, color: color[700], lineHeight:1 }}>{items.length}</div>
        </div>
        <div style={{ display:'flex', gap:4, flexWrap:'wrap' }}>
          {stages.map(s => {
            const on = s.k === stage;
            return (
              <button key={s.k} onClick={()=>setStage(s.k)} style={{
                padding:'4px 10px',
                background: on ? color[50] : 'transparent',
                border: `1px solid ${on ? color[500] : CC.tint[80]}`,
                color: on ? color[700] : CC.shade[820],
                borderRadius:9999, fontSize:11, fontWeight:600, cursor:'pointer',
              }}>
                {s.label} {counts[s.k] || 0}
              </button>
            );
          })}
        </div>
      </div>
      <CandidateList items={list} selectedId={selectedId} onSelect={onSelect} showSourceBadge={false} vocab={null} compact={true}/>
    </div>
  );
}

/* ============================================================
   LAYOUT E — WORKSPACE (Engaged-as-workspace, AI status header,
                          theater on Outreach, just-landed treatment)
   ============================================================ */
function LayoutWorkspace({ candidates, selectedId, onSelect, vocab }) {
  // Defaults to engaged (smart default). User can navigate into upstream stages.
  const [stage, setStage] = React.useState('engaged');

  const counts = {
    sourcing:  candidates.filter(c=>c.stage==='sourcing').length,
    new:       candidates.filter(c=>c.stage==='new').length,
    engaged:   candidates.filter(c=>c.stage==='engaged').length,
    review:    candidates.filter(c=>c.stage==='review').length,
    interview: candidates.filter(c=>c.stage==='interview').length,
  };
  const justLandedList = candidates.filter(c => c.stage === 'engaged' && c.justLanded);

  // Renamed "Sourcing" → "Outreach" (matches internal Contact-stage naming).
  const tabs = [
    { k:'sourcing',  label:'Outreach',  n:counts.sourcing },
    { k:'new',       label:'New',       n:counts.new },
    { k:'engaged',   label:'Engaged',   n:counts.engaged },
    { k:'review',    label:'Review',    n:counts.review },
    { k:'interview', label:'Interview', n:counts.interview },
  ];

  return (
    <React.Fragment>
      {/* Persistent AI working status — only shows when NOT on outreach (since outreach IS the activity view) */}
      {stage !== 'sourcing' && (
        <AIWorkingStrip
          outreachCount={counts.sourcing}
          newCount={counts.new}
          justLandedCount={justLandedList.length}
          onClick={()=>setStage('sourcing')}
          onJumpToJustLanded={()=>{
            setStage('engaged');
            if (justLandedList[0]) onSelect?.(justLandedList[0].id);
          }}
        />
      )}

      <WorkspaceTabRow tabs={tabs} active={stage} onChange={setStage}/>

      {/* When on outreach, full theater. Otherwise normal candidate list with just-landed treatment on engaged. */}
      {stage === 'sourcing' ? (
        <OutreachTheater
          outreachCount={counts.sourcing}
          candidates={candidates.filter(c=>c.stage==='sourcing')}
          selectedId={selectedId}
          onSelect={onSelect}
          onBackToWorkspace={()=>setStage('engaged')}
        />
      ) : (
        <React.Fragment>
          <SortRow/>
          <CandidateList
            items={candidates.filter(c => c.stage === stage)}
            selectedId={selectedId}
            onSelect={onSelect}
            showSourceBadge={false}
            vocab={vocab}
            showJustLanded={stage==='engaged'}
          />
        </React.Fragment>
      )}
    </React.Fragment>
  );
}

/* The pulsing AI status header — thin, single line, peripheral */
function AIWorkingStrip({ outreachCount, newCount, justLandedCount, onClick, onJumpToJustLanded }) {
  return (
    <div style={{
      borderBottom:`1px solid ${CC.tint[80]}`,
      padding:'9px 18px',
      background:'#fff',
      display:'flex', alignItems:'center', gap:10,
    }}>
      <span style={{ flex:'none', display:'inline-flex', alignItems:'center', justifyContent:'center', width:10, height:10 }}>
        <span className="ai-dot" style={{ width:7, height:7 }}/>
      </span>

      <span style={{ fontSize:12, color: CC.shade[820], lineHeight:1.3 }}>
        <span style={{ color: CC.shade[700] }}>AI is working —</span>{' '}
        <button onClick={onClick} style={{ background:'transparent', border:0, padding:0, cursor:'pointer', color: CC.shade[880], fontWeight:600, fontSize:12 }}>
          <strong>{outreachCount}</strong> in outreach
        </button>
        <span style={{ opacity:.35, margin:'0 6px' }}>·</span>
        <strong style={{ color: CC.shade[880] }}>{newCount}</strong> in screening
        {justLandedCount > 0 && (
          <React.Fragment>
            <span style={{ opacity:.35, margin:'0 6px' }}>·</span>
            <button onClick={onJumpToJustLanded} style={{
              background:'transparent', border:0, padding:0, cursor:'pointer',
              color: CC.copilot[700], fontWeight:700, fontSize:12,
            }}>
              {justLandedCount} just landed →
            </button>
          </React.Fragment>
        )}
      </span>
    </div>
  );
}

/* Workspace tab row — plain tabs, no group labels */
function WorkspaceTabRow({ tabs, active, onChange }) {
  return (
    <div style={{ padding:'12px 16px 0', display:'flex', alignItems:'center', gap:6, flexWrap:'nowrap', overflowX:'auto' }}>
      {tabs.map(t => {
        const on = t.k === active;
        return (
          <button key={t.k} onClick={()=>onChange(t.k)} style={{
            display:'inline-flex', alignItems:'center', gap:6, padding:'6px 12px',
            background: on ? CC.highlight[50] : 'transparent',
            border: `1px solid ${on ? CC.highlight[500] : CC.tint[80]}`,
            color: on ? CC.highlight[700] : CC.shade[820],
            borderRadius:9999, fontSize:13, fontWeight: on ? 700 : 500, cursor:'pointer', whiteSpace:'nowrap',
          }}>
            {on && <span style={{ width:6, height:6, borderRadius:'50%', background: CC.highlight[500] }}/>}
            {t.label} {t.n ? <span style={{ opacity:.7, fontWeight:600 }}>{t.n}</span> : null}
          </button>
        );
      })}
    </div>
  );
}

/* The Outreach tab — full theater. Live scanning animation + the actual candidates in outreach */
function OutreachTheater({ outreachCount, candidates, selectedId, onSelect, onBackToWorkspace }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', flex:1, minHeight:0 }}>
      {/* Back to workspace */}
      <div style={{ padding:'10px 16px 0' }}>
        <button onClick={onBackToWorkspace} style={{
          display:'inline-flex', alignItems:'center', gap:4,
          background:'transparent', border:0, padding:0, cursor:'pointer',
          color: CC.shade[700], fontSize:12, fontWeight:600,
        }}>
          <img src="assets/icons/chevron-left.svg" width={12} height={12} style={{ opacity:.55 }}/>
          Back to workspace
        </button>
      </div>

      {/* Theater */}
      <div style={{
        margin:'10px 16px 0', padding:'16px 16px 12px',
        background: 'linear-gradient(180deg, #29104D 0%, #1B0A38 100%)',
        borderRadius:12, color:'#fff', position:'relative', overflow:'hidden',
        boxShadow:'0 8px 28px rgba(80,30,180,.18)',
      }}>
        {/* Animated background dot grid */}
        <DotGridBackground/>

        <div style={{ position:'relative', display:'flex', alignItems:'center', gap:10, marginBottom:8 }}>
          <span style={{ position:'relative', display:'inline-flex', alignItems:'center', justifyContent:'center', width:24, height:24 }}>
            <span className="ai-dot"/>
          </span>
          <div style={{ flex:1 }}>
            <div style={{ fontSize:14, fontWeight:800, letterSpacing:'-.005em' }}>Your AI recruiter is actively sourcing</div>
            <div style={{ fontSize:11.5, color:'rgba(255,255,255,.7)', marginTop:1 }}>
              Scanning the FactoryFix talent pool for Machine Operator I — Greensboro, NC
            </div>
          </div>
        </div>

        {/* Scan stripes */}
        <div style={{ position:'relative', height:180, marginTop:6, borderRadius:8, overflow:'hidden', background:'rgba(255,255,255,.03)', border:'1px solid rgba(255,255,255,.06)' }}>
          <ScanCards/>
          <div className="ai-scan-line"/>
        </div>

        {/* Stats */}
        <div style={{ position:'relative', display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:8, marginTop:10 }}>
          <TheaterStat n={148}  label="Profiles scanned" color="#fff"/>
          <TheaterStat n={outreachCount} label="In outreach"  color="#FFC8FF"/>
          <TheaterStat n={3}    label="Replies this hour" color="#9FF6C1"/>
        </div>
      </div>

      {/* Sub-header for the candidate list */}
      <div style={{ padding:'14px 16px 4px', display:'flex', alignItems:'baseline', justifyContent:'space-between' }}>
        <div style={{ fontSize:12, fontWeight:700, color: CC.shade[700], textTransform:'uppercase', letterSpacing:'.06em' }}>
          Found and reaching out
        </div>
        <div style={{ fontSize:11, color: CC.shade[700] }}>{candidates.length} candidates</div>
      </div>

      <CandidateList
        items={candidates}
        selectedId={selectedId}
        onSelect={onSelect}
        showSourceBadge={false}
        vocab={null}
      />
    </div>
  );
}

function TheaterStat({ n, label, color }) {
  return (
    <div style={{
      background:'rgba(255,255,255,.06)',
      border:'1px solid rgba(255,255,255,.08)',
      borderRadius:8, padding:'8px 10px',
    }}>
      <div style={{ fontSize:20, fontWeight:800, color, lineHeight:1.05, letterSpacing:'-.01em' }}>{n}</div>
      <div style={{ fontSize:10.5, color:'rgba(255,255,255,.65)', marginTop:2 }}>{label}</div>
    </div>
  );
}

/* The little fake candidate cards being "scanned" */
function ScanCards() {
  // 8 fake rows: avatar circle + 2 bars. A few are "matched" (highlighted).
  const rows = [
    { matched:false }, { matched:true },  { matched:false }, { matched:false },
    { matched:true },  { matched:false }, { matched:false }, { matched:true  },
  ];
  return (
    <div style={{ position:'absolute', inset:0, padding:'8px 10px', display:'flex', flexDirection:'column', gap:6 }}>
      {rows.map((r,i) => (
        <div key={i} style={{
          display:'flex', alignItems:'center', gap:8,
          padding:'4px 6px', borderRadius:5,
          background: r.matched ? 'rgba(255,200,255,.10)' : 'transparent',
          opacity: r.matched ? 1 : .55,
        }}>
          <span style={{ width:14, height:14, borderRadius:'50%', background: r.matched ? '#FFC8FF' : 'rgba(255,255,255,.25)', flex:'none' }}/>
          <span style={{ height:5, borderRadius:3, flex:1, background:'rgba(255,255,255,.18)' }}/>
          <span style={{ height:5, borderRadius:3, width:'30%', background:'rgba(255,255,255,.12)' }}/>
          {r.matched && (
            <span style={{ fontSize:9, fontWeight:700, color:'#FFC8FF', flex:'none', letterSpacing:'.04em' }}>MATCH</span>
          )}
        </div>
      ))}
    </div>
  );
}

function DotGridBackground() {
  return (
    <div style={{
      position:'absolute', inset:0,
      backgroundImage:'radial-gradient(circle, rgba(255,255,255,.05) 1px, transparent 1px)',
      backgroundSize:'14px 14px',
      pointerEvents:'none',
    }}/>
  );
}

/* ============================================================
   SHARED — candidate list + row
   ============================================================ */
// `triggerFor` is optional: pass a (candidate) => trigger|null and each row
// renders its Action-needed reason. Omitted by every layout but Focus, so
// behaviour is unchanged everywhere else.
/* ============================================================
   SCORE BADGE — ported from ats-ui's ApplicationScoreCompactDisplay
   (+ the compact branch of ApplicationScoreCard that wraps it).

   Thresholds are CriteriaThresholdEnum: GREEN 3.5, YELLOW 2. Note the
   yellow band — the prototype previously had only two tones and split at
   3.0, so anything from 2.0–3.4 was showing green when production shows
   amber. Score always renders to one decimal.
   ============================================================ */
function ScoreStar() {
  return (
    <svg width="12" height="12" viewBox="0 0 10 11" fill="none" style={{ flex:'none', color: CC.black }} aria-hidden>
      <path d="M4.14319 1.42372C4.53185 0.777902 5.46815 0.777902 5.85681 1.42372L6.75651 2.91871C6.89613 3.15073 7.12388 3.31619 7.38769 3.37729L9.08753 3.77098C9.82185 3.94105 10.1112 4.83152 9.61707 5.40073L8.47327 6.71837C8.29576 6.92286 8.20877 7.19059 8.23218 7.46036L8.38304 9.19867C8.44821 9.9496 7.69073 10.4999 6.9967 10.2059L5.39009 9.52526C5.14076 9.41963 4.85924 9.41963 4.60991 9.52526L3.0033 10.2059C2.30927 10.4999 1.55179 9.9496 1.61696 9.19867L1.76782 7.46036C1.79123 7.19059 1.70424 6.92286 1.52673 6.71837L0.382932 5.40073C-0.111176 4.83152 0.178155 3.94105 0.912469 3.77098L2.61231 3.37729C2.87612 3.31619 3.10387 3.15073 3.24349 2.91871L4.14319 1.42372Z" fill="currentColor"/>
    </svg>
  );
}

function ScoreBadge({ score, jobTitle, hideJobTitle, isSelected, isViewed }) {
  const hasScore = typeof score === 'number' && !Number.isNaN(score);
  const badgeBg = !hasScore
    ? (isViewed ? CC.tint[60] : CC.tint[80])
    : score >= 3.5 ? CC.primary[300]
    : score >= 2   ? CC.caution[300]
    : CC.critical[400];

  return (
    <div style={{
      display:'inline-flex', maxWidth:'100%', minWidth:0, alignItems:'center',
      borderRadius:4, padding:'2px 4px 2px 0',
      background: isSelected ? CC.white : CC.tint[40],
    }}>
      {hasScore ? (
        <div style={{ display:'flex', alignItems:'center', gap:2, borderRadius:2, padding:'2px 4px', background: badgeBg, flex:'none' }}>
          <ScoreStar/>
          <span style={{ fontSize:12, lineHeight:'16px', fontWeight:600, color: CC.shade[880] }}>{score.toFixed(1)}</span>
        </div>
      ) : (
        <span style={{ borderRadius:2, padding:'2px 4px', fontSize:12, fontWeight:600, lineHeight:1, color: CC.shade[840], background: badgeBg, flex:'none' }}>
          Not scored
        </span>
      )}
      {jobTitle && !hideJobTitle && (
        <React.Fragment>
          <span style={{ marginLeft:8, marginRight:4, fontSize:12, color: CC.shade[880], flex:'none' }}>for</span>
          <span title={jobTitle} style={{
            minWidth:0, maxWidth:188, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap',
            fontSize:12, fontWeight:700, color: CC.shade[880],
          }}>{jobTitle}</span>
        </React.Fragment>
      )}
    </div>
  );
}

function CandidateList({ items, selectedId, onSelect, showSourceBadge, vocab, compact, showJustLanded, triggerFor, triggerStyle }) {
  if (!items.length) {
    return (
      <div style={{ padding:'40px 20px', textAlign:'center', color: CC.shade[700], fontSize:13 }}>
        No candidates in this stage yet.
      </div>
    );
  }
  return (
    <div style={{ flex:1, overflow:'auto', borderTop:`1px solid ${CC.tint[80]}` }}>
      {items.map(c => (
        <CandidateRow
          key={c.id}
          c={c}
          selected={c.id === selectedId}
          onSelect={onSelect}
          showSourceBadge={showSourceBadge}
          vocab={vocab}
          compact={compact}
          justLanded={!!(showJustLanded && c.justLanded)}
          trigger={triggerFor ? triggerFor(c) : null}
          triggerStyle={triggerStyle}
        />
      ))}
    </div>
  );
}

function CandidateRow({ c, selected, onSelect, showSourceBadge, vocab, compact, justLanded, trigger, triggerStyle }) {
  const v = vocab ? window.FFLIB.vocab(vocab) : window.FFLIB.vocab('applied-sourced');
  const applied = c.source === 'applied';
  // Production grades the score badge: green when it's a good match, red when
  // it isn't (shipped panel shows 0.3 / 0.8 / 1.3 in red, 3.5 / 4.3 in green).
  return (
    <div onClick={()=>onSelect?.(c.id)} className="ff-crow" style={{
      position:'relative', padding: compact ? '10px 12px 10px 14px' : '12px 16px 14px',
      borderBottom:`1px solid ${CC.tint[80]}`, cursor:'pointer',
      background: selected ? CC.highlight[50]+'66' : '#fff',
    }}>
      {selected && <div style={{ position:'absolute', left:0, top:0, bottom:0, width:3, background: CC.highlight[500] }}/>}

      {/* Row 1: checkbox + name + time. The checkbox lives on THIS line only,
          so revealing it shifts the name across while the role and score lines
          below stay put — that's the production behaviour. */}
      <div style={{ display:'flex', alignItems:'center', gap:0, marginBottom:2 }}>
        <input type="checkbox" className="ff-cbx" style={{ height:14, accentColor: CC.highlight[500] }} onClick={e=>e.stopPropagation()}/>
        <div style={{ flex:1, display:'flex', alignItems:'center', gap:8, minWidth:0 }}>
          <h3 style={{ margin:0, fontSize: compact ? 13 : 14, fontWeight:700, color: CC.shade[880], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{c.name}</h3>
          {trigger && triggerStyle === 'badge' && (
            <span title={trigger.reason} style={{
              display:'inline-flex', alignItems:'center', gap:5, flex:'none',
              padding:'2px 8px 2px 6px', borderRadius:9999,
              background: CC.primary[50], color: CC.primary[800],
              fontSize:10.5, fontWeight:700,
            }}>
              <span style={{ width:6, height:6, borderRadius:'50%', background: CC.primary[500] }}/>
              Action needed
            </span>
          )}
          {justLanded && (
            <span style={{
              display:'inline-flex', alignItems:'center', gap:3,
              padding:'1px 6px', borderRadius:9999, flex:'none',
              fontSize:10, fontWeight:700, letterSpacing:'.02em',
              background: CC.highlight[50], color: CC.highlight[700],
            }}>
              ✦ Just landed
            </span>
          )}
        </div>
        <span style={{ fontSize:11, color: CC.shade[800], flex:'none' }}>{c.time}</span>
      </div>

      {/* Row 2: current role */}
      <div style={{ fontSize: compact ? 12 : 13, color: CC.shade[800], marginBottom:8, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
        {c.role} at {c.company}
      </div>

      {/* Row 3: score · job · provenance chip. Per ConversationIndexCard the
          chip flows immediately after the score group rather than anchoring
          right — the score sits in a min-w-0 wrapper so the job title is what
          truncates, and the chip is shrink-0. */}
      <div style={{ display:'flex', alignItems:'center', gap:4 }}>
        <div style={{ minWidth:0 }}>
          <ScoreBadge score={c.score} jobTitle={'Machine Operator I – O\u2019Neal Manufacturing'}
            isSelected={selected} isViewed={!c.isNew}/>
        </div>
        {showSourceBadge !== false && (
          <span style={{
            display:'inline-flex', alignItems:'center', gap:4, flex:'none',
            padding:'2px 8px', borderRadius:9999,
            fontSize:10.5, fontWeight:700,
            background: applied ? CC.tint[40] : CC.copilot[50],
            color: applied ? CC.shade[820] : CC.copilot[800],
          }}>
            {applied
              ? <span style={{ width:11, height:11, borderRadius:'50%', background: CC.shade[880], color:'#fff', fontSize:8, fontWeight:800, display:'inline-flex', alignItems:'center', justifyContent:'center' }}>i</span>
              : <img src="assets/icons/lightning-20.svg" width={10} height={10}/>}
            {applied ? v.applied : v.sourced}
          </span>
        )}
      </div>

      {/* Row 4 (opt-in): the Action-needed reason — why this person is blocked
          on a human, and what to do. Only rendered when a layout passes it. */}
      {trigger && triggerStyle !== 'badge' && (
        <div style={{
          display:'flex', alignItems:'center', gap:7, marginTop:8,
          paddingLeft:8, borderLeft:`2px solid ${CC.primary[500]}`,
        }}>
          <span style={{ flex:'none', fontSize:9.5, fontWeight:800, letterSpacing:'.04em', textTransform:'uppercase', color: CC.primary[600] }}>{trigger.cat}</span>
          <span style={{ fontSize:12, color: CC.shade[820], whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{trigger.reason}</span>
          <span style={{ flex:'none', fontSize:11, fontWeight:700, color: CC.shade[800] }}>{trigger.action} →</span>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { CandidatesColumn });
