// ═══════════════════════════════════════════════════════════════
// SCREEN · Dashboard (Admin/GC)
// ═══════════════════════════════════════════════════════════════

// ── Constantes de custo (modeladas conforme política Escalab) ────────────────
// Apenas FIXOS recebem 13º, VT e PLR. Associados = só salário.
const CUSTO_VT_MENSAL_FIXO = 200; // R$ 200,00/mês de VT por colaborador fixo
const PLR_MULTIPLO_SALARIO  = 2;   // PLR de 2 salários para fixos em 2025

// ── Tooltip de hover global (gráficos) ──────────────────────────────────────
const Tooltip = ({ x, y, children, show }) => {
  if (!show) return null;
  return (
    <div style={{ position: 'absolute', left: x + 12, top: y - 10, background: 'rgba(15,20,28,.96)', color: '#fff', borderRadius: 8, padding: '7px 12px', fontSize: 12, fontFamily: 'var(--font-sans)', pointerEvents: 'none', whiteSpace: 'normal', boxShadow: '0 6px 18px rgba(0,0,0,.25)', zIndex: 10, lineHeight: 1.5, maxWidth: 240 }}>
      {children}
    </div>
  );
};

// ── Helpers de leitura genéricos ─────────────────────────────────────────────
function lerLS(key, fallback) { try { const r = JSON.parse(localStorage.getItem(key) || 'null'); return r != null ? r : fallback; } catch { return fallback; } }
function getDadosOrgAll() {
  const out = {};
  COLABORADORES.forEach(c => { out[c.id] = lerLS(`escalab_dados_org_${c.id}`, {}); });
  return out;
}
function getDiversidadeAll() {
  const out = {};
  COLABORADORES.forEach(c => { out[c.id] = lerLS(`escalab_diversidade_${c.id}`, {}); });
  return out;
}
function getHistoricoOrgAll() {
  const out = {};
  COLABORADORES.forEach(c => { out[c.id] = lerLS(`escalab_dados_org_${c.id}_log`, []); });
  return out;
}

// ── Estatísticas auxiliares ──────────────────────────────────────────────────
function mediana(vals) {
  const v = vals.filter(n => Number.isFinite(n)).slice().sort((a,b) => a-b);
  if (!v.length) return 0;
  const m = Math.floor(v.length/2);
  return v.length % 2 ? v[m] : (v[m-1]+v[m])/2;
}
function percentil(vals, p) {
  const v = vals.filter(n => Number.isFinite(n)).slice().sort((a,b) => a-b);
  if (!v.length) return 0;
  const rank = (p/100) * (v.length - 1);
  const lo = Math.floor(rank), hi = Math.ceil(rank);
  if (lo === hi) return v[lo];
  return v[lo] + (v[hi] - v[lo]) * (rank - lo);
}
function media(vals) {
  const v = vals.filter(n => Number.isFinite(n));
  if (!v.length) return 0;
  return v.reduce((s,n) => s+n, 0) / v.length;
}
function parseMoeda(s) {
  if (s == null) return 0;
  if (typeof s === 'number') return s;
  const limpo = String(s).replace(/[^\d,.-]/g, '').replace(/\.(?=\d{3}(\D|$))/g, '').replace(',', '.');
  const n = parseFloat(limpo);
  return Number.isFinite(n) ? n : 0;
}
function fmtBRL(n) {
  try { return n.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL', maximumFractionDigits: 0 }); } catch { return 'R$ ' + Math.round(n).toLocaleString('pt-BR'); }
}
function fmtPct(n, dec=0) { return (Number.isFinite(n) ? n : 0).toFixed(dec) + '%'; }
function delta(prev, atual) {
  if (!Number.isFinite(prev) || !Number.isFinite(atual) || prev === 0) return null;
  return ((atual - prev) / Math.abs(prev)) * 100;
}

// ── Recuperar movimentações de qualquer kanban ───────────────────────────────
function getMovimentacoesAll() {
  const all = lerLS('escalab_movimentacao', {});
  return {
    admissao:     all.admissao     || [],
    promocao:     all.promocao     || [],
    desligamento: all.desligamento || [],
  };
}

// ── Custos mensais por colaborador (lógica do docx 11) ───────────────────────
function custoMensalColab(colabId, dadosOrg) {
  const c = COLABORADORES.find(x => x.id === colabId);
  if (!c) return 0;
  const isFixo = (typeof getCategoriaKey === 'function' ? getCategoriaKey(colabId) : 'fixo') === 'fixo';
  const salario = parseMoeda(dadosOrg?.[colabId]?.salarioBruto);
  if (!isFixo) return salario; // Associado: só salário
  // Fixo: salário + (13º + PLR)/12 + VT
  const decimo = salario / 12;
  const plr = (PLR_MULTIPLO_SALARIO * salario) / 12;
  return salario + decimo + plr + CUSTO_VT_MENSAL_FIXO;
}
function custoTotalEmpresa(dadosOrg) {
  return COLABORADORES.reduce((s, c) => s + custoMensalColab(c.id, dadosOrg), 0);
}

// ── Faixa etária a partir de dataNascimento ─────────────────────────────────
const FAIXAS_ETARIAS = [
  { id:'lt25',  label:'Até 25 anos',  min: 0,  max: 24 },
  { id:'25_34', label:'25 a 34 anos', min: 25, max: 34 },
  { id:'35_44', label:'35 a 44 anos', min: 35, max: 44 },
  { id:'45_54', label:'45 a 54 anos', min: 45, max: 54 },
  { id:'gte55', label:'55+ anos',     min: 55, max: 999 },
];
function calcIdade(iso) {
  if (!iso) return null;
  const d = new Date(iso);
  if (isNaN(d.getTime())) return null;
  const hoje = new Date();
  let i = hoje.getFullYear() - d.getFullYear();
  const m = hoje.getMonth() - d.getMonth();
  if (m < 0 || (m === 0 && hoje.getDate() < d.getDate())) i--;
  return i;
}
function faixaEtariaDe(idade) {
  if (idade == null) return null;
  return FAIXAS_ETARIAS.find(f => idade >= f.min && idade <= f.max)?.id;
}

// ── Faixas de tempo de empresa ──────────────────────────────────────────────
const FAIXAS_TEMPO = [
  { id:'lt1y',   label:'Até 1 ano',  min: 0,  max: 11   },
  { id:'1_3y',   label:'1 a 3 anos', min: 12, max: 35   },
  { id:'3_5y',   label:'3 a 5 anos', min: 36, max: 59   },
  { id:'5_10y',  label:'5 a 10 anos',min: 60, max: 119  },
  { id:'gte10y', label:'10+ anos',   min: 120, max: 9999 },
];

// ── Níveis hierárquicos padronizados ────────────────────────────────────────
const NIVEIS_HIER = [
  { id:'diretor',     label:'Diretor(a)/CEO',     match: c => c.nivel === 'diretor' },
  { id:'gerente',     label:'Gerente',            match: c => /gerent/i.test(c.cargo) },
  { id:'coordenador', label:'Coordenador(a)',     match: c => /coordenad/i.test(c.cargo) },
  { id:'lider',       label:'Líder/Especialista', match: c => /(líder|lider|especialista)/i.test(c.cargo) || c.nivel === 'lider' },
  { id:'analista',    label:'Analista',           match: c => /analista/i.test(c.cargo) },
  { id:'assistente',  label:'Assistente/Técnico', match: c => /(assistente|técnico|tecnico)/i.test(c.cargo) },
  { id:'estagio',     label:'Estágio',            match: c => /estagi/i.test(c.cargo) },
  { id:'assoc_proj',  label:'Assoc. de Projetos', match: c => c.setor === 'Associados de Projetos' },
  { id:'assoc_edit',  label:'Assoc. de Editais',  match: c => /editais/i.test(c.setor) },
];
function nivelHierDe(c) {
  for (const n of NIVEIS_HIER) if (n.match(c)) return n.id;
  return 'outros';
}

// PDF Site AVD (2): "Perfil da equipe · mudar para Diretor, líder de setor, liderado".
// Consolidação dos 8 níveis em 3 papéis principais.
const NIVEIS_3 = [
  { id: 'diretor',  label: 'Diretor(a) / CEO', cor: '#1F4A8A', match: c => c.nivel === 'diretor' },
  { id: 'lider',    label: 'Líder de setor',   cor: '#00967B', match: c => c.nivel === 'lider' },
  { id: 'liderado', label: 'Liderado',         cor: '#6B3FA0', match: c => c.nivel === 'liderado' || !c.nivel },
];
function nivel3De(c) {
  for (const n of NIVEIS_3) if (n.match(c)) return n.id;
  return 'liderado';
}
function labelNivel3(id) {
  const n = NIVEIS_3.find(x => x.id === id);
  return n ? n.label : id;
}


// ── FiltroTempo: corte temporal global do painel (PDF Site AVD (2)) ────────
// PDF: "Os indicadores estão todos acumulativos · preciso de corte de tempo
// pra retirar indicadores de trimestre/mês específico".
// periodo é uma string como "12m" | "2026" | "2025" | "1T2026" | "2T2026" etc.
function getAnosDisponiveis() {
  const anoAtual = new Date().getFullYear();
  const anos = [];
  for (let a = anoAtual; a >= anoAtual - 4; a--) anos.push(a);
  return anos;
}
function dentroDoPeriodo(dataISO, periodo) {
  if (!dataISO || !periodo || periodo === '12m') {
    if (!dataISO) return true;
    const d = new Date(dataISO);
    const limite = new Date();
    limite.setMonth(limite.getMonth() - 12);
    return d >= limite;
  }
  const d = new Date(dataISO);
  if (isNaN(d.getTime())) return false;
  const ano = d.getFullYear();
  const tri = Math.floor(d.getMonth() / 3) + 1;
  const m = String(periodo);
  // "AAAA" · ano inteiro
  if (/^\d{4}$/.test(m)) return ano === Number(m);
  // "NTAAAA" · trimestre N do ano AAAA (ex 1T2026)
  const tm = m.match(/^(\d)T(\d{4})$/);
  if (tm) return ano === Number(tm[2]) && tri === Number(tm[1]);
  return true;
}
function rotuloPeriodo(p) {
  if (!p || p === '12m') return 'Últimos 12 meses';
  if (/^\d{4}$/.test(p)) return `Ano ${p}`;
  const tm = String(p).match(/^(\d)T(\d{4})$/);
  if (tm) return `${tm[1]}º Trim. ${tm[2]}`;
  return p;
}
const FiltroTempo = ({ periodo, setPeriodo }) => {
  const anos = getAnosDisponiveis();
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14, padding: '10px 14px', background: '#fff', border: '1px solid var(--escalab-line)', borderRadius: 10 }}>
      <Icon name="calendar" size={14} />
      <span style={{ fontSize: 11, color: 'var(--escalab-mute)', fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase' }}>Período</span>
      <select value={periodo} onChange={e => setPeriodo(e.target.value)}
        style={{ border: '1px solid var(--escalab-line)', borderRadius: 7, padding: '6px 10px', fontSize: 12.5, fontFamily: 'var(--font-sans)', outline: 0, background: '#fff', cursor: 'pointer' }}>
        <option value="12m">Últimos 12 meses</option>
        {anos.map(a => (
          <optgroup key={a} label={`Ano ${a}`}>
            <option value={String(a)}>Ano {a} (inteiro)</option>
            <option value={`1T${a}`}>1º Trim. {a} (jan-mar)</option>
            <option value={`2T${a}`}>2º Trim. {a} (abr-jun)</option>
            <option value={`3T${a}`}>3º Trim. {a} (jul-set)</option>
            <option value={`4T${a}`}>4º Trim. {a} (out-dez)</option>
          </optgroup>
        ))}
      </select>
      <Tag tone="info" size="xs">{rotuloPeriodo(periodo)}</Tag>
    </div>
  );
};

// ── InfoGrafico: guia explicativa abaixo de cada gráfico (PDF Site AVD (2)) ─
// Mostra significado + fórmula/automatização. Use abaixo do <Card> do gráfico.
const InfoGrafico = ({ significado, calculo, fonte }) => (
  <div style={{
    marginTop: -6, marginBottom: 4,
    background: '#FAFBFC', border: '1px solid var(--escalab-line)', borderRadius: 10,
    padding: '12px 16px', fontSize: 12, color: 'var(--escalab-slate)', lineHeight: 1.55,
  }}>
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
      <div style={{ flexShrink: 0, color: 'var(--escalab-brand)', marginTop: 1 }}><Icon name="eye" size={13} /></div>
      <div>
        <div style={{ fontWeight: 600, color: 'var(--escalab-ink)' }}>O que significa</div>
        <div style={{ marginBottom: 6 }}>{significado}</div>
        <div style={{ fontWeight: 600, color: 'var(--escalab-ink)' }}>Como é calculado</div>
        <div style={{ fontFamily: 'var(--font-mono, monospace)', fontSize: 11.5, color: 'var(--escalab-mute)' }}>{calculo}</div>
        {fonte && <div style={{ marginTop: 4, fontSize: 11, color: 'var(--escalab-mute)' }}><strong>Fonte:</strong> {fonte}</div>}
      </div>
    </div>
  </div>
);

const BarChart = ({ data, height = 120 }) => {
  if (!data || !data.length) return null;
  const maxVal = Math.max(...data.map(d => Math.max(d.receberam || 0, d.naoReceberam || 0, d.nota || 0, d.value || 0)));
  const barW = Math.min(28, Math.floor(360 / (data.length * 2.5)));
  const gap = barW * 0.6;
  const totalW = data.length * (barW * 2 + gap) + gap;
  return (
    <svg viewBox={`0 0 ${totalW} ${height + 30}`} style={{ width: '100%', height: 'auto' }}>
      {data.map((d, i) => {
        const x = i * (barW * 2 + gap) + gap;
        const h1 = maxVal > 0 ? (d.receberam / maxVal) * height : 0;
        const h2 = maxVal > 0 ? (d.naoReceberam / maxVal) * height : 0;
        return (
          <g key={i}>
            <rect x={x} y={height - h1} width={barW} height={h1} rx={3} fill="var(--escalab-brand)" opacity=".85" />
            <rect x={x + barW + 2} y={height - h2} width={barW} height={h2} rx={3} fill="var(--escalab-mute)" opacity=".5" />
            <text x={x + barW} y={height + 20} textAnchor="middle" fontSize={11} fontWeight={600} fill="var(--escalab-slate)" fontFamily="var(--font-sans)">{d.trimestre}</text>
          </g>
        );
      })}
    </svg>
  );
};

const LineChart = ({ data, height = 100 }) => {
  if (!data || !data.length) return null;
  const vals = data.map(d => d.nota);
  const metas = data.map(d => d.meta);
  const allVals = [...vals, ...metas];
  const minV = Math.min(...allVals) - 0.3;
  const maxV = Math.max(...allVals) + 0.3;
  const range = maxV - minV;
  const w = 340;
  const stepX = w / (data.length - 1);
  const toY = v => height - ((v - minV) / range) * height;
  const toX = i => i * stepX;
  const pathNota = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${toX(i)},${toY(d.nota)}`).join(' ');
  const pathMeta = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${toX(i)},${toY(d.meta)}`).join(' ');
  return (
    <svg viewBox={`0 0 ${w} ${height + 24}`} style={{ width: '100%', height: 'auto', overflow: 'visible' }}>
      <path d={pathMeta} fill="none" stroke="var(--escalab-mute)" strokeWidth="1.5" strokeDasharray="5 3" />
      <path d={pathNota} fill="none" stroke="var(--escalab-brand)" strokeWidth="2.2" />
      {data.map((d, i) => (
        <g key={i}>
          <circle cx={toX(i)} cy={toY(d.nota)} r={3.5} fill="var(--escalab-brand)" />
          <text x={toX(i)} y={height + 18} textAnchor="middle" fontSize={11} fontWeight={600} fill="var(--escalab-slate)" fontFamily="var(--font-sans)">{d.ciclo}</text>
        </g>
      ))}
    </svg>
  );
};

const ANOS_RETENCAO = [2026, 2025, 2024, 2023];

const TEMPO_CARGO_POR_ANO = {
  2026: [
    { cargo: 'Diretor(a)/CEO',     meses: 42 },
    { cargo: 'Líder/Especialista', meses: 28 },
    { cargo: 'Coordenador(a)',     meses: 12 },
    { cargo: 'Analista',           meses: 20 },
    { cargo: 'Associado',          meses: 8  },
  ],
  2025: [
    { cargo: 'Diretor(a)/CEO',     meses: 38 },
    { cargo: 'Líder/Especialista', meses: 24 },
    { cargo: 'Coordenador(a)',     meses: 10 },
    { cargo: 'Analista',           meses: 17 },
    { cargo: 'Associado',          meses: 6  },
  ],
  2024: [
    { cargo: 'Diretor(a)/CEO',     meses: 30 },
    { cargo: 'Líder/Especialista', meses: 18 },
    { cargo: 'Coordenador(a)',     meses: 8  },
    { cargo: 'Analista',           meses: 14 },
    { cargo: 'Associado',          meses: 5  },
  ],
  2023: [
    { cargo: 'Diretor(a)/CEO',     meses: 24 },
    { cargo: 'Líder/Especialista', meses: 14 },
    { cargo: 'Coordenador(a)',     meses: 6  },
    { cargo: 'Analista',           meses: 11 },
    { cargo: 'Associado',          meses: 4  },
  ],
};

// ── Painel: Admissões e Desligamentos ─────────────────────────────────────────
const MESES_ABREV = ['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez'];

