/* Devonew — Painel da Igreja · Cuidado (pastoral care)
   1) Lista de Cuidado · 2) Perfil 360 + radar · 3) Cuidado por líder + segmentos · 4) Automação + saúde da igreja */
const { useState: useStateCare, useMemo: useMemoCare } = React;

/* ============================================================
   Seed da congregação (dados ilustrativos · vivem no localStorage 'care')
   scores 0-100 por dimensão · journeyStep = índice na Trilha · lastSeenWeeks/lastTouchDays em sync com o cuidado
   ============================================================ */
window.ADMIN.careSeed = [
  { id:'cp1', name:'Beatriz Carvalho', initials:'BC', role:'Visitante', cell:'—', joined:2026, joinedDaysAgo:12, lastSeenWeeks:0, appActiveDays:1, journeyStep:1,
    prayer:false, flags:['novo','visitante','sem_celula'], assignedTo:'Mariana Alves', status:'aberto', lastTouchDays:2,
    scores:{ presenca:62, comunhao:18, devocional:34, servico:8, generosidade:0, discipulado:22 },
    touches:[{ date:'02 jun', by:'Mariana Alves', channel:'whatsapp', note:'Boas-vindas e convite para a célula Centro nesta terça.' }] },

  { id:'cp2', name:'Marcos Pereira', initials:'MP', role:'Membro', cell:'Zona Sul', joined:2021, joinedDaysAgo:1400, lastSeenWeeks:4, appActiveDays:26, journeyStep:4,
    prayer:false, flags:['ausente','sem_devocional'], assignedTo:'Carlos Nunes', status:'andamento', lastTouchDays:19,
    scores:{ presenca:28, comunhao:40, devocional:24, servico:45, generosidade:55, discipulado:48 },
    touches:[{ date:'16 mai', by:'Carlos Nunes', channel:'ligacao', note:'Atendeu, disse que andou desanimado no trabalho. Vou visitar.' }] },

  { id:'cp3', name:'Larissa Monteiro', initials:'LM', role:'Membro', cell:'Jardins', joined:2026, joinedDaysAgo:48, lastSeenWeeks:0, appActiveDays:1, journeyStep:3,
    prayer:false, flags:['novo'], assignedTo:'Tiago Ferreira', status:'aberto', lastTouchDays:5,
    scores:{ presenca:80, comunhao:70, devocional:66, servico:30, generosidade:20, discipulado:55 },
    touches:[{ date:'30 mai', by:'Tiago Ferreira', channel:'presencial', note:'Animadíssima depois do batismo. Convidei para o curso de Fundamentos.' }] },

  { id:'cp4', name:'Eduardo Lima', initials:'EL', role:'Membro', cell:'Centro', joined:2020, joinedDaysAgo:1700, lastSeenWeeks:1, appActiveDays:9, journeyStep:5,
    prayer:false, flags:['estagnado','sem_devocional'], assignedTo:'Rafael Souza', status:'aberto', lastTouchDays:23,
    scores:{ presenca:72, comunhao:58, devocional:30, servico:62, generosidade:48, discipulado:38 },
    touches:[{ date:'12 mai', by:'Rafael Souza', channel:'whatsapp', note:'Parou na etapa do curso há meses. Reenviei o link.' }] },

  { id:'cp5', name:'Patrícia Gomes', initials:'PG', role:'Membro', cell:'Vila Nova', joined:2022, joinedDaysAgo:1000, lastSeenWeeks:2, appActiveDays:14, journeyStep:6,
    prayer:true, flags:['oracao'], assignedTo:'Pra. Sônia Reis', status:'andamento', lastTouchDays:3,
    scores:{ presenca:58, comunhao:64, devocional:60, servico:50, generosidade:62, discipulado:66 },
    touches:[{ date:'01 jun', by:'Pra. Sônia Reis', channel:'visita', note:'Processo de saúde na família. Oramos juntas, levarei à corrente.' }] },

  { id:'cp6', name:'Juliana Dias', initials:'JD', role:'Visitante', cell:'—', joined:2026, joinedDaysAgo:30, lastSeenWeeks:1, appActiveDays:3, journeyStep:0,
    prayer:false, flags:['visitante','sem_celula','novo'], assignedTo:'—', status:'aberto', lastTouchDays:9,
    scores:{ presenca:48, comunhao:10, devocional:20, servico:0, generosidade:0, discipulado:8 },
    touches:[] },

  { id:'cp7', name:'Daniela Rocha', initials:'DR', role:'Membro', cell:'—', joined:2023, joinedDaysAgo:760, lastSeenWeeks:1, appActiveDays:6, journeyStep:4,
    prayer:false, flags:['sem_celula'], assignedTo:'Priscila Gomes', status:'aberto', lastTouchDays:11,
    scores:{ presenca:70, comunhao:22, devocional:58, servico:35, generosidade:40, discipulado:50 },
    touches:[{ date:'24 mai', by:'Priscila Gomes', channel:'whatsapp', note:'Quer uma célula perto de casa, no bairro Aurora.' }] },

  { id:'cp8', name:'Fernando Alves', initials:'FA', role:'Membro', cell:'Centro', joined:2019, joinedDaysAgo:2200, lastSeenWeeks:6, appActiveDays:52, journeyStep:5,
    prayer:false, flags:['ausente','sem_devocional','sem_celula'], assignedTo:'—', status:'aberto', lastTouchDays:41,
    scores:{ presenca:14, comunhao:18, devocional:16, servico:20, generosidade:30, discipulado:40 },
    touches:[{ date:'24 abr', by:'Pr. André Martins', channel:'ligacao', note:'Não atendeu. Deixar recado e tentar pela esposa.' }] },

  { id:'cp9', name:'Camila Nogueira', initials:'CN', role:'Membro', cell:'Vila Nova', joined:2026, joinedDaysAgo:64, lastSeenWeeks:0, appActiveDays:1, journeyStep:4,
    prayer:false, flags:['novo'], assignedTo:'Priscila Gomes', status:'aberto', lastTouchDays:4,
    scores:{ presenca:86, comunhao:74, devocional:70, servico:42, generosidade:35, discipulado:58 },
    touches:[{ date:'31 mai', by:'Priscila Gomes', channel:'presencial', note:'Batizada no domingo! Sede de aprender. Indicar discipulado 1-a-1.' }] },

  { id:'cp10', name:'Roberto Dias', initials:'RD', role:'Membro', cell:'Jardins', joined:2010, joinedDaysAgo:5600, lastSeenWeeks:3, appActiveDays:0, journeyStep:8,
    prayer:true, flags:['oracao','ausente'], assignedTo:'Pra. Sônia Reis', status:'andamento', lastTouchDays:6,
    scores:{ presenca:40, comunhao:55, devocional:78, servico:30, generosidade:72, discipulado:90 },
    touches:[{ date:'29 mai', by:'Pra. Sônia Reis', channel:'visita', note:'Cirurgia marcada. Visita domiciliar combinada com os diáconos.' }] },

  { id:'cp11', name:'Carlos Nunes', initials:'CA', role:'Líder', cell:'Zona Sul', joined:2011, joinedDaysAgo:5300, lastSeenWeeks:3, appActiveDays:12, journeyStep:8,
    prayer:false, flags:['lideranca','ausente'], assignedTo:'Pr. André Martins', status:'aberto', lastTouchDays:15,
    scores:{ presenca:55, comunhao:72, devocional:50, servico:80, generosidade:68, discipulado:85 },
    touches:[{ date:'20 mai', by:'Pr. André Martins', channel:'presencial', note:'Líder cansado — cuida de muitos e parou de descansar. Marcar café.' }] },

  /* base saudável e engajada — não entram na lista, sustentam médias e segmentos */
  { id:'cp12', name:'Leonardo Gomes', initials:'LG', role:'Membro', cell:'Vila Nova', joined:2019, joinedDaysAgo:2300, lastSeenWeeks:0, appActiveDays:1, journeyStep:7,
    prayer:false, flags:['aniversario'], assignedTo:'Priscila Gomes', status:'aberto', lastTouchDays:8,
    scores:{ presenca:90, comunhao:85, devocional:82, servico:78, generosidade:80, discipulado:88 }, touches:[] },
  { id:'cp13', name:'Mariana Alves', initials:'MA', role:'Líder', cell:'Centro', joined:2016, joinedDaysAgo:3500, lastSeenWeeks:0, appActiveDays:1, journeyStep:8,
    prayer:false, flags:['lideranca'], assignedTo:'Pr. André Martins', status:'aberto', lastTouchDays:7,
    scores:{ presenca:92, comunhao:90, devocional:80, servico:88, generosidade:75, discipulado:92 }, touches:[] },
  { id:'cp14', name:'Tiago Ferreira', initials:'TF', role:'Diácono', cell:'Jardins', joined:2014, joinedDaysAgo:4200, lastSeenWeeks:0, appActiveDays:2, journeyStep:8,
    prayer:false, flags:['lideranca'], assignedTo:'Pr. André Martins', status:'aberto', lastTouchDays:10,
    scores:{ presenca:88, comunhao:84, devocional:76, servico:90, generosidade:70, discipulado:90 }, touches:[] },
  { id:'cp15', name:'Rafael Souza', initials:'RS', role:'Tesoureiro', cell:'Centro', joined:2012, joinedDaysAgo:5000, lastSeenWeeks:0, appActiveDays:1, journeyStep:8,
    prayer:false, flags:[], assignedTo:'Pr. André Martins', status:'aberto', lastTouchDays:12,
    scores:{ presenca:86, comunhao:80, devocional:74, servico:82, generosidade:90, discipulado:86 }, touches:[] },
  { id:'cp16', name:'Priscila Gomes', initials:'PR', role:'Líder', cell:'Vila Nova', joined:2021, joinedDaysAgo:1300, lastSeenWeeks:0, appActiveDays:1, journeyStep:7,
    prayer:false, flags:['lideranca'], assignedTo:'Mariana Alves', status:'aberto', lastTouchDays:9,
    scores:{ presenca:84, comunhao:88, devocional:72, servico:80, generosidade:66, discipulado:84 }, touches:[] },

  /* acompanhamento concluído no mês — conta em "Resolvidos", sai da fila */
  { id:'cp17', name:'Sandra Lima', initials:'SL', role:'Membro', cell:'Jardins', joined:2024, joinedDaysAgo:420, lastSeenWeeks:0, appActiveDays:2, journeyStep:5,
    prayer:false, flags:['sem_celula'], assignedTo:'Tiago Ferreira', status:'cuidado_ok', lastTouchDays:4,
    scores:{ presenca:78, comunhao:68, devocional:64, servico:40, generosidade:45, discipulado:60 },
    touches:[{ date:'31 mai', by:'Tiago Ferreira', channel:'presencial', note:'Entrou na célula Jardins e já trouxe uma amiga. Cuidado concluído ✓' }] },
];

