// ═══ GENESIS BUILD rbac-logbook-bridge · 2026-07-10 ═══
// Tidal — Bridge · módulo do passadiço · Quadro de Fainas

// ── helpers de apresentação ──
const CLASSE_LABEL = { tm_master:'TM Master', email:'E-mail', geral:'Geral' };
const CLASSE_LABEL_EN = { tm_master:'TM Master', email:'E-mail', geral:'General' };
const _brL = (dic, dicEn, k, lang) => (lang==='en' ? (dicEn[k] || dic[k]) : dic[k]) || k;
const CLASSE_COR   = { tm_master:'var(--sky)', email:'var(--sun)', geral:'var(--muted)' };
const PRIO_LABEL   = { alta:'Alta', media:'Média', baixa:'Baixa' };
const PRIO_LABEL_EN = { alta:'High', media:'Medium', baixa:'Low' };
const PRIO_COR     = { alta:'var(--rose)', media:'var(--sun)', baixa:'var(--leaf)' };
const PRIO_SOFT    = { alta:'rgba(177,78,92,0.12)', media:'rgba(198,138,31,0.14)', baixa:'rgba(92,126,79,0.14)' };

const fmtFainaData = (d) => {
  if (!d) return '';
  const dt = new Date(d);
  if (isNaN(dt.getTime())) return '';
  return dt.toLocaleDateString('pt-BR', {day:'2-digit', month:'short', hour:'2-digit', minute:'2-digit'});
};

// Pílula de prioridade
const PrioPill = ({p}) => (
  <span style={{
    display:'inline-flex', alignItems:'center', gap:5, padding:'3px 9px', borderRadius:999,
    background: PRIO_SOFT[p]||'var(--cream-2)', color: PRIO_COR[p]||'var(--muted)',
    fontFamily:'var(--fm)', fontSize:11, fontWeight:600, whiteSpace:'nowrap'
  }}>
    <span style={{width:6,height:6,borderRadius:'50%',background: PRIO_COR[p]||'var(--muted)'}}/>
    {_brL(PRIO_LABEL, PRIO_LABEL_EN, p, useT().lang)||p}
  </span>
);

// Tag de classe
const ClassePill = ({c}) => (
  <span style={{
    display:'inline-block', padding:'2px 8px', borderRadius:6, fontFamily:'var(--fm)', fontSize:10.5,
    letterSpacing:0.3, color:'var(--surface)', background: CLASSE_COR[c]||'var(--muted)', whiteSpace:'nowrap'
  }}>{_brL(CLASSE_LABEL, CLASSE_LABEL_EN, c, useT().lang)||c}</span>
);

// ── Compressão de imagem no navegador (resize + JPEG) ──
function compressImage(file, maxW = 1280, quality = 0.72) {
  return new Promise((resolve, reject) => {
    if (!file.type.startsWith('image/')) { resolve(file); return; }
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      URL.revokeObjectURL(url);
      let { width, height } = img;
      if (width > maxW) { height = Math.round(height * maxW / width); width = maxW; }
      const canvas = document.createElement('canvas');
      canvas.width = width; canvas.height = height;
      canvas.getContext('2d').drawImage(img, 0, 0, width, height);
      canvas.toBlob(b => b ? resolve(b) : reject(new Error('Falha ao comprimir')), 'image/jpeg', quality);
    };
    img.onerror = () => { URL.revokeObjectURL(url); reject(new Error('Imagem inválida')); };
    img.src = url;
  });
}