const PainelAdmissoesDeslig = ({ periodo = '12m' }) => {
  const [mesSel, setMesSel] = useState(null);
  const desligsAll = getDesligamentos();
  const admsAll    = ADMISSOES_DEMO;
  const desligs = desligsAll.filter(d => dentroDoPeriodo(d.dataSaida, periodo));
  const adms    = admsAll.filter(a => dentroDoPeriodo(a.admitidoEm, periodo));
  const ativos  = getColaboradoresAtivos();

  const headFixo  = ativos.filter(c => getCategoriaKey(c.id) === 'fixo').length;
  const headTotal = ativos.length;
  const headAssoc = headTotal - headFixo;

  const catDe = d => d.categoriaKey === 'fixo' ? 'fixo' : 'associado';
  const mesDe = ymd => (ymd || '').slice(0, 7);

  const base = new Date(); base.setDate(1);
  const meses = [];
  for (let i = 11; i >= 0; i--) {
    const d = new Date(base); d.setMonth(d.getMonth() - i);
    meses.push({ key: `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`, label: MESES_ABREV[d.getMonth()] });
  }

  const dataMes = meses.map(m => {
    const desM = desligs.filter(d => mesDe(d.dataSaida) === m.key);
    const admM = adms.filter(a => mesDe(a.admitidoEm) === m.key);
    return {
      trimestre: m.label, label: m.label, key: m.key,
      receberam: admM.length, naoReceberam: desM.length,
      admissoes: admM.length, desligamentos: desM.length,
      deslFixo: desM.filter(d => catDe(d) === 'fixo').length,
      deslAssoc: desM.filter(d => catDe(d) === 'associado').length,
      desligados: desM,
    };
  });

  const totalDesl = desligs.length, totalAdm = adms.length;
  const deslFixo = desligs.filter(d => catDe(d) === 'fixo').length, deslAssoc = totalDesl - deslFixo;
  const admFixo = adms.filter(a => a.categoria === 'fixo').length, admAssoc = totalAdm - admFixo;

  const turnover = (adm, desl, head) => head > 0 ? Math.round(((adm + desl) / 2) / head * 100) : 0;
  const taxaAdmissao = headTotal > 0 ? Math.round(totalAdm / headTotal * 100) : 0;

  const mediaDias = arr => arr.length ? Math.round(arr.reduce((s, a) => s + a.diasProcesso, 0) / arr.length) : 0;
  const tempoFixo = mediaDias(adms.filter(a => a.categoria === 'fixo'));
  const tempoAssoc = mediaDias(adms.filter(a => a.categoria === 'associado'));

  const motivos = getMotivosDeslig().map(m => ({ ...m, n: desligs.filter(d => d.motivoId === m.id).length })).filter(m => m.n > 0).sort((a, b) => b.n - a.n);
  const maxDeslCat = Math.max(1, ...dataMes.map(m => m.deslFixo + m.deslAssoc));

  // Agrupamento trimestral (PDF Site AVD (2)): admissão + desligamento + linha turnover
  const dataTrim = (() => {
    const trims = {};
    dataMes.forEach(m => {
      const [y, mm] = m.key.split('-');
      const trimIdx = Math.floor((Number(mm) - 1) / 3) + 1;
      const tkey = `${trimIdx}T${y.slice(2)}`;
      if (!trims[tkey]) trims[tkey] = { key: tkey, label: tkey, adm: 0, des: 0 };
      trims[tkey].adm += m.admissoes;
      trims[tkey].des += m.desligamentos;
    });
    const arr = Object.values(trims);
    // Calcula turnover trimestral
    arr.forEach(t => { t.turnover = headTotal > 0 ? Math.round(((t.adm + t.des) / 2) / headTotal * 1000) / 10 : 0; });
    return arr;
  })();

  // Tipo primário (Pedido / Empresa / Acordo). Lê do form de desligamento (tipo) ou inferir do motivoId
  // Padrão: motivoId 'pedido' -> pedido; 'reestruturacao'|'performance'|'justa_causa' -> empresa; outros -> acordo
  function tipoPrimarioDe(d) {
    const tipo = (d.tipoDesligamento || d.dados?.tipoDesligamento || '').toLowerCase();
    if (/pedido|colaborador/.test(tipo)) return 'pedido';
    if (/empresa|patron/.test(tipo))  return 'empresa';
    if (/acordo/.test(tipo))           return 'acordo';
    // Fallback: classifica pelo motivoId
    if (d.motivoId === 'pedido' || d.motivoId === 'mudanca_carreira') return 'pedido';
    if (['reestruturacao','performance','justa_causa'].includes(d.motivoId)) return 'empresa';
    return 'acordo';
  }
  const tiposPrimarios = [
    { id: 'pedido',  label: 'Pedido do colaborador', cor: '#1F4A8A' },
    { id: 'empresa', label: 'Saída por parte da empresa', cor: '#B3261E' },
    { id: 'acordo',  label: 'Acordo entre as partes', cor: '#6B3FA0' },
  ].map(t => ({ ...t, n: desligs.filter(d => tipoPrimarioDe(d) === t.id).length }));

  // PDF Site AVD (2): Taxa de admissao removida (acumulativa demais, sem corte temporal).
  const turnoverCards = [
    { label: 'Turnover anual', val: turnover(totalAdm, totalDesl, headTotal) + '%', sub: 'geral (12 meses)', g: 'linear-gradient(135deg,#6B3FA0,#3A1E70)', icon: 'trend_up' },
    { label: 'Turnover · Fixos', val: turnover(admFixo, deslFixo, headFixo) + '%', sub: `${headFixo} fixos ativos`, g: 'linear-gradient(135deg,#1F4A8A,#0A1E50)', icon: 'user' },
    { label: 'Turnover · Associados', val: turnover(admAssoc, deslAssoc, headAssoc) + '%', sub: `${headAssoc} associados ativos`, g: 'linear-gradient(135deg,#00967B,#004A3C)', icon: 'users' },
  ];

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14, animation: 'fadeIn .22s var(--ease-out)' }}>
      {/* KPIs de turnover */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 14 }}>
        {turnoverCards.map(k => (
          <div key={k.label} style={{ background: k.g, borderRadius: 16, padding: '20px 20px 18px', color: '#fff', position: 'relative', overflow: 'hidden', boxShadow: '0 8px 28px rgba(0,0,0,.18)' }}>
            <div style={{ position: 'absolute', right: -20, top: -20, width: 90, height: 90, borderRadius: '50%', background: 'rgba(255,255,255,.08)' }} />
            <div style={{ position: 'absolute', right: 18, bottom: 14, opacity: .3 }}><Icon name={k.icon} size={32} /></div>
            <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'rgba(255,255,255,.7)', marginBottom: 8 }}>{k.label}</div>
            <div style={{ fontSize: 32, fontWeight: 900, lineHeight: 1, letterSpacing: '-.03em', marginBottom: 5 }}>{k.val}</div>
            <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,.65)' }}>{k.sub}</div>
          </div>
        ))}
      </div>

      {/* Admissão × Desligamento por trimestre + linha de turnover (PDF Site AVD (2)) */}
      <Card pad={22}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 }}>
          <div>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Movimentação · Integrado</div>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Admissões × Desligamentos por trimestre + Turnover</div>
          </div>
          <div style={{ flex: 1 }} />
          <div style={{ display: 'flex', gap: 14, fontSize: 11.5, color: 'var(--escalab-mute)' }}>
            <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}><div style={{ width: 9, height: 9, borderRadius: 2, background: '#1F4A8A' }} /> Admissões</div>
            <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}><div style={{ width: 9, height: 9, borderRadius: 2, background: '#B3261E' }} /> Desligamentos</div>
            <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}><div style={{ width: 18, height: 2, background: '#E89B3B' }} /> Turnover %</div>
          </div>
        </div>
        {(() => {
          if (!dataTrim.length) return <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Sem dados no período.</div>;
          const maxBar = Math.max(2, ...dataTrim.map(t => Math.max(t.adm, t.des)));
          const maxTurn = Math.max(5, ...dataTrim.map(t => t.turnover));
          const W = 640, H = 220, padL = 30, padR = 30, padT = 16, padB = 32;
          const innerW = W - padL - padR, innerH = H - padT - padB;
          const slotW = innerW / dataTrim.length;
          const barW = slotW * 0.32;
          return (
            <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', height: 'auto', maxHeight: 240 }}>
              {/* Grid horizontal */}
              {[0, 0.25, 0.5, 0.75, 1].map((g, i) => (
                <line key={i} x1={padL} y1={padT + innerH * (1 - g)} x2={W - padR} y2={padT + innerH * (1 - g)} stroke="#EEF1F5" strokeWidth="1" />
              ))}
              {/* Barras */}
              {dataTrim.map((t, i) => {
                const cx = padL + slotW * (i + 0.5);
                const hAdm = (t.adm / maxBar) * innerH;
                const hDes = (t.des / maxBar) * innerH;
                return (
                  <g key={t.key}>
                    <rect x={cx - barW - 2} y={padT + innerH - hAdm} width={barW} height={hAdm} fill="#1F4A8A" rx={3} />
                    <rect x={cx + 2} y={padT + innerH - hDes} width={barW} height={hDes} fill="#B3261E" rx={3} />
                    <text x={cx - barW/2 - 2} y={padT + innerH - hAdm - 4} fontSize="10" textAnchor="middle" fill="#1F4A8A" fontWeight="700">{t.adm || ''}</text>
                    <text x={cx + barW/2 + 2} y={padT + innerH - hDes - 4} fontSize="10" textAnchor="middle" fill="#B3261E" fontWeight="700">{t.des || ''}</text>
                    <text x={cx} y={H - 12} fontSize="11" textAnchor="middle" fill="var(--escalab-slate)">{t.label}</text>
                  </g>
                );
              })}
              {/* Linha turnover */}
              <polyline
                fill="none" stroke="#E89B3B" strokeWidth="2.5"
                points={dataTrim.map((t, i) => {
                  const cx = padL + slotW * (i + 0.5);
                  const cy = padT + innerH - (t.turnover / maxTurn) * innerH;
                  return `${cx},${cy}`;
                }).join(' ')}
              />
              {dataTrim.map((t, i) => {
                const cx = padL + slotW * (i + 0.5);
                const cy = padT + innerH - (t.turnover / maxTurn) * innerH;
                return (
                  <g key={'t' + t.key}>
                    <circle cx={cx} cy={cy} r="4" fill="#E89B3B" stroke="#fff" strokeWidth="1.5" />
                    <text x={cx} y={cy - 10} fontSize="10.5" textAnchor="middle" fill="#B56500" fontWeight="700">{t.turnover.toFixed(1)}%</text>
                  </g>
                );
              })}
            </svg>
          );
        })()}
      </Card>
      <InfoGrafico
        significado="Movimentação consolidada por trimestre: admissões (azul) e desligamentos (vermelho) em barras, taxa de turnover trimestral em linha."
        calculo="Por trimestre: Σ admissões + Σ desligamentos. Turnover = ((admissões + desligamentos) ÷ 2) ÷ headcount × 100."
        fonte="kanban Admissão e Desligamento + headcount atual"
      />

      {/* Card "Movimentação · Mensal · Admissões × Desligamentos por mês" removido a pedido (sessão 2026-06-15 #4). */}

      {/* Taxa de desligamento por mês (clicável) + Motivos */}
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 14 }}>
        <Card pad={22}>
          <div style={{ marginBottom: 16 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Desligamentos por mês</div>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Fixos × Associados · clique no mês para ver quem saiu</div>
          </div>
          <div style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height: 150, paddingBottom: 22, position: 'relative' }}>
            {dataMes.map(m => {
              const total = m.deslFixo + m.deslAssoc;
              const hFixo = (m.deslFixo / maxDeslCat) * 120;
              const hAssoc = (m.deslAssoc / maxDeslCat) * 120;
              return (
                <div key={m.key} onClick={() => total > 0 && setMesSel(m)} title={`${m.label}: ${total} desligamento(s)`}
                  style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'flex-end', gap: 2, cursor: total > 0 ? 'pointer' : 'default', position: 'relative', height: '100%' }}>
                  {total > 0 && <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--escalab-ink)' }}>{total}</div>}
                  <div style={{ width: '70%', maxWidth: 28, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', gap: 2 }}>
                    {m.deslAssoc > 0 && <div style={{ height: hAssoc, background: '#00967B', borderRadius: '4px 4px 0 0', transition: 'height .4s' }} />}
                    {m.deslFixo > 0 && <div style={{ height: hFixo, background: '#1F4A8A', borderRadius: m.deslAssoc > 0 ? 0 : '4px 4px 0 0', transition: 'height .4s' }} />}
                    {total === 0 && <div style={{ height: 3, background: 'var(--escalab-line)', borderRadius: 999 }} />}
                  </div>
                  <div style={{ position: 'absolute', bottom: -22, fontSize: 11, color: 'var(--escalab-slate)', fontWeight: 600 }}>{m.label}</div>
                </div>
              );
            })}
          </div>
          <div style={{ display: 'flex', gap: 14, marginTop: 8, fontSize: 11.5, color: 'var(--escalab-mute)' }}>
            <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}><div style={{ width: 9, height: 9, borderRadius: 2, background: '#1F4A8A' }} /> Fixos</div>
            <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}><div style={{ width: 9, height: 9, borderRadius: 2, background: '#00967B' }} /> Associados</div>
          </div>
        </Card>

        <Card pad={22}>
          <div style={{ marginBottom: 16 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Motivos · Tipo primário</div>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Pedido × Empresa × Acordo</div>
          </div>
          {totalDesl === 0 ? <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Sem desligamentos registrados.</div> : (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 11 }}>
              {tiposPrimarios.map(t => {
                const pct = totalDesl > 0 ? Math.round(t.n / totalDesl * 100) : 0;
                return (
                  <div key={t.id}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                      <span style={{ fontSize: 12.5, color: 'var(--escalab-ink)' }}>{t.label}</span>
                      <span style={{ fontSize: 12.5, fontWeight: 700, color: t.cor }}>{pct}% <span style={{ fontWeight: 400, color: 'var(--escalab-mute)', fontSize: 11 }}>({t.n})</span></span>
                    </div>
                    <div style={{ height: 7, background: 'var(--escalab-line)', borderRadius: 999 }}>
                      <div style={{ width: pct + '%', height: '100%', background: t.cor, borderRadius: 999, transition: 'width .5s' }} />
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </Card>
      </div>
      <InfoGrafico
        significado="Quando a empresa perde gente e por qual tipo de motivo. Esquerda: distribuição mensal por categoria (fixo × associado), clicável para ver quem saiu. Direita: motivo primário (pedido/empresa/acordo)."
        calculo="Mês = data de desligamento dentro do mês. Tipo primário = nº de desligamentos por categoria ÷ total de desligamentos do período × 100."
        fonte="kanban Desligamento + MOTIVOS_DESLIGAMENTO" />

      {/* Motivos secundários (lista editável em Admin) · PDF Site AVD (2) */}
      <Card pad={22}>
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Motivos · Secundários</div>
          <div style={{ fontSize: 15, fontWeight: 600 }}>Detalhe do motivo (preenchido no formulário de desligamento)</div>
        </div>
        {motivos.length === 0 ? <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Sem desligamentos registrados.</div> : (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 11 }}>
            {motivos.map(m => {
              const pct = Math.round(m.n / totalDesl * 100);
              return (
                <div key={m.id}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                    <span style={{ fontSize: 12.5, color: 'var(--escalab-ink)' }}>{m.label}</span>
                    <span style={{ fontSize: 12.5, fontWeight: 700, color: m.cor }}>{pct}% <span style={{ fontWeight: 400, color: 'var(--escalab-mute)', fontSize: 11 }}>({m.n})</span></span>
                  </div>
                  <div style={{ height: 7, background: 'var(--escalab-line)', borderRadius: 999 }}>
                    <div style={{ width: pct + '%', height: '100%', background: m.cor, borderRadius: 999, transition: 'width .5s' }} />
                  </div>
                </div>
              );
            })}
          </div>
        )}
        <div style={{ marginTop: 14, padding: '10px 12px', background: '#FFF7EB', border: '1px solid #FFD6A3', borderRadius: 8, fontSize: 11.5, color: '#7A4A00' }}>
          Lista personalizada em Admin → Cargos & Deptos → Motivos de desligamento (em breve). Para já, edite em <code>data.jsx</code> → MOTIVOS_DESLIGAMENTO ou use o botão "+ Novo" no formulário.
        </div>
      </Card>
      <InfoGrafico
        significado="Detalha o motivo específico de cada desligamento (descontentamento, mudança de carreira, falta de fit, etc). Sinaliza onde focar retenção."
        calculo="Por motivo secundário: nº de desligamentos com esse motivo ÷ total de desligamentos × 100."
        fonte="campo motivoSecundarioId do desligamento (kanban + MOTIVOS_DESLIGAMENTO)" />

      {/* PDF Site AVD (2): "Tempo médio entre abertura e admissão" foi removido daqui.
          Já aparece em Movimentos → Recrutamento como "Tempo médio de fechamento". */}

      {/* Modal: quem foi desligado no mês */}
      <Modal open={!!mesSel} onClose={() => setMesSel(null)} title={mesSel ? `Desligamentos · ${mesSel.label}` : ''} width={460}>
        {mesSel && (mesSel.desligados.length === 0 ? <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Nenhum desligamento neste mês.</div> : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {mesSel.desligados.map(d => {
              const motivo = getMotivoDeslig(d.motivoId);
              return (
                <div key={d.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 12px', border: '1px solid var(--escalab-line)', borderRadius: 10 }}>
                  <div style={{ width: 36, height: 36, borderRadius: '50%', background: 'var(--escalab-line)', color: 'var(--escalab-mute)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Icon name="user" size={16} /></div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13.5, fontWeight: 600 }}>{d.nome}</div>
                    <div style={{ fontSize: 11.5, color: 'var(--escalab-mute)' }}>{d.setor} · {CATEGORIA_LABEL[d.categoriaKey] || (d.categoriaKey === 'fixo' ? 'Fixo' : 'Associado')}</div>
                  </div>
                  {motivo && <Tag tone="neutral" size="xs">{motivo.label}</Tag>}
                </div>
              );
            })}
          </div>
        ))}
      </Modal>
    </div>
  );
};

const PainelFeriasResumo = () => {
  const fer = typeof getFeriasSolicitacoes === 'function' ? getFeriasSolicitacoes() : [];
  const aprovadas = fer.filter(f => f.status === 'aprovada');
  const pendentes = fer.filter(f => (f.status || '').startsWith('pendente'));
  const hoje = new Date().toISOString().slice(0, 10);
  const proximas = aprovadas.filter(f => (f.inicio || '') >= hoje).sort((a, b) => (a.inicio || '').localeCompare(b.inicio || '')).slice(0, 6);
  const nomeDe = id => (COLABORADORES.find(c => c.id === id)?.nome) || 'Colaborador';
  return (
    <Card pad={22}>
      <div style={{ marginBottom: 16 }}>
        <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Férias & Day Off</div>
        <div style={{ fontSize: 15, fontWeight: 600 }}>Resumo de férias</div>
      </div>
      <div style={{ display: 'flex', gap: 20, marginBottom: 16 }}>
        <div><div style={{ fontSize: 30, fontWeight: 900, color: 'var(--escalab-brand-deep)', lineHeight: 1 }}>{aprovadas.length}</div><div style={{ fontSize: 11.5, color: 'var(--escalab-mute)', marginTop: 4 }}>aprovadas</div></div>
        <div><div style={{ fontSize: 30, fontWeight: 900, color: '#B56500', lineHeight: 1 }}>{pendentes.length}</div><div style={{ fontSize: 11.5, color: 'var(--escalab-mute)', marginTop: 4 }}>pendentes</div></div>
      </div>
      <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 8 }}>Próximas férias</div>
      {proximas.length === 0 ? <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Nenhuma férias aprovada futura.</div> : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          {proximas.map(f => (
            <div key={f.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 0', borderBottom: '1px solid var(--escalab-line)' }}>
              <span style={{ fontSize: 13, color: 'var(--escalab-ink)', flex: 1 }}>{nomeDe(f.colaboradorId)}</span>
              <span style={{ fontSize: 12, color: 'var(--escalab-mute)' }}>{(f.inicio || '').split('-').reverse().join('/')} – {(f.fim || '').split('-').reverse().join('/')}</span>
            </div>
          ))}
        </div>
      )}
    </Card>
  );
};

const PainelRemuneracao = () => {
  const fmt = v => 'R$ ' + (Number(v) || 0).toLocaleString('pt-BR');
  const ativos = getColaboradoresAtivos();
  const salarios = ativos.map(c => getSalario(c));
  const folha = salarios.reduce((s, v) => s + v, 0);
  const medGeral = medianaArr(salarios);
  const minS = Math.min(...salarios), maxS = Math.max(...salarios);

  // PDF Site AVD (2): 3 níveis padronizados (Diretor / Líder de setor / Liderado)
  const porNivel = [
    { key: 'diretor',  label: 'Diretor(a) / CEO',    cor: '#1F4A8A' },
    { key: 'lider',    label: 'Líder de setor',      cor: '#00967B' },
    { key: 'liderado', label: 'Liderado',            cor: '#6B3FA0' },
  ].map(n => {
    const arr = ativos.filter(c => c.nivel === n.key).map(getSalario);
    return { ...n, n: arr.length, mediana: medianaArr(arr) };
  }).filter(n => n.n > 0);

  const porSetor = Object.entries(ativos.reduce((acc, c) => { (acc[c.setor] = acc[c.setor] || []).push(getSalario(c)); return acc; }, {}))
    .map(([setor, arr]) => ({ setor, n: arr.length, mediana: medianaArr(arr) }))
    .sort((a, b) => b.mediana - a.mediana).slice(0, 10);

  const fixoArr  = ativos.filter(c => getCategoriaKey(c.id) === 'fixo').map(getSalario);
  const assocArr = ativos.filter(c => getCategoriaKey(c.id) !== 'fixo').map(getSalario);
  const cats = [
    { label: 'Fixos',      n: fixoArr.length,  mediana: medianaArr(fixoArr),  cor: '#1F4A8A', bg: '#EEF3FA' },
    { label: 'Associados', n: assocArr.length, mediana: medianaArr(assocArr), cor: '#00967B', bg: '#E6F5F1' },
  ];

  const maxNivel = Math.max(1, ...porNivel.map(n => n.mediana));
  const maxSetor = Math.max(1, ...porSetor.map(s => s.mediana));

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14, animation: 'fadeIn .22s var(--ease-out)' }}>
      <div style={{ background: '#FFF7EB', border: '1px solid #FFD6A3', borderRadius: 12, padding: '11px 14px', fontSize: 12.5, color: '#7A4A00', display: 'flex', gap: 8, alignItems: 'center' }}>
        <Icon name="lock" size={14} /> Dados sensíveis · visível apenas para o GC. Analise sempre com contexto e atenção ao tamanho das bases.
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 14 }}>
        {[
          { label: 'Mediana salarial', val: fmt(medGeral), sub: `${ativos.length} colaboradores`, g: 'linear-gradient(135deg,#00967B,#004A3C)', icon: 'chart' },
          { label: 'Folha mensal',     val: fmt(folha),    sub: 'soma dos salários ativos',  g: 'linear-gradient(135deg,#1F4A8A,#0A1E50)', icon: 'trend_up' },
          { label: 'Faixa salarial',   val: fmt(minS) + ' – ' + fmt(maxS), sub: 'menor e maior', g: 'linear-gradient(135deg,#6B3FA0,#3A1E70)', icon: 'users' },
        ].map(k => (
          <div key={k.label} style={{ background: k.g, borderRadius: 16, padding: '20px 20px 18px', color: '#fff', position: 'relative', overflow: 'hidden', boxShadow: '0 8px 28px rgba(0,0,0,.18)' }}>
            <div style={{ position: 'absolute', right: -20, top: -20, width: 90, height: 90, borderRadius: '50%', background: 'rgba(255,255,255,.08)' }} />
            <div style={{ position: 'absolute', right: 18, bottom: 14, opacity: .3 }}><Icon name={k.icon} size={32} /></div>
            <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'rgba(255,255,255,.7)', marginBottom: 8 }}>{k.label}</div>
            <div style={{ fontSize: 26, fontWeight: 900, lineHeight: 1.05, letterSpacing: '-.02em', marginBottom: 5 }}>{k.val}</div>
            <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,.65)' }}>{k.sub}</div>
          </div>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card pad={22}>
          <div style={{ marginBottom: 16 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Por nível</div>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Mediana salarial por nível</div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {porNivel.map(n => (
              <div key={n.key}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5 }}>
                  <span style={{ fontSize: 13, color: 'var(--escalab-ink)' }}>{n.label} <span style={{ color: 'var(--escalab-mute)', fontSize: 11 }}>({n.n})</span></span>
                  <span style={{ fontSize: 13, fontWeight: 700, color: n.cor }}>{fmt(n.mediana)}</span>
                </div>
                <div style={{ height: 8, background: 'var(--escalab-line)', borderRadius: 999 }}>
                  <div style={{ width: (n.mediana / maxNivel * 100) + '%', height: '100%', background: n.cor, borderRadius: 999, transition: 'width .5s' }} />
                </div>
              </div>
            ))}
          </div>
          <div style={{ marginTop: 18, paddingTop: 14, borderTop: '1px solid var(--escalab-line)', display: 'flex', gap: 14 }}>
            {cats.map(c => (
              <div key={c.label} style={{ flex: 1, background: c.bg, border: `1px solid ${c.cor}25`, borderRadius: 10, padding: '12px 14px' }}>
                <div style={{ fontSize: 18, fontWeight: 900, color: c.cor, lineHeight: 1 }}>{fmt(c.mediana)}</div>
                <div style={{ fontSize: 11, color: 'var(--escalab-mute)', marginTop: 3 }}>{c.label} · mediana ({c.n})</div>
              </div>
            ))}
          </div>
        </Card>

        <Card pad={22}>
          <div style={{ marginBottom: 16 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Por setor</div>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Mediana salarial por setor</div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {porSetor.map((s, i) => (
              <div key={s.setor} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <span style={{ fontSize: 12, color: 'var(--escalab-slate)', minWidth: 130, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{s.setor}</span>
                <div style={{ flex: 1, height: 7, background: 'var(--escalab-line)', borderRadius: 999 }}>
                  <div style={{ width: (s.mediana / maxSetor * 100) + '%', height: '100%', background: 'var(--escalab-brand)', borderRadius: 999, transition: 'width .5s' }} />
                </div>
                <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--escalab-brand-deep)', minWidth: 78, textAlign: 'right' }}>{fmt(s.mediana)}</span>
              </div>
            ))}
          </div>
        </Card>
      </div>
      <InfoGrafico
        significado="Mediana salarial por nível hierárquico e por setor. Mediana (não média) reduz o efeito de salários extremos."
        calculo="Para cada agrupamento: ordena salários, pega o valor central. Cards extras destacam fixos vs associados separadamente."
        fonte="campo salarioBruto de Dados Organizacionais"
      />

      {/* Percentis e faixas salariais · docx 11 */}
      {(() => {
        const p25 = percentil(salarios, 25);
        const p75 = percentil(salarios, 75);
        const medAri = media(salarios);
        const faixas = [
          { label: 'até R$ 2.000',       min: 0,     max: 2000 },
          { label: 'R$ 2.000 – 4.000',   min: 2000,  max: 4000 },
          { label: 'R$ 4.000 – 6.000',   min: 4000,  max: 6000 },
          { label: 'R$ 6.000 – 10.000',  min: 6000,  max: 10000 },
          { label: 'R$ 10.000 – 15.000', min: 10000, max: 15000 },
          { label: '> R$ 15.000',        min: 15000, max: Infinity },
        ];
        const distrFaixa = faixas.map(f => ({
          label: f.label,
          valor: salarios.filter(s => s >= f.min && s < f.max).length,
        }));

        // Mediana de aumento salarial por tipo (histórico org)
        const historicoAll = getHistoricoOrgAll();
        const aumentosPromocao = [], aumentosAjuste = [], aumentosCargo = [];
        Object.entries(historicoAll).forEach(([colabId, log]) => {
          (log || []).forEach(h => {
            const sal = (h.mudancas || []).find(m => /sal[áa]rio/i.test(m.campo));
            const tipo = (h.mudancas || []).find(m => /tipo.*movimenta/i.test(m.campo));
            if (sal) {
              const antes = parseMoeda(sal.antes), depois = parseMoeda(sal.depois);
              if (antes > 0 && depois > antes) {
                const pct = ((depois - antes) / antes) * 100;
                const t = tipo?.depois || '';
                if (/promo/i.test(t)) aumentosPromocao.push(pct);
                else if (/ajuste/i.test(t)) aumentosAjuste.push(pct);
                else if (/cargo/i.test(t)) aumentosCargo.push(pct);
                else aumentosAjuste.push(pct);
              }
            }
          });
        });
        return (
          <>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14, marginTop: 14 }}>
              <KpiCard titulo="Percentil 25 (P25)" valor={fmt(p25)} sub="25% dos colaboradores ganham até este valor" cor="linear-gradient(135deg,#1F4A8A,#0A1E50)" icon="trend_down" tooltip="P25: o salário no qual 25% das pessoas ganham menos ou igual." />
              <KpiCard titulo="Média salarial" valor={fmt(medAri)} sub="média aritmética da folha" cor="linear-gradient(135deg,#00836B,#004A3C)" icon="chart" tooltip="Σ salários ÷ headcount." />
              <KpiCard titulo="Percentil 75 (P75)" valor={fmt(p75)} sub="75% dos colaboradores ganham até este valor" cor="linear-gradient(135deg,#B56500,#7A3F00)" icon="trend_up" tooltip="P75: o salário no qual 75% das pessoas ganham menos ou igual." />
            </div>

            <Card pad={22}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Distribuição salarial por faixa</div>
              <BarsHover data={distrFaixa} formatValor={v => v + ' pessoa(s)'} cor="#1F4A8A" height={160} />
            </Card>
            <InfoGrafico
              significado="Quantas pessoas se enquadram em cada faixa de salário."
              calculo="Faixas pré-definidas (até R$2k, R$2k-4k, R$4k-7k, R$7k-12k, R$12k+); contagem de colabs com salário registrado em Dados Organizacionais que cai em cada faixa."
              fonte="dados_org (campo salarioBruto)"
            />

            <Card pad={22}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 10 }}>Mediana de aumento salarial por tipo</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
                {[
                  { l: 'Promoção',           arr: aumentosPromocao,  cor: '#6B3FA0' },
                  { l: 'Ajuste salarial',    arr: aumentosAjuste,    cor: '#1F4A8A' },
                  { l: 'Alteração de cargo', arr: aumentosCargo,     cor: '#00836B' },
                ].map(x => (
                  <div key={x.l} style={{ background: 'var(--escalab-paper)', borderRadius: 10, padding: '14px' }}>
                    <div style={{ fontSize: 11, color: 'var(--escalab-mute)' }}>{x.l}</div>
                    <div style={{ fontSize: 26, fontWeight: 900, color: x.cor, lineHeight: 1 }}>
                      {x.arr.length ? mediana(x.arr).toFixed(1) + '%' : '·'}
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--escalab-mute)', marginTop: 4 }}>{x.arr.length} evento(s) registrado(s)</div>
                  </div>
                ))}
              </div>
              <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Mediana calculada a partir do histórico de alterações em Dados Organizacionais (campo Salário Bruto).</div>
            </Card>
          </>
        );
      })()}

      {/* PDF Site AVD 5 · itens 15, 16, 17 · Margem de contribuição /colab + Pessoas × Faturamento × Lucro */}
      {(() => {
        const indic = (typeof getIndicadoresFinanceiros === 'function') ? getIndicadoresFinanceiros() : [];
        if (!indic.length) return null;
        const desligList = (typeof getDesligamentos === 'function') ? getDesligamentos() : [];
        const headcountAno = (ano) => {
          const ref = `${ano}-12-31`;
          let n = 0;
          COLABORADORES.forEach(c => {
            const dorg = getDadosOrg(c.id);
            const adm = (dorg.dataAdmissao || c.dataAdmissao || '').slice(0, 10);
            if (!adm || adm > ref) return;
            const dRec = desligList.find(d => d.colaboradorId === c.id);
            const desl = (dRec?.dataDesligamento || '').slice(0, 10);
            if (desl && desl <= ref) return;
            n++;
          });
          return n;
        };
        // Headcount médio anual: média entre 1/jan e 31/dez do ano (aproximação)
        const headcountMedioAno = (ano) => {
          const fim = headcountAno(ano);
          const ini = headcountAno(ano - 1) || fim;
          return Math.round((ini + fim) / 2);
        };
        const linhas = indic
          .filter(x => x.ano >= 2022 && x.ano <= new Date().getFullYear())
          .sort((a,b) => a.ano - b.ano)
          .map(x => {
            const head = headcountMedioAno(x.ano);
            const fat = x.faturamento || 0;
            const lucro = x.lucro || 0;
            const margem = head > 0 ? Math.round(lucro / head) : 0;
            const fatPorColab = head > 0 ? Math.round(fat / head) : 0;
            return { ano: x.ano, fat, lucro, head, margem, fatPorColab };
          });
        const anoVigente = linhas[linhas.length - 1];
        const maxFat = Math.max(1, ...linhas.map(l => l.fat));
        const maxLucro = Math.max(1, ...linhas.map(l => l.lucro));
        const maxHead = Math.max(1, ...linhas.map(l => l.head));

        return (
          <>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14, marginTop: 14 }}>
              <KpiCard titulo="Margem de contribuição /colab" valor={fmt(anoVigente?.margem || 0)}
                sub={`Lucro ${anoVigente?.ano} ÷ headcount médio (${anoVigente?.head})`}
                cor="linear-gradient(135deg,#00836B,#004A3C)" icon="trend_up"
                tooltip="Aproximação: lucro do ano ÷ headcount médio anual. Substitua por (faturamento − custos variáveis) ÷ headcount quando o custo variável estiver cadastrado." />
              <KpiCard titulo="Faturamento /colab" valor={fmt(anoVigente?.fatPorColab || 0)}
                sub={`Faturamento ${anoVigente?.ano} ÷ headcount médio`}
                cor="linear-gradient(135deg,#1F4A8A,#0A1E50)" icon="chart"
                tooltip="Faturamento ÷ headcount médio. Métrica de produtividade financeira por pessoa." />
              <KpiCard titulo="Headcount médio (atual)" valor={anoVigente?.head || 0}
                sub={`média entre 31/dez/${(anoVigente?.ano || 0) - 1} e 31/dez/${anoVigente?.ano}`}
                cor="linear-gradient(135deg,#6B3FA0,#3A1E70)" icon="users"
                tooltip="Aproximação do headcount médio do ano. Útil para cruzar com indicadores anuais." />
            </div>

            <Card pad={22}>
              <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14, gap: 8, flexWrap: 'wrap' }}>
                <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase' }}>Pessoas × Faturamento × Lucro · comparativo anual</div>
                <div style={{ display: 'flex', gap: 14, fontSize: 11.5, color: 'var(--escalab-mute)' }}>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 12, height: 12, background: '#00967B', borderRadius: 3 }} /> Faturamento</span>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 12, height: 12, background: '#E89B3B', borderRadius: 3 }} /> Lucro</span>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 12, height: 12, background: '#1F4A8A', borderRadius: 3 }} /> Headcount</span>
                </div>
              </div>
              <div style={{ display: 'flex', gap: 18, alignItems: 'flex-end', padding: '8px 0 4px', minHeight: 180 }}>
                {linhas.map(l => {
                  const hFat = Math.round((l.fat / maxFat) * 145);
                  const hLucro = Math.round((l.lucro / maxLucro) * 145);
                  const hHead = Math.round((l.head / maxHead) * 145);
                  return (
                    <div key={l.ano} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
                      <div style={{ fontSize: 10, color: 'var(--escalab-mute)' }}>R$/colab: <strong style={{ color: 'var(--escalab-slate)' }}>{fmt(l.fatPorColab)}</strong></div>
                      <div style={{ fontSize: 10, color: 'var(--escalab-mute)' }}>Margem/colab: <strong style={{ color: '#00836B' }}>{fmt(l.margem)}</strong></div>
                      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 4, height: 150 }}>
                        <div title={`Faturamento ${l.ano}: ${fmt(l.fat)}`} style={{ width: 20, height: hFat, background: 'linear-gradient(180deg,#00967B,#004A3C)', borderRadius: '4px 4px 0 0', position: 'relative' }}>
                          <span style={{ position: 'absolute', top: -16, left: '50%', transform: 'translateX(-50%)', fontSize: 9.5, color: '#00836B', fontWeight: 700, whiteSpace: 'nowrap' }}>{(l.fat / 1_000_000).toFixed(1)}M</span>
                        </div>
                        <div title={`Lucro ${l.ano}: ${fmt(l.lucro)}`} style={{ width: 20, height: hLucro, background: 'linear-gradient(180deg,#E89B3B,#B56500)', borderRadius: '4px 4px 0 0', position: 'relative' }}>
                          <span style={{ position: 'absolute', top: -16, left: '50%', transform: 'translateX(-50%)', fontSize: 9.5, color: '#B56500', fontWeight: 700, whiteSpace: 'nowrap' }}>{l.lucro >= 1_000_000 ? (l.lucro / 1_000_000).toFixed(1) + 'M' : Math.round(l.lucro / 1000) + 'k'}</span>
                        </div>
                        <div title={`Headcount médio ${l.ano}: ${l.head}`} style={{ width: 20, height: hHead, background: 'linear-gradient(180deg,#1F4A8A,#0A1E50)', borderRadius: '4px 4px 0 0', position: 'relative' }}>
                          <span style={{ position: 'absolute', top: -16, left: '50%', transform: 'translateX(-50%)', fontSize: 9.5, color: '#1F4A8A', fontWeight: 700 }}>{l.head}</span>
                        </div>
                      </div>
                      <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--escalab-ink)', marginTop: 4 }}>{l.ano}</div>
                    </div>
                  );
                })}
              </div>
            </Card>
            <InfoGrafico
              significado="Compara, ano a ano, headcount médio, faturamento e lucro. Mostra se a empresa cresce em receita/lucro com ou sem expansão de quadro."
              calculo="Headcount médio = média entre 31/dez do ano anterior e 31/dez do ano. Margem de contribuição /colab = lucro ÷ headcount médio. Faturamento /colab = faturamento ÷ headcount médio."
              fonte="getIndicadoresFinanceiros + COLABORADORES + getDesligamentos"
            />
          </>
        );
      })()}
    </div>
  );
};