/* estado on/off das automações (persistido em 'care_rules') */
window.ADMIN.careRulesSeed = { ausencia:true, boas_vindas:true, sem_celula:true, aniversario:true, devocional:false, curso:false, oracao:true };

/* tendência de retenção (12 semanas) e lacunas ilustrativas entre etapas da trilha */
window.ADMIN.careHealthSeed = {
  retentionTrend: [83, 85, 84, 87, 86, 89, 88, 90, 89, 91, 90, 92],
  velocityGaps: [
    { from: 'Decisão → Devocional', days: 4 },
    { from: 'Devocional → Célula', days: 11 },
    { from: 'Célula → Batismo', days: 19 },
    { from: 'Batismo → Curso', days: 28 },
  ],
};

/* ============================================================
   Catálogos e helpers de cuidado
   ============================================================ */
const TONES = {
  danger: { fg:'oklch(0.52 0.15 32)',  bg:'oklch(0.955 0.045 38)', bd:'oklch(0.88 0.07 38)' },
  warn:   { fg:'oklch(0.52 0.12 68)',  bg:'oklch(0.96 0.05 78)',   bd:'oklch(0.89 0.07 78)' },
  ok:     { fg:'oklch(0.46 0.1 150)',  bg:'oklch(0.95 0.04 150)',  bd:'oklch(0.87 0.06 150)' },
  info:   { fg:'oklch(0.5 0.11 248)',  bg:'oklch(0.95 0.04 248)',  bd:'oklch(0.88 0.06 248)' },
  grow:   { fg:'oklch(0.5 0.13 300)',  bg:'oklch(0.96 0.04 300)',  bd:'oklch(0.9 0.06 300)' },
  accent: { fg:'var(--accent-strong)', bg:'var(--accent-tint)',    bd:'transparent' },
  muted:  { fg:'var(--muted)',         bg:'var(--bg-2)',           bd:'var(--line)' },
};
const Chip = ({ tone = 'muted', icon, children, title }) => {
  const t = TONES[tone] || TONES.muted;
  return (
    <span className="cchip" title={title} style={{ color: t.fg, background: t.bg, borderColor: t.bd }}>
      {icon && <Icon name={icon} size={12}/>}{children}
    </span>
  );
};

const DIMS = [
  { key:'presenca',     short:'Presença',    label:'Presença nos cultos', icon:'church',  hint:(v)=> v<35?'Faltando aos cultos':v<70?`~${Math.round(v/25)} de 4 cultos no mês`:'Presente toda semana' },
  { key:'comunhao',     short:'Célula',      label:'Comunhão em célula',  icon:'users',   hint:(v)=> v<30?'Fora de uma célula':v<65?'Frequência irregular':'Firme na célula' },
  { key:'devocional',   short:'Devoção',     label:'Hábito devocional',   icon:'book',    hint:(v)=> v<35?'Devocional parado':v<70?'Devocional às vezes':'Devocional diário' },
  { key:'servico',      short:'Serviço',     label:'Serviço/ministério',  icon:'hands',   hint:(v)=> v<30?'Ainda não serve':v<65?'Serve eventualmente':'Servindo com constância' },
  { key:'generosidade', short:'Doação',      label:'Generosidade',        icon:'gift',    hint:(v)=> v<25?'Sem contribuição':v<65?'Contribui às vezes':'Dizimista fiel' },
  { key:'discipulado',  short:'Trilha',      label:'Discipulado/trilha',  icon:'sparkle', hint:(v)=> v<40?'Trilha estagnada':v<70?'Avançando na trilha':'Discipulando outros' },
];
const DIM_W = { presenca:0.2, comunhao:0.18, devocional:0.17, servico:0.15, generosidade:0.1, discipulado:0.2 };