// Comprime, sobe no /api/upload/photo e registra o anexo na faina
async function uploadAnexo(fainaId, file, token) {
  const blob = await compressImage(file);
  const fd = new FormData();
  fd.append('photo', blob, (file.name || 'foto').replace(/\.[^.]+$/, '') + '.jpg');
  const up = await fetch('/api/upload/photo', { method: 'POST', headers: { 'Authorization': `Bearer ${token()}` }, body: fd });
  const d = await up.json();
  if (!d.url) throw new Error(d.error || 'Upload falhou');
  await fetch(`/api/bridge/fainas/${fainaId}/anexos`, {
    method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token()}` },
    body: JSON.stringify({ url: d.url, nome: file.name || null })
  });
}

// ── Modal de anexos (ver/adicionar/remover fotos de uma faina) ──
const AnexosModal = ({token, toast, faina, onClose, onChanged}) => {
  const _tt = useT();
  const lang = _tt.lang;
  const [anexos, setAnexos] = useState([]);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const inputRef = React.useRef(null);

  const load = async () => {
    try {
      const r = await fetch(`/api/bridge/fainas/${faina.id}/anexos`, { headers: { 'Authorization': `Bearer ${token()}` } });
      if (r.ok) setAnexos(await r.json());
    } catch (e) {} finally { setLoading(false); }
  };
  useEffect(() => { load(); }, []);

  const addFiles = async (files) => {
    if (!files || !files.length) return;
    setBusy(true);
    try {
      for (const f of Array.from(files)) await uploadAnexo(faina.id, f, token);
      toast.push({ icon: 'check', title: files.length > 1 ? 'Fotos anexadas' : 'Foto anexada' });
      await load(); onChanged && onChanged();
    } catch (e) { toast.push({ icon: 'x', title: (lang==='pt'?'Erro no anexo':'Attachment error'), body: e.message }); }
    finally { setBusy(false); }
  };

  const remover = async (id) => {
    if (!window.confirm('Remover este anexo?')) return;
    setBusy(true);
    try {
      await fetch(`/api/bridge/anexos/${id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token()}` } });
      await load(); onChanged && onChanged();
    } catch (e) {} finally { setBusy(false); }
  };

  return (
    <div style={{position:'fixed',inset:0,zIndex:210,background:'rgba(31,42,46,0.55)',backdropFilter:'blur(3px)',display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'6vh 16px',overflowY:'auto'}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:460,maxHeight:'88vh',overflowY:'auto',background:'var(--cream)',borderRadius:24,padding:'24px 26px'}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:10,marginBottom:6}}>
          <div style={{fontFamily:'var(--fs)',fontSize:22,letterSpacing:'-0.4px'}}>Anexos</div>
          <button className="btn btn-sm" onClick={onClose}>{lang==='pt'?'fechar':'close'}</button>
        </div>
        <div style={{fontFamily:'var(--fm)',fontSize:11.5,color:'var(--muted)',marginBottom:16,lineHeight:1.4}}>{faina.descricao}</div>

        {loading ? <div style={{color:'var(--muted)',fontFamily:'var(--fm)',fontSize:12}}>{lang==='pt'?'Carregando…':'Loading…'}</div> : (
          <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(120px,1fr))',gap:10,marginBottom:16}}>
            {anexos.map(a => (
              <div key={a.id} style={{position:'relative',borderRadius:12,overflow:'hidden',border:'1px solid var(--line)',aspectRatio:'1',background:'var(--cream-2)'}}>
                <a href={a.url} target="_blank" rel="noopener">
                  <img src={a.url} alt={a.nome||''} style={{width:'100%',height:'100%',objectFit:'cover',display:'block'}}/>
                </a>
                <button onClick={()=>remover(a.id)} title="Remover" style={{position:'absolute',top:5,right:5,width:24,height:24,borderRadius:'50%',border:'none',background:'rgba(31,42,46,0.7)',color:'#fff',cursor:'pointer',fontSize:12,lineHeight:1}}>×</button>
              </div>
            ))}
            {anexos.length === 0 && <div style={{gridColumn:'1/-1',fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',fontStyle:'italic'}}>{lang==='pt'?'Nenhum anexo ainda.':'No attachments yet.'}</div>}
          </div>
        )}

        <input ref={inputRef} type="file" accept="image/*" multiple style={{display:'none'}}
          onChange={e=>{ const fs = Array.from(e.target.files || []); e.target.value=''; if (fs.length) addFiles(fs); }}/>
        <button className="btn btn-primary" style={{width:'100%'}} disabled={busy} onClick={()=>inputRef.current && inputRef.current.click()}>
          {busy ? (lang==='pt'?'Enviando…':'Sending…') : '📷 Adicionar foto'}
        </button>
        <div style={{fontFamily:'var(--fm)',fontSize:10,color:'var(--muted)',textAlign:'center',marginTop:8}}>As fotos são comprimidas automaticamente antes do envio.</div>
      </div>
    </div>
  );
};

// ── Modal de cadastro/edição rápida ──
const FainaModal = ({token, toast, pessoas, faina, onClose, onSaved}) => {
  const _tt = useT();
  const lang = _tt.lang;
  const editMode = !!faina;
  const [form, setForm] = useState(editMode ? {
    descricao: faina.descricao||'', classe: faina.classe||'geral',
    prioridade: faina.prioridade||'media', responsavel_id: faina.responsavel_id||'',
    prazo: faina.prazo ? String(faina.prazo).slice(0,10) : ''
  } : { descricao:'', classe:'geral', prioridade:'media', responsavel_id:'', prazo:'' });
  const [saving, setSaving] = useState(false);
  const [pending, setPending] = useState([]);   // Files a anexar após salvar
  const fileRef = React.useRef(null);

  const save = async () => {
    if (!form.descricao.trim()) { toast.push({icon:'x', title:(lang==='pt'?'Descreva a faina':'Describe the task')}); return; }
    setSaving(true);
    try {
      const res = await fetch(editMode ? `/api/bridge/fainas/${faina.id}` : '/api/bridge/fainas', {
        method: editMode ? 'PATCH' : 'POST',
        headers: {'Content-Type':'application/json','Authorization':`Bearer ${token()}`},
        body: JSON.stringify(form)
      });
      if (res.ok) {
        const saved = await res.json().catch(()=>({}));
        const fainaId = saved.id || (faina && faina.id);
        if (pending.length && fainaId) {
          for (const f of pending) { try { await uploadAnexo(fainaId, f, token); } catch(e){} }
        }
        toast.push({icon:'check', title: editMode?(lang==='pt'?'Faina atualizada':'Task updated'):'Faina lançada no quadro'}); onSaved();
      }
      else { const d = await res.json(); toast.push({icon:'x', title:'Erro', body:d.error}); }
    } catch(e) { toast.push({icon:'x', title:(lang==='pt'?'Erro de conexão':'Connection error')}); }
    finally { setSaving(false); }
  };

  const remover = async () => {
    if (!window.confirm((lang==='pt'?'Excluir esta faina?':'Delete this task?'))) return;
    setSaving(true);
    try {
      const res = await fetch(`/api/bridge/fainas/${faina.id}`, { method:'DELETE', headers:{'Authorization':`Bearer ${token()}`} });
      if (res.ok) { toast.push({icon:'check', title:'Faina excluída'}); onSaved(); }
    } catch(e) { toast.push({icon:'x', title:'Erro'}); }
    finally { setSaving(false); }
  };

  return (
    <div style={{position:'fixed',inset:0,zIndex:200,background:'rgba(31,42,46,0.55)',backdropFilter:'blur(3px)',display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'6vh 16px',overflowY:'auto'}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:480,maxHeight:'88vh',overflowY:'auto',background:'var(--cream)',borderRadius:24,padding:'26px 28px'}}>
        <div style={{fontFamily:'var(--fs)',fontSize:26,letterSpacing:'-0.5px',marginBottom:18}}>
          {editMode?'Editar':'Nova'} <em style={{fontStyle:'italic',color:'var(--accent)'}}>faina</em>
        </div>

        <label className="label">{lang==='pt'?'O que precisa ser feito?':'What needs to be done?'}</label>
        <textarea className="input" style={{width:'100%',boxSizing:'border-box',minHeight:64,resize:'vertical',marginBottom:14}}
          placeholder="Ex.: trocar a placa da boia de bombordo" value={form.descricao}
          onChange={e=>setForm(f=>({...f,descricao:e.target.value}))} autoFocus/>

        <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12,marginBottom:14}}>
          <div>
            <label className="label">{lang==='pt'?'Prioridade':'Priority'}</label>
            <select className="input select" style={{width:'100%',boxSizing:'border-box'}} value={form.prioridade}
              onChange={e=>setForm(f=>({...f,prioridade:e.target.value}))}>
              <option value="baixa">{lang==='pt'?'Baixa':'Low'}</option>
              <option value="media">{lang==='pt'?'Média':'Medium'}</option>
              <option value="alta">{lang==='pt'?'Alta':'High'}</option>
            </select>
          </div>
          <div>
            <label className="label">{lang==='pt'?'Classe':'Class'}</label>
            <select className="input select" style={{width:'100%',boxSizing:'border-box'}} value={form.classe}
              onChange={e=>setForm(f=>({...f,classe:e.target.value}))}>
              <option value="geral">{lang==='pt'?'Geral':'General'}</option>
              <option value="tm_master">TM Master</option>
              <option value="email">E-mail</option>
            </select>
          </div>
        </div>

        <label className="label">{lang==='pt'?'Responsável':'Owner'}</label>
        <select className="input select" style={{width:'100%',boxSizing:'border-box',marginBottom:6}} value={form.responsavel_id}
          onChange={e=>setForm(f=>({...f,responsavel_id:e.target.value}))}>
          <option value="">{lang==='pt'?'Em aberto (quem quiser puxa)':'Open (anyone can take it)'}</option>
          {pessoas.map(p => <option key={p.id} value={p.id}>{p.nome}</option>)}
        </select>
        <label className="label">{lang==='pt'?'Prazo':'Due date'} <span style={{color:'var(--muted-2)',fontWeight:400}}>{lang==='pt'?'(opcional — vencida sobe no quadro e avisa o responsável)':'(optional — overdue rises and notifies the owner)'}</span></label>
        <div style={{display:'flex',gap:8,alignItems:'center',marginBottom:6}}>
          <input className="input" type="date" value={form.prazo} onChange={e=>setForm(f=>({...f,prazo:e.target.value}))} style={{flex:1,boxSizing:'border-box'}}/>
          {form.prazo && <button className="btn btn-sm" onClick={()=>setForm(f=>({...f,prazo:''}))}>{lang==='pt'?'sem prazo':'no due date'}</button>}
        </div>
        <div style={{display:'flex',gap:6,marginBottom:14,flexWrap:'wrap'}}>
          {[['hoje',0],['amanhã',1],['+3 dias',3],['+7 dias',7]].map(([rot,n])=>(
            <button key={rot} type="button" className="btn btn-sm" style={{fontSize:11,padding:'4px 10px'}}
              onClick={()=>{ const d = new Date(Date.now()+n*864e5); setForm(f=>({...f,prazo:d.toISOString().slice(0,10)})); }}>{rot}</button>
          ))}
        </div>
        <label className="label">{lang==='pt'?'Anexos (opcional)':'Attachments (optional)'}</label>
        <input ref={fileRef} type="file" accept="image/*" multiple style={{display:'none'}}
          onChange={e=>{ const fs = Array.from(e.target.files || []); e.target.value=''; if (fs.length) setPending(p=>[...p, ...fs]); }}/>
        <div style={{display:'flex',gap:8,flexWrap:'wrap',alignItems:'center',marginBottom:20}}>
          <button type="button" className="btn btn-sm" onClick={()=>fileRef.current && fileRef.current.click()}>📷 Anexar foto</button>
          {pending.map((f,i)=>(
            <div key={i} style={{position:'relative',width:46,height:46,borderRadius:8,overflow:'hidden',border:'1px solid var(--line)'}}>
              <img src={URL.createObjectURL(f)} alt="" style={{width:'100%',height:'100%',objectFit:'cover'}}/>
              <button type="button" onClick={()=>setPending(p=>p.filter((_,j)=>j!==i))} style={{position:'absolute',top:1,right:1,width:16,height:16,borderRadius:'50%',border:'none',background:'rgba(31,42,46,0.75)',color:'#fff',cursor:'pointer',fontSize:10,lineHeight:1}}>×</button>
            </div>
          ))}
          {pending.length>0 && <span style={{fontFamily:'var(--fm)',fontSize:10,color:'var(--muted)'}}>{pending.length} foto{pending.length>1?'s':''} · comprimidas no envio</span>}
        </div>

        <div style={{display:'flex',gap:10,alignItems:'center'}}>
          {editMode && <button className="btn" onClick={remover} disabled={saving} style={{color:'var(--rose)',borderColor:'var(--rose)',background:'transparent'}}>{lang==='pt'?'Excluir':'Delete'}</button>}
          <div style={{flex:1}}/>
          <button className="btn" onClick={onClose}>{lang==='pt'?'Cancelar':'Cancel'}</button>
          <button className="btn-tidal" onClick={save} disabled={saving}>{saving?'Salvando…':(editMode?'Salvar':'Lançar')}</button>
        </div>
      </div>
    </div>
  );
};

// ── Linha de faina (desktop) ──
// ─── Tempo visível: idade, prazo e score de urgência ─────────────────────────
const _fainaIdadeDias = (f) => Math.max(0, Math.floor((Date.now() - new Date(f.created_at).getTime()) / 86400000));
const _fainaVencida = (f) => { if (!f.prazo) return false; const p = new Date(String(f.prazo).slice(0,10) + 'T23:59:59'); return p < new Date(); };
const _fainaDiasPrazo = (f) => { const p = new Date(String(f.prazo).slice(0,10) + 'T23:59:59'); return Math.floor((p - new Date()) / 86400000); };
const _fainaScore = (f) => (f.orfa ? 2 : 0) + (!f.responsavel_id ? 2 : 0) + (({alta:3, media:2, baixa:1})[f.prioridade] || 1) * 2 + Math.min(_fainaIdadeDias(f), 30) / 10 + (_fainaVencida(f) ? 6 : 0);
// Explica, em linguagem humana, por que a faina está no topo do quadro
const _fainaMotivos = (f) => {
  const m = [];
  if (_fainaVencida(f)) m.push('prazo vencido');
  if (f.orfa) m.push('órfã (dono desembarcou)');
  if (!f.responsavel_id) m.push('sem responsável');
  if (f.prioridade === 'alta') m.push('prioridade alta');
  const idade = _fainaIdadeDias(f);
  if (idade > 10) m.push(`parada há ${idade} dias`);
  return m;
};
const _fainaFmtPrazo = (p) => { const d = new Date(String(p).slice(0,10) + 'T12:00'); return `${String(d.getDate()).padStart(2,'0')}/${String(d.getMonth()+1).padStart(2,'0')}`; };

// badge de idade/prazo com cor progressiva (cinza → âmbar → vermelho)
const FainaIdade = ({f}) => {
  const idade = _fainaIdadeDias(f);
  const pills = [];
  const corIdade = idade <= 3 ? 'var(--muted-2)' : idade <= 10 ? 'var(--sun)' : 'var(--rose)';
  pills.push(
    <span key="idade" title={`criada há ${idade} dia${idade===1?'':'s'}`} style={{fontFamily:'var(--fm)',fontSize:9.5,color:corIdade,fontWeight:idade>10?700:500,whiteSpace:'nowrap'}}>
      {idade === 0 ? 'hoje' : `há ${idade}d`}
    </span>
  );
  if (f.prazo) {
    const venc = _fainaVencida(f);
    const dias = _fainaDiasPrazo(f);
    const rotulo = venc ? `⏰ vencida há ${Math.max(1, Math.abs(dias))}d` : dias === 0 ? '⏰ vence hoje' : dias === 1 ? '⏰ vence amanhã' : `⏰ ${_fainaFmtPrazo(f.prazo)}`;
    pills.push(
      <span key="prazo" title={venc ? `prazo vencido (${_fainaFmtPrazo(f.prazo)})` : `prazo: ${_fainaFmtPrazo(f.prazo)}`}
        style={{fontFamily:'var(--fm)',fontSize:9.5,fontWeight:600,whiteSpace:'nowrap',padding:'1px 7px',borderRadius:999,
          background: venc ? 'var(--rose)' : dias <= 2 ? 'rgba(198,138,31,0.18)' : 'var(--cream-2)',
          color: venc ? '#fff' : dias <= 2 ? '#8B6313' : 'var(--muted)'}}>
        {rotulo}
      </span>
    );
  }
  return <span style={{display:'inline-flex',alignItems:'center',gap:6}}>{pills}</span>;
};

// sinais compactos: anexos, subtasks, comentários
const FainaSinais = ({f, onAnexos}) => {
  const nAnexos = Number(f.anexos_count) || 0;
  const subsT = Number(f.subs_total) || 0, subsF = Number(f.subs_feitas) || 0;
  const nUpd = Number(f.updates_count) || 0;
  return (
    <span style={{display:'inline-flex',alignItems:'center',gap:9,fontFamily:'var(--fm)',fontSize:11.5}}>
      <button onClick={(e)=>{ e.stopPropagation(); onAnexos(f); }} title="anexos" style={{background:'transparent',border:'none',cursor:'pointer',fontFamily:'var(--fm)',fontSize:11.5,color:nAnexos>0?'var(--ink)':'var(--muted-3)',padding:0}}>📎{nAnexos>0?` ${nAnexos}`:''}</button>
      {subsT > 0 && <span title={`${subsF} de ${subsT} etapas feitas`} style={{color: subsF===subsT ? 'var(--leaf)' : 'var(--muted)'}}>☑ {subsF}/{subsT}</span>}
      {nUpd > 0 && <span title={`${nUpd} atualização(ões)${f.ultima_atividade ? ' · última ' + fmtFainaData(f.ultima_atividade) : ''}`} style={{color:'var(--muted)'}}>💬 {nUpd}</span>}
    </span>
  );
};

// ─── Concluir com nota de fechamento (opcional — vira conhecimento no histórico) ───
const ConcluirFainaModal = ({ faina, onConfirmar, onClose }) => {
  const lang = useT().lang;
  const [nota, setNota] = useState('');
  const [busy, setBusy] = useState(false);
  return (
    <div onClick={onClose} style={{position:'fixed',inset:0,zIndex:8200,background:'rgba(31,42,46,0.5)',backdropFilter:'blur(4px)',display:'flex',alignItems:'center',justifyContent:'center',padding:16}}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:420,background:'var(--cream)',borderRadius:20,padding:'20px 22px',boxShadow:'var(--shadow-lg)'}}>
        <div style={{fontFamily:'var(--fs)',fontSize:19,marginBottom:4}}>{lang==='pt'?<>Concluir <em style={{fontStyle:'italic',color:'var(--leaf)'}}>faina</em></>:<>Complete <em style={{fontStyle:'italic',color:'var(--leaf)'}}>task</em></>}</div>
        <div style={{fontFamily:'var(--fm)',fontSize:11.5,color:'var(--muted)',marginBottom:12,lineHeight:1.4}}>{faina.descricao}</div>
        <div className="label">{lang==='pt'?'Como resolveu?':'How did you solve it?'} <span style={{color:'var(--muted-2)',fontWeight:400}}>{lang==='pt'?'(opcional — fica no histórico pra próxima vez)':'(optional — stays in history for next time)'}</span></div>
        <textarea className="input" autoFocus value={nota} onChange={e=>setNota(e.target.value)} placeholder={lang==='pt'?'ex.: patch 4.2 aplicado, precisa reiniciar o servidor depois…':'e.g.: patch 4.2 applied, server needs a restart after…'}
          onKeyDown={e=>{ if (e.key==='Enter' && (e.metaKey||e.ctrlKey)) { setBusy(true); onConfirmar(nota.trim()||null); } }}
          style={{width:'100%',boxSizing:'border-box',minHeight:64,resize:'vertical',marginBottom:12}}/>
        <div style={{display:'flex',justifyContent:'flex-end',gap:8}}>
          <button className="btn" onClick={onClose}>{lang==='pt'?'Cancelar':'Cancel'}</button>
          <button className="btn-tidal verde" disabled={busy} onClick={()=>{ setBusy(true); onConfirmar(nota.trim()||null); }}>{lang==='pt'?'✓ Concluir':'✓ Complete'}</button>
        </div>
      </div>
    </div>
  );
};

// ─── Redistribuir órfãs: escolhe quais, pra quem — ou distribui pela carga ───
const OrfasModal = ({ token, pessoas, fainas, onEscolher, onDistribuir, onClose }) => {
  const lang = useT().lang;
  const [busy, setBusy] = useState(false);
  const [cargas, setCargas] = useState({});      // user_id → {peso, total}
  const orfas = fainas.filter(f => f.orfa);
  const [sel, setSel] = useState(() => orfas.map(f => f.id));   // default: todas
  useEffect(() => {
    fetch('/api/bridge/fainas/overview', { headers:{'Authorization':`Bearer ${token()}`} })
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d && d.pessoas) { const m = {}; d.pessoas.forEach(p => m[p.responsavel_id] = p); setCargas(m); } })
      .catch(() => {});
  }, []);
  const toggle = (id) => setSel(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const escolher = (fn, arg) => { if (!sel.length || busy) return; setBusy(true); fn(arg); };
  const cargaDe = (u) => { const c = cargas[u.user_id != null ? u.user_id : u.id]; return c ? tempCarga(c.peso) : null; };
  return (
    <div onClick={onClose} style={{position:'fixed',inset:0,zIndex:8200,background:'rgba(31,42,46,0.5)',backdropFilter:'blur(4px)',display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'6vh 16px',overflowY:'auto'}}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:520,background:'var(--cream)',borderRadius:20,padding:'20px 22px',boxShadow:'var(--shadow-lg)'}}>
        <div style={{fontFamily:'var(--fs)',fontSize:19,marginBottom:4}}>{lang==='pt'?<>Redistribuir <em style={{fontStyle:'italic',color:'var(--accent)'}}>órfãs</em></>:<>Reassign <em style={{fontStyle:'italic',color:'var(--accent)'}}>orphans</em></>}</div>
        <div style={{fontFamily:'var(--fm)',fontSize:11.5,color:'var(--muted)',marginBottom:12}}>
          {lang==='pt'?'Marque as fainas e escolha o destino — ou deixe o quadro dividir pela carga atual.':'Pick the tasks and a destination — or let the board split by current load.'}
        </div>

        {/* seleção das órfãs */}
        <div style={{display:'grid',gap:6,maxHeight:'26vh',overflowY:'auto',marginBottom:14,paddingRight:2}}>
          {orfas.map(f => (
            <label key={f.id} style={{display:'flex',alignItems:'center',gap:10,padding:'8px 11px',borderRadius:11,cursor:'pointer',background: sel.includes(f.id)?'var(--accent-soft)':'var(--surface)',border:'1px solid var(--line-soft)'}}>
              <input type="checkbox" checked={sel.includes(f.id)} onChange={()=>toggle(f.id)} style={{width:15,height:15,accentColor:'var(--accent)',cursor:'pointer',flexShrink:0}}/>
              <span style={{flex:1,fontFamily:'var(--f)',fontSize:13,lineHeight:1.3,color:'var(--ink)'}}>{f.descricao}</span>
              <PrioPill p={f.prioridade}/>
            </label>
          ))}
        </div>
        <div style={{fontFamily:'var(--fm)',fontSize:10.5,color:'var(--muted)',marginBottom:10}}>{sel.length} {lang==='pt'?'de':'of'} {orfas.length} {lang==='pt'?'selecionada(s)':'selected'}</div>

        {/* destino único com carga visível */}
        <div style={{fontFamily:'var(--fm)',fontSize:10,letterSpacing:1,textTransform:'uppercase',color:'var(--muted)',marginBottom:8}}>{lang==='pt'?'dar todas pra':'give all to'}</div>
        <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill, minmax(104px, 1fr))',gap:8,maxHeight:'24vh',overflowY:'auto',marginBottom:12}}>
          {pessoas.map(u => {
            const t = cargaDe(u);
            return (
              <button key={u.user_id || u.id} disabled={busy || !sel.length} onClick={()=>escolher(onEscolher, { pessoa: u, ids: sel })}
                style={{display:'flex',flexDirection:'column',alignItems:'center',gap:4,padding:'11px 6px 9px',borderRadius:14,cursor:'pointer',border:'2px solid var(--line-soft)',background:'var(--surface)',opacity:(busy||!sel.length)?0.55:1}}>
                <FainaAvatar foto={u.foto_url} initials={u.initials} nome={u.nome} size={38}/>
                <span style={{fontFamily:'var(--f)',fontSize:11.5,color:'var(--ink)',lineHeight:1.2,textAlign:'center',maxWidth:'100%',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{u.nome}</span>
                {t && <span style={{fontFamily:'var(--fm)',fontSize:9,color:t.cor,fontWeight:600}}>{t.label}</span>}
              </button>
            );
          })}
        </div>
        <div style={{display:'flex',gap:8,justifyContent:'space-between',alignItems:'center'}}>
          <button className="btn btn-sm" disabled={busy || !sel.length} onClick={()=>escolher(onDistribuir, sel)} style={{color:'var(--teal)',borderColor:'var(--teal)'}}>
            ⚖ {lang==='pt'?'distribuir pela carga':'split by load'}
          </button>
          <button className="btn btn-sm" onClick={onClose}>{lang==='pt'?'cancelar':'cancel'}</button>
        </div>
      </div>
    </div>
  );
};

// chip "por que está no topo" — a ordenação deixa de ser mágica
const FainaMotivo = ({f}) => {
  const motivos = _fainaMotivos(f);
  if (!motivos.length) return null;
  return (
    <span title={`no topo porque: ${motivos.join(' · ')}`}
      style={{fontFamily:'var(--fm)',fontSize:9,color:'var(--accent)',background:'var(--accent-soft)',borderRadius:999,padding:'1px 8px',whiteSpace:'nowrap',cursor:'help'}}>
      ⏫ {motivos[0]}{motivos.length > 1 ? ` +${motivos.length-1}` : ''}
    </span>
  );
};

const FainaRow = ({f, me, canManage, onAssumir, onConcluir, onEdit, onAnexos, onOpen}) => {
  const lang = useT().lang;
  const minha = f.responsavel_id === me.id;
  const emAberto = !f.responsavel_id;
  const nAnexos = Number(f.anexos_count) || 0;
  return (
    <tr onClick={()=>onOpen(f)} style={{borderBottom:'1px solid var(--line-soft)',cursor:'pointer'}}
      onMouseEnter={e=>e.currentTarget.style.background='var(--cream-2)'} onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
      <td style={{padding:'12px 10px',verticalAlign:'top'}}>
        <div style={{fontFamily:'var(--fs)',fontSize:15,lineHeight:1.3,color:'var(--ink)'}}>{f.descricao}</div>
        {f.orfa && (
          <div style={{fontFamily:'var(--fm)',fontSize:10.5,color:'var(--rose)',marginTop:3}}>
            ⚠ {lang==='pt'?'órfã':'orphan'}{f.dono_anterior_nome?(lang==='pt'?` — estava com ${f.dono_anterior_nome}`:` — was with ${f.dono_anterior_nome}`):''}
          </div>
        )}
        <div style={{display:'flex',alignItems:'center',gap:8,marginTop:4,flexWrap:'wrap'}}>
          <FainaIdade f={f}/>
          <FainaMotivo f={f}/>
          <span style={{fontFamily:'var(--fm)',fontSize:10,color:'var(--muted-2)'}}>{f.criado_por_nome?`${lang==='pt'?'por':'by'} ${f.criado_por_nome.split(' ')[0]}`:''} · {fmtFainaData(f.created_at)}</span>
        </div>
      </td>
      <td style={{padding:'12px 10px',verticalAlign:'top'}}><ClassePill c={f.classe}/></td>
      <td style={{padding:'12px 10px',verticalAlign:'top'}}><PrioPill p={f.prioridade}/></td>
      <td style={{padding:'12px 10px',verticalAlign:'top'}}>
        {emAberto
          ? <span style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',fontStyle:'italic'}}>{lang==='pt'?'Em aberto':'Open'}</span>
          : <span style={{fontFamily:'var(--f)',fontSize:13,fontWeight:minha?600:400,color:minha?'var(--teal)':'var(--ink)'}}>{f.responsavel_nome||'—'}{minha?(lang==='pt'?' (você)':' (you)'):''}</span>}
      </td>
      <td style={{padding:'12px 10px',verticalAlign:'top',textAlign:'center',whiteSpace:'nowrap'}}>
        <FainaSinais f={f} onAnexos={onAnexos}/>
      </td>
      <td style={{padding:'12px 10px',verticalAlign:'top',whiteSpace:'nowrap',textAlign:'right'}}>
        {emAberto && <button className="btn-icone sm" onClick={(e)=>{ e.stopPropagation(); onAssumir(f); }} title="puxar pra mim" style={{marginRight:6}}>✋</button>}
        {(minha || canManage) && <button className="btn btn-sm" onClick={(e)=>{ e.stopPropagation(); onConcluir(f); }} title="Concluir" style={{color:'var(--leaf)',borderColor:'var(--leaf)',marginRight:6}}>✓</button>}
        {canManage && <button onClick={(e)=>{ e.stopPropagation(); onEdit(f); }} title="Editar" style={{background:'transparent',border:'none',cursor:'pointer',fontSize:14,color:'var(--muted)'}}>✏️</button>}
      </td>
    </tr>
  );
};

// ── Card de faina (mobile) ──
const FainaCard = ({f, me, canManage, onAssumir, onConcluir, onEdit, onAnexos, onOpen}) => {
  const lang = useT().lang;
  const minha = f.responsavel_id === me.id;
  const emAberto = !f.responsavel_id;
  const nAnexos = Number(f.anexos_count) || 0;
  return (
    <div onClick={()=>onOpen(f)} style={{cursor:'pointer',background:'var(--surface)',border:'1px solid var(--line-soft)',borderTop:`3px solid ${PRIO_COR[f.prioridade]||'var(--accent)'}`,borderRadius:16,padding:'14px 16px',boxShadow:'var(--shadow-sm)'}}>
      <div style={{display:'flex',justifyContent:'space-between',gap:10,marginBottom:8}}>
        <PrioPill p={f.prioridade}/>
        <ClassePill c={f.classe}/>
      </div>
      <div style={{fontFamily:'var(--fs)',fontSize:16,lineHeight:1.3,marginBottom:6}}>{f.descricao}</div>
      {f.orfa && <div style={{fontFamily:'var(--fm)',fontSize:11,color:'var(--rose)',marginBottom:6}}>⚠ {lang==='pt'?'órfã':'orphan'}{f.dono_anterior_nome?(lang==='pt'?` — estava com ${f.dono_anterior_nome}`:` — was with ${f.dono_anterior_nome}`):''}</div>}
      <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:8,flexWrap:'wrap'}}>
        <FainaIdade f={f}/>
        <FainaMotivo f={f}/>
        <FainaSinais f={f} onAnexos={onAnexos}/>
      </div>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:8,flexWrap:'wrap'}}>
        <span style={{fontFamily:'var(--fm)',fontSize:12,color:emAberto?'var(--muted)':'var(--teal)',fontStyle:emAberto?'italic':'normal'}}>
          {emAberto?'Em aberto':(f.responsavel_nome+(minha?(lang==='pt'?' (você)':' (you)'):''))}
        </span>
        <div style={{display:'flex',gap:6}}>
          {emAberto && <button className="btn-icone sm" onClick={(e)=>{ e.stopPropagation(); onAssumir(f); }} title="puxar pra mim">✋</button>}
          <button className="btn btn-sm" onClick={(e)=>{ e.stopPropagation(); onConcluir(f); }} style={{color:'var(--leaf)',borderColor:'var(--leaf)'}}>✓</button>
          {canManage && <button onClick={(e)=>{ e.stopPropagation(); onEdit(f); }} style={{background:'transparent',border:'none',cursor:'pointer',fontSize:16,color:'var(--muted)'}}>✏️</button>}
        </div>
      </div>
    </div>
  );
};

// Sobe uma foto (comprimida) e devolve só a URL (sem registrar como anexo)
async function uploadFoto(file, token) {
  const blob = await compressImage(file);
  const fd = new FormData();
  fd.append('photo', blob, 'foto.jpg');
  const up = await fetch('/api/upload/photo', { method: 'POST', headers: { 'Authorization': `Bearer ${token()}` }, body: fd });
  const d = await up.json();
  if (!d.url) throw new Error(d.error || 'Upload falhou');
  return d.url;
}

const LOG_LABEL = { criada:'Faina criada', assumida:'Puxada pra si', editada:'Editada', concluida:'Concluída', reaberta:'Reaberta', update:'Atualização', orfa:'Ficou órfã (dono desembarcou)' };
const LOG_LABEL_EN = { criada:'Task created', assumida:'Taken over', editada:'Edited', concluida:'Completed', reaberta:'Reopened', update:'Update', orfa:'Orphaned (owner disembarked)' };
const LOG_ICON  = { criada:'🗒️', assumida:'✋', editada:'✏️', concluida:'✓', reaberta:'↩', update:'💬', orfa:'⚓' };
const primeiroNome = (n) => (n||'').split(' ')[0];

// Seção do dossiê (definida fora do componente p/ não recriar a cada tecla)
const Sec = ({title, extra, children}) => (
  <div style={{marginTop:22}}>
    <div style={{display:'flex',alignItems:'baseline',justifyContent:'space-between',marginBottom:10}}>
      <div className="t-eyebrow" style={{color:'var(--accent)'}}>{title}</div>
      {extra}
    </div>
    {children}
  </div>
);

// ── Dossiê da faina ──
const FainaDossie = ({token, toast, me, canManage, faina, onClose, onChanged, onEdit, onConcluir}) => {
  const _tt = useT();
  const lang = _tt.lang;
  const [data, setData] = useState(null);
  const [novoUpdate, setNovoUpdate] = useState('');
  const [updateFoto, setUpdateFoto] = useState(null);
  const [novaSub, setNovaSub] = useState('');
  const [busy, setBusy] = useState(false);
  const updFileRef = React.useRef(null);
  const anexoRef = React.useRef(null);

  const load = async () => {
    try {
      const r = await fetch(`/api/bridge/fainas/${faina.id}/detalhe`, { headers:{'Authorization':`Bearer ${token()}`} });
      if (r.ok) setData(await r.json());
    } catch(e) {}
  };
  useEffect(() => { load(); }, []);

  const refresh = () => { load(); onChanged && onChanged(); };

  const f = (data && data.faina) || faina;
  const emAberto = !f.responsavel_id;
  const minha = f.responsavel_id === me.id;

  // ações principais
  const assumir = async () => {
    const r = await fetch(`/api/bridge/fainas/${f.id}/assumir`,{method:'PATCH',headers:{'Authorization':`Bearer ${token()}`}});
    if (r.ok) { toast.push({icon:'check',title:(lang==='pt'?'Faina é sua!':'The task is yours!')}); refresh(); }
    else { const d = await r.json().catch(()=>({})); toast.push({icon:'x',title:(lang==='pt'?'Não deu pra puxar':'Could not take it'),body:d.error}); }
  };
  const concluir = () => { onClose(); onConcluir && onConcluir(f); };   // sempre pelo modal de nota — o "como resolveu" não se perde
  const podeConcluir = minha || canManage;

  // updates
  const enviarUpdate = async () => {
    if (!novoUpdate.trim() && !updateFoto) { toast.push({icon:'x',title:(lang==='pt'?'Escreva algo ou anexe uma foto':'Write something or attach a photo')}); return; }
    setBusy(true);
    try {
      let url = null;
      if (updateFoto) url = await uploadFoto(updateFoto, token);
      await fetch(`/api/bridge/fainas/${f.id}/updates`, {
        method:'POST', headers:{'Content-Type':'application/json','Authorization':`Bearer ${token()}`},
        body: JSON.stringify({ texto: novoUpdate.trim(), url })
      });
      setNovoUpdate(''); setUpdateFoto(null); load();
    } catch(e) { toast.push({icon:'x',title:'Erro',body:e.message}); }
    finally { setBusy(false); }
  };
  const delUpdate = async (id) => { await fetch(`/api/bridge/updates/${id}`,{method:'DELETE',headers:{'Authorization':`Bearer ${token()}`}}); load(); };

  // subtasks
  const addSub = async () => {
    if (!novaSub.trim()) return;
    await fetch(`/api/bridge/fainas/${f.id}/subtasks`, { method:'POST', headers:{'Content-Type':'application/json','Authorization':`Bearer ${token()}`}, body: JSON.stringify({ texto: novaSub.trim() }) });
    setNovaSub(''); load();
  };
  const toggleSub = async (s) => { await fetch(`/api/bridge/subtasks/${s.id}`,{method:'PATCH',headers:{'Content-Type':'application/json','Authorization':`Bearer ${token()}`},body:JSON.stringify({feito:!s.feito})}); load(); };
  const delSub = async (id) => { await fetch(`/api/bridge/subtasks/${id}`,{method:'DELETE',headers:{'Authorization':`Bearer ${token()}`}}); load(); };

  // anexos
  const addAnexos = async (files) => {
    if (!files || !files.length) return;
    setBusy(true);
    try { for (const file of Array.from(files)) await uploadAnexo(f.id, file, token); refresh(); }
    catch(e) { toast.push({icon:'x',title:(lang==='pt'?'Erro no anexo':'Attachment error'),body:e.message}); }
    finally { setBusy(false); }
  };
  const delAnexo = async (id) => { await fetch(`/api/bridge/anexos/${id}`,{method:'DELETE',headers:{'Authorization':`Bearer ${token()}`}}); refresh(); };

  const subs = (data && data.subtasks) || [];
  const subsFeitas = subs.filter(s=>s.feito).length;
  const updates = (data && data.updates) || [];
  const anexos = (data && data.anexos) || [];
  const log = (data && data.log) || [];

  return (
    <div style={{position:'fixed',inset:0,zIndex:210,background:'rgba(31,42,46,0.55)',backdropFilter:'blur(3px)',display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'4vh 14px',overflowY:'auto'}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:560,background:'var(--cream)',borderRadius:24,padding:'24px 26px',marginBottom:40}}>

        {/* Header */}
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:10}}>
          <div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
            <PrioPill p={f.prioridade}/><ClassePill c={f.classe}/>
            {f.orfa && <span style={{fontFamily:'var(--fm)',fontSize:10.5,color:'var(--rose)'}}>⚠ órfã</span>}
          </div>
          <button className="btn btn-sm" onClick={onClose}>{lang==='pt'?'fechar':'close'}</button>
        </div>
        <div style={{fontFamily:'var(--fs)',fontSize:23,letterSpacing:'-0.4px',lineHeight:1.2,margin:'12px 0 6px'}}>{f.descricao}</div>
        <div style={{fontFamily:'var(--fm)',fontSize:11.5,color:'var(--muted)'}}>
          {emAberto ? 'Em aberto' : <span style={{color:minha?'var(--teal)':'var(--ink)'}}>👤 {f.responsavel_nome}{minha?(lang==='pt'?' (você)':' (you)'):''}</span>}
          {f.criado_por_nome ? ` · aberta por ${primeiroNome(f.criado_por_nome)}` : ''} · {fmtFainaData(f.created_at)}
        </div>

        {/* Ações */}
        <div style={{display:'flex',gap:8,marginTop:14,flexWrap:'wrap'}}>
          {emAberto && <button className="btn-tidal" onClick={assumir}>✋ Puxar</button>}
          {podeConcluir && <button className="btn btn-sm" onClick={concluir} style={{color:'var(--leaf)',borderColor:'var(--leaf)'}}>{lang==='pt'?'✓ Concluir':'✓ Complete'}</button>}
          {canManage && <button className="btn btn-sm" onClick={()=>{ onClose(); onEdit(f); }}>✏️ Editar</button>}
        </div>

        {/* Sub-tarefas */}
        <Sec title="Sub-tarefas" extra={subs.length>0 && <span style={{fontFamily:'var(--fm)',fontSize:11,color:'var(--muted)'}}>{subsFeitas}/{subs.length}</span>}>
          <div style={{display:'grid',gap:6}}>
            {subs.map(s=>(
              <div key={s.id} style={{display:'flex',alignItems:'center',gap:9,background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:10,padding:'8px 11px'}}>
                <input type="checkbox" checked={s.feito} onChange={()=>toggleSub(s)} style={{width:16,height:16,accentColor:'var(--leaf)',cursor:'pointer',flexShrink:0}}/>
                <span style={{flex:1,fontFamily:'var(--f)',fontSize:13.5,color:s.feito?'var(--muted)':'var(--ink)',textDecoration:s.feito?'line-through':'none'}}>{s.texto}</span>
                <button onClick={()=>delSub(s.id)} style={{background:'transparent',border:'none',cursor:'pointer',color:'var(--muted-3)',fontSize:14}}>×</button>
              </div>
            ))}
          </div>
          <div style={{display:'flex',gap:8,marginTop:8}}>
            <input className="input" style={{flex:1}} placeholder="Nova sub-tarefa…" value={novaSub}
              onChange={e=>setNovaSub(e.target.value)} onKeyDown={e=>{ if(e.key==='Enter') addSub(); }}/>
            <button className="btn btn-sm" onClick={addSub}>+</button>
          </div>
        </Sec>

        {/* Atualizações */}
        <Sec title="Atualizações">
          {/* caixa de novo update */}
          <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,padding:'10px 12px'}}>
            <textarea className="input" style={{width:'100%',boxSizing:'border-box',minHeight:48,resize:'vertical',border:'none',boxShadow:'none',padding:0,background:'transparent'}}
              placeholder="Postar um andamento…" value={novoUpdate} onChange={e=>setNovoUpdate(e.target.value)}/>
            <input ref={updFileRef} type="file" accept="image/*" style={{display:'none'}} onChange={e=>{ const f = e.target.files && e.target.files[0]; e.target.value=''; if (f) setUpdateFoto(f); }}/>
            <div style={{display:'flex',alignItems:'center',gap:8,marginTop:6}}>
              <button className="btn btn-sm" onClick={()=>updFileRef.current&&updFileRef.current.click()}>📷</button>
              {updateFoto && <span style={{fontFamily:'var(--fm)',fontSize:10,color:'var(--leaf)'}}>1 foto ✓</span>}
              <div style={{flex:1}}/>
              <button className="btn btn-primary btn-sm" onClick={enviarUpdate} disabled={busy}>{busy?'…':'Postar'}</button>
            </div>
          </div>
          {/* feed */}
          <div style={{display:'grid',gap:10,marginTop:12}}>
            {updates.map(u=>(
              <div key={u.id} style={{display:'flex',gap:10}}>
                <div style={{width:30,height:30,borderRadius:'50%',background:'var(--teal)',color:'#fff',display:'grid',placeItems:'center',fontFamily:'var(--fm)',fontSize:11,flexShrink:0}}>{(primeiroNome(u.autor_nome)||'?').slice(0,1)}</div>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{fontFamily:'var(--fm)',fontSize:10.5,color:'var(--muted)'}}>{primeiroNome(u.autor_nome)} · {fmtFainaData(u.created_at)}
                    {(canManage || u.autor_id === me.id) && <button onClick={()=>delUpdate(u.id)} style={{background:'transparent',border:'none',cursor:'pointer',color:'var(--muted-3)',fontSize:11,marginLeft:6}}>{lang==='pt'?'excluir':'delete'}</button>}
                  </div>
                  {u.texto && <div style={{fontFamily:'var(--f)',fontSize:13.5,color:'var(--ink)',marginTop:2,whiteSpace:'pre-wrap'}}>{u.texto}</div>}
                  {u.url && <a href={u.url} target="_blank" rel="noopener"><img src={u.url} alt="" style={{maxWidth:160,borderRadius:10,marginTop:6,border:'1px solid var(--line)'}}/></a>}
                </div>
              </div>
            ))}
            {updates.length===0 && <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',fontStyle:'italic'}}>{lang==='pt'?'Sem atualizações ainda.':'No updates yet.'}</div>}
          </div>
        </Sec>

        {/* Anexos */}
        <Sec title="Anexos" extra={
          <>
            <input ref={anexoRef} type="file" accept="image/*" multiple style={{display:'none'}} onChange={e=>{ const fs = Array.from(e.target.files || []); e.target.value=''; if (fs.length) addAnexos(fs); }}/>
            <button className="btn btn-sm" disabled={busy} onClick={()=>anexoRef.current&&anexoRef.current.click()}>📷 Adicionar</button>
          </>
        }>
          {anexos.length===0 ? <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',fontStyle:'italic'}}>{lang==='pt'?'Nenhum anexo.':'No attachments.'}</div> : (
            <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(96px,1fr))',gap:8}}>
              {anexos.map(a=>(
                <div key={a.id} style={{position:'relative',borderRadius:10,overflow:'hidden',border:'1px solid var(--line)',aspectRatio:'1'}}>
                  <a href={a.url} target="_blank" rel="noopener"><img src={a.url} alt="" style={{width:'100%',height:'100%',objectFit:'cover',display:'block'}}/></a>
                  {(canManage || a.uploaded_by === me.id) && <button onClick={()=>delAnexo(a.id)} style={{position:'absolute',top:4,right:4,width:20,height:20,borderRadius:'50%',border:'none',background:'rgba(31,42,46,0.7)',color:'#fff',cursor:'pointer',fontSize:11,lineHeight:1}}>×</button>}
                </div>
              ))}
            </div>
          )}
        </Sec>

        {/* Histórico (log) */}
        <Sec title="Histórico">
          <div style={{display:'grid',gap:7}}>
            {log.map(l=>(
              <div key={l.id} style={{display:'flex',gap:9,alignItems:'baseline',fontFamily:'var(--fm)',fontSize:11.5}}>
                <span style={{flexShrink:0}}>{LOG_ICON[l.tipo]||'•'}</span>
                <span style={{color:'var(--ink)'}}>{_brL(LOG_LABEL, LOG_LABEL_EN, l.tipo, lang)}{l.texto?`: ${l.texto}`:''}</span>
                <div style={{flex:1,borderBottom:'1px dotted var(--line)',transform:'translateY(-3px)'}}/>
                <span style={{color:'var(--muted)',whiteSpace:'nowrap'}}>{primeiroNome(l.autor_nome)} · {fmtFainaData(l.created_at)}</span>
              </div>
            ))}
            {log.length===0 && <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',fontStyle:'italic'}}>{lang==='pt'?'Sem registros.':'No records.'}</div>}
          </div>
        </Sec>

      </div>
    </div>
  );
};

// ── Temperatura de carga (peso ponderado por prioridade) ──
const tempCarga = (peso) => peso<=4 ? {cor:'var(--leaf)', label:'tranquilo'} : peso<=9 ? {cor:'var(--sun)', label:'ocupado'} : {cor:'var(--rose)', label:'sobrecarregado'};

// Avatar (foto ou iniciais)
const FainaAvatar = ({foto, initials, nome, size=44}) => (
  foto
    ? <img src={foto} alt={nome||''} style={{width:size,height:size,borderRadius:'50%',objectFit:'cover',flexShrink:0}}/>
    : <div style={{width:size,height:size,borderRadius:'50%',background:'var(--teal)',color:'#fff',display:'grid',placeItems:'center',fontFamily:'var(--fm)',fontSize:size*0.34,flexShrink:0}}>{initials||(nome||'?').slice(0,1)}</div>
);

// ── Modal: configurar quem aparece no overview ──
const ConfigMembrosModal = ({token, toast, pessoas, onClose, onSaved}) => {
  const _tt = useT();
  const lang = _tt.lang;
  const [sel, setSel] = useState([]);
  const [loaded, setLoaded] = useState(false);
  useEffect(() => {
    fetch('/api/bridge/overview/membros', { headers:{'Authorization':`Bearer ${token()}`} })
      .then(r=>r.json()).then(ids=>{ setSel(ids.map(Number)); setLoaded(true); }).catch(()=>setLoaded(true));
  }, []);
  const toggle = (id) => setSel(s => s.includes(id) ? s.filter(x=>x!==id) : [...s, id]);
  const salvar = async () => {
    await fetch('/api/bridge/overview/membros', { method:'POST', headers:{'Content-Type':'application/json','Authorization':`Bearer ${token()}`}, body: JSON.stringify({ user_ids: sel }) });
    toast.push({icon:'check', title:'Quadro de carga atualizado'}); onSaved();
  };
  return (
    <div style={{position:'fixed',inset:0,zIndex:210,background:'rgba(31,42,46,0.55)',backdropFilter:'blur(3px)',display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'6vh 16px',overflowY:'auto'}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{width:'100%',maxWidth:440,maxHeight:'84vh',overflowY:'auto',background:'var(--cream)',borderRadius:24,padding:'24px 26px'}}>
        <div style={{fontFamily:'var(--fs)',fontSize:22,letterSpacing:'-0.4px'}}>{lang==='pt'?'Quem aparece na carga':'Who shows on the load board'}</div>
        <div style={{fontFamily:'var(--fm)',fontSize:11.5,color:'var(--muted)',marginTop:4,marginBottom:16,lineHeight:1.5}}>Quem está a bordo. Marque os oficiais que devem compor o quadro (normalmente os 3 + imediato).</div>
        {!loaded ? <div style={{color:'var(--muted)',fontFamily:'var(--fm)',fontSize:12}}>{lang==='pt'?'Carregando…':'Loading…'}</div> : (
          <div style={{display:'grid',gap:6,marginBottom:18}}>
            {pessoas.map(p=>(
              <label key={p.id} style={{display:'flex',alignItems:'center',gap:11,padding:'8px 10px',borderRadius:12,cursor:'pointer',background: sel.includes(p.id)?'var(--accent-soft)':'var(--surface)',border:'1px solid var(--line-soft)'}}>
                <input type="checkbox" checked={sel.includes(p.id)} onChange={()=>toggle(p.id)} style={{width:16,height:16,accentColor:'var(--accent)',cursor:'pointer'}}/>
                <FainaAvatar foto={p.foto_url} initials={p.initials} nome={p.nome} size={32}/>
                <span style={{fontFamily:'var(--f)',fontSize:13.5}}>{p.nome}</span>
              </label>
            ))}
            {pessoas.length===0 && <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',fontStyle:'italic'}}>{lang==='pt'?'Ninguém a bordo encontrado.':'Nobody aboard found.'}</div>}
          </div>
        )}
        <div style={{display:'flex',gap:10,justifyContent:'flex-end'}}>
          <button className="btn" onClick={onClose}>{lang==='pt'?'Cancelar':'Cancel'}</button>
          <button className="btn-tidal" onClick={salvar}>Salvar ({sel.length})</button>
        </div>
      </div>
    </div>
  );
};

// ── Overview — quadro de carga da equipe ──
const OverviewView = ({token, toast, pessoas, onPickPerson, isMobile, reload, onConfig}) => {
  const _tt = useT();
  const lang = _tt.lang;
  const [data, setData] = useState(null);
  const load = async () => {
    try { const r = await fetch('/api/bridge/fainas/overview', { headers:{'Authorization':`Bearer ${token()}`} }); if (r.ok) setData(await r.json()); } catch(e){}
  };
  useEffect(() => { load(); }, [reload]);

  const d = data || { pessoas:[], em_aberto:0, configurado:false };

  return (
    <div>
      {!d.configurado ? (
        <div style={{textAlign:'center',padding:'40px 20px',background:'var(--surface)',border:'1px dashed var(--line)',borderRadius:18}}>
          <div style={{fontSize:30,marginBottom:8}}>📊</div>
          <div style={{fontFamily:'var(--fs)',fontSize:17}}>{lang==='pt'?'Monte o quadro de carga':'Set up the load board'}</div>
          <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',marginTop:4,marginBottom:14}}>{lang==='pt'?'Escolha os oficiais que o comandante acompanha.':'Choose the officers the master follows.'}</div>
          <button className="btn-tidal" onClick={onConfig}>⚙ Configurar</button>
        </div>
      ) : (
        <div style={{display:'grid',gridTemplateColumns:isMobile?'1fr':'repeat(auto-fill,minmax(240px,1fr))',gap:12}}>
          {d.pessoas.map(p=>{
            const t = tempCarga(p.peso);
            const alta=Number(p.alta), media=Number(p.media), baixa=Number(p.baixa), total=Number(p.total);
            const venc=Number(p.vencidas)||0, idade=Math.round(Number(p.idade_media)||0);
            return (
              <div key={p.responsavel_id} onClick={()=>onPickPerson(p.responsavel_id, p.nome)} style={{cursor:'pointer',background:'var(--surface)',border:'1px solid var(--line-soft)',borderLeft:`4px solid ${t.cor}`,borderRadius:14,padding:'14px 16px',boxShadow:'var(--shadow-sm)',transition:'transform .15s'}}
                onMouseEnter={e=>e.currentTarget.style.transform='translateY(-2px)'} onMouseLeave={e=>e.currentTarget.style.transform=''}>
                <div style={{display:'flex',alignItems:'center',gap:11,marginBottom:10}}>
                  <FainaAvatar foto={p.foto_url} initials={p.initials} nome={p.nome} size={42}/>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontFamily:'var(--fs)',fontSize:15,letterSpacing:'-0.2px',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{p.nome}</div>
                    <div style={{fontFamily:'var(--fm)',fontSize:10.5,color:t.cor,fontWeight:600}}>{t.label} · {total} {total===1?'faina':'fainas'}</div>
                    <div style={{fontFamily:'var(--fm)',fontSize:9.5,color:'var(--muted)',marginTop:1}}>
                      {total>0 && idade>0 && <span>{lang==='pt'?`há ~${idade}d com elas`:`~${idade}d old`}</span>}
                      {venc>0 && <span style={{color:'var(--rose)',fontWeight:600}}>{idade>0?' · ':''}⏰ {venc} {lang==='pt'?'vencida(s)':'overdue'}</span>}
                    </div>
                  </div>
                </div>
                <div style={{display:'flex',gap:6}}>
                  {[['alta',alta],['media',media],['baixa',baixa]].map(([k,v])=>(
                    <div key={k} style={{flex:1,textAlign:'center',background:PRIO_SOFT[k],borderRadius:8,padding:'5px 0'}}>
                      <div style={{fontFamily:'var(--fs)',fontSize:17,color:PRIO_COR[k]}}>{v}</div>
                      <div style={{fontFamily:'var(--fm)',fontSize:8.5,color:'var(--muted)',textTransform:'uppercase',letterSpacing:0.4}}>{PRIO_LABEL[k]}</div>
                    </div>
                  ))}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
};

// ── Card-resumo do Purchase no hub (mini-tabela + abre a página no topo) ──
const Bridge = ({state, setState, setPage}) => {
  const _tt = useT();
  const lang = _tt.lang;
  const toast = useToast();
  const isMobile = useMobile();
  const token = () => localStorage.getItem('genesis_token');
  const me = state.currentUser || {};
  const chaves = state.currentUser?.permissoes || [];
  const canManage = me.role === 'admin' || me.is_staff === true || chaves.includes('bridge.gerir');

  const [tab, setTab] = useState('quadro');          // quadro | historico
  const [fainas, setFainas] = useState([]);
  const [historico, setHistorico] = useState([]);
  const [busca, setBusca] = useState('');
  const [pessoas, setPessoas] = useState([]);
  const [loading, setLoading] = useState(true);
  const [creating, setCreating] = useState(false);
  const [configCarga, setConfigCarga] = useState(false);
  const [editing, setEditing] = useState(null);
  const [anexosFaina, setAnexosFaina] = useState(null);
  const [dossieFaina, setDossieFaina] = useState(null);
  const [filtroResp, setFiltroResp] = useState(null);  // {id, nome} — filtra o quadro por responsável
  const [filtroOrfa, setFiltroOrfa] = useState(false);  // filtra só as órfãs
  const [modulo, setModulo] = useState('fainas');       // fainas | npt | po — abas do passadiço
  const [filtroMeu, setFiltroMeu] = useState(canManage ? 'todas' : 'minhas');  // tripulação abre nas suas; gerência vê o todo
  const [buscaQuadro, setBuscaQuadro] = useState('');
  const [fClasse, setFClasse] = useState('all');
  const [fPrio, setFPrio] = useState('all');
  const [concluindo, setConcluindo] = useState(null);   // faina no modal de nota
  const [orfasOpen, setOrfasOpen] = useState(false);

  const fetchFainas = async () => {
    try {
      const res = await fetch('/api/bridge/fainas', { headers:{'Authorization':`Bearer ${token()}`} });
      if (res.ok) setFainas(await res.json());
    } catch(e) { console.error(e); } finally { setLoading(false); }
  };
  const fetchHistorico = async (q='') => {
    try {
      const res = await fetch('/api/bridge/fainas/historico'+(q?`?q=${encodeURIComponent(q)}`:''), { headers:{'Authorization':`Bearer ${token()}`} });
      if (res.ok) setHistorico(await res.json());
    } catch(e) { console.error(e); }
  };

  useEffect(() => {
    fetchFainas();
    fetch('/api/boarding/manifesto', { headers:{'Authorization':`Bearer ${token()}`} })
      .then(r=>r.json()).then(d=> setPessoas((d.abordo||[]).filter(u=>u.nome && (u.is_staff===true || u.role==='admin')).sort((a,b)=>a.nome.localeCompare(b.nome)))).catch(()=>{});
  }, []);
  useEffect(() => { if (tab==='historico') fetchHistorico(busca); }, [tab]);

  // Quadro vivo: rebusca a cada 60s (só com a aba visível) e ao voltar pro app —
  // a faina que o outro tripulante criou aparece sem F5.
  useEffect(() => {
    const tick = () => { if (document.visibilityState === 'visible') fetchFainas(); };
    const iv = setInterval(tick, 60000);
    const onVis = () => { if (document.visibilityState === 'visible') fetchFainas(); };
    document.addEventListener('visibilitychange', onVis);
    return () => { clearInterval(iv); document.removeEventListener('visibilitychange', onVis); };
  }, []);

  const assumir = async (f) => {
    const r = await fetch(`/api/bridge/fainas/${f.id}/assumir`, { method:'PATCH', headers:{'Authorization':`Bearer ${token()}`} });
    if (r.ok) { toast.push({icon:'check', title:(lang==='pt'?'Faina é sua!':'The task is yours!')}); fetchFainas(); }
    else { const d = await r.json().catch(()=>({})); toast.push({icon:'x', title:(lang==='pt'?'Não deu pra puxar':'Could not take it'), body:d.error}); fetchFainas(); }
  };
  const concluir = (f) => setConcluindo(f);
  const reabrir = async (f) => {
    const r = await fetch(`/api/bridge/fainas/${f.id}/reabrir`, { method:'PATCH', headers:{'Authorization':`Bearer ${token()}`} });
    if (r.ok) { toast.push({icon:'check', title:(lang==='pt'?'De volta ao quadro':'Back on the board')}); fetchFainas(); fetchHistorico(busca); }
    else { const d = await r.json().catch(()=>({})); toast.push({icon:'x', title:d.error || (lang==='pt'?'Não consegui reabrir':'Could not reopen')}); }
  };
  const concluirConfirmar = async (nota) => {
    const f = concluindo; setConcluindo(null);
    const r = await fetch(`/api/bridge/fainas/${f.id}/concluir`, { method:'PATCH', headers:{'Content-Type':'application/json','Authorization':`Bearer ${token()}`}, body: JSON.stringify({ nota }) });
    if (!r.ok) { const d = await r.json().catch(()=>({})); toast.push({icon:'x', title:d.error || (lang==='pt'?'Não consegui concluir':'Could not complete')}); return; }
    toast.push({
      icon:'check', title:(lang==='pt'?'Concluída — foi pro histórico':'Completed — moved to history'),
      body: nota ? (lang==='pt'?'com a nota de fechamento':'with the closing note') : undefined,
      duration: 8000,
      cta: { label:(lang==='pt'?'Desfazer':'Undo'), onClick: () => reabrir({ id: f.id }) }
    });
    fetchFainas();
  };
  const redistribuirOrfas = async ({ pessoa, ids }) => {
    const uid = pessoa.user_id != null ? pessoa.user_id : pessoa.id;
    const r = await fetch('/api/bridge/fainas/orfas/atribuir', { method:'POST', headers:{'Content-Type':'application/json','Authorization':`Bearer ${token()}`}, body: JSON.stringify({ user_id: uid, ids }) });
    const d = await r.json().catch(()=>({}));
    setOrfasOpen(false);
    if (r.ok) { toast.push({icon:'check', title:`${d.redistribuidas} faina(s) agora com ${pessoa.nome}`}); setFiltroOrfa(false); fetchFainas(); }
    else toast.push({icon:'x', title: d.error || (lang==='pt'?'Erro ao redistribuir':'Error reassigning')});
  };
  const distribuirOrfas = async (ids) => {
    const r = await fetch('/api/bridge/fainas/orfas/atribuir', { method:'POST', headers:{'Content-Type':'application/json','Authorization':`Bearer ${token()}`}, body: JSON.stringify({ distribuir: true, ids }) });
    const d = await r.json().catch(()=>({}));
    setOrfasOpen(false);
    if (r.ok) { toast.push({icon:'check', title:(lang==='pt'?`${d.redistribuidas} órfã(s) divididas pela carga`:`${d.redistribuidas} orphan(s) split by load`)}); setFiltroOrfa(false); fetchFainas(); }
    else toast.push({icon:'x', title: d.error || (lang==='pt'?'Erro ao distribuir':'Error splitting')});
  };

  const abertas = fainas.filter(f=>!f.responsavel_id).length;   // sem dono, incluindo órfãs — mesmo número do filtro
  const orfas = fainas.filter(f=>f.orfa).length;
  const fainasView = (filtroResp ? fainas.filter(f=>f.responsavel_id===filtroResp.id)
                   : filtroOrfa ? fainas.filter(f=>f.orfa)
                   : fainas)
    .filter(f => filtroMeu==='minhas' ? f.responsavel_id===me.id : filtroMeu==='abertas' ? (!f.responsavel_id || f.orfa) : true)
    .filter(f => fClasse==='all' ? true : f.classe===fClasse)
    .filter(f => fPrio==='all' ? true : f.prioridade===fPrio)
    .filter(f => !buscaQuadro.trim() ? true : (f.descricao||'').toLowerCase().includes(buscaQuadro.trim().toLowerCase()))
    .slice().sort((a,b) => (_fainaScore(b) - _fainaScore(a)) || (new Date(a.created_at) - new Date(b.created_at)));
  const pickPerson = (id, nome) => { setFiltroOrfa(false); setFiltroResp({id, nome}); setTab('quadro'); };

  const barraModulos = (
    <div style={{display:'inline-flex',background:'var(--cream-2)',borderRadius:12,padding:4,gap:4}}>
      {[['fainas',lang==='pt'?'Quadro de Fainas':'Task Board'],['npt','NPT'],['po',"PO's"]].map(([id,rot])=>(
        <button key={id} onClick={()=>setModulo(id)} style={{padding:'8px 16px',borderRadius:9,border:'none',cursor:'pointer',fontFamily:'var(--fm)',fontSize:12.5,letterSpacing:0.3,
          background: modulo===id?'var(--surface)':'transparent', color: modulo===id?'var(--ink)':'var(--muted)',
          boxShadow: modulo===id?'var(--shadow-sm)':'none', transition:'all .15s'}}>{rot}</button>
      ))}
    </div>
  );

  if (modulo === 'npt') return (
    <div style={{flex:1,minWidth:0,display:'flex',flexDirection:'column'}}>
      <div style={{padding: isMobile ? '16px 16px 0' : '26px 36px 0'}}>{barraModulos}</div>
      <NPT state={state} setState={setState} setPage={setPage}/>
    </div>
  );
  if (modulo === 'po') return (
    <div style={{flex:1,minWidth:0,display:'flex',flexDirection:'column'}}>
      <div style={{padding: isMobile ? '16px 16px 0' : '26px 36px 0'}}>{barraModulos}</div>
      <PurchaseOrders state={state} setState={setState} setPage={setPage}/>
    </div>
  );

  return (
    <main style={{padding: isMobile ? '16px 16px 80px' : '30px 36px 56px', flex:1}}>
      <div style={{marginBottom:16}}>{barraModulos}</div>
      {/* Cabeçalho */}
      <div style={{marginBottom:18}}>
        <div className="t-eyebrow">{lang==='pt'?'passadiço':'bridge'}</div>
        <h1 style={{fontFamily:'var(--fs)',fontSize:isMobile?30:38,letterSpacing:'-0.8px',lineHeight:1.05,marginTop:6}}>
          {lang==='pt'?<>Quadro de <em style={{fontStyle:'italic',color:'var(--accent)'}}>Fainas.</em></>:<>Task <em style={{fontStyle:'italic',color:'var(--accent)'}}>Board.</em></>}
        </h1>
        <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',marginTop:6}}>
          {lang==='pt'?'Vi um problema, joguei na lista.':'Saw a problem, threw it on the list.'} {abertas>0 && <b style={{color:'var(--rose)'}}>{abertas} {lang==='pt'?'sem dono':'ownerless'}</b>}
          {orfas>0 && <> · <b onClick={()=>{ setFiltroResp(null); setFiltroOrfa(true); setTab('quadro'); }} style={{color:'var(--accent)',cursor:'pointer',textDecoration:'underline'}}>{orfas} {lang==='pt'?`órfã${orfas>1?'s':''}`:`orphan${orfas>1?'s':''}`}</b></>}
        </div>
      </div>

      {/* Toggle + ação */}
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:18,flexWrap:'wrap',gap:10}}>
        <div className="toggle">
          <button className={tab==='quadro'?'active':''} onClick={()=>setTab('quadro')}>{lang==='pt'?'Quadro':'Board'}{fainas.length?` · ${fainas.length}`:''}</button>
          {isMobile && <button className={tab==='carga'?'active':''} onClick={()=>setTab('carga')}>{lang==='pt'?'Carga':'Load'}</button>}
          <button className={tab==='historico'?'active':''} onClick={()=>setTab('historico')}>{lang==='pt'?'Histórico':'History'}</button>
        </div>
        <div style={{display:'flex',gap:8,alignItems:'center'}}>
          <button className="btn-tidal" onClick={()=>setCreating(true)}>+ Faina</button>
          {((!isMobile && tab==='quadro') || (isMobile && tab==='carga')) && <button className="btn-icone" onClick={()=>setConfigCarga(true)} title="configurar o quadro de carga">⚙</button>}
        </div>
      </div>

      {/* Filtros do quadro: Minhas · Em aberto · Todas + busca + classe/prioridade */}
      {tab==='quadro' && (
        <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:14,flexWrap:'wrap'}}>
          <div className="toggle">
            {[['todas',lang==='pt'?'Todas':'All'],['minhas',lang==='pt'?'Minhas':'Mine'],['abertas',lang==='pt'?'Em aberto':'Open']].map(([id,rot])=>(
              <button key={id} className={filtroMeu===id?'active':''} onClick={()=>setFiltroMeu(id)}>{rot}{id==='abertas'&&abertas>0?` · ${abertas}`:''}</button>
            ))}
          </div>
          <input className="input" placeholder={lang==='pt'?'🔍 buscar no quadro…':'🔍 search the board…'} value={buscaQuadro} onChange={e=>setBuscaQuadro(e.target.value)} style={{flex:'1 1 160px',minWidth:130,boxSizing:'border-box',padding:'8px 12px',fontSize:13}}/>
          <select className="input select" value={fClasse} onChange={e=>setFClasse(e.target.value)} style={{boxSizing:'border-box',padding:'8px 10px',fontSize:12}}>
            <option value="all">{lang==='pt'?'Todas as classes':'All classes'}</option>
            <option value="tm_master">TM Master</option>
            <option value="email">E-mail</option>
            <option value="geral">{lang==='pt'?'Geral':'General'}</option>
          </select>
          <select className="input select" value={fPrio} onChange={e=>setFPrio(e.target.value)} style={{boxSizing:'border-box',padding:'8px 10px',fontSize:12}}>
            <option value="all">{lang==='pt'?'Toda prioridade':'Any priority'}</option>
            <option value="alta">{lang==='pt'?'Alta':'High'}</option>
            <option value="media">{lang==='pt'?'Média':'Medium'}</option>
            <option value="baixa">{lang==='pt'?'Baixa':'Low'}</option>
          </select>
        </div>
      )}

      {/* QUADRO */}
      {tab==='quadro' && filtroResp && (
        <div style={{display:'inline-flex',alignItems:'center',gap:8,background:'var(--teal)',color:'#fff',borderRadius:999,padding:'6px 14px',marginBottom:14,fontFamily:'var(--fm)',fontSize:12}}>
          {lang==='pt'?'Fainas de':'Tasks of'} {filtroResp.nome}
          <button onClick={()=>setFiltroResp(null)} style={{background:'transparent',border:'none',color:'#fff',cursor:'pointer',fontSize:14,lineHeight:1}}>×</button>
        </div>
      )}
      {tab==='quadro' && filtroOrfa && (
        <div style={{display:'inline-flex',alignItems:'center',gap:8,background:'var(--accent)',color:'#fff',borderRadius:999,padding:'6px 14px',marginBottom:14,fontFamily:'var(--fm)',fontSize:12}}>
          ⚓ {lang==='pt'?'Órfãs — sem dono após desembarque':'Orphans — ownerless after disembark'}
          <button onClick={()=>setOrfasOpen(true)} style={{background:'rgba(255,255,255,0.2)',border:'none',color:'#fff',cursor:'pointer',fontSize:11,fontFamily:'var(--fm)',borderRadius:999,padding:'3px 10px'}}>{lang==='pt'?'redistribuir todas →':'reassign all →'}</button>
          <button onClick={()=>setFiltroOrfa(false)} style={{background:'transparent',border:'none',color:'#fff',cursor:'pointer',fontSize:14,lineHeight:1}}>×</button>
        </div>
      )}
      {tab==='quadro' && (
        <div style={!isMobile ? {display:'flex',gap:18,alignItems:'stretch',minHeight:420} : undefined}>
          <div style={!isMobile ? {flex:1,minWidth:0,position:'relative'} : {flex:1,minWidth:0}}>
          <div style={!isMobile ? {position:'absolute',inset:0,overflowY:'auto'} : undefined}>
          {loading ? <div style={{color:'var(--muted)',fontFamily:'var(--fm)',fontSize:13,padding:20}}>{lang==='pt'?'Carregando…':'Loading…'}</div> :
        fainasView.length===0 ? (
          <div style={{textAlign:'center',padding:'50px 20px',background:'var(--surface)',border:'1px dashed var(--line)',borderRadius:18}}>
            <div style={{fontSize:34,marginBottom:8}}>🗒️</div>
            <div style={{fontFamily:'var(--fs)',fontSize:18}}>
              {filtroResp ? (lang==='pt'?'Sem fainas pra essa pessoa':'No tasks for this person')
               : filtroMeu==='minhas' ? (lang==='pt'?'Nada com você agora.':'Nothing on you right now.')
               : (lang==='pt'?'Quadro limpo!':'Clean board!')}
            </div>
            <div style={{fontFamily:'var(--fm)',fontSize:12,color:'var(--muted)',marginTop:4}}>
              {filtroResp ? (lang==='pt'?'Nada pendente com esse responsável.':'Nothing pending with this owner.')
               : filtroMeu==='minhas' ? (lang==='pt'?'Suas fainas aparecem aqui quando alguém te passar uma — ou puxe uma em aberto.':'Your tasks land here when assigned — or take an open one.')
               : (lang==='pt'?'Nenhuma faina pendente. Bom trabalho. 🚢':'No pending tasks. Good job. 🚢')}
            </div>
            {filtroMeu==='minhas' && abertas>0 && (
              <button className="btn-tidal" style={{marginTop:14}} onClick={()=>setFiltroMeu('abertas')}>
                {lang==='pt'?`✋ Puxar uma das ${abertas} em aberto`:`✋ Take one of the ${abertas} open`}
              </button>
            )}
          </div>
        ) : isMobile ? (
          <div style={{display:'grid',gap:12}}>
            {fainasView.map(f => <FainaCard key={f.id} f={f} me={me} canManage={canManage} onAssumir={assumir} onConcluir={concluir} onEdit={setEditing} onAnexos={setAnexosFaina} onOpen={setDossieFaina}/>)}
          </div>
        ) : (
          <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:18,overflow:'hidden',boxShadow:'var(--shadow-sm)'}}>
            <table style={{width:'100%',borderCollapse:'collapse'}}>
              <thead>
                <tr style={{background:'var(--cream-2)',borderBottom:'1px solid var(--line)'}}>
                  {(lang==='pt'?['Tarefa','Classe','Prioridade','Responsável','Sinais','']:['Task','Class','Priority','Owner','Signals','']).map((h,i)=>(
                    <th key={i} style={{padding:'10px',textAlign:i===4?'center':'left',fontFamily:'var(--fm)',fontSize:10,letterSpacing:0.6,textTransform:'uppercase',color:'var(--muted)'}}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {fainasView.map(f => <FainaRow key={f.id} f={f} me={me} canManage={canManage} onAssumir={assumir} onConcluir={concluir} onEdit={setEditing} onAnexos={setAnexosFaina} onOpen={setDossieFaina}/>)}
              </tbody>
            </table>
          </div>
        )}
          </div>
          </div>
          {!isMobile && (
            <aside style={{width:320,flexShrink:0}}>
              <div className="t-eyebrow" style={{marginBottom:10}}>{lang==='pt'?'carga da equipe':'team load'}</div>
              <OverviewView token={token} toast={toast} pessoas={pessoas} onPickPerson={pickPerson} isMobile={false} reload={fainas} onConfig={()=>setConfigCarga(true)}/>
            </aside>
          )}
        </div>
      )}

      {/* CARGA (overview) */}
      {tab==='carga' && <OverviewView token={token} toast={toast} pessoas={pessoas} onPickPerson={pickPerson} isMobile={isMobile} reload={fainas} onConfig={()=>setConfigCarga(true)}/>}

      {/* HISTÓRICO */}
      {tab==='historico' && (
        <div>
          <input className="input" style={{width:'100%',boxSizing:'border-box',marginBottom:16}} placeholder={lang==='pt'?'🔍 Buscar no histórico — inclusive nas notas de resolução…':'🔍 Search history — including resolution notes…'}
            value={busca} onChange={e=>{ const v = e.target.value; setBusca(v); clearTimeout(window._histDeb); window._histDeb = setTimeout(()=>fetchHistorico(v), 400); }}/>
          {historico.length > 0 && (() => {
            const dias = (f) => Math.max(0, (new Date(f.completed_at) - new Date(f.created_at)) / 86400000);
            const media = historico.reduce((a, f) => a + dias(f), 0) / historico.length;
            const fmtD = (d) => d < 1 ? (lang==='pt'?'no mesmo dia':'same day') : `${d.toFixed(d < 10 ? 1 : 0)} ${lang==='pt'?(d >= 2 ?'dias':'dia'):(d >= 2 ?'days':'day')}`;
            const porClasse = ['tm_master','email','geral'].map(c => { const fs = historico.filter(f => f.classe === c); return fs.length ? { c, n: fs.length, m: fs.reduce((a,f)=>a+dias(f),0)/fs.length } : null; }).filter(Boolean);
            const sem7 = historico.filter(f => (Date.now() - new Date(f.completed_at)) < 7*864e5).length;
            const agingQuadro = fainas.length ? fainas.reduce((a,f)=>a+_fainaIdadeDias(f),0)/fainas.length : 0;
            const comNota = historico.filter(f => f.nota_conclusao).length;
            return (
              <div style={{display:'flex',gap:10,flexWrap:'wrap',marginBottom:16}}>
                <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,padding:'10px 16px'}}>
                  <div style={{fontFamily:'var(--fs)',fontSize:20}}>{historico.length}</div>
                  <div style={{fontFamily:'var(--fm)',fontSize:9.5,letterSpacing:0.8,textTransform:'uppercase',color:'var(--muted)'}}>{lang==='pt'?'concluídas':'completed'}</div>
                </div>
                <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,padding:'10px 16px'}}>
                  <div style={{fontFamily:'var(--fs)',fontSize:20}}>{sem7}</div>
                  <div style={{fontFamily:'var(--fm)',fontSize:9.5,letterSpacing:0.8,textTransform:'uppercase',color:'var(--muted)'}}>{lang==='pt'?'últimos 7 dias':'last 7 days'}</div>
                </div>
                <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,padding:'10px 16px'}}>
                  <div style={{fontFamily:'var(--fs)',fontSize:20}}>{fmtD(media)}</div>
                  <div style={{fontFamily:'var(--fm)',fontSize:9.5,letterSpacing:0.8,textTransform:'uppercase',color:'var(--muted)'}}>{lang==='pt'?'tempo médio':'avg time'}</div>
                </div>
                <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,padding:'10px 16px'}}>
                  <div style={{fontFamily:'var(--fs)',fontSize:20,color:agingQuadro>10?'var(--rose)':agingQuadro>5?'var(--sun)':'var(--ink)'}}>{agingQuadro.toFixed(agingQuadro<10?1:0)}d</div>
                  <div style={{fontFamily:'var(--fm)',fontSize:9.5,letterSpacing:0.8,textTransform:'uppercase',color:'var(--muted)'}}>{lang==='pt'?'idade média do quadro':'board avg age'}</div>
                </div>
                <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,padding:'10px 16px'}}>
                  <div style={{fontFamily:'var(--fs)',fontSize:20,color:'var(--leaf)'}}>{comNota}</div>
                  <div style={{fontFamily:'var(--fm)',fontSize:9.5,letterSpacing:0.8,textTransform:'uppercase',color:'var(--muted)'}}>{lang==='pt'?'com nota de resolução':'with resolution note'}</div>
                </div>
                {porClasse.map(x => (
                  <div key={x.c} style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,padding:'10px 16px'}}>
                    <div style={{fontFamily:'var(--fs)',fontSize:20}}>{fmtD(x.m)}</div>
                    <div style={{fontFamily:'var(--fm)',fontSize:9.5,letterSpacing:0.8,textTransform:'uppercase',color:'var(--muted)'}}>{CLASSE_LABEL[x.c]} · {x.n}</div>
                  </div>
                ))}
              </div>
            );
          })()}
          {historico.length===0 ? (
            <div style={{color:'var(--muted)',fontFamily:'var(--fm)',fontSize:13,padding:20,textAlign:'center'}}>{lang==='pt'?'Nenhuma faina concluída ainda.':'No completed tasks yet.'}</div>
          ) : (
            <div style={{display:'grid',gap:10}}>
              {historico.map(f => (
                <div key={f.id} style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:14,padding:'12px 16px',display:'flex',justifyContent:'space-between',alignItems:'center',gap:12,flexWrap:'wrap'}}>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontFamily:'var(--fs)',fontSize:14.5,textDecoration:'line-through',color:'var(--muted)'}}>{f.descricao}</div>
                    <div style={{fontFamily:'var(--fm)',fontSize:10.5,color:'var(--muted-2)',marginTop:2}}>
                      ✓ {f.completed_by_nome?`${lang==='pt'?'por':'by'} ${f.completed_by_nome.split(' ')[0]}`:''} · {fmtFainaData(f.completed_at)}
                    </div>
                    {f.nota_conclusao && (
                      <div style={{fontFamily:'var(--f)',fontSize:12,color:'var(--ink)',marginTop:5,background:'var(--cream-2)',borderLeft:'3px solid var(--leaf)',borderRadius:'0 8px 8px 0',padding:'6px 10px'}}>
                        💡 {f.nota_conclusao}
                      </div>
                    )}
                  </div>
                  <div style={{display:'flex',alignItems:'center',gap:10,flexShrink:0}}>
                    <ClassePill c={f.classe}/>
                    {canManage && (
                      <button className="btn btn-sm" onClick={()=>reabrir(f)} title={lang==='pt'?'reabrir — volta pro quadro':'reopen — back to the board'} style={{whiteSpace:'nowrap'}}>
                        ↩ {lang==='pt'?'reabrir':'reopen'}
                      </button>
                    )}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}


      {creating && <FainaModal token={token} toast={toast} pessoas={pessoas} onClose={()=>setCreating(false)} onSaved={()=>{ setCreating(false); fetchFainas(); }}/>}
      {configCarga && <ConfigMembrosModal token={token} toast={toast} pessoas={pessoas} onClose={()=>setConfigCarga(false)} onSaved={()=>{ setConfigCarga(false); fetchFainas(); }}/>}
      {concluindo && <ConcluirFainaModal faina={concluindo} onConfirmar={concluirConfirmar} onClose={()=>setConcluindo(null)}/>}
      {orfasOpen && <OrfasModal token={token} pessoas={pessoas} fainas={fainas} onEscolher={redistribuirOrfas} onDistribuir={distribuirOrfas} onClose={()=>setOrfasOpen(false)}/>}
      {editing && <FainaModal token={token} toast={toast} pessoas={pessoas} faina={editing} onClose={()=>setEditing(null)} onSaved={()=>{ setEditing(null); fetchFainas(); }}/>}
      {anexosFaina && <AnexosModal token={token} toast={toast} faina={anexosFaina} onClose={()=>setAnexosFaina(null)} onChanged={fetchFainas}/>}
      {dossieFaina && <FainaDossie token={token} toast={toast} me={me} canManage={canManage} faina={dossieFaina} onClose={()=>setDossieFaina(null)} onChanged={fetchFainas} onEdit={setEditing} onConcluir={(f)=>setConcluindo(f)}/>}
    </main>
  );
};

// ── BridgeHandoverResumo — "fainas quentes" no Desk do DP ─────────────────────
// Bloco compacto renderizado dentro do LogDeskModal (logbook.jsx) no momento da
// troca de turno: mostra o que quem assume herda — fainas vencidas, vencendo em
// até 2 dias ou de prioridade alta. Sem nada quente, o bloco simplesmente some.
const BridgeHandoverResumo = ({token}) => {
  const lang = useT().lang;
  const [dados, setDados] = React.useState(null);
  React.useEffect(() => {
    let vivo = true;
    fetch('/api/bridge/fainas/handover', { headers: { 'Authorization': `Bearer ${token()}` } })
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (vivo) setDados(d); })
      .catch(() => {});
    return () => { vivo = false; };
  }, []);
  if (!dados || !dados.fainas || !dados.fainas.length) return null;
  return (
    <div style={{marginBottom:14}}>
      <div style={{fontFamily:'var(--fm)',fontSize:10,letterSpacing:1,textTransform:'uppercase',color:'var(--muted)',marginBottom:8}}>
        ⚓ {lang==='pt'?'a ponte passa com o turno':'the bridge hands over with the watch'}
        {dados.vencidas > 0 && <span style={{color:'var(--rose)',fontWeight:700}}> · {dados.vencidas} {lang==='pt'?'vencida(s)':'overdue'}</span>}
        {!dados.vencidas && dados.altas > 0 && <span style={{color:'var(--sun)',fontWeight:700}}> · {dados.altas} {lang==='pt'?'em prioridade alta':'high priority'}</span>}
      </div>
      <div style={{background:'var(--surface)',border:'1px solid var(--line-soft)',borderRadius:12,overflow:'hidden'}}>
        {dados.fainas.map((f, i) => {
          const venc = _fainaVencida(f);
          const dias = f.prazo ? _fainaDiasPrazo(f) : null;
          const rotulo = !f.prazo ? null
            : venc ? (lang==='pt' ? `vencida há ${Math.max(1,Math.abs(dias))}d` : `${Math.max(1,Math.abs(dias))}d overdue`)
            : dias === 0 ? (lang==='pt'?'vence hoje':'due today')
            : dias === 1 ? (lang==='pt'?'vence amanhã':'due tomorrow')
            : `${lang==='pt'?'até':'due'} ${_fainaFmtPrazo(f.prazo)}`;
          return (
            <div key={f.id} style={{display:'flex',alignItems:'center',gap:8,padding:'8px 12px',borderTop:i?'1px solid var(--line-soft)':'none'}}>
              <span style={{width:7,height:7,borderRadius:'50%',flexShrink:0,background:PRIO_COR[f.prioridade]||'var(--muted-2)'}} title={`${lang==='pt'?'prioridade':'priority'} ${f.prioridade||'normal'}`}/>
              <span style={{flex:1,minWidth:0,fontFamily:'var(--f)',fontSize:12.5,color:'var(--ink)',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{f.descricao}</span>
              <span style={{fontFamily:'var(--fm)',fontSize:9.5,color:f.responsavel_nome?'var(--muted)':'var(--rose)',whiteSpace:'nowrap'}}>{f.responsavel_nome ? f.responsavel_nome.split(' ')[0] : (lang==='pt'?'sem dono':'no owner')}</span>
              {rotulo && <span style={{fontFamily:'var(--fm)',fontSize:9.5,fontWeight:(venc||dias<=0)?700:500,color:venc?'var(--rose)':'var(--sun)',whiteSpace:'nowrap'}}>⏰ {rotulo}</span>}
            </div>
          );
        })}
      </div>
      <div style={{fontFamily:'var(--fm)',fontSize:9.5,color:'var(--muted-2)',marginTop:6}}>
        {lang==='pt'?'quem assume já sabe o que está pegando fogo na ponte':'whoever takes over knows what is burning on the bridge'}
      </div>
    </div>
  );
};

// Export explícito: consts top-level NÃO viram propriedades de window, e o
// logbook.jsx referencia o componente defensivamente via window.BridgeHandoverResumo.
Object.assign(window, { BridgeHandoverResumo });