// Snapshots de dashboard salvos por ano (para comparação retroativa)
const DASH_SNAP_KEY = 'escalab_dashboard_snapshots';
function getSnapshots() { try { return JSON.parse(localStorage.getItem(DASH_SNAP_KEY) || '{}'); } catch { return {}; } }
function salvarSnapshot(ano, dados) {
  const all = getSnapshots();
  all[ano] = { ...dados, em: new Date().toISOString() };
  try { localStorage.setItem(DASH_SNAP_KEY, JSON.stringify(all)); } catch {}
}
function downloadJson(nome, dados) {
  try {
    const blob = new Blob([JSON.stringify(dados, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = nome;
    document.body.appendChild(a); a.click(); a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 500);
  } catch { alert('Não foi possível gerar o download.'); }
}
function downloadCsvFromRows(nome, rows) {
  try {
    if (!rows.length) { alert('Nenhum dado para exportar.'); return; }
    const headers = Object.keys(rows[0]);
    const csv = [headers.join(','), ...rows.map(r => headers.map(h => JSON.stringify(r[h] ?? '')).join(','))].join('\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = nome;
    document.body.appendChild(a); a.click(); a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 500);
  } catch { alert('Não foi possível gerar o CSV.'); }
}

// ─────────────────────────────────────────────────────────────────────────
// ── Painéis novos (docx 11) ──────────────────────────────────────────────
// ─────────────────────────────────────────────────────────────────────────

// Componente KPI grande com hover/tooltip
const KpiCard = ({ titulo, valor, sub, cor, icon, tooltip, deltaPct, badge }) => {
  const [hov, setHov] = useState(false);
  return (
    <div onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}
      style={{ background: cor, borderRadius: 16, padding: '20px 22px 18px', color: '#fff', position: 'relative', overflow: 'hidden', boxShadow: hov ? '0 14px 38px rgba(0,0,0,.24)' : '0 8px 24px rgba(0,0,0,.16)', transform: hov ? 'translateY(-2px)' : 'none', transition: 'all .2s' }}>
      <div style={{ position: 'absolute', right: -20, top: -20, width: 90, height: 90, borderRadius: '50%', background: 'rgba(255,255,255,.08)' }} />
      <div style={{ position: 'absolute', right: 18, bottom: 14, opacity: .3 }}><Icon name={icon} size={32} /></div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 10.5, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'rgba(255,255,255,.78)', marginBottom: 8 }}>
        {titulo}
        {badge && <span style={{ background: 'rgba(255,255,255,.18)', borderRadius: 6, padding: '1px 7px', fontSize: 9.5, letterSpacing: '.04em' }}>{badge}</span>}
      </div>
      <div style={{ fontSize: 30, fontWeight: 900, lineHeight: 1, letterSpacing: '-.03em', marginBottom: 5 }}>{valor}</div>
      <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,.7)' }}>{sub}</div>
      {Number.isFinite(deltaPct) && (
        <div style={{ marginTop: 7, display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 11.5, fontWeight: 700, color: deltaPct >= 0 ? '#A7F3D0' : '#FCA5A5' }}>
          <Icon name={deltaPct >= 0 ? 'trend_up' : 'trend_down'} size={11} />
          {(deltaPct >= 0 ? '+' : '') + deltaPct.toFixed(1) + '%'} vs período anterior
        </div>
      )}
      {hov && tooltip && (
        <div style={{ position: 'absolute', left: 16, right: 16, bottom: -2, background: 'rgba(0,0,0,.6)', borderRadius: 8, padding: '6px 10px', fontSize: 11, color: '#fff', transform: 'translateY(100%)', marginTop: 6, zIndex: 5, lineHeight: 1.5 }}>
          {tooltip}
        </div>
      )}
    </div>
  );
};

// Gráfico de barras com hover/tooltip
const BarsHover = ({ data, formatValor, cor = 'var(--escalab-brand)', height = 130 }) => {
  const [hov, setHov] = useState(null);
  const max = Math.max(1, ...data.map(d => d.valor || 0));
  return (
    <div style={{ position: 'relative' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height, paddingBottom: 28 }}>
        {data.map((d, i) => {
          const h = ((d.valor || 0) / max) * (height - 30);
          return (
            <div key={i} onMouseEnter={e => setHov({ d, x: e.clientX, y: e.clientY })} onMouseLeave={() => setHov(null)}
              style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'flex-end', cursor: 'default', position: 'relative', height: '100%' }}>
              {(d.valor || 0) > 0 && (
                <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-ink)', marginBottom: 3 }}>{formatValor ? formatValor(d.valor) : d.valor}</div>
              )}
              <div style={{ width: '70%', maxWidth: 36, height: Math.max(3, h), background: d.cor || cor, borderRadius: '5px 5px 0 0', transition: 'height .4s', opacity: hov && hov.d !== d ? .5 : 1 }} />
              <div style={{ position: 'absolute', bottom: -22, left: 0, right: 0, fontSize: 11.5, color: 'var(--escalab-slate)', fontWeight: 600, textAlign: 'center', maxWidth: '100%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', padding: '0 2px' }}>{d.label}</div>
            </div>
          );
        })}
      </div>
      {hov && (
        <div style={{ position: 'fixed', left: hov.x + 12, top: hov.y - 30, background: 'rgba(15,20,28,.96)', color: '#fff', borderRadius: 8, padding: '7px 12px', fontSize: 12, fontFamily: 'var(--font-sans)', pointerEvents: 'none', boxShadow: '0 6px 18px rgba(0,0,0,.25)', zIndex: 9999, lineHeight: 1.5 }}>
          <div style={{ fontWeight: 700 }}>{hov.d.label}</div>
          <div>{formatValor ? formatValor(hov.d.valor) : hov.d.valor}{hov.d.detalhe ? ' · ' + hov.d.detalhe : ''}</div>
        </div>
      )}
    </div>
  );
};