const FLAGS = {
  oracao:        { label:()=>'Pediu oração',          icon:'pray',     tone:'grow' },
  ausente:       { label:(p)=>`Ausente há ${p.lastSeenWeeks} sem`, icon:'calendar', tone:'danger' },
  novo:          { label:()=>'Novo na fé',            icon:'flame',    tone:'accent' },
  visitante:     { label:()=>'Visitante',             icon:'userPlus', tone:'info' },
  sem_celula:    { label:()=>'Sem célula',            icon:'church',   tone:'warn' },
  sem_devocional:{ label:()=>'Devocional parado',     icon:'book',     tone:'warn' },
  estagnado:     { label:()=>'Trilha estagnada',      icon:'sparkle',  tone:'grow' },
  aniversario:   { label:()=>'Aniversário',           icon:'gift',     tone:'accent' },
  lideranca:     { label:()=>'Cuidar do líder',       icon:'shield',   tone:'info' },
};
const FLAG_W = { oracao:30, ausente:24, sem_celula:14, novo:15, visitante:12, sem_devocional:13, estagnado:18, aniversario:6, lideranca:8 };

const CHANNELS = [
  { key:'whatsapp',   label:'WhatsApp',  icon:'chat' },
  { key:'ligacao',    label:'Ligação',   icon:'bell' },
  { key:'visita',     label:'Visita',    icon:'home' },
  { key:'presencial', label:'No culto',  icon:'church' },
  { key:'oracao',     label:'Oração',    icon:'pray' },
];
const chMeta = (k) => CHANNELS.find((c) => c.key === k) || CHANNELS[0];
const CARE_TEAM = ['Pr. André Martins', 'Pra. Sônia Reis', 'Mariana Alves', 'Priscila Gomes', 'Tiago Ferreira', 'Carlos Nunes', 'Rafael Souza'];

const careFlags = (p) => {
  const f = new Set(p.flags || []);
  if (p.lastSeenWeeks >= 3) f.add('ausente'); else f.delete('ausente');
  if (p.prayer) f.add('oracao');
  return [...f];
};
const healthOf = (p) => Math.round(DIMS.reduce((s, d) => s + (p.scores[d.key] || 0) * DIM_W[d.key], 0));
const isLeaderRole = (p) => /Líder|Diácono|Presbítero|Pastor/.test(p.role || '');
/* motivos "brandos": sozinhos não jogam a pessoa na fila de cuidado (viram segmento/automação) */
const SOFT_FLAGS = new Set(['aniversario', 'lideranca']);
const needsCare = (p) => p.status !== 'cuidado_ok' && careFlags(p).some((f) => !SOFT_FLAGS.has(f));
const riskOf = (p) => { const h = healthOf(p); return h >= 70 ? { k:'ok', label:'Saudável' } : h >= 50 ? { k:'warn', label:'Atenção' } : { k:'danger', label:'Prioridade' }; };
const priorityOf = (p) => {
  const h = healthOf(p);
  let s = (100 - h) * 0.6 + (p.lastSeenWeeks || 0) * 5 + (p.lastTouchDays > 14 ? 14 : 0);
  careFlags(p).forEach((f) => { s += FLAG_W[f] || 0; });
  return Math.round(s);
};

const SEGMENTS = [
  { id:'novos',     label:'Novos na fé',        icon:'flame',    tone:'accent', desc:'Recém-convertidos e batizados nos últimos meses.',  test:(p)=> careFlags(p).includes('novo') },
  { id:'integrar',  label:'Visitantes a integrar', icon:'userPlus', tone:'info', desc:'Vieram aos cultos, ainda sem vínculo firmado.',    test:(p)=> careFlags(p).includes('visitante') },
  { id:'sem_celula',label:'Fora de célula',     icon:'church',   tone:'warn',   desc:'Sem um pequeno grupo de comunhão e cuidado.',       test:(p)=> careFlags(p).includes('sem_celula') },
  { id:'risco',     label:'Em risco / afastados', icon:'calendar', tone:'danger', desc:'Ausentes há 3+ semanas ou com saúde frágil.',     test:(p)=> careFlags(p).includes('ausente') || healthOf(p) < 50 },
  { id:'estagnados',label:'Discipulado estagnado', icon:'sparkle', tone:'grow', desc:'Pararam de avançar na trilha de crescimento.',     test:(p)=> careFlags(p).includes('estagnado') || careFlags(p).includes('sem_devocional') },
  { id:'lideres',   label:'Liderança',          icon:'shield',   tone:'info',   desc:'Quem cuida também precisa de cuidado.',             test:(p)=> isLeaderRole(p) },
  { id:'engajados', label:'Plenamente engajados', icon:'trophy', tone:'ok',     desc:'Firmes em presença, comunhão e serviço.',          test:(p)=> healthOf(p) >= 72 && !needsCare(p) },
];

const CARE_RULES = [
  { id:'ausencia',    icon:'calendar', name:'Resgate de ausentes',   trigger:'Membro ausente há 3+ semanas',
    action:'Cria tarefa de cuidado para o líder da célula e envia um incentivo no app.', count:(r)=> r.filter((p)=> p.lastSeenWeeks >= 3).length },
  { id:'boas_vindas', icon:'userPlus', name:'Boas-vindas ao novo',   trigger:'Cadastro aprovado na Secretaria',
    action:'Dispara uma sequência de 3 toques em 30 dias e convida para uma célula.', count:(r)=> r.filter((p)=> careFlags(p).includes('novo') || careFlags(p).includes('visitante')).length },
  { id:'sem_celula',  icon:'church',   name:'Conexão em célula',     trigger:'Membro sem célula há 14 dias',
    action:'Sugere as 3 células mais próximas e avisa o pastor de integração.', count:(r)=> r.filter((p)=> careFlags(p).includes('sem_celula')).length },
  { id:'aniversario', icon:'gift',     name:'Aniversário abençoado', trigger:'Aniversário nos próximos 3 dias',
    action:'Lembra o líder e gera uma mensagem pronta de parabéns.', count:(r)=> r.filter((p)=> careFlags(p).includes('aniversario')).length },
  { id:'devocional',  icon:'book',     name:'Reacender o devocional', trigger:'Sem devocional há 14 dias',
    action:'Envia um devocional curto e um versículo de incentivo no app.', count:(r)=> r.filter((p)=> p.scores.devocional < 35).length },
  { id:'curso',       icon:'grad',     name:'Próximo passo na trilha', trigger:'Concluiu um curso de discipulado',
    action:'Convida para a próxima etapa da Trilha de Crescimento.', count:(r)=> r.filter((p)=> p.journeyStep >= 5).length },
  { id:'oracao',      icon:'pray',     name:'Pedido de oração',      trigger:'Pediu oração na Corrente de Intercessão',
    action:'Notifica os intercessores e abre acompanhamento pastoral.', count:(r)=> r.filter((p)=> p.prayer).length },
];

const churchAvg = (roster) => {
  const n = roster.length || 1;
  const o = {};
  DIMS.forEach((d) => { o[d.key] = Math.round(roster.reduce((s, p) => s + (p.scores[d.key] || 0), 0) / n); });
  return o;
};
function careStats(roster, totalSteps) {
  const n = roster.length || 1;
  const care = roster.filter(needsCare);
  const retention = Math.round(roster.filter((p) => p.lastSeenWeeks <= 4).length / n * 100);
  const engagement = Math.round(roster.filter((p) => p.appActiveDays <= 7).length / n * 100);
  // velocidade = ritmo da coorte recém-convertida (até 1 ano); membros antigos distorceriam a média
  const cohort = roster.filter((p) => p.joinedDaysAgo <= 365 && p.journeyStep > 0);
  const pool = cohort.length >= 3 ? cohort : roster.filter((p) => p.journeyStep > 0);
  const velocity = Math.round(pool.reduce((s, p) => s + p.joinedDaysAgo / p.journeyStep, 0) / (pool.length || 1));
  const monthsToFinish = +(velocity * (totalSteps || 8) / 30).toFixed(1);
  const covered = care.filter((p) => p.assignedTo && p.assignedTo !== '—' && p.lastTouchDays <= 30).length;
  const coverage = care.length ? Math.round(covered / care.length * 100) : 100;
  const avgHealth = Math.round(roster.reduce((s, p) => s + healthOf(p), 0) / n);
  const overdue = care.filter((p) => p.lastTouchDays > 14).length;
  const resolvedMonth = roster.filter((p) => p.status === 'cuidado_ok').length;
  const unassigned = care.filter((p) => !p.assignedTo || p.assignedTo === '—').length;
  return { n, care: care.length, retention, engagement, velocity, monthsToFinish, coverage, avgHealth, overdue, resolvedMonth, unassigned };
}
const todayLabel = () => new Date().toLocaleDateString('pt-BR', { day: '2-digit', month: 'short' }).replace('.', '');
const firstName = (n) => (n || '').replace(/^(Pr\.|Pra\.|Diác\.|Rev\.)\s*/, '').trim().split(/\s+/)[0] || (n || '');

/* ---------- ponte com a Secretaria: deriva uma ficha de cuidado a partir de um membro real ----------
   reaproveita os membros/células reais do painel; quem é aprovado na Secretaria aparece aqui automaticamente */
const norm = (s) => (s || '').trim().toLowerCase();
function deriveFromMember(m, cells) {
  const status = m.status || 'Ativo';
  const isVisit = status === 'Visitante' || /visit/i.test(m.role || '');
  const inactive = status === 'Inativo';
  const leader = isLeaderRole(m);
  const hasCell = m.cell && m.cell !== '—' && m.cell !== '';
  const yr = new Date().getFullYear();
  const sinceYr = parseInt(m.since) || yr;
  const base = isVisit ? 30 : inactive ? 24 : leader ? 78 : 60;
  const jit = (k, amp) => Math.round(((hashStr(m.name + k) % 1000) / 1000 - 0.5) * amp);
  const cl = (v) => Math.max(0, Math.min(100, v));
  const scores = {
    presenca:     cl(base + (inactive ? -30 : 0) + jit('p', 16)),
    comunhao:     cl((hasCell ? base + 6 : base - 30) + jit('c', 16)),
    devocional:   cl(base - 6 + jit('d', 18)),
    servico:      cl((leader ? base + 8 : base - 12) + jit('s', 16)),
    generosidade: cl(base - 8 + jit('g', 18)),
    discipulado:  cl((leader ? base + 10 : base - 4) + jit('t', 16)),
  };
  const flags = [];
  if (isVisit) flags.push('visitante');
  if (!hasCell && !leader) flags.push('sem_celula');
  if (!leader && !isVisit && sinceYr >= yr - 1) flags.push('novo');
  if (leader) flags.push('lideranca');
  let assignedTo = '—';
  if (hasCell) {
    const cell = (cells || []).find((cc) => norm(cc.name).includes(norm(m.cell)) || norm(m.cell).includes(norm((cc.name || '').replace(/^célula\s*/i, ''))));
    if (cell && cell.leader && norm(cell.leader) !== norm(m.name)) assignedTo = cell.leader;
  }
  return {
    id: m.id || 'mem:' + norm(m.name), name: m.name, initials: m.initials || mkInitials(m.name),
    role: m.role || 'Membro', cell: hasCell ? m.cell : '—', joined: sinceYr,
    joinedDaysAgo: Math.max(30, (yr - sinceYr) * 365 + 120),
    lastSeenWeeks: inactive ? 5 : isVisit ? 1 : 0, appActiveDays: inactive ? 40 : isVisit ? 5 : 3,
    journeyStep: isVisit ? 0 : leader ? 8 : Math.min(8, Math.max(1, yr - sinceYr + 1)),
    scores, prayer: false, flags, assignedTo, status: 'aberto', lastTouchDays: 21, touches: [], derived: true,
  };
}
/* roster final = fichas de cuidado (com edições/toques) + membros reais ainda sem ficha */
function mergeCare(care, members, cells) {
  const list = (care || []).map((p) => ({ ...p }));
  const have = new Set(list.map((p) => norm(p.name)));
  (members || []).forEach((m) => { if (m && m.name && !have.has(norm(m.name))) { list.push(deriveFromMember(m, cells)); have.add(norm(m.name)); } });
  return list;
}

/* ============================================================
   Radar (perfil espiritual) — SVG puro
   ============================================================ */