// Linha temporal com hover
const LineHover = ({ data, formatValor, cor = 'var(--escalab-brand)', height = 120, mostrarMeta = false }) => {
  const [hov, setHov] = useState(null);
  if (!data.length) return <div style={{ fontSize: 12, color: 'var(--escalab-mute)', textAlign: 'center', padding: 30 }}>Sem dados</div>;
  const w = 460;
  const vals = data.map(d => d.valor).concat(mostrarMeta && data.length ? data.map(d => d.meta || 0) : []);
  const min = Math.min(...vals, 0);
  const max = Math.max(...vals, 1);
  const range = (max - min) || 1;
  const stepX = data.length > 1 ? w / (data.length - 1) : 0;
  const toY = v => height - ((v - min) / range) * (height - 10);
  const toX = i => i * stepX;
  const path = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${toX(i)},${toY(d.valor)}`).join(' ');
  return (
    <div style={{ position: 'relative' }}>
      <svg viewBox={`0 0 ${w} ${height + 24}`} style={{ width: '100%', height: 'auto', overflow: 'visible' }}>
        <path d={path} fill="none" stroke={cor} strokeWidth="2.4" />
        {data.map((d, i) => (
          <g key={i} onMouseEnter={e => setHov({ d, i, x: e.clientX, y: e.clientY })} onMouseLeave={() => setHov(null)}>
            <circle cx={toX(i)} cy={toY(d.valor)} r={hov?.i === i ? 6 : 4} fill={cor} stroke="#fff" strokeWidth="2" />
            <rect x={toX(i) - 14} y={0} width={28} height={height} fill="transparent" />
            <text x={toX(i)} y={height + 20} textAnchor="middle" fontSize={11} fontWeight={600} fill="var(--escalab-slate)" fontFamily="var(--font-sans)">{d.label}</text>
          </g>
        ))}
      </svg>
      {hov && (
        <div style={{ position: 'fixed', left: hov.x + 12, top: hov.y - 30, background: 'rgba(15,20,28,.96)', color: '#fff', borderRadius: 8, padding: '7px 12px', fontSize: 12, fontFamily: 'var(--font-sans)', pointerEvents: 'none', boxShadow: '0 6px 18px rgba(0,0,0,.25)', zIndex: 9999, lineHeight: 1.5 }}>
          <div style={{ fontWeight: 700 }}>{hov.d.label}</div>
          <div>{formatValor ? formatValor(hov.d.valor) : hov.d.valor}</div>
        </div>
      )}
    </div>
  );
};

// ── PAINEL: Indicadores Principais (topo) ───────────────────────────────────
const PainelTopo = ({ snaps, periodo = '12m' }) => {
  const ativos = COLABORADORES;
  const headTotal = ativos.length;
  const headFixo = ativos.filter(c => getCategoriaKey(c.id) === 'fixo').length;
  const headAssoc = headTotal - headFixo;

  // Histórico (snapshot do ano anterior)
  const anoAtual = new Date().getFullYear();
  const snapPrev = snaps?.[anoAtual - 1];
  const deltaHead = delta(snapPrev?.totalColab, headTotal);

  // Turnover · filtrado pelo período selecionado (PDF Site AVD (2))
  const mov = getMovimentacoesAll();
  const hoje = new Date();
  const desligs12m = mov.desligamento.filter(d => {
    const data = d.dados?.dataSaida || d.criadoEm;
    return data && dentroDoPeriodo(data, periodo);
  });
  const ehVoluntario = d => /pedido|colaborador|desistência|desistencia/i.test(d.dados?.tipoDesligamento || '');
  const desligVoluntario = desligs12m.filter(ehVoluntario).length;
  const desligInvol = desligs12m.length - desligVoluntario;
  const headMedio = headTotal; // aproximação
  const turnoverGeral = headMedio > 0 ? (desligs12m.length / headMedio) * 100 : 0;
  const turnoverVol = headMedio > 0 ? (desligVoluntario / headMedio) * 100 : 0;
  const turnoverInvol = headMedio > 0 ? (desligInvol / headMedio) * 100 : 0;
  // Split fixo × associado (PDF Site AVD 5 · item 4): cada desligamento é classificado pela categoria do colab
  const colabDoDeslig = d => {
    const nome = (d.dados?.nomeColaborador || d.nome || '').toLowerCase();
    if (!nome) return null;
    return COLABORADORES.find(c => nome.includes(c.nome.toLowerCase().split(' ')[0]));
  };
  const ehFixo = d => { const c = colabDoDeslig(d); return c ? getCategoriaKey(c.id) === 'fixo' : false; };
  const desligFixo = desligs12m.filter(ehFixo);
  const desligAssoc = desligs12m.filter(d => !ehFixo(d));
  const desligVolFixo = desligFixo.filter(ehVoluntario).length;
  const desligVolAssoc = desligAssoc.filter(ehVoluntario).length;
  const desligInvolFixo = desligFixo.length - desligVolFixo;
  const desligInvolAssoc = desligAssoc.length - desligVolAssoc;
  const tGeralFixo  = headFixo  > 0 ? (desligFixo.length  / headFixo)  * 100 : 0;
  const tGeralAssoc = headAssoc > 0 ? (desligAssoc.length / headAssoc) * 100 : 0;
  const tVolFixo    = headFixo  > 0 ? (desligVolFixo      / headFixo)  * 100 : 0;
  const tVolAssoc   = headAssoc > 0 ? (desligVolAssoc     / headAssoc) * 100 : 0;
  const tInvolFixo  = headFixo  > 0 ? (desligInvolFixo    / headFixo)  * 100 : 0;
  const tInvolAssoc = headAssoc > 0 ? (desligInvolAssoc   / headAssoc) * 100 : 0;

  // Absenteísmo (respeita período se for "AAAA" ou trimestre)
  const ausencias = lerLS('escalab_ausencias', []);
  const ausFiltradas = periodo === '12m'
    ? ausencias.filter(a => a.status === 'aprovado' && (a.dataInicio || '').slice(0,7) === hoje.toISOString().slice(0,7))
    : ausencias.filter(a => a.status === 'aprovado' && dentroDoPeriodo(a.dataInicio, periodo));
  // Número de meses do período (pra horas esperadas proporcional)
  const mesesPeriodo = (periodo === '12m') ? 1 : (/^\d{4}$/.test(periodo) ? 12 : 3);
  const diasUteisMes = 22;
  const horasEsperadas = headTotal * diasUteisMes * 8 * mesesPeriodo;
  const horasAusentes = ausFiltradas.reduce((s, a) => {
    const ini = new Date(a.dataInicio + 'T00:00:00');
    const fim = new Date((a.dataFim || a.dataInicio) + 'T00:00:00');
    const dias = Math.max(1, Math.round((fim - ini) / 86400000) + 1);
    return s + dias * 8;
  }, 0);
  const absenteismo = horasEsperadas > 0 ? (horasAusentes / horasEsperadas) * 100 : 0;
  const labelAbsen = (periodo === '12m') ? 'Mês atual' : rotuloPeriodo(periodo);

  // Engajamento (PCO geral) · média da última PCO ativa, separado fixo/assoc
  const pcoResp = lerLS('escalab_pco_respostas', []);
  const calcEngaj = (filtroIds) => {
    const respFil = pcoResp.filter(r => !filtroIds || filtroIds.includes(r.colaboradorId));
    const notas = respFil.flatMap(r => Object.values(r.respostas || {}).filter(v => typeof v === 'number'));
    return notas.length ? media(notas) * 10 : null;
  };
  const idsFixo = ativos.filter(c => getCategoriaKey(c.id) === 'fixo').map(c => c.id);
  const idsAssoc = ativos.filter(c => getCategoriaKey(c.id) !== 'fixo').map(c => c.id);
  const engajGeral = calcEngaj(null);
  const engajFixo  = calcEngaj(idsFixo);
  const engajAssoc = calcEngaj(idsAssoc);

  // eNPS · pergunta específica (id contém 'enps' ou texto). Se não houver, mostra placeholder.
  const calcEnps = (filtroIds) => {
    const respFil = pcoResp.filter(r => !filtroIds || filtroIds.includes(r.colaboradorId));
    const notas = [];
    respFil.forEach(r => {
      Object.entries(r.respostas || {}).forEach(([k, v]) => {
        if (/enps|recomendaria|recomendar/i.test(k) && typeof v === 'number') notas.push(v);
      });
    });
    if (!notas.length) return null;
    const prom = notas.filter(n => n >= 9).length;
    const det  = notas.filter(n => n <= 6).length;
    return Math.round(((prom - det) / notas.length) * 100);
  };
  const enpsGeral = calcEnps(null);
  const enpsFixo  = calcEnps(idsFixo);
  const enpsAssoc = calcEnps(idsAssoc);

  // Custo por colaborador
  const dadosOrg = getDadosOrgAll();
  const custoTotal = custoTotalEmpresa(dadosOrg);
  const custoPorColab = headTotal > 0 ? custoTotal / headTotal : 0;
  const custoFixoMedio = headFixo > 0 ? COLABORADORES.filter(c => getCategoriaKey(c.id) === 'fixo').reduce((s, c) => s + custoMensalColab(c.id, dadosOrg), 0) / headFixo : 0;
  const custoAssocMedio = headAssoc > 0 ? COLABORADORES.filter(c => getCategoriaKey(c.id) !== 'fixo').reduce((s, c) => s + custoMensalColab(c.id, dadosOrg), 0) / headAssoc : 0;

  const zonaEnps = v => v == null ? 'sem dados' : v < 0 ? 'crítica' : v < 30 ? 'melhoria' : v < 70 ? 'qualidade' : 'excelência';

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      <div style={{ background: '#fff', border: '1px solid var(--escalab-line)', borderRadius: 12, padding: '12px 16px', fontSize: 12.5, color: 'var(--escalab-slate)', lineHeight: 1.55 }}>
        Indicadores calculados em tempo real a partir dos dados da plataforma. Passe o mouse em qualquer cartão para ver a fórmula e os valores brutos.
      </div>

      {/* Linha 1: Headcount + Turnover */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
        <KpiCard titulo="Headcount Total" valor={headTotal} sub={`${headFixo} fixos · ${headAssoc} associados`} cor="linear-gradient(135deg,#00967B,#004A3C)" icon="users" deltaPct={deltaHead} tooltip="Pessoas ativas no último dia do mês. Fixos e Associados separados." />
        <KpiCard titulo="Turnover (12m)" valor={fmtPct(turnoverGeral, 1)} sub={`${desligs12m.length} saídas / ${headMedio} headcount médio`} cor="linear-gradient(135deg,#6B3FA0,#3A1E70)" icon="trend_down" tooltip="Fórmula: Nº desligamentos ÷ headcount médio × 100. Voluntário + involuntário." />
        <KpiCard titulo="Custo médio /colab" valor={fmtBRL(custoPorColab)} sub={`Fixo: ${fmtBRL(custoFixoMedio)} · Assoc: ${fmtBRL(custoAssocMedio)}`} cor="linear-gradient(135deg,#1F4A8A,#0A1E50)" icon="trend_up" tooltip="Fixos: salário + 13º/12 + PLR (2 sal/12) + VT R$200. Associados: só salário. Soma ÷ headcount." />
      </div>

      {/* Linha 2: Turnover detalhado */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card pad={20}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover · Voluntário × Involuntário</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
            {[
              { l: 'Geral',        v: turnoverGeral, vFixo: tGeralFixo,  vAssoc: tGeralAssoc, n: desligs12m.length,  nFixo: desligFixo.length,  nAssoc: desligAssoc.length, cor: '#6B3FA0' },
              { l: 'Voluntário',   v: turnoverVol,   vFixo: tVolFixo,    vAssoc: tVolAssoc,   n: desligVoluntario,    nFixo: desligVolFixo,      nAssoc: desligVolAssoc,    cor: '#1F4A8A' },
              { l: 'Involuntário', v: turnoverInvol, vFixo: tInvolFixo,  vAssoc: tInvolAssoc, n: desligInvol,         nFixo: desligInvolFixo,    nAssoc: desligInvolAssoc,  cor: '#B3261E' },
            ].map(x => (
              <div key={x.l} style={{ background: 'var(--escalab-paper)', borderRadius: 10, padding: '12px 14px' }}>
                <div style={{ fontSize: 11, color: 'var(--escalab-mute)' }}>{x.l}</div>
                <div style={{ fontSize: 22, fontWeight: 800, color: x.cor, lineHeight: 1.1 }}>{fmtPct(x.v,1)}</div>
                <div style={{ fontSize: 11, color: 'var(--escalab-mute)' }}>{x.n} desligamento(s)</div>
                <div style={{ marginTop: 8, paddingTop: 8, borderTop: '1px dashed var(--escalab-line)', display: 'flex', flexDirection: 'column', gap: 3 }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10.5 }}>
                    <span style={{ color: 'var(--escalab-slate)' }}>Fixos</span>
                    <span style={{ color: x.cor, fontWeight: 700 }}>{fmtPct(x.vFixo,1)} <span style={{ color:'var(--escalab-mute)', fontWeight:400 }}>({x.nFixo})</span></span>
                  </div>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10.5 }}>
                    <span style={{ color: 'var(--escalab-slate)' }}>Associados</span>
                    <span style={{ color: x.cor, fontWeight: 700 }}>{fmtPct(x.vAssoc,1)} <span style={{ color:'var(--escalab-mute)', fontWeight:400 }}>({x.nAssoc})</span></span>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </Card>
        <Card pad={20}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Absenteísmo · {labelAbsen}</div>
          <div style={{ fontSize: 36, fontWeight: 900, color: absenteismo > 5 ? '#B3261E' : '#1F4A8A', lineHeight: 1 }}>{fmtPct(absenteismo, 2)}</div>
          <div style={{ fontSize: 12, color: 'var(--escalab-mute)', marginTop: 6 }}>{Math.round(horasAusentes)} h ausentes ÷ {horasEsperadas} h esperadas</div>
          <div style={{ marginTop: 12, fontSize: 11, color: 'var(--escalab-mute)' }}>Fórmula: horas ausentes ÷ horas esperadas × 100 (jornada de 8h, {diasUteisMes} dias úteis).</div>
        </Card>
      </div>

      {/* Linha 3: Engajamento + eNPS */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card pad={20}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Engajamento (PCO)</div>
          {[
            { l: 'Geral',      v: engajGeral, cor: '#00836B' },
            { l: 'Fixos',      v: engajFixo,  cor: '#1F4A8A' },
            { l: 'Associados', v: engajAssoc, cor: '#E89B3B' },
          ].map(x => (
            <div key={x.l} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '6px 0' }}>
              <span style={{ width: 90, fontSize: 12, color: 'var(--escalab-slate)' }}>{x.l}</span>
              <div style={{ flex: 1, height: 8, background: 'var(--escalab-line)', borderRadius: 999 }}>
                <div style={{ width: ((x.v || 0)) + '%', maxWidth: '100%', height: '100%', background: x.cor, borderRadius: 999, transition: 'width .5s' }} />
              </div>
              <span style={{ fontSize: 13, fontWeight: 700, color: x.cor, minWidth: 60, textAlign: 'right' }}>{x.v == null ? '·' : x.v.toFixed(1) + '%'}</span>
            </div>
          ))}
          {engajGeral == null && <div style={{ fontSize: 11.5, color: 'var(--escalab-mute)', marginTop: 6 }}>Sem respostas de PCO ainda · calcula automaticamente quando houver.</div>}
        </Card>
        <Card pad={20}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>eNPS · Recomendaria o Escalab?</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10 }}>
            {[
              { l: 'Geral',      v: enpsGeral, cor: '#6B3FA0' },
              { l: 'Fixos',      v: enpsFixo,  cor: '#1F4A8A' },
              { l: 'Associados', v: enpsAssoc, cor: '#E89B3B' },
            ].map(x => (
              <div key={x.l} style={{ background: 'var(--escalab-paper)', borderRadius: 10, padding: '12px' }}>
                <div style={{ fontSize: 11, color: 'var(--escalab-mute)' }}>{x.l}</div>
                <div style={{ fontSize: 26, fontWeight: 900, color: x.cor, lineHeight: 1 }}>{x.v == null ? '·' : (x.v > 0 ? '+' + x.v : x.v)}</div>
                <div style={{ fontSize: 10.5, color: 'var(--escalab-mute)', marginTop: 4, textTransform: 'uppercase', letterSpacing: '.04em' }}>{zonaEnps(x.v)}</div>
              </div>
            ))}
          </div>
          <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Escalas: &lt;0 crítico · 0-30 melhoria · 30-70 qualidade · 70+ excelência.</div>
        </Card>
      </div>

      {/* Linha 4: Motivação PCO (dim2) + Nota Infraestrutura + Acidentes Graves (PDF Site AVD (2)) */}
      {(() => {
        // Motivação = dimensão 2 do PCO (PCO_DIMENSOES_SHORT[2] = "Motivação")
        const calcMotiv = (filtroIds) => {
          const respFil = pcoResp.filter(r => !filtroIds || filtroIds.includes(r.colaboradorId));
          const notas = [];
          respFil.forEach(r => Object.entries(r.respostas || {}).forEach(([k, v]) => {
            if (typeof v === 'number' && /^dim2/i.test(k)) notas.push(v);
          }));
          return notas.length ? media(notas) * 10 : null;
        };
        const motivGeral = calcMotiv(null);
        const motivFixo  = calcMotiv(idsFixo);
        const motivAssoc = calcMotiv(idsAssoc);

        // Nota Infraestrutura (anual) · consome OP_INFRA_*
        const opResp = lerLS('escalab_op_respostas', []);
        const calcInfra = (pesquisaId) => {
          const r = opResp.filter(x => x.pesquisaId === pesquisaId);
          if (!r.length) return null;
          const notas = [];
          r.forEach(x => Object.values(x.respostas || {}).forEach(v => { if (typeof v === 'number') notas.push(v); }));
          return notas.length ? Math.round(media(notas) * 10) / 10 : null;
        };
        const infra2025 = calcInfra('OP_INFRA_2025');
        const infra2024 = calcInfra('OP_INFRA_2024');
        const infraDelta = (infra2025 != null && infra2024 != null) ? (infra2025 - infra2024) : null;

        // Acidentes Graves · conta respostas marcadas como Grave/Fatal
        const acid = opResp.filter(x => x.pesquisaId === 'OP_ACIDENTES_GRAVES');
        // Filtra por período (Q2 é data)
        const acidPeriodo = acid.filter(x => dentroDoPeriodo(x.respostas?.Q2, periodo));
        const acidGraves = acidPeriodo.filter(x => /grave|fatal/i.test(x.respostas?.Q4 || '')).length;
        const acidTotal  = acidPeriodo.length;

        return (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
            <Card pad={20}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Motivação · PCO (dimensão)</div>
              {[
                { l: 'Geral',      v: motivGeral, cor: '#00836B' },
                { l: 'Fixos',      v: motivFixo,  cor: '#1F4A8A' },
                { l: 'Associados', v: motivAssoc, cor: '#E89B3B' },
              ].map(x => (
                <div key={x.l} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '6px 0' }}>
                  <span style={{ width: 90, fontSize: 12, color: 'var(--escalab-slate)' }}>{x.l}</span>
                  <div style={{ flex: 1, height: 8, background: 'var(--escalab-line)', borderRadius: 999 }}>
                    <div style={{ width: ((x.v || 0)) + '%', maxWidth: '100%', height: '100%', background: x.cor, borderRadius: 999, transition: 'width .5s' }} />
                  </div>
                  <span style={{ fontSize: 13, fontWeight: 700, color: x.cor, minWidth: 60, textAlign: 'right' }}>{x.v == null ? '·' : x.v.toFixed(1) + '%'}</span>
                </div>
              ))}
              {motivGeral == null && <div style={{ fontSize: 11.5, color: 'var(--escalab-mute)', marginTop: 6 }}>Sem respostas de PCO ainda.</div>}
            </Card>

            <Card pad={20}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Nota de Infraestrutura</div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginBottom: 8 }}>
                <div style={{ fontSize: 36, fontWeight: 900, color: '#1F4A8A', lineHeight: 1 }}>{infra2025 == null ? '·' : infra2025.toFixed(1)}</div>
                <div style={{ fontSize: 12, color: 'var(--escalab-mute)' }}>em 2025 (0–10)</div>
              </div>
              <div style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12, color: 'var(--escalab-mute)' }}>
                <span>2024: <strong style={{ color: 'var(--escalab-slate)' }}>{infra2024 == null ? '·' : infra2024.toFixed(1)}</strong></span>
                {infraDelta != null && (
                  <Tag tone={infraDelta >= 0 ? 'success' : 'danger'} size="xs">{infraDelta >= 0 ? '+' : ''}{infraDelta.toFixed(1)} vs 2024</Tag>
                )}
              </div>
              <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Pesquisa anual em Outras Pesquisas (Infraestrutura). Média das notas de ambiente, equipamentos, ferramentas e remoto/híbrido.</div>
            </Card>

            <Card pad={20}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Acidentes Graves · {rotuloPeriodo(periodo)}</div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 6 }}>
                <div style={{ fontSize: 36, fontWeight: 900, color: acidGraves > 0 ? '#B3261E' : '#00836B', lineHeight: 1 }}>{acidGraves}</div>
                <div style={{ fontSize: 12, color: 'var(--escalab-mute)' }}>Grave/Fatal</div>
              </div>
              <div style={{ fontSize: 12, color: 'var(--escalab-mute)' }}>{acidTotal} registro(s) total(is) no período</div>
              <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Formulário contínuo em Outras Pesquisas (Registro de Acidentes Graves). GC lança ocorrências.</div>
            </Card>
          </div>
        );
      })()}

      {/* Linha 5: Pessoas x Faturamento por ano (PDF Site AVD (3)) */}
      {(() => {
        const indic = (typeof getIndicadoresFinanceiros === 'function') ? getIndicadoresFinanceiros() : [];
        if (!indic.length) return null;
        const deslSet = new Set(getDesligamentos().map(d => ({ id: d.colaboradorId, data: d.dataDesligamento || d.data })).map(JSON.stringify));
        const desligList = getDesligamentos();
        // Headcount ao fim de cada ano: ativos em 31/dez
        const ymdLastOfYear = (a) => `${a}-12-31`;
        const headcountAno = (ano) => {
          const ref = ymdLastOfYear(ano);
          let n = 0;
          COLABORADORES.forEach(c => {
            const dorg = getDadosOrg(c.id);
            const adm = (dorg.dataAdmissao || c.dataAdmissao || '').slice(0, 10);
            if (!adm || adm > ref) return;
            const dRec = desligList.find(d => d.colaboradorId === c.id);
            const desl = (dRec?.dataDesligamento || '').slice(0, 10);
            if (desl && desl <= ref) return;
            n++;
          });
          return n;
        };
        const linhas = indic
          .filter(x => x.ano >= 2022 && x.ano <= new Date().getFullYear())
          .map(x => ({ ano: x.ano, fat: x.faturamento || 0, lucro: x.lucro || 0, head: headcountAno(x.ano) }));
        const maxFat = Math.max(1, ...linhas.map(l => l.fat));
        const maxHead = Math.max(1, ...linhas.map(l => l.head));
        return (
          <Card pad={22}>
            <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Pessoas × Faturamento · comparativo anual</div>
            <div style={{ display: 'flex', gap: 18, alignItems: 'flex-end', padding: '8px 0 4px', minHeight: 170 }}>
              {linhas.map(l => {
                const hFat = Math.round((l.fat / maxFat) * 140);
                const hHead = Math.round((l.head / maxHead) * 140);
                const fatPorPessoa = l.head > 0 ? Math.round(l.fat / l.head) : 0;
                return (
                  <div key={l.ano} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
                    <div style={{ fontSize: 10, color: 'var(--escalab-mute)', marginBottom: 2 }}>R$/colab: <strong style={{ color: 'var(--escalab-slate)' }}>{fmtBRL(fatPorPessoa)}</strong></div>
                    <div style={{ display: 'flex', alignItems: 'flex-end', gap: 4, height: 145 }}>
                      <div title={`Faturamento ${l.ano}: ${fmtBRL(l.fat)}`} style={{ width: 22, height: hFat, background: 'linear-gradient(180deg,#00967B,#004A3C)', borderRadius: '4px 4px 0 0', position: 'relative' }}>
                        <span style={{ position: 'absolute', top: -16, left: '50%', transform: 'translateX(-50%)', fontSize: 9.5, color: '#00836B', fontWeight: 700, whiteSpace: 'nowrap' }}>{(l.fat / 1_000_000).toFixed(1)}M</span>
                      </div>
                      <div title={`Pessoas ${l.ano}: ${l.head}`} style={{ width: 22, height: hHead, background: 'linear-gradient(180deg,#1F4A8A,#0A1E50)', borderRadius: '4px 4px 0 0', position: 'relative' }}>
                        <span style={{ position: 'absolute', top: -16, left: '50%', transform: 'translateX(-50%)', fontSize: 9.5, color: '#1F4A8A', fontWeight: 700 }}>{l.head}</span>
                      </div>
                    </div>
                    <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--escalab-ink)', marginTop: 4 }}>{l.ano}</div>
                  </div>
                );
              })}
            </div>
            <div style={{ display: 'flex', gap: 18, marginTop: 12, fontSize: 11.5, color: 'var(--escalab-mute)' }}>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 12, height: 12, background: '#00967B', borderRadius: 3, display: 'inline-block' }} /> Faturamento (R$)</span>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 12, height: 12, background: '#1F4A8A', borderRadius: 3, display: 'inline-block' }} /> Headcount (31/dez)</span>
            </div>
          </Card>
        );
      })()}
      <InfoGrafico
        significado="Compara a evolução de pessoas (headcount) com o faturamento e o R$/colab a cada ano. Permite ver se o crescimento de receita acompanha o de quadro."
        calculo="Headcount = colaboradores com dataAdmissao ≤ 31/dez/ano e sem desligamento até essa data. Faturamento = configurado em Admin → Indicadores Financeiros."
        fonte="COLABORADORES + getDesligamentos + getIndicadoresFinanceiros (cadastrado em Admin)"
      />
    </div>
  );
};

// ── PAINEL: Recrutamento & Seleção ──────────────────────────────────────────
const PainelRecrutamento = () => {
  const mov = getMovimentacoesAll();
  const admConcluidas = mov.admissao.filter(a => a.etapa === 'admitido');
  // Time to fill: diferença entre criadoEm e dataInicio do contrato (admissão).
  const dias = admConcluidas.map(a => {
    if (!a.criadoEm || !a.dados?.dataInicio) return null;
    return Math.max(0, Math.round((new Date(a.dados.dataInicio) - new Date(a.criadoEm)) / 86400000));
  }).filter(n => n != null);
  const ttfMedio = dias.length ? media(dias) : 0;
  const ttfFixo = (() => {
    const d = admConcluidas.filter(a => /clt|fixo/i.test(a.dados?.vinculo || '')).map(a => {
      if (!a.criadoEm || !a.dados?.dataInicio) return null;
      return Math.max(0, Math.round((new Date(a.dados.dataInicio) - new Date(a.criadoEm)) / 86400000));
    }).filter(n => n != null);
    return d.length ? media(d) : 0;
  })();
  const ttfAssoc = (() => {
    const d = admConcluidas.filter(a => !/clt|fixo/i.test(a.dados?.vinculo || '')).map(a => {
      if (!a.criadoEm || !a.dados?.dataInicio) return null;
      return Math.max(0, Math.round((new Date(a.dados.dataInicio) - new Date(a.criadoEm)) / 86400000));
    }).filter(n => n != null);
    return d.length ? media(d) : 0;
  })();

  // Retenção de talentos: lideranças (nivel='lider'/'diretor') que continuam ativas vs total no início do período.
  const talentos = COLABORADORES.filter(c => c.nivel === 'lider' || c.nivel === 'diretor');
  const desligsTalentos = mov.desligamento.filter(d => {
    const nome = (d.dados?.nomeColaborador || '').toLowerCase();
    return talentos.some(t => nome.includes(t.nome.toLowerCase().split(' ')[0]));
  }).length;
  const retencao = talentos.length ? (1 - desligsTalentos / talentos.length) * 100 : 100;

  // Custo de contratação: usa Maria Clara (analista de GC) configurável em Admin → Config GC.
  // Fórmula: (salário do analista GC ÷ horas mensais) × horas dela por contratação.
  const calcCusto = (typeof calcularCustoContratacao === 'function') ? calcularCustoContratacao() : { custoUnitario: 0, custoHora: 0, analistaNome: '·', horasPorContratacao: 0 };
  const custoMedio = calcCusto.custoUnitario;
  const totalContratacoes = admConcluidas.length;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
        <KpiCard titulo="Tempo médio de fechamento" valor={`${Math.round(ttfMedio)} dias`} sub={`Fixo: ${Math.round(ttfFixo)}d · Assoc: ${Math.round(ttfAssoc)}d`} cor="linear-gradient(135deg,#1F4A8A,#0A1E50)" icon="clock" tooltip="Σ (data admissão − data abertura) ÷ nº de vagas fechadas. Fonte: kanban Admissão." />
        <KpiCard titulo="Retenção de talentos" valor={fmtPct(retencao, 1)} sub={`${talentos.length} lideranças · ${desligsTalentos} desligamento(s) no período`} cor="linear-gradient(135deg,#00967B,#004A3C)" icon="star" tooltip="(1 − desligamentos de talentos ÷ total de talentos) × 100. Considera 'talento' = lideranças e diretores." />
        <KpiCard titulo="Custo médio de contratação" valor={fmtBRL(custoMedio)} sub={`${calcCusto.horasPorContratacao}h × R$ ${(calcCusto.custoHora || 0).toFixed(2).replace('.', ',')}/h · ${calcCusto.analistaNome} · ${totalContratacoes} contratações`} cor="linear-gradient(135deg,#B56500,#7A3F00)" icon="trend_up" tooltip={`(salário do analista GC ÷ ${calcCusto.horasPorContratacao || 24}h mensais) × horas dela por contratação. Configurável em Admin → Config GC.`} />
      </div>
      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Time to fill por categoria</div>
        <BarsHover data={[
          { label: 'Fixos', valor: Math.round(ttfFixo), cor: '#1F4A8A' },
          { label: 'Associados', valor: Math.round(ttfAssoc), cor: '#00967B' },
          { label: 'Média geral', valor: Math.round(ttfMedio), cor: '#6B3FA0' },
        ]} formatValor={v => v + ' dias'} height={140} />
      </Card>
      <InfoGrafico
        significado="Quantos dias em média entre abrir a vaga e o colab começar — comparando Fixos × Associados."
        calculo="Por categoria: Σ (data admissão − data abertura) ÷ nº de vagas fechadas no período."
        fonte="processos de recrutamento + dataAdmissao em dados_org"
      />

      {/* PDF Site AVD (3): Fontes de contratação */}
      {(() => {
        // Origens vindas do recrutamento (campo comoSoube/fonte do candidato aprovado).
        // Fallback: usa o campo `fonte` setado manualmente no kanban; default 'Outros'.
        const processos = (typeof getProcessos === 'function') ? getProcessos() : [];
        const aprovados = processos.flatMap(p => (p.candidatos || []).filter(c => c.etapa === 'aprovado'));
        const fontesContagem = {};
        aprovados.forEach(c => {
          const f = (c.fonte || c.comoSoube || 'Outros').toString().trim() || 'Outros';
          fontesContagem[f] = (fontesContagem[f] || 0) + 1;
        });
        const totalFontes = Object.values(fontesContagem).reduce((s, n) => s + n, 0);
        const fontes = Object.entries(fontesContagem)
          .map(([k, v]) => ({ label: k, valor: v, pct: totalFontes ? (v / totalFontes) * 100 : 0 }))
          .sort((a, b) => b.valor - a.valor);
        const coresFontes = ['#1F4A8A', '#00836B', '#6B3FA0', '#E89B3B', '#B56500', '#B3261E'];
        return (
          <>
            <Card pad={22}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Fontes de contratação</div>
              {fontes.length === 0 ? (
                <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Sem candidatos aprovados com origem registrada ainda. Use o campo "Como soube" no cadastro de candidato.</div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                  {fontes.map((f, i) => (
                    <div key={f.label}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                        <span style={{ fontSize: 12.5, color: 'var(--escalab-ink)' }}>{f.label}</span>
                        <span style={{ fontSize: 12.5, fontWeight: 700 }}>{f.valor} ({f.pct.toFixed(1)}%)</span>
                      </div>
                      <div style={{ height: 8, background: 'var(--escalab-line)', borderRadius: 999 }}>
                        <div style={{ width: f.pct + '%', height: '100%', background: coresFontes[i % coresFontes.length], borderRadius: 999, transition: 'width .5s' }} />
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </Card>
            <InfoGrafico
              significado="De onde vieram os candidatos que foram contratados · ajuda a decidir onde investir na captação."
              calculo="Conta candidatos com etapa='aprovado' agrupando pelo campo 'comoSoube' / 'fonte'. Percentual = origem ÷ total de contratações × 100."
              fonte="Recrutamento → cadastro de candidato (campo 'Como ficou sabendo da vaga')"
            />
          </>
        );
      })()}
    </div>
  );
};

// ── PAINEL: Perfil do Quadro ────────────────────────────────────────────────
const PainelPerfilQuadro = () => {
  const div = getDiversidadeAll();
  const dadosOrg = getDadosOrgAll();
  const mov = getMovimentacoesAll();
  const desligsLista = mov.desligamento;

  // Turnover por gênero
  const gens = ['Mulher cisgênero','Homem Cisgênero','Mulher Transgênero','Homem Transgênero','Não-binário','Gênero fluido','Prefiro não declarar'];
  const turnPorGen = gens.map(g => {
    const ativos = COLABORADORES.filter(c => div[c.id]?.genero === g).length;
    const desligs = desligsLista.filter(d => {
      const c = COLABORADORES.find(x => (d.dados?.nomeColaborador || '').toLowerCase().includes(x.nome.toLowerCase().split(' ')[0]));
      return c && div[c.id]?.genero === g;
    }).length;
    const turn = ativos > 0 ? (desligs / ativos) * 100 : 0;
    return { label: g, valor: Math.round(turn * 10) / 10, detalhe: `${desligs}/${ativos}` };
  });

  // Turnover por faixa etária
  const turnPorIdade = FAIXAS_ETARIAS.map(f => {
    const idsFaixa = COLABORADORES.filter(c => {
      const idade = calcIdade(dadosOrg[c.id]?.dataNascimento);
      return faixaEtariaDe(idade) === f.id;
    }).map(c => c.id);
    const ativos = idsFaixa.length;
    const desligs = desligsLista.filter(d => {
      const c = COLABORADORES.find(x => (d.dados?.nomeColaborador || '').toLowerCase().includes(x.nome.toLowerCase().split(' ')[0]));
      return c && idsFaixa.includes(c.id);
    }).length;
    const turn = ativos > 0 ? (desligs / ativos) * 100 : 0;
    return { label: f.label, valor: Math.round(turn * 10) / 10, detalhe: `${desligs}/${ativos}` };
  });

  // Distribuição por tempo de empresa
  const distrTempo = FAIXAS_TEMPO.map(f => {
    const n = COLABORADORES.filter(c => c.tempoEmpresa >= f.min && c.tempoEmpresa <= f.max).length;
    const pct = COLABORADORES.length > 0 ? (n / COLABORADORES.length) * 100 : 0;
    return { label: f.label, valor: Math.round(pct * 10) / 10, detalhe: `${n} pessoa(s)` };
  });

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Distribuição por tempo de empresa</div>
        <BarsHover data={distrTempo} formatValor={v => v.toFixed(1) + '%'} cor="#00836B" height={150} />
      </Card>
      <InfoGrafico
        significado="Quantos % do quadro estão em cada faixa de tempo de empresa. Indicador de maturidade e renovação."
        calculo="Para cada faixa: nº colaboradores com tempoEmpresa nessa faixa ÷ headcount total × 100."
        fonte="campo tempoEmpresa (meses) de cada colaborador"
      />
      <div style={{ padding: '14px 18px', background: '#F4EEFF', border: '1px solid #E0D4FF', borderRadius: 10, fontSize: 12.5, color: '#5B2EAA', display: 'flex', alignItems: 'center', gap: 10 }}>
        <Icon name="trend_down" size={14} />
        <span>Turnover por gênero, idade, etnia e tempo de empresa ficam agora consolidados na guia <strong>Movimentos → Turnover · Consolidado</strong>.</span>
      </div>
    </div>
  );
};

// ── PAINEL: Turnover Consolidado (unifica todas análises de turnover) ────────
const PainelTurnoverConsolidado = () => {
  const div = getDiversidadeAll();
  const dadosOrg = getDadosOrgAll();
  const mov = getMovimentacoesAll();
  const desligs = getDesligamentos();
  const ativos = getColaboradoresAtivos();

  const headTotal = ativos.length;
  const headFixo = ativos.filter(c => getCategoriaKey(c.id) === 'fixo').length;
  const headAssoc = headTotal - headFixo;
  const headMedio = Math.max(1, Math.round((headTotal + (headTotal + desligs.length)) / 2));

  const totalDesl = desligs.length;
  const turnoverGeral = headMedio > 0 ? (totalDesl / headMedio) * 100 : 0;
  const ehVol = d => ['pedido', 'mudanca_carreira'].includes(d.motivoId);
  const desligVoluntario = desligs.filter(ehVol).length;
  const desligInvol = totalDesl - desligVoluntario;
  const turnoverVol = headMedio > 0 ? (desligVoluntario / headMedio) * 100 : 0;
  const turnoverInvol = headMedio > 0 ? (desligInvol / headMedio) * 100 : 0;
  // Split fixo × associado (PDF Site AVD 5 · item 4)
  const colabDoDeslig2 = d => {
    const nome = (d.dados?.nomeColaborador || d.nome || '').toLowerCase();
    if (!nome) return null;
    return COLABORADORES.find(c => nome.includes(c.nome.toLowerCase().split(' ')[0]));
  };
  const ehFixo2 = d => { const c = colabDoDeslig2(d); return c ? getCategoriaKey(c.id) === 'fixo' : false; };
  const desligFixoArr2 = desligs.filter(ehFixo2);
  const desligAssocArr2 = desligs.filter(d => !ehFixo2(d));
  const tcGeralFixo  = headFixo  > 0 ? (desligFixoArr2.length  / headFixo)  * 100 : 0;
  const tcGeralAssoc = headAssoc > 0 ? (desligAssocArr2.length / headAssoc) * 100 : 0;
  const tcVolFixo    = headFixo  > 0 ? (desligFixoArr2.filter(ehVol).length  / headFixo)  * 100 : 0;
  const tcVolAssoc   = headAssoc > 0 ? (desligAssocArr2.filter(ehVol).length / headAssoc) * 100 : 0;
  const tcInvolFixo  = headFixo  > 0 ? (desligFixoArr2.filter(d => !ehVol(d)).length  / headFixo)  * 100 : 0;
  const tcInvolAssoc = headAssoc > 0 ? (desligAssocArr2.filter(d => !ehVol(d)).length / headAssoc) * 100 : 0;

  // Por gênero
  const gens = ['Mulher cisgênero','Homem Cisgênero','Mulher Transgênero','Homem Transgênero','Não-binário','Gênero fluido','Prefiro não declarar'];
  const turnPorGen = gens.map(g => {
    const ativosG = COLABORADORES.filter(c => div[c.id]?.genero === g).length;
    const deslG = desligs.filter(d => {
      const c = COLABORADORES.find(x => (d.nome || '').toLowerCase().includes(x.nome.toLowerCase().split(' ')[0]));
      return c && div[c.id]?.genero === g;
    }).length;
    return { label: g, valor: ativosG ? Math.round((deslG / ativosG) * 1000) / 10 : 0, detalhe: `${deslG}/${ativosG}` };
  });

  // Por faixa etária
  const turnPorIdade = FAIXAS_ETARIAS.map(f => {
    const idsFaixa = COLABORADORES.filter(c => {
      const idade = calcIdade(dadosOrg[c.id]?.dataNascimento);
      return faixaEtariaDe(idade) === f.id;
    }).map(c => c.id);
    const deslF = desligs.filter(d => {
      const c = COLABORADORES.find(x => (d.nome || '').toLowerCase().includes(x.nome.toLowerCase().split(' ')[0]));
      return c && idsFaixa.includes(c.id);
    }).length;
    return { label: f.label, valor: idsFaixa.length ? Math.round((deslF / idsFaixa.length) * 1000) / 10 : 0, detalhe: `${deslF}/${idsFaixa.length}` };
  });

  // Por etnia
  const etnias = ['Branca','Parda','Preta','Amarela','Indígena','Prefiro não declarar'];
  const turnPorEtnia = etnias.map(e => {
    const ids = COLABORADORES.filter(c => div[c.id]?.etnia === e).map(c => c.id);
    const desl = desligs.filter(d => {
      const c = COLABORADORES.find(x => (d.nome || '').toLowerCase().includes(x.nome.toLowerCase().split(' ')[0]));
      return c && ids.includes(c.id);
    }).length;
    return { label: e, valor: ids.length ? Math.round((desl / ids.length) * 1000) / 10 : 0, detalhe: `${desl}/${ids.length}` };
  });

  // Por departamento (top 10)
  const turnPorDepto = SETORES.map(s => {
    const ids = COLABORADORES.filter(c => c.setor === s).map(c => c.id);
    const desl = desligs.filter(d => d.setor === s).length;
    return { label: s, valor: ids.length ? Math.round((desl / ids.length) * 1000) / 10 : 0, detalhe: `${desl}/${ids.length}` };
  }).filter(x => x.detalhe !== '0/0').sort((a,b) => b.valor - a.valor).slice(0, 10);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      {/* KPIs gerais */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
        <KpiCard titulo="Turnover Geral (12m)" valor={fmtPct(turnoverGeral, 1)} sub={`${totalDesl} saídas / ${headMedio} headcount médio`} cor="linear-gradient(135deg,#6B3FA0,#3A1E70)" icon="trend_down" tooltip="Desligamentos ÷ headcount médio × 100." />
        <KpiCard titulo="Voluntário" valor={fmtPct(turnoverVol, 1)} sub={`${desligVoluntario} saída(s) · pedido ou mudança de carreira`} cor="linear-gradient(135deg,#1F4A8A,#0A1E50)" icon="trend_down" tooltip="Saídas iniciadas pelo colaborador." />
        <KpiCard titulo="Involuntário" valor={fmtPct(turnoverInvol, 1)} sub={`${desligInvol} saída(s) · empresa, performance, contrato`} cor="linear-gradient(135deg,#B3261E,#7A0000)" icon="trend_down" tooltip="Saídas iniciadas pela empresa." />
      </div>

      {/* Split fixo × associado (PDF Site AVD 5 · item 4) */}
      <Card pad={18}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 12 }}>Turnover por categoria · Fixos × Associados</div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
          {[
            { l: 'Geral',        cor: '#6B3FA0', vFixo: tcGeralFixo,  vAssoc: tcGeralAssoc, nFixo: desligFixoArr2.length, nAssoc: desligAssocArr2.length },
            { l: 'Voluntário',   cor: '#1F4A8A', vFixo: tcVolFixo,    vAssoc: tcVolAssoc,   nFixo: desligFixoArr2.filter(ehVol).length, nAssoc: desligAssocArr2.filter(ehVol).length },
            { l: 'Involuntário', cor: '#B3261E', vFixo: tcInvolFixo,  vAssoc: tcInvolAssoc, nFixo: desligFixoArr2.filter(d => !ehVol(d)).length, nAssoc: desligAssocArr2.filter(d => !ehVol(d)).length },
          ].map(x => (
            <div key={x.l} style={{ background: 'var(--escalab-paper)', borderRadius: 10, padding: '12px 14px' }}>
              <div style={{ fontSize: 11, color: 'var(--escalab-mute)', marginBottom: 6 }}>{x.l}</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                  <span style={{ fontSize: 11.5, color: 'var(--escalab-slate)' }}>Fixos · {headFixo}</span>
                  <span style={{ fontSize: 16, fontWeight: 800, color: x.cor }}>{fmtPct(x.vFixo,1)}</span>
                </div>
                <div style={{ fontSize: 10.5, color: 'var(--escalab-mute)', marginTop: -3 }}>{x.nFixo} desligamento(s)</div>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginTop: 4 }}>
                  <span style={{ fontSize: 11.5, color: 'var(--escalab-slate)' }}>Associados · {headAssoc}</span>
                  <span style={{ fontSize: 16, fontWeight: 800, color: x.cor }}>{fmtPct(x.vAssoc,1)}</span>
                </div>
                <div style={{ fontSize: 10.5, color: 'var(--escalab-mute)', marginTop: -3 }}>{x.nAssoc} desligamento(s)</div>
              </div>
            </div>
          ))}
        </div>
      </Card>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card pad={22}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover por gênero</div>
          <BarsHover data={turnPorGen} formatValor={v => v.toFixed(1) + '%'} cor="#6B3FA0" height={130} />
        </Card>
        <Card pad={22}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover por faixa etária</div>
          <BarsHover data={turnPorIdade} formatValor={v => v.toFixed(1) + '%'} cor="#1F4A8A" height={130} />
        </Card>
        <Card pad={22}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover por etnia/cor</div>
          <BarsHover data={turnPorEtnia} formatValor={v => v.toFixed(1) + '%'} cor="#00836B" height={130} />
        </Card>
        <Card pad={22}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover por departamento (top 10)</div>
          <BarsHover data={turnPorDepto} formatValor={v => v.toFixed(1) + '%'} cor="#B56500" height={130} />
        </Card>
      </div>
      <InfoGrafico
        significado="Mostra qual recorte (gênero, faixa etária, etnia, departamento) está perdendo mais gente. Sinaliza onde há viés de retenção que merece olhar."
        calculo="Para cada grupo: nº de desligamentos do grupo ÷ nº de pessoas do grupo × 100."
        fonte="getDesligamentos + getDiversidadeAll + COLABORADORES" />
    </div>
  );
};

// ── PAINEL: Treinamento & Desenvolvimento ───────────────────────────────────
// PDF Site AVD (2): tipos de treinamento p/ filtro do painel (espelha TIPOS_TREINO do screen-treinamentos.jsx)
const TIPOS_TREINO_PAINEL = [
  { id: 'todos', label: 'Todos' }, { id: 'onboarding', label: 'Onboarding' }, { id: 'tecnico', label: 'Técnico' },
  { id: 'comportamental', label: 'Comportamental' }, { id: 'lideranca', label: 'Liderança' },
  { id: 'comercial', label: 'Comercial' }, { id: 'escalabday', label: 'EscalabDay' },
];

const PainelTreinamento = ({ periodo = '12m' }) => {
  // PDF Site AVD (2): filtros por tipo + categoria (fixo/assoc) + gráfico de investimento R$
  const [filtroTipo, setFiltroTipo] = useState('todos');
  const [filtroCateg, setFiltroCateg] = useState('todos'); // todos | fixo | associado

  // Le da chave v2 (atualizada com treinos reais) com fallback pro v1 antigo
  const treinosAll = lerLS('escalab_treinamentos_v2', null) || lerLS('escalab_treinamentos', []);
  const hoje = new Date();

  // Filtros aplicados
  const treinos = treinosAll
    .filter(t => filtroTipo === 'todos' || t.tipo === filtroTipo)
    .filter(t => dentroDoPeriodo(t.data, periodo));

  const treinosConc = treinos.filter(t => t.status === 'concluido');
  // Categoria fixo/assoc afeta cálculo de presenças
  const contaPresentes = t => {
    if (filtroCateg === 'fixo')      return Number(t.presentes_fixos) || 0;
    if (filtroCateg === 'associado') return Number(t.presentes_assoc) || 0;
    return (Number(t.presentes_fixos) || 0) + (Number(t.presentes_assoc) || 0);
  };
  const contaEsperados = t => {
    if (filtroCateg === 'fixo')      return Number(t.total_fixos) || 0;
    if (filtroCateg === 'associado') return Number(t.total_assoc) || 0;
    return (Number(t.total_fixos) || 0) + (Number(t.total_assoc) || 0);
  };

  // KPIs
  const horasInvestidas = treinosConc.reduce((s, t) => s + (Number(t.duracaoHoras) || 0) * contaPresentes(t), 0);
  const investimentoTotal = treinosConc.reduce((s, t) => s + (Number(t.custo) || 0), 0);
  const totalPresentes = treinosConc.reduce((s, t) => s + contaPresentes(t), 0);
  const totalEsperados = treinosConc.reduce((s, t) => s + contaEsperados(t), 0);
  const taxaPart = totalEsperados > 0 ? (totalPresentes / totalEsperados) * 100 : 0;

  // Histórico de horas por mês (12 meses) ou por trimestre (se periodo = ano)
  const dataMeses = [];
  for (let i = 11; i >= 0; i--) {
    const d = new Date(hoje); d.setMonth(d.getMonth() - i);
    const k = d.toISOString().slice(0,7);
    const tnos = treinos.filter(t => (t.data || '').startsWith(k));
    const h = tnos.reduce((s, t) => s + ((Number(t.duracaoHoras) || 0) * contaPresentes(t)), 0);
    const inv = tnos.reduce((s, t) => s + (Number(t.custo) || 0), 0);
    dataMeses.push({ label: ['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez'][d.getMonth()], valor: h, investimento: inv });
  }

  // Por tipo (na ABA atual, mostra distribuição mesmo se tipo='todos')
  const porTipo = TIPOS_TREINO_PAINEL.filter(t => t.id !== 'todos').map(tp => {
    const ts = treinosAll
      .filter(t => t.tipo === tp.id)
      .filter(t => dentroDoPeriodo(t.data, periodo));
    const tsConc = ts.filter(t => t.status === 'concluido');
    const horas = tsConc.reduce((s, t) => s + (Number(t.duracaoHoras) || 0) * contaPresentes(t), 0);
    const part = tsConc.reduce((s, t) => s + contaPresentes(t), 0);
    return { id: tp.id, label: tp.label, n: ts.length, horas, part, inv: tsConc.reduce((s, t) => s + (Number(t.custo) || 0), 0) };
  }).filter(t => t.n > 0);

  const filtroInp = { border: '1px solid var(--escalab-line)', borderRadius: 7, padding: '6px 10px', fontSize: 12.5, fontFamily: 'var(--font-sans)', outline: 0, background: '#fff', cursor: 'pointer' };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      {/* Filtros */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', background: '#fff', border: '1px solid var(--escalab-line)', borderRadius: 10 }}>
        <Icon name="filter" size={13} />
        <span style={{ fontSize: 11, color: 'var(--escalab-mute)', fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase' }}>Tipo</span>
        <select value={filtroTipo} onChange={e => setFiltroTipo(e.target.value)} style={filtroInp}>
          {TIPOS_TREINO_PAINEL.map(t => <option key={t.id} value={t.id}>{t.label}</option>)}
        </select>
        <span style={{ fontSize: 11, color: 'var(--escalab-mute)', fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', marginLeft: 12 }}>Quadro</span>
        <select value={filtroCateg} onChange={e => setFiltroCateg(e.target.value)} style={filtroInp}>
          <option value="todos">Total</option>
          <option value="fixo">Só fixos</option>
          <option value="associado">Só associados</option>
        </select>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
        <KpiCard titulo={`Horas de treinamento`} valor={Math.round(horasInvestidas) + ' h'} sub={`${treinosConc.length} treinamento(s) concluído(s)`} cor="linear-gradient(135deg,#00967B,#004A3C)" icon="star" tooltip="Σ (duração × presentes). Filtra por tipo e quadro." />
        <KpiCard titulo="Taxa de participação" valor={fmtPct(taxaPart, 1)} sub={`${totalPresentes} presentes / ${totalEsperados} esperados`} cor="linear-gradient(135deg,#1F4A8A,#0A1E50)" icon="users" tooltip="Presentes ÷ esperados × 100. Reflete filtro de quadro (fixo/associado/total)." />
        <KpiCard titulo="Investimento (R$)" valor={'R$ ' + Math.round(investimentoTotal).toLocaleString('pt-BR')} sub="soma do custo de cada treino" cor="linear-gradient(135deg,#B56500,#7A3F00)" icon="trend_up" tooltip="Σ campo 'custo' dos treinamentos concluídos no período." />
      </div>

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Horas investidas · últimos 12 meses</div>
        <BarsHover data={dataMeses} formatValor={v => v + 'h'} cor="#00967B" height={150} />
      </Card>
      <InfoGrafico
        significado="Total de horas de capacitação consumidas pelo time a cada mês (soma do tempo gasto por todos os participantes)."
        calculo="Por mês: Σ (duracaoHoras × nº de presentes confirmados) de treinamentos concluídos, aplicando os filtros."
        fonte="treinamentos + chamadas de presença"
      />

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Investimento (R$) · últimos 12 meses</div>
        <BarsHover data={dataMeses.map(m => ({ label: m.label, valor: m.investimento }))} formatValor={v => 'R$ ' + Math.round(v).toLocaleString('pt-BR')} cor="#B56500" height={150} />
      </Card>
      <InfoGrafico
        significado="Quanto a empresa investiu em treinamentos por mês."
        calculo="Por mês: Σ campo 'custo' dos treinamentos com data nesse mês."
        fonte="campo custo (R$) de cada treinamento"
      />

      {/* Comparação ano a ano (YoY) · treinamentos + Escalab School por ano */}
      {(() => {
        // Coleta anos com dados (treinamentos + cursos school) e ordena crescente.
        let school = [];
        try { school = JSON.parse(localStorage.getItem('escalab_school') || '[]'); } catch {}
        const anosSet = new Set();
        treinosAll.forEach(t => { const y = (t.data || '').slice(0, 4); if (y && /^\d{4}$/.test(y)) anosSet.add(Number(y)); });
        school.forEach(c => { const y = (c.dataInicio || c.dataFim || '').slice(0, 4); if (y && /^\d{4}$/.test(y)) anosSet.add(Number(y)); });
        // Garante pelo menos os 3 anos relevantes pro lançamento (2024-2026), mesmo que zerados.
        const anoCorrente = hoje.getFullYear();
        [anoCorrente - 2, anoCorrente - 1, anoCorrente].forEach(y => anosSet.add(y));
        const anos = [...anosSet].sort((a, b) => a - b);

        const porAno = anos.map(y => {
          // Treinamentos: aplica filtro de tipo + considera só os concluídos do ano.
          const tdoAno = treinosAll
            .filter(t => filtroTipo === 'todos' || t.tipo === filtroTipo)
            .filter(t => (t.data || '').startsWith(String(y)))
            .filter(t => t.status === 'concluido');
          const treinos = tdoAno.reduce((s, t) => s + (Number(t.custo) || 0), 0);
          // Escalab School: usa dataInicio como referência do ano (semelhante a contemplados).
          const cAno = school.filter(c => (c.dataInicio || '').startsWith(String(y)));
          const sch = cAno.reduce((s, c) => s + (Number(c.custo) || 0), 0);
          return { ano: y, treinos, school: sch, total: treinos + sch };
        });

        const maxV = Math.max(1, ...porAno.map(p => p.total));
        const fmt = v => 'R$ ' + Math.round(v).toLocaleString('pt-BR');

        return (
          <>
            <Card pad={22}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14, flexWrap: 'wrap', gap: 8 }}>
                <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase' }}>Investimento ano a ano · comparativo</div>
                <div style={{ display: 'flex', gap: 12, fontSize: 11.5, color: 'var(--escalab-slate)' }}>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
                    <span style={{ width: 10, height: 10, borderRadius: 2, background: '#00967B' }} /> Treinamentos
                  </span>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
                    <span style={{ width: 10, height: 10, borderRadius: 2, background: '#6B3FA0' }} /> Escalab School
                  </span>
                </div>
              </div>
              <div style={{ display: 'flex', gap: 14, alignItems: 'flex-end', minHeight: 180, padding: '6px 4px 0' }}>
                {porAno.map(p => {
                  const altT = (p.treinos / maxV) * 150;
                  const altS = (p.school / maxV) * 150;
                  const ehAtual = p.ano === anoCorrente;
                  return (
                    <div key={p.ano} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
                      <div style={{ fontSize: 12.5, fontWeight: 800, color: ehAtual ? 'var(--escalab-brand-deep)' : 'var(--escalab-ink)' }}>{fmt(p.total)}</div>
                      <div title={`Treinamentos: ${fmt(p.treinos)} · Escalab School: ${fmt(p.school)}`}
                        style={{ display: 'flex', flexDirection: 'column-reverse', width: '100%', maxWidth: 88, height: 160, background: ehAtual ? 'rgba(0,150,123,.06)' : 'var(--escalab-paper)', borderRadius: 8, padding: 4, position: 'relative', justifyContent: 'flex-end', border: ehAtual ? '1px solid var(--escalab-brand-soft)' : '1px solid transparent' }}>
                        {p.treinos > 0 && <div style={{ height: Math.max(2, altT), background: '#00967B', borderRadius: '4px 4px 0 0', transition: 'height .4s' }} />}
                        {p.school > 0 && <div style={{ height: Math.max(2, altS), background: '#6B3FA0', borderRadius: p.treinos === 0 ? '4px 4px 0 0' : 0, marginBottom: p.treinos > 0 ? 1 : 0, transition: 'height .4s' }} />}
                        {p.treinos === 0 && p.school === 0 && <div style={{ alignSelf: 'center', justifySelf: 'center', fontSize: 11, color: 'var(--escalab-mute)', margin: 'auto 0' }}>·</div>}
                      </div>
                      <div style={{ fontSize: 12, fontWeight: ehAtual ? 800 : 600, color: ehAtual ? 'var(--escalab-brand-deep)' : 'var(--escalab-slate)' }}>
                        {p.ano}{ehAtual ? ' · em curso' : ''}
                      </div>
                    </div>
                  );
                })}
              </div>
              {/* Variação YoY entre os dois últimos anos com dado */}
              {(() => {
                if (porAno.length < 2) return null;
                const ult = porAno[porAno.length - 1];
                const pen = porAno[porAno.length - 2];
                if (pen.total === 0) return null;
                const delta = ult.total - pen.total;
                const pct = (delta / pen.total) * 100;
                const cor = delta >= 0 ? '#00836B' : '#B3261E';
                return (
                  <div style={{ marginTop: 14, fontSize: 12, color: 'var(--escalab-slate)', display: 'flex', alignItems: 'center', gap: 8 }}>
                    <span style={{ fontWeight: 700, color: cor }}>{delta >= 0 ? '↑' : '↓'} {Math.abs(pct).toFixed(1)}%</span>
                    <span>{ult.ano} vs {pen.ano} ({delta >= 0 ? '+' : ''}{fmt(delta)})</span>
                  </div>
                );
              })()}
            </Card>
            <InfoGrafico
              significado="Comparativo de quanto a empresa investiu em desenvolvimento de pessoas em cada ano · útil pra avaliar evolução orçamentária."
              calculo="Por ano: Σ custo dos treinamentos concluídos com data naquele ano + Σ custo dos cursos do Escalab School com dataInicio naquele ano. Aplica o filtro de tipo de treinamento."
              fonte="treinamentos (escalab_treinamentos) + escalab_school"
            />
          </>
        );
      })()}

      {/* Investimento financeiro consolidado: total / treinamentos / Escalab School */}
      {(() => {
        const investTreinos = treinosConc.reduce((s, t) => s + (Number(t.custo) || 0), 0);
        let investSchool = 0;
        try {
          const school = JSON.parse(localStorage.getItem('escalab_school') || '[]');
          investSchool = school.reduce((s, c) => s + (Number(c.custo) || 0), 0);
        } catch {}
        const investTotal = investTreinos + investSchool;
        const fmt = v => 'R$ ' + Math.round(v).toLocaleString('pt-BR');
        const maxV = Math.max(1, investTotal);
        const linhas = [
          { label: 'Investimento total',           v: investTotal,   cor: '#B56500', bg: '#FFF7EB' },
          { label: 'Investimento em treinamentos', v: investTreinos, cor: '#00967B', bg: '#E6F5F1' },
          { label: 'Investimento no Escalab School', v: investSchool, cor: '#6B3FA0', bg: '#F4EEFF' },
        ];
        return (
          <>
            <Card pad={22}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Investimento financeiro · consolidado</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
                {linhas.map(l => (
                  <div key={l.label}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5 }}>
                      <span style={{ fontSize: 13, color: 'var(--escalab-ink)', fontWeight: 600 }}>{l.label}</span>
                      <span style={{ fontSize: 14, fontWeight: 800, color: l.cor }}>{fmt(l.v)}</span>
                    </div>
                    <div style={{ height: 9, background: 'var(--escalab-paper)', borderRadius: 999, overflow: 'hidden' }}>
                      <div style={{ height: '100%', width: `${(l.v / maxV) * 100}%`, background: l.cor, transition: 'width .4s', borderRadius: 999 }} />
                    </div>
                  </div>
                ))}
              </div>
            </Card>
            <InfoGrafico
              significado="Total que a empresa investiu em desenvolvimento de pessoas no período · separa treinamentos internos (eventos do escalab) de cursos pagos via Escalab School."
              calculo="Investimento total = treinamentos concluídos (Σ custo) + Escalab School (Σ custo de todos os cursos cadastrados)."
              fonte="treinamentos (escalab_treinamentos) + escalab_school"
            />
          </>
        );
      })()}

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Horas por tipo de treinamento ({rotuloPeriodo(periodo)})</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {porTipo.length === 0 ? <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Sem dados no período.</div> : porTipo.map(tp => {
            const max = Math.max(1, ...porTipo.map(x => x.horas));
            const pct = Math.round((tp.horas / max) * 100);
            return (
              <div key={tp.id}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                  <span style={{ fontSize: 12.5, color: 'var(--escalab-ink)' }}>{tp.label} <span style={{ color: 'var(--escalab-mute)', fontSize: 11 }}>({tp.n})</span></span>
                  <span style={{ fontSize: 12.5, fontWeight: 700 }}>{Math.round(tp.horas)} h · R$ {Math.round(tp.inv).toLocaleString('pt-BR')}</span>
                </div>
                <div style={{ height: 7, background: 'var(--escalab-line)', borderRadius: 999 }}>
                  <div style={{ width: pct + '%', height: '100%', background: '#1F4A8A', borderRadius: 999, transition: 'width .5s' }} />
                </div>
              </div>
            );
          })}
        </div>
      </Card>
    </div>
  );
};

// ── PAINEL: AVD & Feedback ──────────────────────────────────────────────────
const PainelAvdFeedback = () => {
  const feedAll = lerLS('escalab_feedbacks_arquivos', {});
  // Feedbacks por setor separado por trimestre · usamos data dos arquivos
  const todos = [];
  Object.entries(feedAll).forEach(([colabId, lista]) => {
    const c = COLABORADORES.find(x => x.id === Number(colabId));
    (lista || []).forEach(f => {
      if (!f.data) return;
      const d = new Date(f.data);
      const trim = `T${Math.floor(d.getMonth()/3)+1}/${d.getFullYear()}`;
      todos.push({ setor: c?.setor || '·', trim });
    });
  });
  const setores = [...new Set(todos.map(t => t.setor))];
  const trims = [...new Set(todos.map(t => t.trim))].sort();
  // Contar
  const dados = setores.map(s => ({
    label: s,
    valor: todos.filter(t => t.setor === s).length,
    detalhe: trims.map(tr => `${tr}: ${todos.filter(t => t.setor === s && t.trim === tr).length}`).join(' · '),
  })).sort((a,b) => b.valor - a.valor);

  // AVD: quantos receberam = colaboradores com nota_geral != null
  const status = lerLS('escalab_avd_status', {});
  const receberamAvd = Object.values(status).filter(s => s?.nota_geral != null).length;
  const totalColab = COLABORADORES.length;
  const pctAvd = totalColab ? (receberamAvd / totalColab) * 100 : 0;

  // PDF Site AVD 5 · item 9: 3 níveis de performance baseados na nota_geral
  const notas = COLABORADORES.map(c => ({ colab: c, nota: status[c.id]?.nota_geral })).filter(x => x.nota != null);
  const nivelDe = n => n < 3 ? 'recuperacao' : n < 4 ? 'desenvolvimento' : 'alta';
  const niveisAvd = [
    { id: 'alta',            label: 'Alta performance', faixa: '4–5', cor: '#00836B', bg: '#E6F5F1' },
    { id: 'desenvolvimento', label: 'Desenvolvimento',  faixa: '3–4', cor: '#1F4A8A', bg: '#EEF3FA' },
    { id: 'recuperacao',     label: 'Recuperação',      faixa: '0–3', cor: '#B3261E', bg: '#FDECEC' },
  ].map(n => ({ ...n, qtd: notas.filter(x => nivelDe(x.nota) === n.id).length }));

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <KpiCard titulo="Feedbacks registrados" valor={todos.length} sub={`${setores.length} setor(es) · ${trims.length} trimestre(s)`} cor="linear-gradient(135deg,#6B3FA0,#3A1E70)" icon="message" tooltip="Conta arquivos de feedback registrados em todos os colaboradores." />
        <KpiCard titulo="AVD recebidas" valor={`${receberamAvd}/${totalColab}`} sub={fmtPct(pctAvd, 1) + ' cobertura'} cor="linear-gradient(135deg,#00836B,#004A3C)" icon="star" tooltip="Colaboradores com nota geral calculada no ciclo. Fonte: status AVD." />
      </div>

      {/* PDF Site AVD 5 · item 9: AVD em 3 níveis de performance */}
      <Card pad={22}>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14, flexWrap: 'wrap', gap: 8 }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase' }}>Distribuição por nível de performance</div>
          <div style={{ fontSize: 11, color: 'var(--escalab-mute)' }}>{notas.length} pessoa(s) com nota geral</div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
          {niveisAvd.map(n => {
            const pct = notas.length ? (n.qtd / notas.length) * 100 : 0;
            return (
              <div key={n.id} style={{ background: n.bg, borderRadius: 12, padding: '14px 16px', border: `1px solid ${n.cor}25` }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
                  <div style={{ width: 28, height: 28, borderRadius: 8, background: n.cor + '22', color: n.cor, fontWeight: 800, fontSize: 11, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{n.faixa}</div>
                  <div style={{ fontSize: 12.5, fontWeight: 700, color: n.cor }}>{n.label}</div>
                </div>
                <div style={{ fontSize: 28, fontWeight: 900, color: n.cor, lineHeight: 1 }}>{n.qtd}</div>
                <div style={{ fontSize: 11, color: 'var(--escalab-mute)', marginTop: 4 }}>{fmtPct(pct, 1)} do quadro avaliado</div>
              </div>
            );
          })}
        </div>
        <div style={{ marginTop: 12, fontSize: 11, color: 'var(--escalab-mute)' }}>Faixas: 0–3 recuperação · 3–4 desenvolvimento · 4–5 alta performance. Calculado sobre a nota geral do ciclo AVD ativo.</div>
      </Card>

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Feedbacks por setor</div>
        {dados.length === 0
          ? <div style={{ fontSize: 13, color: 'var(--escalab-mute)' }}>Sem feedbacks registrados ainda.</div>
          : <BarsHover data={dados} cor="#6B3FA0" height={150} />}
      </Card>
      <InfoGrafico
        significado="Quantos feedbacks 1:1 foram registrados em cada setor — proxy de cultura de feedback."
        calculo="Por setor: contagem de registros em FEEDBACKS cujo colaborador pertence ao setor, no ciclo ativo."
        fonte="feedbacks + colaboradores.setor"
      />
    </div>
  );
};

// ── PAINEL: Censo de Diversidade ────────────────────────────────────────────
const PainelDiversidade = () => {
  const div = getDiversidadeAll();
  const contagem = {};
  ['genero','etnia','orientacao','deficiencia','religiao','estadoCivil'].forEach(campo => {
    contagem[campo] = {};
    Object.values(div).forEach(d => {
      const v = d[campo] || 'Não declarado';
      contagem[campo][v] = (contagem[campo][v] || 0) + 1;
    });
  });
  const total = COLABORADORES.length;
  function distrToData(map) {
    return Object.entries(map).map(([k, n]) => ({ label: k, valor: Math.round(n / total * 1000) / 10, detalhe: `${n} pessoa(s)` })).sort((a,b) => b.valor - a.valor);
  }
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      <div style={{ background: '#fff', border: '1px solid var(--escalab-line)', borderRadius: 12, padding: '12px 16px', fontSize: 12.5, color: 'var(--escalab-slate)' }}>
        Dados auto-declarados na aba <strong>Dados de Diversidade</strong> do perfil de cada colaborador.
        Percentuais calculados sobre o headcount total ({total}).
      </div>
      {[
        { campo: 'genero',      titulo: 'Gênero' },
        { campo: 'etnia',       titulo: 'Etnia/Cor' },
        { campo: 'orientacao',  titulo: 'Orientação sexual' },
        { campo: 'deficiencia', titulo: 'Pessoa com deficiência (PCD)' },
      ].map(({ campo, titulo }) => (
        <Card key={campo} pad={22}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>{titulo}</div>
          <BarsHover data={distrToData(contagem[campo])} formatValor={v => v.toFixed(1) + '%'} cor="#00836B" height={140} />
        </Card>
      ))}
      <InfoGrafico
        significado="Recortes do censo de diversidade auto-declarado — nunca individualiza, sempre agregado."
        calculo="Por categoria (gênero/etnia/orientação/PCD): (nº auto-declarações ÷ headcount total) × 100. Quem não declarou entra como 'Não declarado'."
        fonte="diversidade (auto-cadastro Caju)"
      />
    </div>
  );
};

// ── PAINEL: Férias e Ausências (versão completa do docx 11) ─────────────────
const PainelFeriasAusencias = () => {
  const ferias = lerLS('escalab_ferias', []);
  const ausencias = lerLS('escalab_ausencias', []);
  const dayoffs = lerLS('escalab_dayoff', []);
  const hoje = new Date();
  const meses12 = [];
  for (let i = 11; i >= 0; i--) {
    const d = new Date(hoje); d.setMonth(d.getMonth() - i);
    meses12.push({ key: `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}`, label: ['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez'][d.getMonth()] });
  }

  // Pessoas em férias por mês (intersecção do período aprovado com cada mês)
  const feriasMes = meses12.map(m => {
    const ini = m.key + '-01';
    const finalDoMes = new Date(Number(m.key.slice(0,4)), Number(m.key.slice(5,7)), 0).toISOString().slice(0,10);
    const pessoas = ferias.filter(f => f.status === 'aprovada' && f.inicio <= finalDoMes && f.fim >= ini).length;
    return { label: m.label, valor: pessoas };
  });

  // Absenteísmo por departamento (mês atual)
  const mesAtual = hoje.toISOString().slice(0,7);
  const ausMes = ausencias.filter(a => a.status === 'aprovado' && (a.dataInicio||'').slice(0,7) === mesAtual);
  const setores = [...new Set(COLABORADORES.map(c => c.setor))];
  const absentDept = setores.map(s => {
    const idsSet = COLABORADORES.filter(c => c.setor === s).map(c => c.id);
    const horasAus = ausMes.filter(a => idsSet.includes(a.colaboradorId)).reduce((acc, a) => {
      const dias = Math.max(1, Math.round((new Date(a.dataFim||a.dataInicio) - new Date(a.dataInicio))/86400000) + 1);
      return acc + dias * 8;
    }, 0);
    const horasEsperadas = idsSet.length * 22 * 8;
    const pct = horasEsperadas > 0 ? (horasAus / horasEsperadas) * 100 : 0;
    return { label: s, valor: Math.round(pct * 100) / 100 };
  }).sort((a,b) => b.valor - a.valor).slice(0, 12);

  // Motivos de ausência (12m)
  const ha12m = new Date(hoje); ha12m.setMonth(ha12m.getMonth() - 12);
  const aus12 = ausencias.filter(a => a.status === 'aprovado' && new Date(a.dataInicio||0) >= ha12m);
  const motivosMap = {};
  aus12.forEach(a => { const m = (a.motivo || '').split(':')[0].trim() || 'Não informado'; motivosMap[m] = (motivosMap[m]||0)+1; });
  const motivosArr = Object.entries(motivosMap).map(([k,n]) => ({ label: k, valor: n })).sort((a,b) => b.valor - a.valor).slice(0, 10);

  // % colaboradores que perderam dias de férias por setor
  // "perderam dias" = pessoa com vencimento passado em BANCO_FERIAS_MOCK e ainda tem saldo
  const banco = typeof BANCO_FERIAS_MOCK === 'object' ? BANCO_FERIAS_MOCK : [];
  const perdidosSetor = setores.map(s => {
    const idsSet = COLABORADORES.filter(c => c.setor === s).map(c => c.id);
    if (!idsSet.length) return { label: s, valor: 0 };
    const perderam = banco.filter(b => idsSet.includes(b.colaboradorId) && new Date(b.vencimento) < hoje && b.saldo > 0).length;
    return { label: s, valor: Math.round((perderam / idsSet.length) * 100) };
  }).sort((a,b) => b.valor - a.valor).slice(0, 12);

  // Taxa absenteísmo geral
  const totalHorasEsperadas = COLABORADORES.length * 22 * 8;
  const totalHorasAus = ausMes.reduce((s, a) => {
    const dias = Math.max(1, Math.round((new Date(a.dataFim||a.dataInicio) - new Date(a.dataInicio))/86400000) + 1);
    return s + dias * 8;
  }, 0);
  const absGeral = totalHorasEsperadas > 0 ? (totalHorasAus / totalHorasEsperadas) * 100 : 0;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, animation: 'fadeIn .22s' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <KpiCard titulo="Taxa de absenteísmo" valor={fmtPct(absGeral, 2)} sub={`${Math.round(totalHorasAus)} h ausentes / ${totalHorasEsperadas} h esperadas`} cor="linear-gradient(135deg,#B56500,#7A3F00)" icon="clock" tooltip="(horas ausentes ÷ horas esperadas) × 100 · mês atual." />
        <KpiCard titulo="Pessoas em férias agora" valor={ferias.filter(f => f.status === 'aprovada' && f.inicio <= hoje.toISOString().slice(0,10) && f.fim >= hoje.toISOString().slice(0,10)).length} sub="período em curso" cor="linear-gradient(135deg,#00836B,#004A3C)" icon="calendar" tooltip="Pessoas com férias aprovadas cujo intervalo cobre o dia de hoje." />
      </div>

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Pessoas em férias por mês · últimos 12</div>
        <BarsHover data={feriasMes} formatValor={v => v + ' pessoa(s)'} cor="#00967B" height={150} />
      </Card>
      <InfoGrafico
        significado="Quantas pessoas tiveram período de férias aprovado em cada mês. Picos = mês de alta demanda de cobertura."
        calculo="Por mês: nº de férias com status 'aprovada' cujo intervalo (inicio · fim) intersecta o mês."
        fonte="escalab_ferias (localStorage)" />

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card pad={22}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Absenteísmo por departamento</div>
          <BarsHover data={absentDept} formatValor={v => v.toFixed(2) + '%'} cor="#B56500" height={180} />
          <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Horas ausentes ÷ horas esperadas no mês, por setor. Sinaliza onde há sobrecarga ou problema de gestão.</div>
        </Card>
        <Card pad={22}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Motivos de ausência (12m)</div>
          <BarsHover data={motivosArr} formatValor={v => v + ' caso(s)'} cor="#6B3FA0" height={180} />
        </Card>
      </div>
      <InfoGrafico
        significado="Onde a empresa perde horas trabalhadas. Esquerda: peso do absenteísmo por setor (sobrecarga ou gestão). Direita: tipo de ausência (atestado, falta justificada, etc) nos últimos 12 meses."
        calculo="Por setor: Σ horas ausentes ÷ Σ horas esperadas × 100. Por motivo: nº de ocorrências do motivo nos últimos 12 meses."
        fonte="escalab_ausencias (localStorage) + COLABORADORES + jornada de Dados Org" />

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>% colaboradores que perderam dias de férias por setor</div>
        <BarsHover data={perdidosSetor} formatValor={v => v + '%'} cor="#B3261E" height={180} />
        <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Perda = saldo ainda disponível depois do vencimento do período aquisitivo.</div>
      </Card>
      <InfoGrafico
        significado="Setores onde mais gente está deixando dias de férias vencerem. Sinal de sobrecarga ou de gestão de calendário fraca."
        calculo="Por setor: nº de pessoas com vencimento < hoje e saldo > 0 dividido pelo nº de pessoas do setor × 100."
        fonte="BANCO_FERIAS_MOCK + COLABORADORES" />
    </div>
  );
};

// ── Detalhes adicionais de turnover (raça, tempo de empresa, departamento) ──
const PainelTurnoverDetalhado = () => {
  const div = getDiversidadeAll();
  const mov = getMovimentacoesAll();
  const desligs = mov.desligamento;

  function colabDoDeslig(d) {
    const nome = (d.dados?.nomeColaborador || '').toLowerCase();
    return COLABORADORES.find(x => nome.includes(x.nome.toLowerCase().split(' ')[0]));
  }

  // Turnover por raça/etnia
  const racas = ['Branca','Preta','Parda','Amarela','Indígena','Prefiro não declarar'];
  const tvRaca = racas.map(r => {
    const ativos = COLABORADORES.filter(c => div[c.id]?.etnia === r).length;
    const ds = desligs.filter(d => { const c = colabDoDeslig(d); return c && div[c.id]?.etnia === r; }).length;
    return { label: r, valor: ativos > 0 ? Math.round((ds/ativos)*1000)/10 : 0, detalhe: `${ds}/${ativos}` };
  });

  // Turnover por tempo de empresa (em faixas)
  const tvTempo = FAIXAS_TEMPO.map(f => {
    const idsFaixa = COLABORADORES.filter(c => c.tempoEmpresa >= f.min && c.tempoEmpresa <= f.max).map(c => c.id);
    const ds = desligs.filter(d => { const c = colabDoDeslig(d); return c && idsFaixa.includes(c.id); }).length;
    return { label: f.label, valor: idsFaixa.length > 0 ? Math.round((ds/idsFaixa.length)*1000)/10 : 0, detalhe: `${ds}/${idsFaixa.length}` };
  });

  // Turnover por departamento
  const setores = [...new Set(COLABORADORES.map(c => c.setor))];
  const tvDept = setores.map(s => {
    const ids = COLABORADORES.filter(c => c.setor === s).map(c => c.id);
    const ds = desligs.filter(d => { const c = colabDoDeslig(d); return c && ids.includes(c.id); }).length;
    return { label: s, valor: ids.length > 0 ? Math.round((ds/ids.length)*1000)/10 : 0, detalhe: `${ds}/${ids.length}` };
  }).sort((a,b) => b.valor - a.valor).slice(0, 12);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover por etnia/cor</div>
        <BarsHover data={tvRaca} formatValor={v => v.toFixed(1) + '%'} cor="#6B3FA0" height={150} />
      </Card>
      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover por tempo de empresa</div>
        <BarsHover data={tvTempo} formatValor={v => v.toFixed(1) + '%'} cor="#1F4A8A" height={150} />
      </Card>
      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Turnover por departamento (top 12)</div>
        <BarsHover data={tvDept} formatValor={v => v.toFixed(1) + '%'} cor="#B3261E" height={180} />
      </Card>
      <InfoGrafico
        significado="Onde a empresa está perdendo gente — recorta turnover por etnia/cor, faixa de tempo de empresa e setor."
        calculo="Por recorte: (nº desligados no período ÷ nº ativos no recorte) × 100."
        fonte="movimentacao (tipo=desligamento) + colaboradores + diversidade"
      />
    </div>
  );
};

// ── Painel ampliado: Distribuição por nível hierárquico (3 níveis) + evolução ──
// PDF Site AVD (2): consolidação em Diretor / Líder de setor / Liderado.
const PainelDistribuicaoQuadro = () => {
  const distrNivel = NIVEIS_3.map(n => ({
    label: n.label,
    valor: COLABORADORES.filter(c => nivel3De(c) === n.id).length,
  })).filter(d => d.valor > 0);

  // Evolução de colaboradores ativos (12 meses, simplificada via tempoEmpresa)
  const hoje = new Date();
  const evol = [];
  for (let i = 11; i >= 0; i--) {
    const ref = new Date(hoje); ref.setMonth(ref.getMonth() - i);
    const ativos = COLABORADORES.filter(c => {
      const mesesAtras = i;
      return c.tempoEmpresa >= mesesAtras;
    }).length;
    evol.push({ label: ['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez'][ref.getMonth()], valor: ativos });
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Perfil da equipe · Diretor × Líder de setor × Liderado</div>
        <BarsHover data={distrNivel} formatValor={v => v + ' pessoa(s)'} cor="#1F4A8A" height={180} />
      </Card>
      <InfoGrafico
        significado="Quantas pessoas em cada um dos três papéis principais da organização."
        calculo="Conta colaboradores ativos pelo campo nivel (diretor / lider / liderado). Outros campos como 'gerente' ou 'coordenador' caem em 'líder de setor' se nivel='lider'."
        fonte="campo nivel de cada colaborador (data.jsx)"
      />
      <Card pad={12} style={{ maxWidth: 380 }}>
        <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--escalab-slate)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 6 }}>Evolução do headcount · 12 meses</div>
        <LineHover data={evol} formatValor={v => v + ' pessoas'} cor="#00836B" height={56} />
      </Card>
      <InfoGrafico
        significado="Como o quadro de pessoal evoluiu nos últimos 12 meses. Tendência ajuda a entender se a empresa está em crescimento, estabilidade ou enxugamento."
        calculo="Para cada um dos 12 meses: nº de colaboradores cujo tempoEmpresa é ≥ (12 − mês)."
        fonte="campo tempoEmpresa de cada colaborador (data.jsx)" />
    </div>
  );
};

// ── Painel Folha + % progressão/reajuste por setor (Remuneração extra) ──────
const PainelFolhaProgressao = () => {
  const dadosOrg = getDadosOrgAll();
  const histAll = getHistoricoOrgAll();
  const hoje = new Date();

  // Folha por mês · soma do salarioBruto atual (proxy estável)
  const folhaFixo = COLABORADORES.filter(c => getCategoriaKey(c.id) === 'fixo').reduce((s, c) => s + parseMoeda(dadosOrg[c.id]?.salarioBruto), 0);
  const folhaAssoc = COLABORADORES.filter(c => getCategoriaKey(c.id) !== 'fixo').reduce((s, c) => s + parseMoeda(dadosOrg[c.id]?.salarioBruto), 0);

  // % progressão de carreira por setor: nº de promoções nos últimos 12m ÷ headcount do setor
  const setores = [...new Set(COLABORADORES.map(c => c.setor))];
  const ha12m = new Date(hoje); ha12m.setMonth(ha12m.getMonth() - 12);

  const progSetor = setores.map(s => {
    const ids = COLABORADORES.filter(c => c.setor === s).map(c => c.id);
    let promos = 0, reajustes = 0, tempos = [];
    ids.forEach(id => {
      const log = histAll[id] || [];
      // Histórico já vem ordenado do mais recente para o mais antigo (h.data ISO)
      let ultimoEvento = null;
      log.forEach(h => {
        if (new Date(h.data) >= ha12m) {
          const tipo = (h.mudancas || []).find(m => /tipo.*movimenta/i.test(m.campo))?.depois || '';
          if (/promo/i.test(tipo)) promos++;
          if (/ajuste|dissídio|dissidio|step|mérito|merito/i.test(tipo)) reajustes++;
        }
        if (ultimoEvento && new Date(ultimoEvento) > new Date(h.data)) {
          const dias = Math.round((new Date(ultimoEvento) - new Date(h.data)) / 86400000);
          if (dias > 0) tempos.push(dias);
        }
        ultimoEvento = h.data;
      });
    });
    const tempoMedioDias = tempos.length ? media(tempos) : null;
    return {
      label: s,
      progressao: ids.length ? Math.round((promos/ids.length)*1000)/10 : 0,
      reajuste: ids.length ? Math.round((reajustes/ids.length)*1000)/10 : 0,
      tempo: tempoMedioDias ? Math.round(tempoMedioDias/30) : null,
      promos, reajustes,
    };
  });

  // Mediana de aumento por tipo de movimentação (já calculado em outro painel, mas mostro aqui também)
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Folha mensal · fixos × associados (mês atual)</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
          <div style={{ background: '#EEF3FA', borderRadius: 12, padding: '16px 18px' }}>
            <div style={{ fontSize: 11, color: '#1F4A8A', fontWeight: 700, letterSpacing: '.08em', textTransform: 'uppercase' }}>Fixos</div>
            <div style={{ fontSize: 24, fontWeight: 900, color: '#1F4A8A', marginTop: 4 }}>{fmtBRL(folhaFixo)}</div>
            <div style={{ fontSize: 11, color: '#1F4A8A99', marginTop: 4 }}>(+13º/12 + PLR/12 + VT por colab)</div>
          </div>
          <div style={{ background: '#E6F5F1', borderRadius: 12, padding: '16px 18px' }}>
            <div style={{ fontSize: 11, color: '#00836B', fontWeight: 700, letterSpacing: '.08em', textTransform: 'uppercase' }}>Associados</div>
            <div style={{ fontSize: 24, fontWeight: 900, color: '#00836B', marginTop: 4 }}>{fmtBRL(folhaAssoc)}</div>
            <div style={{ fontSize: 11, color: '#00836B99', marginTop: 4 }}>(apenas salário)</div>
          </div>
          <div style={{ background: 'var(--escalab-paper)', borderRadius: 12, padding: '16px 18px' }}>
            <div style={{ fontSize: 11, color: 'var(--escalab-mute)', fontWeight: 700, letterSpacing: '.08em', textTransform: 'uppercase' }}>Total</div>
            <div style={{ fontSize: 24, fontWeight: 900, color: 'var(--escalab-ink)', marginTop: 4 }}>{fmtBRL(folhaFixo + folhaAssoc)}</div>
            <div style={{ fontSize: 11, color: 'var(--escalab-mute)', marginTop: 4 }}>folha bruta</div>
          </div>
        </div>
        <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Evolução mensal aparece quando você salvar snapshots (botão no topo).</div>
      </Card>

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>% progressão de carreira por setor (12m)</div>
        <BarsHover data={progSetor.map(s => ({ label: s.label, valor: s.progressao, detalhe: `${s.promos} promoção(ões)` }))} formatValor={v => v + '%'} cor="#00836B" height={170} />
      </Card>

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>% reajuste salarial por setor (12m)</div>
        <BarsHover data={progSetor.map(s => ({ label: s.label, valor: s.reajuste, detalhe: `${s.reajustes} reajuste(s)` }))} formatValor={v => v + '%'} cor="#1F4A8A" height={170} />
      </Card>

      <Card pad={22}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', letterSpacing: '.1em', textTransform: 'uppercase', marginBottom: 14 }}>Tempo médio entre movimentações (meses) · por setor</div>
        <BarsHover data={progSetor.filter(s => s.tempo != null).map(s => ({ label: s.label, valor: s.tempo }))} formatValor={v => v + ' meses'} cor="#6B3FA0" height={170} />
        <div style={{ marginTop: 10, fontSize: 11, color: 'var(--escalab-mute)' }}>Calculado a partir do histórico de alterações em Dados Organizacionais.</div>
      </Card>
      <InfoGrafico
        significado="Onde a empresa está movimentando gente — quem promove mais, quem reajusta, e a velocidade dessas mudanças por setor."
        calculo="Por setor (últimos 12m): % progressão = nº de promoções ÷ headcount; % reajuste = nº de reajustes salariais ÷ headcount; tempo médio = média (em meses) entre movimentações consecutivas no histórico."
        fonte="histórico de Dados Organizacionais (log de alterações)"
      />
    </div>
  );
};

// ── Navegação em 2 níveis (categorias + sub-abas) ──────────────────────────
const DASH_NAV = [
  {
    id: 'executivo', label: 'Visão Executiva', icon: 'chart', cor: '#00836B', bg: '#E6F5F1',
    abas: [
      { id: 'topo', label: 'Indicadores Principais', icon: 'chart' },
      { id: 'geral', label: 'Visão geral (legado)', icon: 'eye' },
    ],
  },
  {
    id: 'pessoas', label: 'Pessoas & Quadro', icon: 'users', cor: '#1F4A8A', bg: '#EEF3FA',
    abas: [
      { id: 'perfil',       label: 'Perfil do Quadro',  icon: 'users' },
      { id: 'diversidade',  label: 'Censo Diversidade', icon: 'org' },
      { id: 'treinamento',  label: 'T & D',              icon: 'star' },
      { id: 'avd_feedback', label: 'AVD & Feedback',     icon: 'message' },
    ],
  },
  {
    id: 'movimentos', label: 'Movimentos do Time', icon: 'trend_up', cor: '#6B3FA0', bg: '#F4EEFF',
    abas: [
      { id: 'recrutamento',  label: 'Recrutamento & Seleção',    icon: 'plus' },
      { id: 'admissoes',     label: 'Admissões e Desligamentos', icon: 'users' },
      { id: 'turnover',      label: 'Turnover · Consolidado',     icon: 'trend_down' },
      { id: 'movimentacoes', label: 'Movimentações internas',     icon: 'trend_up' },
    ],
  },
  {
    id: 'tempo', label: 'Tempo & Vida', icon: 'calendar', cor: '#B56500', bg: '#FFF7EB',
    abas: [
      { id: 'ferias', label: 'Férias e Ausências', icon: 'calendar' },
    ],
  },
  {
    id: 'financeiro', label: 'Financeiro', icon: 'trend_up', cor: '#B3261E', bg: '#FDECEC',
    abas: [
      { id: 'remuneracao', label: 'Remuneração', icon: 'trend_up' },
    ],
  },
];

function categoriaDaAba(abaId) {
  for (const cat of DASH_NAV) if (cat.abas.some(a => a.id === abaId)) return cat.id;
  return DASH_NAV[0].id;
}

const NavDashboard = ({ abaPainel, setAbaPainel }) => {
  const [cat, setCat] = useState(() => categoriaDaAba(abaPainel));
  const catAtiva = DASH_NAV.find(c => c.id === cat) || DASH_NAV[0];

  // Sincroniza categoria com aba (se trocar aba via deep link)
  useEffect(() => {
    const novaCat = categoriaDaAba(abaPainel);
    if (novaCat !== cat) setCat(novaCat);
  }, [abaPainel]);

  function selecionarCategoria(catId) {
    setCat(catId);
    const c = DASH_NAV.find(x => x.id === catId);
    if (c && !c.abas.some(a => a.id === abaPainel)) {
      setAbaPainel(c.abas[0].id);
    }
  }

  return (
    <div style={{ marginBottom: 22 }}>
      {/* Tier 1: Categorias coloridas (chips grandes) */}
      <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginBottom: 14 }}>
        {DASH_NAV.map(c => {
          const ativo = c.id === cat;
          return (
            <button key={c.id} onClick={() => selecionarCategoria(c.id)} style={{
              border: `1.5px solid ${ativo ? c.cor : 'var(--escalab-line)'}`,
              background: ativo ? c.bg : '#fff',
              borderRadius: 12, padding: '11px 18px', cursor: 'pointer',
              display: 'flex', alignItems: 'center', gap: 9,
              fontFamily: 'var(--font-sans)',
              boxShadow: ativo ? `0 8px 20px ${c.cor}25` : '0 1px 2px rgba(15,30,55,.04)',
              transform: ativo ? 'translateY(-1px)' : 'none',
              transition: 'all .18s',
            }}>
              <div style={{ width: 30, height: 30, borderRadius: 9, background: ativo ? c.cor : c.bg, display: 'flex', alignItems: 'center', justifyContent: 'center', color: ativo ? '#fff' : c.cor }}>
                <Icon name={c.icon} size={15} />
              </div>
              <div style={{ textAlign: 'left' }}>
                <div style={{ fontSize: 13.5, fontWeight: 700, color: ativo ? c.cor : 'var(--escalab-ink)', letterSpacing: '-.005em', lineHeight: 1.15 }}>{c.label}</div>
                <div style={{ fontSize: 10.5, color: 'var(--escalab-mute)', letterSpacing: '.04em', textTransform: 'uppercase', marginTop: 2 }}>
                  {c.abas.length > 1 ? `${c.abas.length} painéis` : '1 painel'}
                </div>
              </div>
            </button>
          );
        })}
      </div>

      {/* Tier 2: Sub-abas da categoria selecionada */}
      <div style={{ background: 'var(--escalab-paper)', borderRadius: 12, padding: '6px', display: 'flex', flexWrap: 'wrap', gap: 4 }}>
        {catAtiva.abas.map(a => {
          const ativo = a.id === abaPainel;
          return (
            <button key={a.id} onClick={() => setAbaPainel(a.id)} style={{
              border: 0, background: ativo ? '#fff' : 'transparent',
              borderRadius: 9, padding: '8px 14px', cursor: 'pointer',
              display: 'flex', alignItems: 'center', gap: 7,
              fontFamily: 'var(--font-sans)', fontSize: 13,
              fontWeight: ativo ? 700 : 500,
              color: ativo ? catAtiva.cor : 'var(--escalab-slate)',
              boxShadow: ativo ? '0 1px 4px rgba(15,30,55,.08)' : 'none',
              transition: 'all .15s',
            }}>
              <Icon name={a.icon} size={12} />
              {a.label}
            </button>
          );
        })}
      </div>
    </div>
  );
};

const ScreenDashboard = ({ user, onNavigate }) => {
  const [abaPainel, setAbaPainel] = useState('geral');
  const [anoRetencao, setAnoRetencao] = useState(2026);
  const [movClassificar, setMovClassificar] = useState('nivel');
  // Filtro temporal global (PDF Site AVD (2))
  const [periodo, setPeriodo] = useState('12m');
  const [snaps, setSnaps] = useState(() => getSnapshots());
  const [salvouSnap, setSalvouSnap] = useState(false);
  const cicloAtivo = CICLOS.find(c => c.status === 'ativo');
  const totalColab = COLABORADORES.length;
  const tempoMedio = Math.round(COLABORADORES.reduce((s, c) => s + c.tempoEmpresa, 0) / totalColab);
  const avsConc = AVALIACOES.filter(a => a.status === 'concluida' && a.cicloId === cicloAtivo?.id).length;
  const avsTot  = AVALIACOES.filter(a => a.cicloId === cicloAtivo?.id).length;
  const feedTrim = FEEDBACKS_TRIM[FEEDBACKS_TRIM.length - 1];

  const cicloIdRef = cicloAtivo?.id || CICLOS[CICLOS.length - 1]?.id;
  const mediasSetor = SETORES.map(s => ({
    setor: s,
    media: cicloIdRef ? (getMediaSetor(s, cicloIdRef) || 0) : 0,
    avSetor: AVALIACOES_SETOR.find(a => a.setor === s && a.cicloId === cicloIdRef)?.nota || 0,
  })).filter(m => m.media > 0 || m.avSetor > 0).sort((a, b) => b.media - a.media);

  const tempoMedioCargo = COLABORADORES.reduce((s, c) => s + c.tempoEmpresa, 0) / totalColab;

  const alertas = [
    { tipo: 'danger', msg: `${FEEDBACKS_SETOR_ATUAL.filter(f => f.pct < 60).length} setores com cobertura de feedback abaixo de 60%`, screen: 'feedbacks' },
    { tipo: 'warn',   msg: `${AVALIACOES.filter(a => a.status === 'pendente' && a.cicloId === cicloAtivo?.id).length} avaliações pendentes no ciclo ativo`, screen: 'avaliacao' },
    { tipo: 'info',   msg: `${AVALIACOES_SETOR.filter(a => a.status === 'pendente' && a.cicloId === cicloAtivo?.id).length} gestores não responderam avaliação de setor`, screen: 'avaliacao' },
  ];

  return (
    <div style={{ animation: 'fadeIn .22s var(--ease-out)' }}>
      {/* Header */}
      <div style={{ marginBottom: 18, display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap' }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.12em', textTransform: 'uppercase', color: 'var(--escalab-brand)' }}>Dashboard</div>
            <Tag tone="brand">{cicloAtivo?.nome}</Tag>
            <Tag tone="success">Ativo</Tag>
          </div>
          <h2 style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-.015em', margin: 0 }}>Visão Geral da Empresa</h2>
        </div>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          <button onClick={() => {
            const anoAtual = new Date().getFullYear();
            const snap = {
              ano: anoAtual,
              totalColab,
              tempoMedio,
              avsConc, avsTot,
              mediasSetor,
              headcountSetor: COLABORADORES.reduce((acc, c) => { acc[c.setor] = (acc[c.setor] || 0) + 1; return acc; }, {}),
              fixos: COLABORADORES.filter(c => getCategoriaKey(c.id) === 'fixo').length,
              associados: COLABORADORES.filter(c => getCategoriaKey(c.id) !== 'fixo').length,
            };
            salvarSnapshot(anoAtual, snap);
            setSnaps(getSnapshots());
            setSalvouSnap(true); setTimeout(() => setSalvouSnap(false), 3000);
          }} style={{ border:'1px solid var(--escalab-brand-soft)', background:'var(--escalab-brand-tint)', color:'var(--escalab-brand-deep)', borderRadius:9, padding:'8px 14px', cursor:'pointer', fontSize:13, fontWeight:700, display:'inline-flex', alignItems:'center', gap:6 }}>
            <Icon name="check" size={12} /> {salvouSnap ? 'Snapshot salvo!' : 'Salvar snapshot do ano'}
          </button>
          <button onClick={() => downloadJson(`escalab_dashboard_${new Date().getFullYear()}.json`, {
            snapshots: getSnapshots(),
            colaboradores: COLABORADORES.map(c => ({ id: c.id, nome: c.nome, setor: c.setor, cargo: c.cargo, categoria: getCategoriaKey(c.id) })),
            avaliacoes: AVALIACOES,
            mediasSetor,
            geradoEm: new Date().toISOString(),
          })} style={{ border:'1px solid var(--escalab-line)', background:'#fff', color:'var(--escalab-slate)', borderRadius:9, padding:'8px 14px', cursor:'pointer', fontSize:13, fontWeight:600, display:'inline-flex', alignItems:'center', gap:6 }}>
            <Icon name="download" size={12} /> Baixar JSON
          </button>
          <button onClick={() => {
            const dadosOrg = getDadosOrgAll();
            const div = getDiversidadeAll();
            const rows = COLABORADORES.map(c => {
              const d = dadosOrg[c.id] || {};
              const dv = div[c.id] || {};
              return {
                id: c.id, nome: c.nome, setor: c.setor, cargo: c.cargo,
                categoria: getCategoriaKey(c.id), nivel: c.nivel, gestor: c.gestorNome || '',
                email: c.email, tempoEmpresa_meses: c.tempoEmpresa, tempoCargo_meses: c.tempoCargo,
                academico: c.academico || '', vinculo: d.vinculo || '',
                salarioBruto: d.salarioBruto || '', jornadaTrabalho: d.jornadaTrabalho || '',
                horasMensais: d.horasMensais || '', centroCusto: d.centroCusto || '',
                dataContratacao: d.dataContratacao || '', dataNascimento: d.dataNascimento || '',
                cargoLideranca: d.cargoLideranca || '', cargoConfianca: d.cargoConfianca || '',
                genero: dv.genero || '', etnia: dv.etnia || '', estadoCivil: dv.estadoCivil || '',
                orientacao: dv.orientacao || '', deficiencia: dv.deficiencia || '',
                religiao: dv.religiao || '',
              };
            });
            downloadCsvFromRows(`escalab_colaboradores_completo_${new Date().getFullYear()}.csv`, rows);
          }} style={{ border:'1px solid var(--escalab-line)', background:'#fff', color:'var(--escalab-slate)', borderRadius:9, padding:'8px 14px', cursor:'pointer', fontSize:13, fontWeight:600, display:'inline-flex', alignItems:'center', gap:6 }}>
            <Icon name="download" size={12} /> CSV Completo (Colab.)
          </button>
          <button onClick={() => {
            const desligs = getDesligamentos();
            const mov = getMovimentacoesAll();
            const ausencias = lerLS('escalab_ausencias', []);
            const ferias = lerLS('escalab_ferias', []);
            const treinos = lerLS('escalab_treinamentos_v2', null) || lerLS('escalab_treinamentos', []);
            const sections = {
              desligamentos: desligs.map(d => ({ id: d.id, nome: d.nome, setor: d.setor, cargo: d.cargo, categoria: d.categoriaKey, motivo: d.motivoId, dataSaida: d.dataSaida })),
              admissoes: ADMISSOES_DEMO.map(a => ({ id: a.id, nome: a.nome, categoria: a.categoria, admitidoEm: a.admitidoEm, aberturaEm: a.aberturaEm, diasProcesso: a.diasProcesso })),
              avaliacoes: AVALIACOES.map(a => ({ id: a.id, cicloId: a.cicloId, avaliadorId: a.avaliadorId, avaliadoId: a.avaliadoId, tipo: a.tipo, nota: a.nota, status: a.status, data: a.data })),
              feedbacks: FEEDBACKS.map(f => ({ id: f.id, colaboradorId: f.colaboradorId, data: f.data, responsavel: f.responsavel, trimestre: f.trimestre })),
              ferias: ferias.map(f => ({ id: f.id, colaboradorId: f.colaboradorId, inicio: f.inicio, fim: f.fim, dias: f.dias, status: f.status })),
              ausencias: ausencias.map(a => ({ id: a.id, colaboradorId: a.colaboradorId, motivo: a.motivo, dataInicio: a.dataInicio, dataFim: a.dataFim, status: a.status })),
              treinamentos: treinos.map(t => ({ id: t.id, titulo: t.titulo, data: t.data, status: t.status, nps: t.nps, freq_fixos: t.freq_fixos, freq_assoc: t.freq_assoc })),
              movimentacoes_admissao: mov.admissao.map(m => ({ id: m.id, etapa: m.etapa, criadoEm: m.criadoEm, nomeColaborador: m.dados?.nomeColaborador })),
              movimentacoes_promocao: mov.promocao.map(m => ({ id: m.id, etapa: m.etapa, criadoEm: m.criadoEm, nomeColaborador: m.dados?.nomeColaborador })),
              movimentacoes_desligamento: mov.desligamento.map(m => ({ id: m.id, etapa: m.etapa, criadoEm: m.criadoEm, nomeColaborador: m.dados?.nomeColaborador })),
            };
            const flat = [];
            Object.entries(sections).forEach(([sec, arr]) => arr.forEach(row => flat.push({ secao: sec, ...row })));
            downloadCsvFromRows(`escalab_dashboard_dados_${new Date().getFullYear()}.csv`, flat);
          }} style={{ border:'1px solid var(--escalab-line)', background:'#fff', color:'var(--escalab-slate)', borderRadius:9, padding:'8px 14px', cursor:'pointer', fontSize:13, fontWeight:600, display:'inline-flex', alignItems:'center', gap:6 }}>
            <Icon name="download" size={12} /> CSV Gráficos
          </button>
        </div>
      </div>

      {/* Snapshots retroativos */}
      {Object.keys(snaps).length > 0 && (
        <div style={{ background: '#fff', border: '1px solid var(--escalab-line)', borderRadius: 14, padding: '14px 18px', marginBottom: 18, display:'flex', alignItems:'center', gap:12, flexWrap:'wrap' }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--escalab-mute)', textTransform: 'uppercase', letterSpacing: '.08em' }}>Snapshots salvos</div>
          {Object.entries(snaps).sort((a,b) => Number(b[0]) - Number(a[0])).map(([ano, s]) => (
            <div key={ano} style={{ display:'inline-flex', alignItems:'center', gap:8, padding:'5px 12px', background:'var(--escalab-paper)', border:'1px solid var(--escalab-line)', borderRadius:999 }}>
              <strong style={{ fontSize:13, color:'var(--escalab-ink)' }}>{ano}</strong>
              <span style={{ fontSize:11.5, color:'var(--escalab-mute)' }}>{s.totalColab} pessoas</span>
              <span style={{ fontSize:11, color:'var(--escalab-mute)' }}>· {(new Date(s.em || Date.now())).toLocaleDateString('pt-BR')}</span>
            </div>
          ))}
          <button onClick={() => downloadJson(`escalab_snapshots_todos_anos.json`, snaps)}
            style={{ marginLeft:'auto', border:'1px solid var(--escalab-line)', background:'#fff', color:'var(--escalab-slate)', borderRadius:8, padding:'5px 12px', cursor:'pointer', fontSize:12, fontWeight:600, display:'inline-flex', alignItems:'center', gap:5 }}>
            <Icon name="download" size={11} /> Baixar todos
          </button>
        </div>
      )}

      {/* Navegação em 2 níveis: categorias coloridas + sub-abas dentro */}
      <NavDashboard abaPainel={abaPainel} setAbaPainel={setAbaPainel} />

      {/* Filtro temporal global · afeta KPIs e gráficos que aceitam corte (PDF Site AVD (2)) */}
      {abaPainel !== 'geral' && <FiltroTempo periodo={periodo} setPeriodo={setPeriodo} />}

      {abaPainel === 'topo'         && <PainelTopo snaps={snaps} periodo={periodo} />}
      {abaPainel === 'recrutamento' && <PainelRecrutamento />}
      {abaPainel === 'perfil'       && (<>
        <PainelPerfilQuadro />
        <div style={{ marginTop: 20 }}><PainelDistribuicaoQuadro /></div>
      </>)}
      {abaPainel === 'treinamento'  && <PainelTreinamento />}
      {abaPainel === 'avd_feedback' && <PainelAvdFeedback />}
      {abaPainel === 'diversidade'  && <PainelDiversidade />}

      {abaPainel === 'geral' && (<>
      {/* KPIs · cartões com gradiente */}
      {(() => {
        const fixos = COLABORADORES.filter(c => getCategoriaKey(c.id) === 'fixo').length;
        const associados = totalColab - fixos;
        const kpis = [
          { label:'Equipe Total',         val:totalColab,                         sub:'colaboradores ativos',              g:'linear-gradient(135deg,#00967B,#004A3C)', icon:'users'     },
          { label:'Fixos',                val:fixos,                              sub:`${Math.round(fixos/totalColab*100)}% da equipe`,  g:'linear-gradient(135deg,#1F4A8A,#0A1E50)', icon:'user'      },
          { label:'AVD '+cicloAtivo?.nome,val:`${avsConc}/${avsTot}`,            sub:'avaliações concluídas',              g:'linear-gradient(135deg,#6B3FA0,#3A1E70)', icon:'clipboard' },
          { label:'Tempo Médio',          val:`${(tempoMedio/12).toFixed(1)} a`,  sub:'de empresa no time',                 g:'linear-gradient(135deg,#B56500,#7A3F00)', icon:'calendar'  },
        ];
        return (
          <div style={{ display:'grid', gridTemplateColumns:'repeat(4,1fr)', gap:14, marginBottom:24 }}>
            {kpis.map(k => (
              <div key={k.label} style={{ background:k.g, borderRadius:16, padding:'22px 22px 20px', color:'#fff', position:'relative', overflow:'hidden', boxShadow:'0 8px 28px rgba(0,0,0,.18)' }}>
                <div style={{ position:'absolute', right:-20, top:-20, width:100, height:100, borderRadius:'50%', background:'rgba(255,255,255,.08)' }} />
                <div style={{ position:'absolute', right:24, bottom:16, opacity:.35 }}><Icon name={k.icon} size={36} /></div>
                <div style={{ fontSize:10.5, fontWeight:700, letterSpacing:'.12em', textTransform:'uppercase', color:'rgba(255,255,255,.7)', marginBottom:10 }}>{k.label}</div>
                <div style={{ fontSize:36, fontWeight:900, lineHeight:1, letterSpacing:'-.03em', marginBottom:6 }}>{k.val}</div>
                <div style={{ fontSize:12, color:'rgba(255,255,255,.65)' }}>{k.sub}</div>
              </div>
            ))}
          </div>
        );
      })()}

      {/* Row 2: Headcount por setor (real) + Distribuição da equipe */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginBottom: 14 }}>
        {/* Headcount por setor · dados reais de COLABORADORES */}
        {(() => {
          const porSetor = Object.entries(
            COLABORADORES.reduce((acc, c) => { acc[c.setor] = (acc[c.setor] || 0) + 1; return acc; }, {})
          ).sort((a, b) => b[1] - a[1]).slice(0, 8);
          const maxN = porSetor[0]?.[1] || 1;
          const CORES_SETOR = ['#00967B','#1F4A8A','#6B3FA0','#E89B3B','#00836B','#B3261E','#4A5560','#005E4D'];
          return (
            <Card pad={22}>
              <div style={{ marginBottom: 16 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Headcount por Setor</div>
                <div style={{ fontSize: 15, fontWeight: 600, color: 'var(--escalab-ink)' }}>Distribuição atual · {COLABORADORES.length} pessoas</div>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                {porSetor.map(([setor, n], i) => (
                  <div key={setor} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <span style={{ fontSize: 12.5, color: 'var(--escalab-slate)', minWidth: 140, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{setor}</span>
                    <div style={{ flex: 1, height: 8, background: 'var(--escalab-line)', borderRadius: 999 }}>
                      <div style={{ width: (n / maxN * 100) + '%', height: '100%', background: CORES_SETOR[i % CORES_SETOR.length], borderRadius: 999, transition: 'width .5s' }} />
                    </div>
                    <span style={{ fontSize: 13, fontWeight: 700, color: 'var(--escalab-ink)', minWidth: 20, textAlign: 'right' }}>{n}</span>
                  </div>
                ))}
              </div>
            </Card>
          );
        })()}

        {/* Distribuição da equipe · fixos vs associados */}
        {(() => {
          const cats = [
            { key: 'fixo',              label: 'Fixo',               cor: '#1F4A8A', bg: '#EEF3FA' },
            { key: 'associado_projetos', label: 'Assoc. Projetos',   cor: '#00836B', bg: '#E6F5F1' },
            { key: 'associado_editais',  label: 'Assoc. Editais',    cor: '#6B3FA0', bg: '#F4EEFF' },
            { key: 'associado_vb',       label: 'Venture Builder',   cor: '#B56500', bg: '#FFF7EB' },
            { key: 'associado_redes',    label: 'Redes',              cor: '#005E4D', bg: '#E6F5F1' },
          ];
          const counts = {};
          COLABORADORES.forEach(c => { const k = getCategoriaKey(c.id); counts[k] = (counts[k] || 0) + 1; });
          const total = COLABORADORES.length;
          return (
            <Card pad={22}>
              <div style={{ marginBottom: 16 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Composição da Equipe</div>
                <div style={{ fontSize: 15, fontWeight: 600, color: 'var(--escalab-ink)' }}>Modalidades de vínculo</div>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                {cats.map(c => {
                  const n = counts[c.key] || 0;
                  if (!n) return null;
                  return (
                    <div key={c.key}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5 }}>
                        <span style={{ fontSize: 13, fontWeight: 500, color: 'var(--escalab-ink)' }}>{c.label}</span>
                        <span style={{ fontSize: 13, fontWeight: 700, color: c.cor }}>{n} <span style={{ fontWeight: 400, color: 'var(--escalab-mute)', fontSize: 11 }}>({Math.round(n/total*100)}%)</span></span>
                      </div>
                      <div style={{ height: 8, background: 'var(--escalab-line)', borderRadius: 999 }}>
                        <div style={{ width: (n/total*100)+'%', height: '100%', background: c.cor, borderRadius: 999, transition: 'width .5s' }} />
                      </div>
                    </div>
                  );
                })}
              </div>
            </Card>
          );
        })()}
      </div>

      {/* Row 3: Nível da equipe + Feedbacks por setor */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginBottom: 14 }}>
        {/* Perfil por nível + tempo médio · dados reais */}
        {(() => {
          const niveis = [
            { key: 'diretor',  label: 'Diretor(a) / CEO',      cor: '#1F4A8A', bg: '#EEF3FA' },
            { key: 'lider',    label: 'Líder / Especialista',   cor: '#00967B', bg: '#E6F5F1' },
            { key: 'liderado', label: 'Colaborador',            cor: '#6B3FA0', bg: '#F4EEFF' },
          ];
          const total = COLABORADORES.length;
          return (
            <Card pad={22}>
              <div style={{ marginBottom: 16 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Perfil da Equipe</div>
                <div style={{ fontSize: 15, fontWeight: 600 }}>Distribuição por nível hierárquico</div>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
                {niveis.map(nv => {
                  const pessoas = COLABORADORES.filter(c => c.nivel === nv.key);
                  const n = pessoas.length;
                  const tempoMedioN = n ? Math.round(pessoas.reduce((s, c) => s + c.tempoEmpresa, 0) / n) : 0;
                  const anos = Math.floor(tempoMedioN / 12);
                  const meses = tempoMedioN % 12;
                  const tempoStr = anos > 0 ? `${anos}a ${meses > 0 ? meses + 'm' : ''}`.trim() : `${meses}m`;
                  return (
                    <div key={nv.key}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6 }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                          <div style={{ width: 10, height: 10, borderRadius: '50%', background: nv.cor, flexShrink: 0 }} />
                          <span style={{ fontSize: 13, fontWeight: 500, color: 'var(--escalab-ink)' }}>{nv.label}</span>
                        </div>
                        <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
                          <span style={{ fontSize: 11.5, color: 'var(--escalab-mute)' }}>⌀ {tempoStr}</span>
                          <span style={{ fontSize: 14, fontWeight: 800, color: nv.cor }}>{n}</span>
                        </div>
                      </div>
                      <div style={{ height: 8, background: 'var(--escalab-line)', borderRadius: 999 }}>
                        <div style={{ width: (n/total*100)+'%', height: '100%', background: nv.cor, borderRadius: 999, transition: 'width .5s' }} />
                      </div>
                    </div>
                  );
                })}
              </div>
              <div style={{ marginTop: 18, paddingTop: 14, borderTop: '1px solid var(--escalab-line)', display: 'flex', gap: 14, flexWrap: 'wrap' }}>
                {[
                  { label: 'Tempo médio geral', val: (() => { const m = Math.round(COLABORADORES.reduce((s, c) => s + c.tempoEmpresa, 0) / total); const a = Math.floor(m/12); return a > 0 ? `${a}a ${m%12}m` : `${m}m`; })() },
                  { label: 'Maior tempo',        val: (() => { const m = Math.max(...COLABORADORES.map(c => c.tempoEmpresa)); const a = Math.floor(m/12); return a > 0 ? `${a}a ${m%12}m` : `${m}m`; })() },
                ].map(s => (
                  <div key={s.label} style={{ flex: 1, minWidth: 100 }}>
                    <div style={{ fontSize: 10.5, color: 'var(--escalab-mute)', marginBottom: 2 }}>{s.label}</div>
                    <div style={{ fontSize: 17, fontWeight: 800, color: 'var(--escalab-brand-deep)' }}>{s.val}</div>
                  </div>
                ))}
              </div>
            </Card>
          );
        })()}

        <Card pad={22}>
          <div style={{ marginBottom: 18 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Feedbacks por Setor</div>
            <div style={{ fontSize: 15, fontWeight: 600 }}>1T2025 · Cobertura atual</div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {FEEDBACKS_SETOR_ATUAL.map(f => {
              const tone = f.pct >= 90 ? '#00967B' : f.pct >= 60 ? '#E89B3B' : '#E05050';
              const bg   = f.pct >= 90 ? '#E6F5F1' : f.pct >= 60 ? '#FFF4E6' : '#FDECEC';
              return (
                <div key={f.setor} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <span style={{ fontSize: 13, color: 'var(--escalab-ink)', minWidth: 90, fontWeight: 500 }}>{f.setor}</span>
                  <div style={{ flex: 1, height: 7, background: 'var(--escalab-line)', borderRadius: 999 }}>
                    <div style={{ width: f.pct + '%', height: '100%', background: tone, borderRadius: 999, transition: 'width .5s' }} />
                  </div>
                  <span style={{ fontSize: 12, fontWeight: 700, color: tone, background: bg, padding: '2px 8px', borderRadius: 6, minWidth: 40, textAlign: 'center' }}>{f.pct}%</span>
                </div>
              );
            })}
          </div>
          <div style={{ display: 'flex', gap: 12, marginTop: 14, fontSize: 11, color: 'var(--escalab-mute)' }}>
            {[['#00967B', '≥90%'], ['#E89B3B', '60-90%'], ['#E05050', '<60%']].map(([c, l]) => (
              <div key={l} style={{ display: 'flex', gap: 5, alignItems: 'center' }}>
                <div style={{ width: 8, height: 8, background: c, borderRadius: '50%' }}/> {l}
              </div>
            ))}
          </div>
        </Card>
      </div>

      </>)}

      {abaPainel === 'movimentacoes' && (() => {
        const totalQuadro = COLABORADORES.length;
        const movs = MOVIMENTACOES.slice().sort((a, b) => b.data.localeCompare(a.data));
        const nPromo = movs.filter(m => m.tipo === 'promocao').length;
        const nMerito = movs.filter(m => m.tipo === 'merito').length;
        const nLateral = movs.filter(m => m.tipo === 'lateral').length;
        const pessoasMovidas = new Set(movs.map(m => m.colaboradorId)).size;
        const taxaMobilidade = totalQuadro ? Math.round(pessoasMovidas / totalQuadro * 100) : 0;

        // Agrupa pela classificação escolhida (nível de destino ou cargo de destino)
        const grupos = {};
        movs.forEach(m => {
          const chave = movClassificar === 'nivel' ? (NIVEL_LABEL[m.nivelPara] || m.nivelPara) : m.para;
          grupos[chave] = (grupos[chave] || 0) + 1;
        });
        const gruposArr = Object.entries(grupos).map(([k, n]) => ({ k, n })).sort((a, b) => b.n - a.n);
        const maxG = Math.max(1, ...gruposArr.map(g => g.n));
        const mesBR = ym => { const [y, mm] = ym.split('-'); const M = ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez']; return `${M[parseInt(mm) - 1]}/${y.slice(2)}`; };

        return (
          <div style={{ animation: 'fadeIn .2s' }}>
            {/* KPIs de mobilidade */}
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginBottom: 14 }}>
              {[
                { label: 'Movimentações', val: movs.length, sub: 'no período', cor: 'var(--escalab-brand)', bg: 'var(--escalab-brand-tint)' },
                { label: 'Promoções', val: nPromo, sub: 'mudança de nível', cor: '#00836B', bg: '#E6F5F1' },
                { label: 'Mérito / lateral', val: nMerito + nLateral, sub: 'mesmo nível', cor: '#1F4A8A', bg: '#EEF3FA' },
                { label: 'Taxa de mobilidade', val: taxaMobilidade + '%', sub: `${pessoasMovidas} de ${totalQuadro} pessoas`, cor: '#B56500', bg: '#FFF7EB' },
              ].map(k => (
                <div key={k.label} style={{ background: '#fff', border: '1px solid var(--escalab-line)', borderRadius: 12, padding: '16px 18px' }}>
                  <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 8 }}>{k.label}</div>
                  <div style={{ fontSize: 26, fontWeight: 800, color: k.cor, lineHeight: 1, marginBottom: 4 }}>{k.val}</div>
                  <div style={{ fontSize: 11.5, color: 'var(--escalab-mute)' }}>{k.sub}</div>
                </div>
              ))}
            </div>

            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
              {/* Progressão por classificação */}
              <Card pad={22}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 18, flexWrap: 'wrap' }}>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Progressão de carreira</div>
                    <div style={{ fontSize: 15, fontWeight: 600 }}>Movimentações por {movClassificar === 'nivel' ? 'nível' : 'cargo'}</div>
                  </div>
                  <div style={{ display: 'flex', background: 'var(--escalab-paper)', border: '1px solid var(--escalab-line)', borderRadius: 8, padding: 2 }}>
                    {[{ id: 'nivel', label: 'Nível' }, { id: 'cargo', label: 'Cargo' }].map(o => (
                      <button key={o.id} onClick={() => setMovClassificar(o.id)} style={{
                        border: 0, borderRadius: 6, padding: '5px 12px', cursor: 'pointer', fontSize: 12.5, fontFamily: 'var(--font-sans)', fontWeight: movClassificar === o.id ? 700 : 500,
                        background: movClassificar === o.id ? '#fff' : 'transparent', color: movClassificar === o.id ? 'var(--escalab-brand-deep)' : 'var(--escalab-mute)',
                        boxShadow: movClassificar === o.id ? '0 1px 3px rgba(0,0,0,.08)' : 'none',
                      }}>{o.label}</button>
                    ))}
                  </div>
                </div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                  {gruposArr.map(g => (
                    <div key={g.k} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                      <span style={{ fontSize: 12.5, color: 'var(--escalab-slate)', minWidth: 150, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={g.k}>{g.k}</span>
                      <div style={{ flex: 1, height: 9, background: 'var(--escalab-line)', borderRadius: 999 }}>
                        <div style={{ width: (g.n / maxG * 100) + '%', height: '100%', background: 'var(--escalab-brand)', borderRadius: 999, transition: 'width .4s var(--ease-out)' }} />
                      </div>
                      <span style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--escalab-brand-deep)', minWidth: 24, textAlign: 'right' }}>{g.n}</span>
                    </div>
                  ))}
                </div>
              </Card>

              {/* Linha do tempo das movimentações */}
              <Card pad={22}>
                <div style={{ marginBottom: 16 }}>
                  <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--escalab-mute)', marginBottom: 4 }}>Histórico</div>
                  <div style={{ fontSize: 15, fontWeight: 600 }}>Movimentações recentes</div>
                </div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 10, maxHeight: 340, overflowY: 'auto' }}>
                  {movs.map(m => {
                    const t = MOV_TIPOS[m.tipo] || MOV_TIPOS.merito;
                    return (
                      <div key={m.id} style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '10px 12px', border: '1px solid var(--escalab-line)', borderLeft: `4px solid ${t.cor}`, borderRadius: 10 }}>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--escalab-ink)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{m.nome.split(' ').slice(0, 2).join(' ')}</div>
                          <div style={{ fontSize: 11.5, color: 'var(--escalab-mute)' }}>{m.de} → <strong style={{ color: t.cor }}>{m.para}</strong></div>
                        </div>
                        <div style={{ textAlign: 'right', flexShrink: 0 }}>
                          <div style={{ fontSize: 10.5, fontWeight: 600, color: t.cor, background: t.cor + '15', borderRadius: 5, padding: '2px 7px', whiteSpace: 'nowrap' }}>{m.tipo === 'promocao' ? 'Promoção' : m.tipo === 'merito' ? 'Mérito' : 'Lateral'}</div>
                          <div style={{ fontSize: 11, color: 'var(--escalab-mute)', marginTop: 3 }}>{mesBR(m.data)}</div>
                        </div>
                      </div>
                    );
                  })}
                </div>
              </Card>
            </div>
          </div>
        );
      })()}

      {abaPainel === 'admissoes' && (<>
        <PainelAdmissoesDeslig periodo={periodo} />
        <div style={{ marginTop: 16, padding: '14px 18px', background: '#F4EEFF', border: '1px solid #E0D4FF', borderRadius: 10, fontSize: 12.5, color: '#5B2EAA', display: 'flex', alignItems: 'center', gap: 10 }}>
          <Icon name="trend_down" size={14} />
          <span>Análises de <strong>turnover</strong> foram consolidadas na guia <strong>Turnover · Consolidado</strong>.</span>
        </div>
      </>)}

      {abaPainel === 'turnover' && <PainelTurnoverConsolidado periodo={periodo} />}

      {abaPainel === 'remuneracao' && (<>
        <PainelRemuneracao periodo={periodo} />
        <div style={{ marginTop: 20 }}>
          <PainelFolhaProgressao />
        </div>
      </>)}

      {abaPainel === 'ferias' && (<>
      {/* PDF Site AVD (2): "Resumo de férias" removido daqui (já existe na tela de Férias).
          "Ausências pendentes" também removido (estava sobrecarregando). */}
      <PainelFeriasAusencias />
      </>)}
    </div>
  );
};

window.ScreenDashboard = ScreenDashboard;