function RadarChart({ axes, series, size = 232, max = 100 }) {
  const n = axes.length, cx = size / 2, cy = size / 2, R = size / 2 - 30;
  const ang = (i) => -Math.PI / 2 + (i * 2 * Math.PI) / n;
  const at = (i, r) => [cx + Math.cos(ang(i)) * r, cy + Math.sin(ang(i)) * r];
  const ringPts = (k) => axes.map((_, i) => at(i, R * k).map((v) => v.toFixed(1)).join(',')).join(' ');
  const seriesPts = (vals) => axes.map((a, i) => { const v = Math.max(0, Math.min(max, vals[a.key] ?? 0)) / max; return at(i, R * v).map((x) => x.toFixed(1)).join(','); }).join(' ');
  return (
    <svg className="radar" viewBox={`-16 -8 ${size + 32} ${size + 16}`} width={size} height={size}>
      {[0.25, 0.5, 0.75, 1].map((k) => <polygon key={k} className="radar-ring" points={ringPts(k)}/>)}
      {axes.map((a, i) => { const [x, y] = at(i, R); return <line key={a.key} className="radar-axis" x1={cx} y1={cy} x2={x} y2={y}/>; })}
      {series.map((s, si) => (
        <polygon key={si} points={seriesPts(s.values)} fill={s.fill || 'none'} fillOpacity={s.fillOpacity ?? 1}
          stroke={s.stroke} strokeWidth={s.width || 2} strokeLinejoin="round" strokeDasharray={s.dash || 'none'}/>
      ))}
      {axes.map((a, i) => {
        const [x, y] = at(i, R + 15);
        const anchor = Math.abs(x - cx) < 8 ? 'middle' : (x > cx ? 'start' : 'end');
        return <text key={a.key} className="radar-lab" x={x} y={y} textAnchor={anchor} dominantBaseline="middle">{a.short}</text>;
      })}
    </svg>
  );
}

/* ============================================================
   Perfil 360 (drawer) — radar + dimensões + trilha + histórico de toques
   ============================================================ */
function Profile360({ person, roster, journeySteps, onClose, onAddTouch, onSetStatus, onReassign, toast }) {
  const [channel, setChannel] = useStateCare('whatsapp');
  const [note, setNote] = useStateCare('');
  if (!person) return null;
  const p = person;
  const h = healthOf(p), risk = riskOf(p), flags = careFlags(p);
  const avg = churchAvg(roster);
  const steps = journeySteps || [];
  const stepName = steps[Math.min(p.journeyStep, steps.length - 1)] ? steps[Math.min(p.journeyStep, steps.length - 1)].name : '—';
  const jpct = steps.length ? Math.round(Math.min(p.journeyStep, steps.length) / steps.length * 100) : 0;

  const submit = () => {
    if (!note.trim()) { toast('Escreva uma nota sobre o contato'); return; }
    onAddTouch(p, { date: todayLabel(), by: window.ADMIN.church.admin.name, channel, note: note.trim() });
    setNote('');
    toast('Toque registrado ✓');
  };

  return (
    <div className="drawer-ov" onClick={onClose}>
      <aside className="drawer" onClick={(e) => e.stopPropagation()}>
        <div className="drawer-head">
          <div className="avatar lg">{p.initials}</div>
          <div style={{ minWidth: 0, flex: 1 }}>
            <div className="dh-name">{p.name}</div>
            <div className="dh-sub">{p.role} · {p.cell !== '—' ? `Célula ${p.cell}` : 'Sem célula'} · desde {p.joined}</div>
            <div className="row gap-8" style={{ marginTop: 8, flexWrap: 'wrap' }}>
              <Chip tone={risk.k} icon={risk.k === 'ok' ? 'check' : 'warning'}>{risk.label} · {h}/100</Chip>
              {p.status === 'cuidado_ok' && <Chip tone="ok" icon="check">Acompanhamento concluído</Chip>}
            </div>
          </div>
          <button className="iconbtn" onClick={onClose} aria-label="fechar"><Icon name="x" size={18}/></button>
        </div>

        <div className="drawer-body">
          {/* ações rápidas */}
          <div className="dh-actions">
            <button className="btn btn-primary btn-sm" onClick={() => toast('Abrindo conversa no WhatsApp…')}><Icon name="chat" size={15}/>WhatsApp</button>
            <div className="flex1">
              <select className="inp" value={p.assignedTo} onChange={(e) => { onReassign(p, e.target.value); toast(`Cuidado com ${e.target.value === '—' ? '— (a definir)' : e.target.value}`); }}>
                <option value="—">— Responsável —</option>
                {CARE_TEAM.map((c) => <option key={c} value={c}>{c}</option>)}
              </select>
            </div>
            <div className="flex1">
              <select className="inp" value={p.status} onChange={(e) => { onSetStatus(p, e.target.value); toast(e.target.value === 'cuidado_ok' ? 'Marcado como cuidado concluído ✓' : 'Status atualizado'); }}>
                <option value="aberto">Aberto</option>
                <option value="andamento">Em andamento</option>
                <option value="cuidado_ok">Cuidado concluído</option>
              </select>
            </div>
          </div>

          {/* motivos de cuidado */}
          {flags.length > 0 && (
            <div className="dsec">
              <div className="dsec-h">Motivos de cuidado</div>
              <div className="row gap-8" style={{ flexWrap: 'wrap' }}>
                {flags.map((f) => <Chip key={f} tone={FLAGS[f].tone} icon={FLAGS[f].icon}>{FLAGS[f].label(p)}</Chip>)}
              </div>
            </div>
          )}

          {/* perfil 360 — radar + dimensões */}
          <div className="dsec">
            <div className="dsec-h">Perfil espiritual 360°</div>
            <div className="p360">
              <div className="p360-radar">
                <RadarChart axes={DIMS} series={[
                  { values: avg, stroke: 'var(--muted)', dash: '4 4', width: 1.5 },
                  { values: p.scores, stroke: 'var(--accent)', fill: 'var(--accent-tint)', fillOpacity: 0.5, width: 2 },
                ]}/>
                <div className="radar-legend">
                  <span><i className="lg-dot member"/>{firstName(p.name)}</span>
                  <span><i className="lg-dot avg"/>Média da igreja</span>
                </div>
              </div>
              <div className="p360-dims">
                {DIMS.map((d) => {
                  const v = p.scores[d.key] || 0;
                  return (
                    <div className="dim-row" key={d.key}>
                      <div className="dim-top">
                        <span className="dim-lab"><Icon name={d.icon} size={14}/>{d.label}</span>
                        <span className="dim-val">{v}</span>
                      </div>
                      <div className="bar"><i style={{ width: v + '%' }}/></div>
                      <div className="dim-hint">{d.hint(v)}</div>
                    </div>
                  );
                })}
              </div>
            </div>
          </div>

          {/* posição na trilha */}
          <div className="dsec">
            <div className="dsec-h">Posição na trilha de discipulado</div>
            <div className="trilha-pos">
              <div className="row" style={{ justifyContent: 'space-between', marginBottom: 8 }}>
                <span className="tp-step"><Icon name="sparkle" size={14}/>{stepName}</span>
                <span className="muted" style={{ fontSize: 12.5 }}>{Math.min(p.journeyStep, steps.length)} de {steps.length} etapas · {jpct}%</span>
              </div>
              <div className="bar"><i style={{ width: jpct + '%' }}/></div>
            </div>
          </div>

          {/* histórico de cuidado */}
          <div className="dsec">
            <div className="dsec-h">Histórico de cuidado · {(p.touches || []).length}</div>
            <div className="touch-form">
              <div className="ch-toggle">
                {CHANNELS.map((c) => (
                  <button key={c.key} className={channel === c.key ? 'on' : ''} onClick={() => setChannel(c.key)} title={c.label}><Icon name={c.icon} size={14}/>{c.label}</button>
                ))}
              </div>
              <textarea className="inp" rows={2} placeholder="Como foi o contato? O que combinaram?" value={note} onChange={(e) => setNote(e.target.value)}/>
              <div className="row" style={{ justifyContent: 'flex-end' }}>
                <button className="btn btn-primary btn-sm" onClick={submit}><Icon name="plus" size={15}/>Registrar toque</button>
              </div>
            </div>
            <div className="touch-list">
              {(p.touches || []).length === 0 && <div className="muted" style={{ fontSize: 13, padding: '6px 0' }}>Nenhum toque registrado ainda. Seja o primeiro a alcançar {p.name.split(' ')[0]}.</div>}
              {(p.touches || []).map((t, i) => (
                <div className="touch-item" key={i}>
                  <span className="touch-ico"><Icon name={chMeta(t.channel).icon} size={14}/></span>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div className="touch-note">{t.note}</div>
                    <div className="touch-meta">{chMeta(t.channel).label} · {t.by} · {t.date}</div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </aside>
    </div>
  );
}

/* ============================================================
   Linha da lista de cuidado
   ============================================================ */
function CareRow({ p, onOpen }) {
  const flags = careFlags(p), risk = riskOf(p), h = healthOf(p);
  const shown = flags.slice(0, 3);
  return (
    <button className="care-row" onClick={() => onOpen(p.id)}>
      <div className="avatar sm">{p.initials}</div>
      <div className="care-id">
        <div className="care-name">{p.name}</div>
        <div className="care-meta">{p.role} · {p.cell !== '—' ? p.cell : 'sem célula'}</div>
      </div>
      <div className="care-flags">
        {shown.map((f) => <Chip key={f} tone={FLAGS[f].tone} icon={FLAGS[f].icon}>{FLAGS[f].label(p)}</Chip>)}
        {flags.length > 3 && <span className="muted" style={{ fontSize: 11.5 }}>+{flags.length - 3}</span>}
      </div>
      <div className="care-carer" title="Responsável pelo cuidado">
        {p.assignedTo && p.assignedTo !== '—'
          ? <><div className="avatar xs">{(p.assignedTo.replace(/^(Pr\.|Pra\.|Diác\.)\s*/, '').trim().split(/\s+/).map((w) => w[0]).slice(0, 2).join('').toUpperCase())}</div><span>{p.assignedTo.replace('Martins', '').trim()}</span></>
          : <span className="care-unassigned"><Icon name="warning" size={13}/>a definir</span>}
      </div>
      <div className={`care-touch ${p.lastTouchDays > 14 ? 'overdue' : ''}`}>
        {p.lastTouchDays === 0 ? 'hoje' : `há ${p.lastTouchDays}d`}
      </div>
      <span className={`st st-${risk.k === 'ok' ? 'ok' : risk.k === 'warn' ? 'pend' : 'danger'}`} style={risk.k === 'danger' ? { color: TONES.danger.fg, background: TONES.danger.bg } : null}>{h}</span>
      <Icon name="chevron" size={17} className="care-chev"/>
    </button>
  );
}

/* ============================================================
   Tela principal · Cuidado
   ============================================================ */
const CARE_FILTERS = [
  { key:'all',        label:'Todos' },
  { key:'prioridade', label:'Prioridade' },
  { key:'ausente',    label:'Ausentes' },
  { key:'novo',       label:'Novos' },
  { key:'sem_celula', label:'Sem célula' },
  { key:'oracao',     label:'Oração' },
  { key:'estagnado',  label:'Estagnados' },
  { key:'resolvido',  label:'Resolvidos' },
];

function CuidadoScreen({ care, setCare, members, cells, journeySteps, toast }) {
  const [tab, setTab] = useStateCare('lista');
  const [filter, setFilter] = useStateCare('all');
  const [q, setQ] = useStateCare('');
  const [openId, setOpenId] = useStateCare(null);

  // roster = fichas de cuidado (com toques/edições) + membros reais da Secretaria ainda sem ficha
  const roster = useMemoCare(() => mergeCare(care, members, cells), [care, members, cells]);
  // upsert: edita a ficha existente OU materializa o membro derivado ao primeiro toque/edição
  const upsert = (person, fn) => setCare((rs) => {
    const i = rs.findIndex((p) => p.id === person.id);
    return i >= 0 ? rs.map((p) => p.id === person.id ? fn(p) : p) : [...rs, fn({ ...person, derived: undefined })];
  });
  const addTouch = (person, t) => upsert(person, (p) => ({ ...p, touches: [t, ...(p.touches || [])], lastTouchDays: 0, status: p.status === 'aberto' ? 'andamento' : p.status }));
  const setStatus = (person, status) => upsert(person, (p) => ({ ...p, status }));
  const reassign = (person, who) => upsert(person, (p) => ({ ...p, assignedTo: who }));

  const stats = useMemoCare(() => careStats(roster, (journeySteps || []).length), [roster, journeySteps]);

  const careList = useMemoCare(() => roster.filter(needsCare).sort((a, b) => priorityOf(b) - priorityOf(a)), [roster]);
  const visible = useMemoCare(() => {
    let list = filter === 'resolvido' ? roster.filter((p) => p.status === 'cuidado_ok') : careList;
    if (filter === 'prioridade') list = list.filter((p) => riskOf(p).k === 'danger');
    else if (['ausente', 'novo', 'sem_celula', 'oracao', 'estagnado'].includes(filter)) list = list.filter((p) => careFlags(p).includes(filter));
    if (q.trim()) { const s = q.toLowerCase(); list = list.filter((p) => (p.name + p.role + p.cell + p.assignedTo).toLowerCase().includes(s)); }
    return list;
  }, [careList, roster, filter, q]);

  const openPerson = openId ? roster.find((p) => p.id === openId) : null;

  return (
    <div className="awrap">
      <div className="lead-tabs" style={{ marginBottom: 18 }}>
        <button className={`lead-tab ${tab === 'lista' ? 'active' : ''}`} onClick={() => setTab('lista')}>Lista de cuidado · {stats.care}</button>
        <button className={`lead-tab ${tab === 'lideres' ? 'active' : ''}`} onClick={() => setTab('lideres')}>Por líder</button>
        <button className={`lead-tab ${tab === 'segmentos' ? 'active' : ''}`} onClick={() => setTab('segmentos')}>Segmentos</button>
        <button className={`lead-tab ${tab === 'saude' ? 'active' : ''}`} onClick={() => setTab('saude')}>Saúde &amp; Automação</button>
      </div>

      {tab === 'lista' && <ListaTab stats={stats} filter={filter} setFilter={setFilter} q={q} setQ={setQ} visible={visible} onOpen={setOpenId}/>}
      {tab === 'lideres' && <LideresTab careList={careList} stats={stats} onOpen={setOpenId} onReassign={(person, who) => { reassign(person, who); toast(`Reatribuído para ${who === '—' ? '— (a definir)' : who}`); }}/>}
      {tab === 'segmentos' && <SegmentosTab roster={roster} onOpen={setOpenId}/>}
      {tab === 'saude' && <SaudeTab roster={roster} stats={stats} journeySteps={journeySteps} toast={toast}/>}

      {openPerson && (
        <Profile360 person={openPerson} roster={roster} journeySteps={journeySteps}
          onClose={() => setOpenId(null)} onAddTouch={addTouch} onSetStatus={setStatus} onReassign={reassign} toast={toast}/>
      )}
    </div>
  );
}

/* ---------- aba: Lista de cuidado ---------- */
function ListaTab({ stats, filter, setFilter, q, setQ, visible, onOpen }) {
  return (
    <>
      <div className="kpi-grid">
        <div className="kpi"><div className="kpi-value">{stats.care}</div><div className="kpi-label">Pessoas em cuidado</div></div>
        <div className="kpi"><div className="kpi-value" style={{ color: stats.overdue ? TONES.danger.fg : null }}>{stats.overdue}</div><div className="kpi-label">Sem toque há +14 dias</div></div>
        <div className="kpi"><div className="kpi-value" style={{ color: stats.unassigned ? TONES.warn.fg : null }}>{stats.unassigned}</div><div className="kpi-label">Sem responsável</div></div>
        <div className="kpi"><div className="kpi-value" style={{ color: 'var(--accent-strong)' }}>{stats.resolvedMonth}</div><div className="kpi-label">Resolvidos no mês</div></div>
      </div>

      <Panel pad={false} title="Quem precisa de um toque" sub="Ordenado por prioridade. Clique numa pessoa para abrir o Perfil 360 e registrar o cuidado.">
        <div className="panel-pad" style={{ paddingBottom: 0 }}>
          <div className="searchbox" style={{ display: 'flex' }}>
            <Icon name="search" size={15}/><input placeholder="Buscar pessoa, célula, líder…" value={q} onChange={(e) => setQ(e.target.value)}/>
          </div>
        </div>
        <div className="care-filters">
          {CARE_FILTERS.map((f) => (
            <button key={f.key} className={`care-fchip ${filter === f.key ? 'on' : ''}`} onClick={() => setFilter(f.key)}>{f.label}</button>
          ))}
        </div>
        <div className="care-rows">
          {visible.map((p) => <CareRow key={p.id} p={p} onOpen={onOpen}/>)}
          {visible.length === 0 && (
            <div className="lrow" style={{ justifyContent: 'center', color: 'var(--muted)', padding: '28px 0' }}>
              <Icon name="check" size={18}/> Ninguém neste filtro. Rebanho cuidado!
            </div>
          )}
        </div>
      </Panel>
    </>
  );
}

/* ---------- aba: Cuidado por líder ---------- */
function LideresTab({ careList, stats, onOpen, onReassign }) {
  const groups = useMemoCare(() => {
    const map = {};
    careList.forEach((p) => { const k = p.assignedTo && p.assignedTo !== '—' ? p.assignedTo : '— A definir'; (map[k] = map[k] || []).push(p); });
    return Object.entries(map).sort((a, b) => (a[0] === '— A definir' ? -1 : b[0] === '— A definir' ? 1 : b[1].length - a[1].length));
  }, [careList]);
  const ratio = stats.care && CARE_TEAM.length ? (stats.care / CARE_TEAM.length).toFixed(1) : '0';

  return (
    <>
      <div className="panel" style={{ marginBottom: 18 }}>
        <div className="panel-pad" style={{ display: 'flex', gap: 28, flexWrap: 'wrap', alignItems: 'center' }}>
          <div className="clib-stat"><div className="n" style={{ fontSize: 22 }}>{CARE_TEAM.length}</div><div className="l">cuidadores ativos</div></div>
          <div className="clib-stat"><div className="n" style={{ fontSize: 22 }}>{ratio}</div><div className="l">pessoas por cuidador</div></div>
          <div className="clib-stat"><div className="n" style={{ fontSize: 22, color: stats.unassigned ? TONES.warn.fg : null }}>{stats.unassigned}</div><div className="l">aguardando responsável</div></div>
          <div style={{ flex: 1 }}/>
          <span className="muted" style={{ fontSize: 12.5, maxWidth: 260 }}><Icon name="users" size={14} style={{ verticalAlign: -2 }}/> Distribua o rebanho para que ninguém fique sem acompanhamento.</span>
        </div>
      </div>

      <div className="carer-grid">
        {groups.map(([leader, people]) => {
          const overdue = people.filter((p) => p.lastTouchDays > 14).length;
          const unassigned = leader === '— A definir';
          return (
            <div className={`panel carer-card ${unassigned ? 'warn' : ''}`} key={leader}>
              <div className="carer-head">
                <div className={`avatar sm ${unassigned ? '' : ''}`}>{unassigned ? '?' : leader.replace(/^(Pr\.|Pra\.|Diác\.)\s*/, '').trim().split(/\s+/).map((w) => w[0]).slice(0, 2).join('').toUpperCase()}</div>
                <div style={{ minWidth: 0, flex: 1 }}>
                  <div className="carer-name">{unassigned ? 'Sem responsável' : leader}</div>
                  <div className="carer-sub">{people.length} {people.length === 1 ? 'pessoa' : 'pessoas'}{overdue > 0 && <span style={{ color: TONES.danger.fg }}> · {overdue} em atraso</span>}</div>
                </div>
              </div>
              <div className="carer-people">
                {people.map((p) => (
                  <div className="carer-row" key={p.id}>
                    <button className="carer-person" onClick={() => onOpen(p.id)}>
                      <div className="avatar xs">{p.initials}</div>
                      <span className="nm">{p.name}</span>
                      <span className={`care-touch ${p.lastTouchDays > 14 ? 'overdue' : ''}`}>{p.lastTouchDays === 0 ? 'hoje' : `há ${p.lastTouchDays}d`}</span>
                    </button>
                    <select className="carer-assign" value={p.assignedTo} onChange={(e) => onReassign(p, e.target.value)} title="Reatribuir">
                      <option value="—">—</option>
                      {CARE_TEAM.map((c) => <option key={c} value={c}>{c.replace(/^(Pr\.|Pra\.|Diác\.)\s*/, '')}</option>)}
                    </select>
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
}

/* ---------- aba: Segmentos ---------- */
function SegmentosTab({ roster, onOpen }) {
  return (
    <div className="seg-grid">
      {SEGMENTS.map((seg) => {
        const people = roster.filter(seg.test);
        const t = TONES[seg.tone];
        return (
          <div className="panel seg-card" key={seg.id}>
            <div className="seg-head">
              <span className="seg-ico" style={{ color: t.fg, background: t.bg }}><Icon name={seg.icon} size={17}/></span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="seg-name">{seg.label}</div>
                <div className="seg-desc">{seg.desc}</div>
              </div>
              <span className="seg-count" style={{ color: t.fg, background: t.bg }}>{people.length}</span>
            </div>
            <div className="seg-people">
              {people.slice(0, 8).map((p) => (
                <button key={p.id} className="seg-chip" onClick={() => onOpen(p.id)} title={p.name}>
                  <div className="avatar xs">{p.initials}</div><span>{firstName(p.name)}</span>
                </button>
              ))}
              {people.length > 8 && <span className="seg-more">+{people.length - 8}</span>}
              {people.length === 0 && <span className="muted" style={{ fontSize: 12.5 }}>Ninguém neste segmento agora.</span>}
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ---------- aba: Saúde da igreja & Automação ---------- */
function SaudeTab({ roster, stats, journeySteps, toast }) {
  const [rules, setRules] = useStateCare(() => {
    try { const v = localStorage.getItem('devonew_care_rules'); return v ? JSON.parse(v) : { ...window.ADMIN.careRulesSeed }; } catch { return { ...window.ADMIN.careRulesSeed }; }
  });
  const toggleRule = (id) => setRules((r) => { const next = { ...r, [id]: !r[id] }; try { localStorage.setItem('devonew_care_rules', JSON.stringify(next)); } catch {} return next; });
  const hs = window.ADMIN.careHealthSeed;
  const activeRules = CARE_RULES.filter((r) => rules[r.id]).length;
  const queued = CARE_RULES.filter((r) => rules[r.id]).reduce((s, r) => s + r.count(roster), 0);
  const retDelta = stats.retention - hs.retentionTrend[0];

  return (
    <>
      {/* KPIs de saúde */}
      <div className="kpi-grid">
        <div className="kpi"><div className="kpi-ico"><Icon name="heart" size={20}/></div><div className="kpi-value">{stats.retention}%</div><div className="kpi-label">Retenção (ativos 30d)</div><div className="kpi-delta" style={retDelta < 0 ? { color: 'oklch(0.55 0.14 35)' } : null}><Icon name="trending" size={13}/>{retDelta >= 0 ? `+${retDelta}` : retDelta} no trimestre</div></div>
        <div className="kpi"><div className="kpi-ico"><Icon name="sparkle" size={20}/></div><div className="kpi-value">{stats.velocity > 0 ? stats.velocity : '—'}{stats.velocity > 0 && <span style={{ fontSize: 15, fontWeight: 500 }}> dias</span>}</div><div className="kpi-label">Velocidade de discipulado</div><div className="kpi-delta" style={{ color: 'var(--muted)' }}>por etapa da trilha</div></div>
        <div className="kpi"><div className="kpi-ico"><Icon name="activity" size={20}/></div><div className="kpi-value">{stats.engagement}%</div><div className="kpi-label">Engajamento no app (7d)</div></div>
        <div className="kpi"><div className="kpi-ico"><Icon name="shield" size={20}/></div><div className="kpi-value" style={{ color: stats.coverage >= 80 ? 'var(--accent-strong)' : TONES.warn.fg }}>{stats.coverage}%</div><div className="kpi-label">Cobertura de cuidado</div></div>
      </div>

      <div className="cols c-2b">
        <Panel title="Retenção da igreja" sub="Membros ativos · últimas 12 semanas">
          <AreaChart data={hs.retentionTrend}/>
          <div className="chart-x"><span>12 sem.</span><span>9</span><span>6</span><span>3</span><span>agora</span></div>
          <p className="muted" style={{ fontSize: 12.5, marginTop: 10 }}>Retenção é o coração da saúde: cuidar bem retém mais do que atrair.</p>
        </Panel>

        <Panel title="Velocidade de discipulado" sub="Tempo médio para avançar na trilha">
          <div className="velo-big">
            <div className="velo-num">{stats.velocity > 0 ? stats.velocity : '—'}<span>dias / etapa</span></div>
            <p className="muted" style={{ fontSize: 13 }}>{stats.velocity > 0
              ? <>No ritmo atual, um novo convertido percorre as {(journeySteps || []).length} etapas em <b style={{ color: 'var(--ink)' }}>~{stats.monthsToFinish} meses</b>.</>
              : <>Assim que os primeiros membros avançarem na trilha, o ritmo aparece aqui.</>}</p>
          </div>
          <div className="velo-gaps">
            {(() => { const maxGap = Math.max(...hs.velocityGaps.map((g) => g.days)); return hs.velocityGaps.map((g) => {
              const w = Math.max(8, Math.round(g.days / maxGap * 100));
              return (
                <div className="velo-row" key={g.from}>
                  <span className="velo-lab">{g.from}</span>
                  <div className="bar" style={{ flex: 1 }}><i style={{ width: w + '%' }}/></div>
                  <span className="velo-d">{g.days}d</span>
                </div>
              );
            }); })()}
          </div>
        </Panel>
      </div>

      {/* perfil espiritual médio + automações */}
      <div className="cols c-2">
        <Panel title="Perfil espiritual médio" sub="Média da congregação nas 6 dimensões">
          <div className="p360-radar" style={{ alignItems: 'center' }}>
            <RadarChart axes={DIMS} series={[{ values: churchAvg(roster), stroke: 'var(--accent)', fill: 'var(--accent-tint)', fillOpacity: 0.5, width: 2 }]}/>
            <div className="row gap-8" style={{ justifyContent: 'center', marginTop: 4 }}>
              <Chip tone="accent" icon="heart">Saúde média {stats.avgHealth}/100</Chip>
            </div>
          </div>
        </Panel>

        <div>
          <div className="sec-h" style={{ marginTop: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <span>Automações de cuidado</span>
            <span className="muted" style={{ fontSize: 12.5, fontWeight: 400 }}>{activeRules} ativas · {queued} pessoas na fila</span>
          </div>
          <div className="rule-list">
            {CARE_RULES.map((r) => {
              const on = !!rules[r.id], n = r.count(roster);
              return (
                <div className={`rule-card ${on ? 'on' : ''}`} key={r.id}>
                  <span className="rule-ico"><Icon name={r.icon} size={17}/></span>
                  <div className="rule-main">
                    <div className="rule-name">{r.name} {n > 0 && <span className="rule-count">{n} agora</span>}</div>
                    <div className="rule-trigger"><b>Quando:</b> {r.trigger}</div>
                    <div className="rule-action">{r.action}</div>
                    {on && n > 0 && <button className="rule-run" onClick={() => toast(`“${r.name}” aplicada a ${n} ${n === 1 ? 'pessoa' : 'pessoas'} ✓`)}><Icon name="megaphone" size={13}/>Executar agora</button>}
                  </div>
                  <button className={`swt ${on ? 'on' : ''}`} role="switch" aria-checked={on} aria-label={r.name} onClick={() => toggleRule(r.id)}><i/></button>
                </div>
              );
            })}
          </div>
          <p className="muted" style={{ fontSize: 12, marginTop: 12 }}>
            <Icon name="activity" size={13} style={{ verticalAlign: -2 }}/> Dados ilustrativos. Numa versão com backend, as automações disparam tarefas e mensagens reais.
          </p>
        </div>
      </div>
    </>
  );
}

Object.assign(window, { CuidadoScreen, RadarChart, Profile360, careStats, healthOf, careFlags, careNeedsCare: needsCare, careRoster: mergeCare });
