import React, { useState, useEffect, useMemo, useRef, Fragment } from 'react';
import { createRoot } from 'react-dom/client';
import {
  Plus, Trash2, ChevronLeft, ChevronRight, ChevronDown, ChevronUp, TrendingUp, TrendingDown,
  Wallet, BarChart3, Megaphone, Check, X, Receipt, Zap, Loader2, RefreshCw,
  PieChart, Users, Percent, Sparkles, Pencil, Package, Truck, Award, Calendar,
  Save, Download, Upload,
} from 'https://esm.sh/lucide-react@0.468.0?external=react';

/* ---------- helpers ---------- */
const brl = (n) => new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(Number(n) || 0);
const num = (n, d = 1) => new Intl.NumberFormat('pt-BR', { minimumFractionDigits: d, maximumFractionDigits: d }).format(Number(n) || 0);
const pct = (n) => new Intl.NumberFormat('pt-BR', { style: 'percent', minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(Number(n) || 0);
const parseBRL = (s) => {
  if (typeof s === 'number') return s;
  if (!s) return 0;
  let t = String(s).trim().replace(/[^\d.,-]/g, '');
  if (t.includes('.') && t.includes(',')) t = t.replace(/\./g, '').replace(',', '.');
  else if (t.includes(',')) t = t.replace(',', '.');
  const v = parseFloat(t);
  return isNaN(v) ? 0 : v;
};
const MESES = ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'];
const monthLabel = (ym) => { const [y, m] = ym.split('-').map(Number); return `${MESES[m - 1]} ${y}`; };
const shiftMonth = (ym, d) => { let [y, m] = ym.split('-').map(Number); m += d; while (m < 1) { m += 12; y--; } while (m > 12) { m -= 12; y++; } return `${y}-${String(m).padStart(2, '0')}`; };
const lastDay = (ym) => { const [y, m] = ym.split('-').map(Number); return String(new Date(y, m, 0).getDate()).padStart(2, '0'); };
const todayISO = () => { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; };
const currentMonth = () => todayISO().slice(0, 7);
const dISO = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
const brDate = (iso) => iso ? `${iso.slice(8, 10)}/${iso.slice(5, 7)}/${iso.slice(0, 4)}` : '';
const uid = () => Math.random().toString(36).slice(2, 10);
const norm = (s) => (s || '').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/\s+/g, ' ').trim();
const mesesEntre = (from, to) => {
  const out = []; let cur = from.slice(0, 7); const end = to.slice(0, 7);
  let guard = 0;
  while (cur <= end && guard < 240) { out.push(cur); cur = shiftMonth(cur, 1); guard++; }
  return out;
};

const LOJAS_SUGERIDAS = ['Essenza Estofados', 'Luna Comfort', 'Empório Sofás'];
const PLATAFORMAS = ['Instagram', 'Facebook', 'WhatsApp', 'Outro'];
const ORIGENS = ['Indicação', 'Cliente antigo', 'Passou na loja', 'Outro'];
const ADX = '__ad_nao_rastreado__';
const ORG = '__organico__';
const DEFAULT_SEC = ['desempenho', 'ajustes', 'windsor', 'comparativo', 'vendas', 'campanhas'];

/* ---------- storage ---------- */
const KEY = 'cpa_whatsapp_v2';
const OLDKEY = 'cpa_whatsapp_v1';
async function readKey(k) {
  try {
    if (typeof window === 'undefined' || !window.localStorage) return null;
    const raw = window.localStorage.getItem(k);
    return raw ? JSON.parse(raw) : null;
  } catch { return null; }
}
const mergeById = (a, b) => { const m = new Map(); [...(b || []), ...(a || [])].forEach((it) => { if (it && it.id) m.set(it.id, it); }); return [...m.values()]; };
const mergeGastos = (a, b) => {
  const m = new Map();
  [...(b || []), ...(a || [])].forEach((g) => {
    if (!g || !g.campanhaId) return;
    const periodo = g.date || g.mes;
    if (!periodo) return;
    m.set(`${g.campanhaId}|${periodo}`, g);
  });
  return [...m.values()];
};
async function loadData() {
  const v2 = await readKey(KEY);
  const v1 = await readKey(OLDKEY);
  if (!v2 && !v1) return null;
  const a = v2 || {}, b = v1 || {};
  return {
    campanhas: mergeById(a.campanhas, b.campanhas),
    gastos: mergeGastos(a.gastos, b.gastos),
    vendas: mergeById(a.vendas, b.vendas),
    modelos: mergeById(a.modelos, b.modelos),
    config: a.config || b.config || { impostoAdPct: 0 },
  };
}
async function saveData(data) {
  try {
    if (typeof window === 'undefined' || !window.localStorage) return;
    window.localStorage.setItem(KEY, JSON.stringify(data));
  } catch (e) { console.error('Erro ao salvar:', e); }
}

function App() {
  const [campanhas, setCampanhas] = useState([]);
  const [gastos, setGastos] = useState([]);
  const [vendas, setVendas] = useState([]);
  const [modelos, setModelos] = useState([]);
  const [config, setConfig] = useState({ impostoAdPct: 0 });
  const [loaded, setLoaded] = useState(false);

  const [periodo, setPeriodo] = useState({ tipo: 'mes', mesRef: currentMonth(), from: todayISO(), to: todayISO() });
  const [lojaFiltro, setLojaFiltro] = useState('todas');
  const [aba, setAba] = useState('anuncio');
  const [expandedCamp, setExpandedCamp] = useState(null);
  const [ordenacao, setOrdenacao] = useState('lucro'); // 'lucro' | 'manual'
  const dragCampIdx = useRef(null);
  const dragSecKey = useRef(null);

  const [vData, setVData] = useState(todayISO());
  const [vCampanha, setVCampanha] = useState('');
  const [vOrigem, setVOrigem] = useState(ORIGENS[0]);
  const [vModelo, setVModelo] = useState('');
  const [vCliente, setVCliente] = useState('');
  const [vReceita, setVReceita] = useState('');
  const [vCusto, setVCusto] = useState('');
  const [vFrete, setVFrete] = useState('');

  const [cNome, setCNome] = useState('');
  const [cLoja, setCLoja] = useState('');
  const [cPlataforma, setCPlataforma] = useState('Instagram');

  const [mNome, setMNome] = useState('');
  const [mPreco, setMPreco] = useState('');
  const [mCusto, setMCusto] = useState('');
  const [mFrete, setMFrete] = useState('');
  const [mFornecedor, setMFornecedor] = useState('');
  const [editModelo, setEditModelo] = useState(null);

  const [confirmDel, setConfirmDel] = useState(null);
  const [mergePending, setMergePending] = useState(null); // { from, to }
  const [editId, setEditId] = useState(null);
  const [editDraft, setEditDraft] = useState(null);

  const [fetchingMeta, setFetchingMeta] = useState(false);
  const [metaRows, setMetaRows] = useState([]);   // [{campanha, gastoTotal, mapId}]
  const [metaDetail, setMetaDetail] = useState([]); // [{campanha, mes, gasto}]
  const [metaError, setMetaError] = useState('');
  const [metaPaste, setMetaPaste] = useState('');
  const [metaMsg, setMetaMsg] = useState('');
  const [backupMsg, setBackupMsg] = useState('');

  useEffect(() => {
    (async () => {
      const d = await loadData();
      if (d) {
        setCampanhas(d.campanhas || []); setGastos(d.gastos || []); setVendas(d.vendas || []);
        setModelos(d.modelos || []); setConfig(d.config || { impostoAdPct: 0 });
      }
      setLoaded(true);
    })();
  }, []);
  useEffect(() => { if (loaded) saveData({ campanhas, gastos, vendas, modelos, config }); }, [campanhas, gastos, vendas, modelos, config, loaded]);

  /* ---------- período ---------- */
  const per = useMemo(() => {
    const p = periodo; const now = new Date();
    if (p.tipo === 'mes') return { from: `${p.mesRef}-01`, to: `${p.mesRef}-${lastDay(p.mesRef)}`, label: monthLabel(p.mesRef) };
    if (p.tipo === 'mes_passado') { const mr = shiftMonth(currentMonth(), -1); return { from: `${mr}-01`, to: `${mr}-${lastDay(mr)}`, label: monthLabel(mr) }; }
    if (p.tipo === 'ano') { const y = now.getFullYear(); return { from: `${y}-01-01`, to: `${y}-12-31`, label: `Ano de ${y}` }; }
    if (p.tipo === 'custom') return { from: p.from, to: p.to, label: `${brDate(p.from)} – ${brDate(p.to)}` };
    return { from: `${currentMonth()}-01`, to: `${currentMonth()}-${lastDay(currentMonth())}`, label: monthLabel(currentMonth()) };
  }, [periodo]);
  const mesesPeriodo = useMemo(() => mesesEntre(per.from, per.to), [per]);
  const mesUnico = per.from.slice(0, 7) === per.to.slice(0, 7) ? per.from.slice(0, 7) : null;
  const mesRefAtual = periodo.tipo === 'mes' ? periodo.mesRef : currentMonth();
  const shiftPeriodo = (delta) => setPeriodo({ ...periodo, tipo: 'mes', mesRef: shiftMonth(mesRefAtual, delta) });

  const impPct = Number(config.impostoAdPct) || 0;
  const comImp = (g) => g * (1 + impPct / 100);

  /* ---------- ações ---------- */
  const dailyMonths = useMemo(() => { const s = new Set(); for (const g of gastos) if (g.date) s.add(g.date.slice(0, 7)); return s; }, [gastos]);
  const getGastoMes = (cid, m) => {
    if (dailyMonths.has(m)) return gastos.filter((g) => g.campanhaId === cid && g.date && g.date.slice(0, 7) === m).reduce((s, g) => s + g.valor, 0);
    return gastos.filter((g) => g.campanhaId === cid && g.mes === m).reduce((s, g) => s + g.valor, 0);
  };
  const getGastoPeriodo = (cid) => {
    let sum = 0;
    for (const g of gastos) {
      if (g.campanhaId !== cid) continue;
      if (g.date) { if (g.date >= per.from && g.date <= per.to) sum += g.valor; }
      else if (g.mes && !dailyMonths.has(g.mes)) { const ms = `${g.mes}-01`, me = `${g.mes}-${lastDay(g.mes)}`; if (per.from <= me && per.to >= ms) sum += g.valor; }
    }
    return sum;
  };
  const upsertGasto = (cid, m, valor) => setGastos((prev) => {
    const rest = prev.filter((g) => !(g.campanhaId === cid && (g.mes === m || (g.date && g.date.slice(0, 7) === m))));
    return valor > 0 ? [...rest, { campanhaId: cid, mes: m, valor }] : rest;
  });

  const isOrg = vCampanha === ORG;
  const onModelo = (id) => {
    setVModelo(id);
    const m = modelos.find((x) => x.id === id);
    if (m) { setVReceita(m.preco ? String(m.preco) : ''); setVCusto(m.custo ? String(m.custo) : ''); setVFrete(m.frete ? String(m.frete) : ''); }
  };
  const addVenda = () => {
    const receita = parseBRL(vReceita);
    if (!vCampanha || receita <= 0) return;
    const base = { id: uid(), data: vData, cliente: vCliente.trim(), receita, custo: parseBRL(vCusto), frete: parseBRL(vFrete), modeloId: vModelo || null };
    let nova;
    if (vCampanha === ORG) nova = { ...base, campanhaId: ORG, origem: vOrigem };
    else if (vCampanha === ADX) nova = { ...base, campanhaId: ADX };
    else nova = { ...base, campanhaId: vCampanha };
    setVendas((p) => [...p, nova]);
    setVCliente(''); setVReceita(''); setVCusto(''); setVFrete(''); setVModelo('');
  };
  const addCampanha = () => {
    if (!cNome.trim()) return;
    setCampanhas((p) => [...p, { id: uid(), nome: cNome.trim(), loja: cLoja.trim(), plataforma: cPlataforma }]);
    setCNome(''); setCLoja('');
  };
  const delVenda = (id) => setVendas((p) => p.filter((v) => v.id !== id));
  const delCampanha = (id) => {
    setCampanhas((p) => p.filter((c) => c.id !== id));
    setGastos((p) => p.filter((g) => g.campanhaId !== id));
    setVendas((p) => p.filter((v) => v.campanhaId !== id));
    if (vCampanha === id) setVCampanha('');
  };
  const mergeCampanha = (fromId, toId) => {
    if (!fromId || !toId || fromId === toId) { setMergePending(null); return; }
    setGastos((prev) => {
      const reassigned = prev.map((g) => (g.campanhaId === fromId ? { ...g, campanhaId: toId } : g));
      const map = new Map();
      reassigned.forEach((g) => {
        const k = `${g.campanhaId}|${g.date || g.mes}`;
        if (map.has(k)) map.get(k).valor += g.valor;
        else map.set(k, { ...g });
      });
      return [...map.values()];
    });
    setVendas((prev) => prev.map((v) => (v.campanhaId === fromId ? { ...v, campanhaId: toId } : v)));
    setCampanhas((prev) => prev.filter((c) => c.id !== fromId));
    if (vCampanha === fromId) setVCampanha(toId);
    setMergePending(null);
  };

  const salvarModelo = () => {
    if (!mNome.trim()) return;
    const rec = { nome: mNome.trim(), preco: parseBRL(mPreco), custo: parseBRL(mCusto), frete: parseBRL(mFrete), fornecedor: mFornecedor.trim() };
    if (editModelo) setModelos((p) => p.map((m) => (m.id === editModelo ? { ...m, ...rec } : m)));
    else setModelos((p) => [...p, { id: uid(), ...rec }]);
    setMNome(''); setMPreco(''); setMCusto(''); setMFrete(''); setMFornecedor(''); setEditModelo(null);
  };
  const startEditModelo = (m) => { setEditModelo(m.id); setMNome(m.nome); setMPreco(m.preco ? String(m.preco) : ''); setMCusto(m.custo ? String(m.custo) : ''); setMFrete(m.frete ? String(m.frete) : ''); setMFornecedor(m.fornecedor || ''); };
  const delModelo = (id) => { setModelos((p) => p.filter((m) => m.id !== id)); setVendas((p) => p.map((v) => (v.modeloId === id ? { ...v, modeloId: null } : v))); };

  const exportBackup = () => {
    try {
      const dump = { app: 'metricas-campanhas-whatsapp', versao: 2, exportadoEm: new Date().toISOString(), campanhas, gastos, vendas, modelos, config };
      const blob = new Blob([JSON.stringify(dump, null, 2)], { type: 'application/json' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url; a.download = `metricas-backup-${todayISO()}.json`;
      document.body.appendChild(a); a.click(); document.body.removeChild(a);
      URL.revokeObjectURL(url);
      setBackupMsg('Backup baixado ✓');
    } catch { setBackupMsg('Não consegui gerar o backup.'); }
  };
  const importBackup = (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => {
      try {
        const d = JSON.parse(String(reader.result));
        setCampanhas(mergeById(d.campanhas, campanhas));
        setGastos(mergeGastos(d.gastos, gastos));
        setVendas(mergeById(d.vendas, vendas));
        setModelos(mergeById(d.modelos, modelos));
        if (d.config) setConfig(d.config);
        setBackupMsg('Backup restaurado e mesclado ✓');
      } catch { setBackupMsg('Arquivo inválido — não consegui ler o backup.'); }
    };
    reader.readAsText(file);
    e.target.value = '';
  };

  const startEdit = (v) => { setEditId(v.id); setEditDraft({ data: v.data || todayISO(), tipo: v.campanhaId, origem: v.origem || ORIGENS[0], modeloId: v.modeloId || '', cliente: v.cliente || '', receita: String(v.receita ?? ''), custo: String(v.custo ?? ''), frete: String(v.frete ?? '') }); };
  const cancelEdit = () => { setEditId(null); setEditDraft(null); };
  const saveEdit = () => {
    if (!editDraft) return;
    const receita = parseBRL(editDraft.receita);
    if (receita <= 0) return;
    setVendas((p) => p.map((v) => {
      if (v.id !== editId) return v;
      const base = { id: v.id, data: editDraft.data, cliente: editDraft.cliente.trim(), receita, custo: parseBRL(editDraft.custo), frete: parseBRL(editDraft.frete), modeloId: editDraft.modeloId || null };
      if (editDraft.tipo === ORG) return { ...base, campanhaId: ORG, origem: editDraft.origem };
      if (editDraft.tipo === ADX) return { ...base, campanhaId: ADX };
      return { ...base, campanhaId: editDraft.tipo };
    }));
    cancelEdit();
  };

  /* ---------- Windsor.ai ---------- */
  const autoMatch = (name) => {
    const n = norm(name);
    if (!n) return '';
    const exact = campanhas.find((c) => norm(c.nome) === n);
    if (exact) return exact.id;
    const part = campanhas.find((c) => norm(c.nome) && (n.includes(norm(c.nome)) || norm(c.nome).includes(n)));
    return part ? part.id : '';
  };
  const loadMetaArray = (arr) => {
    if (!Array.isArray(arr) || arr.length === 0) { setMetaError('Nenhum dado válido encontrado.'); return false; }
    const detail = arr.map((r) => ({ campanha: String(r.campanha ?? r.campaign ?? '—'), date: String(r.data ?? r.date ?? '').slice(0, 10), gasto: parseBRL(r.gasto ?? r.spend ?? 0) })).filter((d) => d.gasto > 0 && d.date.length === 10);
    if (detail.length === 0) { setMetaError('Nenhum registro válido (esperado: campanha, data YYYY-MM-DD e gasto).'); return false; }
    const byName = {};
    detail.forEach((d) => { byName[d.campanha] = (byName[d.campanha] || 0) + d.gasto; });
    setMetaError(''); setMetaMsg('');
    setMetaDetail(detail);
    setMetaRows(Object.keys(byName).map((nome) => ({ campanha: nome, gastoTotal: byName[nome], mapId: autoMatch(nome) || '__new__' })));
    return true;
  };
  const carregarColado = () => {
    setMetaMsg('');
    try {
      const t = (metaPaste || '').trim();
      const a = t.indexOf('['), b = t.lastIndexOf(']');
      if (a === -1 || b === -1) throw new Error('sem json');
      const arr = JSON.parse(t.slice(a, b + 1));
      if (loadMetaArray(arr)) setMetaPaste('');
    } catch { setMetaError('Não consegui ler o texto colado. Cole o JSON exatamente como recebeu.'); }
  };
  const fetchMeta = async () => {
    setFetchingMeta(true); setMetaError(''); setMetaMsg(''); setMetaRows([]); setMetaDetail([]);
    try {
      const qs = new URLSearchParams({ from: per.from, to: per.to });
      const res = await fetch(`/api/windsor-meta.php?${qs.toString()}`, { headers: { Accept: 'application/json' } });
      const payload = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(payload.error || `Falha HTTP ${res.status}`);
      const arr = Array.isArray(payload) ? payload : (payload.data || []);
      if (!Array.isArray(arr) || arr.length === 0) {
        setMetaError('Nenhum gasto retornado para este período. Confirme no Windsor.ai se a conta do Meta está conectada e com dados nas datas escolhidas.');
      } else {
        loadMetaArray(arr);
      }
    } catch (e) {
      setMetaError(e?.message || 'Não consegui puxar do Windsor.ai agora. Use a opção de colar o gasto abaixo ou tente novamente.');
    } finally { setFetchingMeta(false); }
  };

  const applyMeta = () => {
    let newCamps = [...campanhas];
    const nameToCid = {};
    metaRows.forEach((r) => {
      let cid = r.mapId; if (!cid) { nameToCid[r.campanha] = null; return; }
      if (cid === '__new__') { cid = uid(); newCamps.push({ id: cid, nome: r.campanha, loja: lojaFiltro !== 'todas' ? lojaFiltro : '', plataforma: 'Facebook' }); }
      nameToCid[r.campanha] = cid;
    });
    const touched = new Set(Object.values(nameToCid).filter(Boolean));
    const mesesPuxados = new Set(metaDetail.map((d) => d.date.slice(0, 7)));
    // remove registros antigos (diários no intervalo ou mensais legado dos meses puxados) das campanhas atualizadas
    let newGastos = gastos.filter((g) => {
      if (!touched.has(g.campanhaId)) return true;
      if (g.date && g.date >= per.from && g.date <= per.to) return false;
      if (g.mes && mesesPuxados.has(g.mes)) return false;
      return true;
    });
    let n = 0;
    metaDetail.forEach((d) => {
      const cid = nameToCid[d.campanha]; if (!cid) return;
      newGastos.push({ campanhaId: cid, date: d.date, valor: d.gasto });
      n++;
    });
    setCampanhas(newCamps); setGastos(newGastos); setMetaRows([]); setMetaDetail([]);
    setMetaMsg(n > 0 ? `Gasto aplicado (${n} registro(s)) ✓` : 'Nada aplicado — tudo estava como "Ignorar".');
  };

  /* ---------- dados calculados ---------- */
  const lojas = useMemo(() => [...new Set(campanhas.map((c) => c.loja).filter(Boolean))], [campanhas]);
  const emPeriodo = (v) => (v.data || '') >= per.from && (v.data || '') <= per.to;
  const vendasPer = useMemo(() => vendas.filter(emPeriodo), [vendas, per]);
  const hasOrg = useMemo(() => vendas.some((v) => v.campanhaId === ORG), [vendas]);
  const nomeModelo = (id) => modelos.find((m) => m.id === id)?.nome || null;
  const custoTot = (v) => (v.custo || 0) + (v.frete || 0);

  const secOrder = useMemo(() => {
    const saved = Array.isArray(config.secOrder) ? config.secOrder.filter((k) => DEFAULT_SEC.includes(k)) : [];
    return [...saved, ...DEFAULT_SEC.filter((k) => !saved.includes(k))];
  }, [config.secOrder]);
  const visibleSecKeys = () => secOrder.filter((k) => k !== 'vendas' || recentesAba.length > 0);
  const moveSection = (key, dir) => {
    const vis = visibleSecKeys();
    const target = vis[vis.indexOf(key) + dir];
    if (target == null) return;
    const order = secOrder.slice();
    const a = order.indexOf(key), b = order.indexOf(target);
    [order[a], order[b]] = [order[b], order[a]];
    setConfig((c) => ({ ...c, secOrder: order }));
  };
  const secUp = (key) => (visibleSecKeys().indexOf(key) > 0 ? () => moveSection(key, -1) : null);
  const secDown = (key) => { const vis = visibleSecKeys(); return vis.indexOf(key) < vis.length - 1 ? () => moveSection(key, 1) : null; };
  const moveCamp = (i, dir) => {
    const j = i + dir;
    if (j < 0 || j >= campanhas.length) return;
    setCampanhas((prev) => { const a = [...prev]; [a[i], a[j]] = [a[j], a[i]]; return a; });
  };
  const campDetalhe = (cid) => {
    const vs = vendasPer.filter((v) => v.campanhaId === cid);
    const byModel = {};
    vs.forEach((v) => {
      const k = v.modeloId || '__sem__';
      if (!byModel[k]) byModel[k] = { id: k, nome: v.modeloId ? (nomeModelo(v.modeloId) || 'Modelo removido') : 'Sem modelo', n: 0, receita: 0, custo: 0 };
      byModel[k].n++; byModel[k].receita += v.receita; byModel[k].custo += custoTot(v);
    });
    const modelosList = Object.values(byModel).map((m) => ({ ...m, lucro: m.receita - m.custo })).sort((a, b) => b.n - a.n);
    return { vs: vs.slice().sort((a, b) => (b.data > a.data ? 1 : -1)), modelosList };
  };

  const rows = useMemo(() => {
    const filt = campanhas.filter((c) => lojaFiltro === 'todas' || c.loja === lojaFiltro);
    const out = filt.map((c) => {
      const vs = vendasPer.filter((v) => v.campanhaId === c.id);
      const nVendas = vs.length;
      const receita = vs.reduce((s, v) => s + v.receita, 0);
      const custoProd = vs.reduce((s, v) => s + custoTot(v), 0);
      const gastoMidia = getGastoPeriodo(c.id);
      const gasto = comImp(gastoMidia);
      const cpa = nVendas > 0 ? gasto / nVendas : null;
      const ticket = nVendas > 0 ? receita / nVendas : null;
      const roas = gasto > 0 ? receita / gasto : null;
      const lucro = receita - custoProd - gasto;
      return { c, nVendas, receita, custoProd, gastoMidia, gasto, cpa, ticket, roas, lucro };
    });
    return ordenacao === 'manual' ? out : out.sort((a, b) => b.lucro - a.lucro);
  }, [campanhas, vendasPer, gastos, per, lojaFiltro, impPct, ordenacao]);

  const adReal = useMemo(() => {
    const tracked = vendasPer.filter((v) => v.campanhaId !== ORG && v.campanhaId !== ADX);
    const untracked = vendasPer.filter((v) => v.campanhaId === ADX);
    const ad = [...tracked, ...untracked];
    const gastoMidia = campanhas.reduce((s, c) => s + getGastoPeriodo(c.id), 0);
    const imposto = gastoMidia * impPct / 100;
    const gastoTotal = gastoMidia + imposto;
    const receita = ad.reduce((s, v) => s + v.receita, 0);
    const custo = ad.reduce((s, v) => s + custoTot(v), 0);
    const n = ad.length;
    return {
      gastoMidia, imposto, gastoTotal, receita, custo, n, nTracked: tracked.length, nUntracked: untracked.length,
      cpa: n > 0 ? gastoTotal / n : null, roas: gastoTotal > 0 ? receita / gastoTotal : null, lucro: receita - custo - gastoTotal,
      recUntracked: untracked.reduce((s, v) => s + v.receita, 0), custoUntracked: untracked.reduce((s, v) => s + custoTot(v), 0),
    };
  }, [vendasPer, campanhas, gastos, per, impPct]);

  const trackedTot = useMemo(() => rows.reduce((s, r) => ({ gasto: s.gasto + r.gasto, receita: s.receita + r.receita, nVendas: s.nVendas + r.nVendas, lucro: s.lucro + r.lucro }), { gasto: 0, receita: 0, nVendas: 0, lucro: 0 }), [rows]);

  const vendasOrg = useMemo(() => vendasPer.filter((v) => v.campanhaId === ORG), [vendasPer]);
  const orgResumo = useMemo(() => { const receita = vendasOrg.reduce((s, v) => s + v.receita, 0); const custo = vendasOrg.reduce((s, v) => s + custoTot(v), 0); return { n: vendasOrg.length, receita, custo, lucro: receita - custo }; }, [vendasOrg]);
  const orgPorOrigem = useMemo(() => {
    const map = {};
    vendasOrg.forEach((v) => { const k = v.origem || 'Outro'; if (!map[k]) map[k] = { origem: k, n: 0, receita: 0, custo: 0 }; map[k].n++; map[k].receita += v.receita; map[k].custo += custoTot(v); });
    return Object.values(map).map((o) => ({ ...o, lucro: o.receita - o.custo })).sort((a, b) => b.lucro - a.lucro);
  }, [vendasOrg]);

  const geral = useMemo(() => {
    const receitaTotal = adReal.receita + orgResumo.receita;
    const lucroTotal = adReal.lucro + orgResumo.lucro;
    return { receitaTotal, gastoTotal: adReal.gastoTotal, lucroTotal, share: receitaTotal > 0 ? adReal.receita / receitaTotal : null };
  }, [adReal, orgResumo]);

  const modelosRank = useMemo(() => {
    const map = {};
    vendasPer.forEach((v) => {
      if (!v.modeloId) return;
      if (!map[v.modeloId]) map[v.modeloId] = { n: 0, receita: 0, custo: 0 };
      map[v.modeloId].n++; map[v.modeloId].receita += v.receita; map[v.modeloId].custo += custoTot(v);
    });
    const semModelo = vendasPer.filter((v) => !v.modeloId).length;
    const list = modelos.map((m) => { const a = map[m.id] || { n: 0, receita: 0, custo: 0 }; return { m, n: a.n, receita: a.receita, custo: a.custo, lucro: a.receita - a.custo }; })
      .sort((a, b) => b.n - a.n || b.receita - a.receita);
    return { list, semModelo };
  }, [vendasPer, modelos]);

  const nomeVenda = (v) => {
    if (v.campanhaId === ORG) return `Orgânico · ${v.origem || 'Outro'}`;
    if (v.campanhaId === ADX) return 'Anúncio (não rastreado)';
    return campanhas.find((c) => c.id === v.campanhaId)?.nome || '—';
  };
  const recentesAba = useMemo(() => {
    const src = aba === 'organico' ? vendasOrg : vendasPer.filter((v) => v.campanhaId !== ORG);
    return src.slice().sort((a, b) => (b.data > a.data ? 1 : b.data < a.data ? -1 : 0)).slice(0, 20);
  }, [aba, vendasPer, vendasOrg]);

  const modeloOptions = (
    <>
      <option value="">— sem modelo —</option>
      {modelos.map((m) => <option key={m.id} value={m.id}>{m.nome}</option>)}
    </>
  );

  const renderVenda = (v) => {
    if (editId === v.id && editDraft) {
      return (
        <div key={v.id} className="py-3">
          <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-2 items-end">
            <Field label="Data"><input type="date" value={editDraft.data} onChange={(e) => setEditDraft((d) => ({ ...d, data: e.target.value }))} className="inp" /></Field>
            <Field label="De onde veio" className="col-span-2 lg:col-span-1">
              <select value={editDraft.tipo} onChange={(e) => setEditDraft((d) => ({ ...d, tipo: e.target.value }))} className="inp">
                <optgroup label="Não sei qual anúncio"><option value={ADX}>Anúncio não rastreado</option><option value={ORG}>Orgânico de verdade</option></optgroup>
                {campanhas.length > 0 && <optgroup label="Anúncios rastreados">{campanhas.map((c) => <option key={c.id} value={c.id}>{c.nome}</option>)}</optgroup>}
              </select>
            </Field>
            {editDraft.tipo === ORG && <Field label="Origem"><select value={editDraft.origem} onChange={(e) => setEditDraft((d) => ({ ...d, origem: e.target.value }))} className="inp">{ORIGENS.map((o) => <option key={o} value={o}>{o}</option>)}</select></Field>}
            <Field label="Modelo"><select value={editDraft.modeloId} onChange={(e) => { const id = e.target.value; const m = modelos.find((x) => x.id === id); setEditDraft((d) => ({ ...d, modeloId: id, receita: m ? String(m.preco || '') : d.receita, custo: m ? String(m.custo || '') : d.custo, frete: m ? String(m.frete || '') : d.frete })); }} className="inp">{modeloOptions}</select></Field>
            <Field label="Cliente"><input value={editDraft.cliente} onChange={(e) => setEditDraft((d) => ({ ...d, cliente: e.target.value }))} className="inp" /></Field>
            <Field label="Receita"><input value={editDraft.receita} onChange={(e) => setEditDraft((d) => ({ ...d, receita: e.target.value }))} inputMode="decimal" className="inp" /></Field>
            <Field label="Custo"><input value={editDraft.custo} onChange={(e) => setEditDraft((d) => ({ ...d, custo: e.target.value }))} inputMode="decimal" className="inp" /></Field>
            <Field label="Frete"><input value={editDraft.frete} onChange={(e) => setEditDraft((d) => ({ ...d, frete: e.target.value }))} inputMode="decimal" className="inp" /></Field>
          </div>
          <div className="flex gap-2 mt-2">
            <button onClick={saveEdit} disabled={parseBRL(editDraft.receita) <= 0} className="h-8 px-3 rounded-lg bg-emerald-600 text-white text-sm font-medium hover:bg-emerald-700 disabled:opacity-40 flex items-center gap-1.5"><Check size={14} /> Salvar</button>
            <button onClick={cancelEdit} className="h-8 px-3 rounded-lg bg-slate-100 text-slate-600 text-sm font-medium hover:bg-slate-200 flex items-center gap-1.5"><X size={14} /> Cancelar</button>
          </div>
        </div>
      );
    }
    return (
      <div key={v.id} className="flex items-center justify-between py-2 text-sm">
        <div className="min-w-0">
          <span className="text-slate-400 tabular-nums mr-2">{(v.data || '').slice(8, 10)}/{(v.data || '').slice(5, 7)}</span>
          <span className={`font-medium ${v.campanhaId === ADX ? 'text-amber-600' : ''}`}>{nomeVenda(v)}</span>
          {v.modeloId && <span className="text-slate-500"> · {nomeModelo(v.modeloId)}</span>}
          {v.cliente && <span className="text-slate-400"> · {v.cliente}</span>}
        </div>
        <div className="flex items-center gap-3 shrink-0">
          <span className="tabular-nums text-slate-700">{brl(v.receita)}</span>
          <span className="tabular-nums text-slate-400 hidden sm:inline">custo {brl(custoTot(v))}{v.frete ? ` (frete ${brl(v.frete)})` : ''}</span>
          <button onClick={() => startEdit(v)} className="text-slate-300 hover:text-slate-600 transition" aria-label="Editar venda"><Pencil size={14} /></button>
          <button onClick={() => delVenda(v.id)} className="text-slate-300 hover:text-rose-500 transition" aria-label="Excluir venda"><Trash2 size={15} /></button>
        </div>
      </div>
    );
  };

  const font = { fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif' };
  const presetBtn = (tipo, txt) => (
    <button onClick={() => setPeriodo((p) => ({ ...p, tipo }))} className={`px-3 py-1.5 rounded-full text-sm border transition ${periodo.tipo === tipo ? 'bg-slate-900 text-white border-slate-900' : 'bg-white border-slate-300 hover:border-slate-400'}`}>{txt}</button>
  );

  return (
    <div className="min-h-screen bg-slate-50 text-slate-800" style={font}>
      <header className="bg-slate-900 text-white">
        <div className="max-w-6xl mx-auto px-4 sm:px-6 py-5">
          <div className="flex items-start justify-between gap-4 flex-wrap">
            <div>
              <div className="flex items-center gap-2 text-emerald-400 text-xs font-medium tracking-wide uppercase mb-1"><BarChart3 size={14} /> Lucro real por origem</div>
              <h1 className="text-xl sm:text-2xl font-semibold leading-tight">Métricas de Campanhas · WhatsApp</h1>
              <p className="text-slate-400 text-sm mt-1">{per.label}</p>
            </div>
            <div className="flex items-center gap-2">
              <button onClick={() => shiftPeriodo(-1)} className="p-2 rounded-lg bg-slate-800 hover:bg-slate-700 transition" aria-label="Mês anterior"><ChevronLeft size={18} /></button>
              <div className="px-3 py-2 rounded-lg bg-slate-800 min-w-[150px] text-center text-sm font-medium">{monthLabel(mesRefAtual)}</div>
              <button onClick={() => shiftPeriodo(1)} className="p-2 rounded-lg bg-slate-800 hover:bg-slate-700 transition" aria-label="Próximo mês"><ChevronRight size={18} /></button>
            </div>
          </div>
        </div>
      </header>

      <main className="max-w-6xl mx-auto px-4 sm:px-6 py-6 space-y-6">
        {/* Filtro de data */}
        <div className="flex items-center gap-2 flex-wrap">
          <span className="text-xs text-slate-500 uppercase tracking-wide flex items-center gap-1"><Calendar size={13} /> Período</span>
          {presetBtn('mes', 'Este mês')}
          {presetBtn('mes_passado', 'Mês passado')}
          {presetBtn('ano', 'Este ano')}
          {presetBtn('custom', 'Personalizado')}
          {periodo.tipo === 'custom' && (
            <div className="flex items-center gap-2">
              <input type="date" value={periodo.from} onChange={(e) => setPeriodo((p) => ({ ...p, from: e.target.value }))} className="inp !w-auto text-sm" />
              <span className="text-slate-400 text-sm">até</span>
              <input type="date" value={periodo.to} onChange={(e) => setPeriodo((p) => ({ ...p, to: e.target.value }))} className="inp !w-auto text-sm" />
            </div>
          )}
        </div>

        {/* Resumo do mês */}
        <div className="grid grid-cols-2 lg:grid-cols-4 gap-3">
          <Kpi icon={<Receipt size={16} />} label="Receita total" value={brl(geral.receitaTotal)} />
          <Kpi icon={<Wallet size={16} />} label="Gasto anúncios (c/ imposto)" value={brl(geral.gastoTotal)} />
          <Kpi icon={geral.lucroTotal >= 0 ? <TrendingUp size={16} /> : <TrendingDown size={16} />} label="Lucro total" value={brl(geral.lucroTotal)} tone={geral.lucroTotal > 0 ? 'emerald' : geral.lucroTotal < 0 ? 'rose' : 'slate'} />
          <Kpi icon={<Percent size={16} />} label="Veio de anúncio" value={geral.share != null ? pct(geral.share) : '—'} />
        </div>

        {/* Registrar venda */}
        <Card icon={<Plus size={16} className="text-emerald-600" />} title="Registrar venda">
          <div className="p-4 sm:p-5">
            <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3 items-end">
              <Field label="Data"><input type="date" value={vData} onChange={(e) => setVData(e.target.value)} className="inp" /></Field>
              <Field label="De onde veio a venda" className="col-span-2 lg:col-span-1">
                <select value={vCampanha} onChange={(e) => setVCampanha(e.target.value)} className="inp">
                  <option value="">Selecione…</option>
                  <optgroup label="Não sei qual anúncio"><option value={ADX}>Anúncio não rastreado (viu o ad → IG/site → Whats)</option><option value={ORG}>Orgânico de verdade (indicação)</option></optgroup>
                  {campanhas.length > 0 && <optgroup label="Anúncios rastreados">{campanhas.map((c) => <option key={c.id} value={c.id}>{c.nome}{c.loja ? ` · ${c.loja}` : ''}</option>)}</optgroup>}
                </select>
              </Field>
              {isOrg && <Field label="Origem"><select value={vOrigem} onChange={(e) => setVOrigem(e.target.value)} className="inp">{ORIGENS.map((o) => <option key={o} value={o}>{o}</option>)}</select></Field>}
              <Field label="Modelo (preenche sozinho)"><select value={vModelo} onChange={(e) => onModelo(e.target.value)} className="inp">{modeloOptions}</select></Field>
              <Field label="Cliente (opcional)"><input value={vCliente} onChange={(e) => setVCliente(e.target.value)} placeholder="Nome" className="inp" /></Field>
              <Field label="Receita (venda)"><input value={vReceita} onChange={(e) => setVReceita(e.target.value)} placeholder="0,00" inputMode="decimal" className="inp" /></Field>
              <Field label="Custo do produto"><input value={vCusto} onChange={(e) => setVCusto(e.target.value)} placeholder="0,00" inputMode="decimal" className="inp" /></Field>
              <Field label="Frete"><input value={vFrete} onChange={(e) => setVFrete(e.target.value)} placeholder="0,00" inputMode="decimal" className="inp" /></Field>
              <button onClick={addVenda} disabled={!vCampanha || parseBRL(vReceita) <= 0} className="h-[38px] rounded-lg bg-emerald-600 text-white text-sm font-medium hover:bg-emerald-700 disabled:opacity-40 disabled:cursor-not-allowed transition flex items-center justify-center gap-1.5"><Plus size={16} /> Adicionar</button>
            </div>
            <p className="text-xs text-slate-400 mt-2">Escolha um modelo pra puxar receita e custo automaticamente (dá pra editar). Se a pessoa viu um anúncio mas não sabe qual, use “Anúncio não rastreado”.</p>
          </div>
        </Card>

        {/* Abas */}
        <div className="flex gap-1 border-b border-slate-200 flex-wrap">
          <TabBtn active={aba === 'anuncio'} onClick={() => setAba('anuncio')}>Anúncios</TabBtn>
          <TabBtn active={aba === 'modelos'} onClick={() => setAba('modelos')}>Modelos {modelos.length > 0 && <span className="ml-1 text-xs bg-slate-200 text-slate-600 rounded-full px-1.5 py-0.5 tabular-nums">{modelos.length}</span>}</TabBtn>
          {hasOrg && <TabBtn active={aba === 'organico'} onClick={() => setAba('organico')}>Orgânicas {orgResumo.n > 0 && <span className="ml-1 text-xs bg-slate-200 text-slate-600 rounded-full px-1.5 py-0.5 tabular-nums">{orgResumo.n}</span>}</TabBtn>}
        </div>

        {aba === 'anuncio' && (
          <div className="space-y-6">
            {lojas.length > 0 && (
              <div className="flex items-center gap-2 flex-wrap">
                <span className="text-xs text-slate-500 uppercase tracking-wide">Loja</span>
                <button onClick={() => setLojaFiltro('todas')} className={`px-3 py-1.5 rounded-full text-sm border transition ${lojaFiltro === 'todas' ? 'bg-slate-900 text-white border-slate-900' : 'bg-white border-slate-300 hover:border-slate-400'}`}>Todas</button>
                {lojas.map((l) => <button key={l} onClick={() => setLojaFiltro(l)} className={`px-3 py-1.5 rounded-full text-sm border transition ${lojaFiltro === l ? 'bg-slate-900 text-white border-slate-900' : 'bg-white border-slate-300 hover:border-slate-400'}`}>{l}</button>)}
              </div>
            )}

            <p className="text-xs text-slate-400 flex items-center gap-1"><ChevronUp size={12} /> Use as setas ao lado de cada título para reordenar os blocos. Clique num anúncio no comparativo para ver detalhes.</p>

            <div className="flex flex-col gap-6">
              {/* desempenho */}
              <div style={{ order: secOrder.indexOf('desempenho') }}>
                <Card onMoveUp={secUp('desempenho')} onMoveDown={secDown('desempenho')} icon={<Sparkles size={16} className="text-emerald-600" />} title={`Desempenho real dos anúncios · ${per.label}`}>
                  <div className="p-4 sm:p-5">
                    <div className="grid grid-cols-2 lg:grid-cols-5 gap-3">
                      <MiniStat label="Gasto (mídia + imposto)" value={brl(adReal.gastoTotal)} sub={impPct > 0 ? `${brl(adReal.gastoMidia)} + ${brl(adReal.imposto)} imp.` : 'sem imposto'} />
                      <MiniStat label="Vendas de anúncio" value={num(adReal.n, 0)} sub={`${adReal.nTracked} rastr. + ${adReal.nUntracked} não rastr.`} />
                      <MiniStat label="CPA real" value={adReal.cpa != null ? brl(adReal.cpa) : '—'} />
                      <MiniStat label="ROAS real" value={adReal.roas != null ? `${num(adReal.roas, 2)}x` : '—'} tone={adReal.roas != null ? (adReal.roas >= 1 ? 'emerald' : 'rose') : 'slate'} />
                      <MiniStat label="Lucro real" value={brl(adReal.lucro)} tone={adReal.lucro > 0 ? 'emerald' : adReal.lucro < 0 ? 'rose' : 'slate'} />
                    </div>
                    <p className="text-xs text-slate-400 mt-3">CPA e ROAS reais: gasto (com imposto) contra todas as vendas de anúncio, inclusive as {adReal.nUntracked} não rastreadas ({brl(adReal.recUntracked)}).</p>
                  </div>
                </Card>
              </div>

              {/* ajustes */}
              <div style={{ order: secOrder.indexOf('ajustes') }}>
                <Card onMoveUp={secUp('ajustes')} onMoveDown={secDown('ajustes')} icon={<Percent size={16} className="text-slate-600" />} title="Ajustes" defaultOpen={false}>
                  <div className="p-4 sm:p-5">
                    <Field label="Imposto sobre o gasto de mídia (%)" className="max-w-xs">
                      <input value={config.impostoAdPct} onChange={(e) => setConfig((c) => ({ ...c, impostoAdPct: parseBRL(e.target.value) }))} inputMode="decimal" placeholder="0" className="inp" />
                    </Field>
                    <p className="text-xs text-slate-400 mt-2">Aplicado sobre o gasto de cada anúncio para chegar no CPA real. Ex.: paguei R$ 100 de mídia + 20% de imposto = R$ 120 de custo real.</p>
                    <div className="mt-5 pt-4 border-t border-slate-100">
                      <div className="flex items-center gap-2 mb-1"><Save size={15} className="text-slate-500" /><span className="text-sm font-medium text-slate-700">Backup dos dados</span></div>
                      <p className="text-xs text-slate-400 mb-3">Seus dados já ficam salvos no navegador automaticamente e não dependem do Windsor. Ainda assim, baixe um backup de vez em quando — é um arquivo seu, que restaura tudo em qualquer navegador.</p>
                      <div className="flex items-center gap-2 flex-wrap">
                        <button onClick={exportBackup} className="h-9 px-3 rounded-lg bg-slate-900 text-white text-sm font-medium hover:bg-slate-800 transition flex items-center gap-1.5"><Download size={15} /> Baixar backup</button>
                        <label className="h-9 px-3 rounded-lg bg-white border border-slate-300 text-slate-700 text-sm font-medium hover:border-slate-400 transition flex items-center gap-1.5 cursor-pointer"><Upload size={15} /> Restaurar backup<input type="file" accept="application/json,.json" onChange={importBackup} className="hidden" /></label>
                        <span className="text-xs text-slate-500">{campanhas.length} anúncios · {vendas.length} vendas · {modelos.length} modelos guardados</span>
                      </div>
                      {backupMsg && <div className="mt-3 text-sm text-emerald-700 bg-emerald-50 border border-emerald-100 rounded-lg px-3 py-2">{backupMsg}</div>}
                    </div>
                  </div>
                </Card>
              </div>

              {/* windsor */}
              <div style={{ order: secOrder.indexOf('windsor') }}>
                <Card onMoveUp={secUp('windsor')} onMoveDown={secDown('windsor')} icon={<Zap size={16} className="text-amber-500" />} title="Gasto do Meta · automático"
                  right={<button onClick={fetchMeta} disabled={fetchingMeta} className="h-9 px-3 rounded-lg bg-slate-900 text-white text-sm font-medium hover:bg-slate-800 disabled:opacity-50 transition flex items-center gap-1.5">{fetchingMeta ? <Loader2 size={15} className="animate-spin" /> : <RefreshCw size={15} />}{fetchingMeta ? 'Puxando…' : 'Puxar do Meta'}</button>}>
                  <div className="p-4 sm:p-5">
                    <p className="text-sm text-slate-500">Puxa o gasto diário de cada campanha do Meta (via Windsor.ai) no período selecionado.</p>
                    <details className="mt-3">
                      <summary className="text-sm text-slate-600 cursor-pointer hover:text-slate-800">ou colar o gasto (quando o botão falha)</summary>
                      <div className="mt-2">
                        <p className="text-xs text-slate-400 mb-1">Peça no chat “puxa o gasto diário” e cole aqui o texto (JSON) que eu te mandar. Depois é só mapear e aplicar.</p>
                        <textarea value={metaPaste} onChange={(e) => setMetaPaste(e.target.value)} placeholder='[{"campanha":"...","data":"2026-08-01","gasto":56.37}, ...]' rows={4} className="w-full border border-slate-300 rounded-lg p-2 text-xs font-mono outline-none focus:border-slate-400" />
                        <button onClick={carregarColado} disabled={!metaPaste.trim()} className="mt-2 h-9 px-3 rounded-lg bg-slate-900 text-white text-sm font-medium hover:bg-slate-800 disabled:opacity-40 transition">Carregar dados colados</button>
                      </div>
                    </details>
                    {metaError && <div className="mt-3 text-sm text-rose-700 bg-rose-50 border border-rose-100 rounded-lg px-3 py-2">{metaError}</div>}
                    {metaMsg && <div className="mt-3 text-sm text-emerald-700 bg-emerald-50 border border-emerald-100 rounded-lg px-3 py-2">{metaMsg}</div>}
                    {metaRows.length > 0 && (
                      <div className="mt-4">
                        <p className="text-xs text-slate-500 uppercase tracking-wide mb-1">Encontrado no Meta — confirme o anúncio de cada campanha</p>
                        <div className="flex flex-col divide-y divide-slate-100">
                          {metaRows.map((row, i) => (
                            <div key={i} className="flex items-center justify-between gap-3 py-2.5 flex-wrap">
                              <div className="min-w-0"><div className="text-sm font-medium text-slate-800 truncate">{row.campanha}</div><div className="text-xs text-slate-400 tabular-nums">{brl(row.gastoTotal)} no período</div></div>
                              <div className="flex items-center gap-2"><span className="text-xs text-slate-300">→</span>
                                <select value={row.mapId} onChange={(e) => setMetaRows((p) => p.map((r, j) => (j === i ? { ...r, mapId: e.target.value } : r)))} className="inp !w-auto text-sm">
                                  <option value="">Ignorar</option>
                                  <option value="__new__">➕ Criar “{row.campanha.slice(0, 22)}”</option>
                                  {campanhas.map((c) => <option key={c.id} value={c.id}>{c.nome}</option>)}
                                </select>
                              </div>
                            </div>
                          ))}
                        </div>
                        <button onClick={applyMeta} className="mt-3 h-9 px-4 rounded-lg bg-emerald-600 text-white text-sm font-medium hover:bg-emerald-700 transition flex items-center gap-1.5"><Check size={15} /> Aplicar gasto</button>
                      </div>
                    )}
                  </div>
                </Card>
              </div>

              {/* comparativo */}
              <div style={{ order: secOrder.indexOf('comparativo') }}>
                <Card onMoveUp={secUp('comparativo')} onMoveDown={secDown('comparativo')} icon={<BarChart3 size={16} className="text-slate-600" />} title="Comparativo por criativo · só rastreadas"
                  right={<div className="flex rounded-lg border border-slate-200 overflow-hidden"><button onClick={() => setOrdenacao('lucro')} className={`px-2.5 py-1 text-xs ${ordenacao === 'lucro' ? 'bg-slate-900 text-white' : 'bg-white text-slate-500 hover:text-slate-700'}`}>Lucro</button><button onClick={() => setOrdenacao('manual')} className={`px-2.5 py-1 text-xs ${ordenacao === 'manual' ? 'bg-slate-900 text-white' : 'bg-white text-slate-500 hover:text-slate-700'}`}>Manual</button></div>}>
                  {rows.length === 0 ? (
                    <div className="p-8 text-center text-slate-500 text-sm">Cadastre um anúncio (ou puxe do Meta) para ver o comparativo.</div>
                  ) : (
                    <div className="overflow-x-auto">
                      <table className="w-full text-sm min-w-[720px]">
                        <thead><tr className="text-left text-xs text-slate-500 uppercase tracking-wide border-b border-slate-100">
                          <th className="px-4 sm:px-5 py-2.5 font-medium">Anúncio</th>
                          <th className="px-3 py-2.5 font-medium text-right">Gasto mídia</th>
                          <th className="px-3 py-2.5 font-medium text-right">Vendas</th>
                          <th className="px-3 py-2.5 font-medium text-right">CPA</th>
                          <th className="px-3 py-2.5 font-medium text-right">Ticket</th>
                          <th className="px-3 py-2.5 font-medium text-right">Receita</th>
                          <th className="px-3 py-2.5 font-medium text-right">ROAS</th>
                          <th className="px-4 sm:px-5 py-2.5 font-medium text-right">Lucro</th>
                        </tr></thead>
                        <tbody className="divide-y divide-slate-100">
                          {rows.map((r) => {
                            const det = expandedCamp === r.c.id ? campDetalhe(r.c.id) : null;
                            return (
                              <Fragment key={r.c.id}>
                                <tr className="hover:bg-slate-50/60">
                                  <td className="px-4 sm:px-5 py-3">
                                    <button onClick={() => setExpandedCamp(expandedCamp === r.c.id ? null : r.c.id)} className="text-left flex items-start gap-1.5 group">
                                      <ChevronRight size={14} className={`mt-0.5 text-slate-300 group-hover:text-slate-500 transition-transform ${expandedCamp === r.c.id ? 'rotate-90' : ''}`} />
                                      <span><span className="font-medium text-slate-800 group-hover:text-slate-900">{r.c.nome}</span><span className="block text-xs text-slate-400">{[r.c.loja, r.c.plataforma].filter(Boolean).join(' · ')}</span></span>
                                    </button>
                                  </td>
                                  <td className="px-3 py-3 text-right">
                                    {mesUnico ? (
                                      <div className="inline-flex items-center rounded-lg border border-slate-200 focus-within:border-slate-400 bg-white"><span className="pl-2 text-slate-400 text-xs">R$</span><input key={`${r.c.id}-${mesUnico}`} defaultValue={r.gastoMidia ? num(r.gastoMidia, 2) : ''} onBlur={(e) => upsertGasto(r.c.id, mesUnico, parseBRL(e.target.value))} placeholder="0,00" inputMode="decimal" className="w-20 px-1.5 py-1 text-right tabular-nums bg-transparent outline-none text-slate-800" /></div>
                                    ) : <span className="tabular-nums text-slate-700">{brl(r.gastoMidia)}</span>}
                                  </td>
                                  <td className="px-3 py-3 text-right tabular-nums">{r.nVendas}</td>
                                  <td className="px-3 py-3 text-right tabular-nums text-slate-700">{r.cpa != null ? brl(r.cpa) : '—'}</td>
                                  <td className="px-3 py-3 text-right tabular-nums text-slate-500">{r.ticket != null ? brl(r.ticket) : '—'}</td>
                                  <td className="px-3 py-3 text-right tabular-nums">{brl(r.receita)}</td>
                                  <td className="px-3 py-3 text-right tabular-nums">{r.roas != null ? <span className={r.roas >= 1 ? 'text-emerald-600 font-medium' : 'text-rose-600 font-medium'}>{num(r.roas, 2)}x</span> : '—'}</td>
                                  <td className="px-4 sm:px-5 py-3 text-right tabular-nums font-semibold"><span className={r.lucro > 0 ? 'text-emerald-600' : r.lucro < 0 ? 'text-rose-600' : 'text-slate-500'}>{brl(r.lucro)}</span></td>
                                </tr>
                                {det && (
                                  <tr className="bg-slate-50/60">
                                    <td colSpan={8} className="px-4 sm:px-5 py-4">
                                      <div className="text-xs text-slate-500 uppercase tracking-wide mb-2">Modelos vendidos por este anúncio</div>
                                      {det.modelosList.length === 0 ? (
                                        <div className="text-sm text-slate-400">Nenhuma venda rastreada deste anúncio no período.</div>
                                      ) : (
                                        <div className="flex flex-col gap-1 mb-3">
                                          {det.modelosList.map((m) => (
                                            <div key={m.id} className="flex items-center justify-between text-sm gap-3">
                                              <span className="text-slate-700"><span className="font-semibold tabular-nums">{m.n}×</span> {m.nome}</span>
                                              <span className="tabular-nums text-slate-500 shrink-0">receita {brl(m.receita)} · lucro <span className={m.lucro >= 0 ? 'text-emerald-600' : 'text-rose-600'}>{brl(m.lucro)}</span></span>
                                            </div>
                                          ))}
                                        </div>
                                      )}
                                      {det.vs.length > 0 && (
                                        <>
                                          <div className="text-xs text-slate-500 uppercase tracking-wide mb-1">Vendas</div>
                                          <div className="flex flex-col gap-1">
                                            {det.vs.map((v) => (
                                              <div key={v.id} className="flex items-center justify-between text-sm gap-3">
                                                <span className="text-slate-600 truncate"><span className="tabular-nums text-slate-400 mr-2">{(v.data || '').slice(8, 10)}/{(v.data || '').slice(5, 7)}</span>{v.cliente || 'sem nome'}{v.modeloId && <span className="text-slate-400"> · {nomeModelo(v.modeloId)}</span>}</span>
                                                <span className="tabular-nums text-slate-500 shrink-0">{brl(v.receita)}</span>
                                              </div>
                                            ))}
                                          </div>
                                        </>
                                      )}
                                    </td>
                                  </tr>
                                )}
                              </Fragment>
                            );
                          })}
                          {lojaFiltro === 'todas' && adReal.nUntracked > 0 && (
                            <tr className="bg-amber-50/50">
                              <td className="px-4 sm:px-5 py-3"><div className="font-medium text-amber-700 pl-5">Anúncio · não rastreado</div><div className="text-xs text-slate-400 pl-5">viu o ad → IG/site → Whats</div></td>
                              <td className="px-3 py-3 text-right text-slate-300">—</td>
                              <td className="px-3 py-3 text-right tabular-nums">{adReal.nUntracked}</td>
                              <td className="px-3 py-3 text-right text-slate-300">—</td>
                              <td className="px-3 py-3 text-right tabular-nums text-slate-500">{brl(adReal.recUntracked / adReal.nUntracked)}</td>
                              <td className="px-3 py-3 text-right tabular-nums">{brl(adReal.recUntracked)}</td>
                              <td className="px-3 py-3 text-right text-slate-300">—</td>
                              <td className="px-4 sm:px-5 py-3 text-right tabular-nums font-semibold"><span className={(adReal.recUntracked - adReal.custoUntracked) >= 0 ? 'text-emerald-600' : 'text-rose-600'}>{brl(adReal.recUntracked - adReal.custoUntracked)}</span></td>
                            </tr>
                          )}
                        </tbody>
                        <tfoot>
                          {lojaFiltro === 'todas' ? (
                            <tr className="border-t-2 border-slate-200 bg-slate-50 font-semibold">
                              <td className="px-4 sm:px-5 py-3 pl-9">Total anúncios (real)</td>
                              <td className="px-3 py-3 text-right tabular-nums">{brl(adReal.gastoTotal)}</td>
                              <td className="px-3 py-3 text-right tabular-nums">{adReal.n}</td>
                              <td className="px-3 py-3 text-right tabular-nums">{adReal.cpa != null ? brl(adReal.cpa) : '—'}</td>
                              <td className="px-3 py-3"></td>
                              <td className="px-3 py-3 text-right tabular-nums">{brl(adReal.receita)}</td>
                              <td className="px-3 py-3 text-right tabular-nums">{adReal.roas != null ? `${num(adReal.roas, 2)}x` : '—'}</td>
                              <td className="px-4 sm:px-5 py-3 text-right tabular-nums"><span className={adReal.lucro > 0 ? 'text-emerald-600' : adReal.lucro < 0 ? 'text-rose-600' : 'text-slate-500'}>{brl(adReal.lucro)}</span></td>
                            </tr>
                          ) : (
                            <tr className="border-t-2 border-slate-200 bg-slate-50 font-semibold">
                              <td className="px-4 sm:px-5 py-3 pl-9">Total rastreado</td>
                              <td className="px-3 py-3 text-right tabular-nums">{brl(trackedTot.gasto)}</td>
                              <td className="px-3 py-3 text-right tabular-nums">{trackedTot.nVendas}</td>
                              <td className="px-3 py-3"></td><td className="px-3 py-3"></td>
                              <td className="px-3 py-3 text-right tabular-nums">{brl(trackedTot.receita)}</td>
                              <td className="px-3 py-3"></td>
                              <td className="px-4 sm:px-5 py-3 text-right tabular-nums"><span className={trackedTot.lucro > 0 ? 'text-emerald-600' : trackedTot.lucro < 0 ? 'text-rose-600' : 'text-slate-500'}>{brl(trackedTot.lucro)}</span></td>
                            </tr>
                          )}
                        </tfoot>
                      </table>
                    </div>
                  )}
                </Card>
              </div>

              {/* vendas */}
              {recentesAba.length > 0 && (
                <div style={{ order: secOrder.indexOf('vendas') }}>
                  <Card onMoveUp={secUp('vendas')} onMoveDown={secDown('vendas')} icon={<Receipt size={16} className="text-slate-600" />} title={`Vendas de anúncio · ${per.label}`} defaultOpen={false}>
                    <div className="p-4 sm:p-5 flex flex-col divide-y divide-slate-100">{recentesAba.map(renderVenda)}</div>
                  </Card>
                </div>
              )}

              {/* campanhas */}
              <div style={{ order: secOrder.indexOf('campanhas') }}>
                <Card onMoveUp={secUp('campanhas')} onMoveDown={secDown('campanhas')} icon={<Megaphone size={16} className="text-slate-600" />} title="Anúncios cadastrados" defaultOpen={false}>
                  <div className="p-4 sm:p-5">
                    <div className="grid grid-cols-2 sm:grid-cols-4 gap-3 items-end">
                      <Field label="Nome do anúncio" className="col-span-2 sm:col-span-1"><input value={cNome} onChange={(e) => setCNome(e.target.value)} placeholder="Ex.: 2 - Carrossel 4 - Tráfego" className="inp" /></Field>
                      <Field label="Loja / marca"><input value={cLoja} onChange={(e) => setCLoja(e.target.value)} placeholder="Ex.: Essenza" list="lojas-sug" className="inp" /><datalist id="lojas-sug">{LOJAS_SUGERIDAS.map((l) => <option key={l} value={l} />)}</datalist></Field>
                      <Field label="Plataforma"><select value={cPlataforma} onChange={(e) => setCPlataforma(e.target.value)} className="inp">{PLATAFORMAS.map((p) => <option key={p} value={p}>{p}</option>)}</select></Field>
                      <button onClick={addCampanha} disabled={!cNome.trim()} className="h-[38px] rounded-lg bg-slate-900 text-white text-sm font-medium hover:bg-slate-800 disabled:opacity-40 transition flex items-center justify-center gap-1.5"><Plus size={16} /> Cadastrar</button>
                    </div>
                    {campanhas.length > 0 && (
                      <>
                        <p className="text-xs text-slate-400 mt-4 mb-1 flex items-center gap-1"><ChevronUp size={12} /> Use as setas para definir a ordem (usada no comparativo quando ordenado por “Manual”).</p>
                        <div className="flex flex-col divide-y divide-slate-100">
                          {campanhas.map((c, i) => (
                            <div key={c.id} className="flex items-center justify-between py-2.5 group">
                              <div className="flex items-center gap-2 min-w-0">
                                <span className="flex flex-col shrink-0 -my-1">
                                  <button onClick={() => moveCamp(i, -1)} disabled={i === 0} className="text-slate-300 hover:text-slate-600 disabled:opacity-25 leading-none" aria-label="Subir anúncio"><ChevronUp size={14} /></button>
                                  <button onClick={() => moveCamp(i, 1)} disabled={i === campanhas.length - 1} className="text-slate-300 hover:text-slate-600 disabled:opacity-25 leading-none" aria-label="Descer anúncio"><ChevronDown size={14} /></button>
                                </span>
                                <div className="text-sm truncate"><span className="font-medium text-slate-800">{c.nome}</span><span className="text-slate-400"> · {[c.loja, c.plataforma].filter(Boolean).join(' · ')}</span></div>
                              </div>
                              {mergePending && mergePending.from === c.id ? (
                                <div className="flex items-center gap-1.5 text-xs shrink-0"><span className="text-slate-500">Mesclar em “{(campanhas.find((x) => x.id === mergePending.to) || {}).nome}”? (junta gasto e vendas)</span><button onClick={() => mergeCampanha(mergePending.from, mergePending.to)} className="p-1.5 rounded bg-emerald-50 text-emerald-600 hover:bg-emerald-100"><Check size={14} /></button><button onClick={() => setMergePending(null)} className="p-1.5 rounded bg-slate-100 text-slate-500 hover:bg-slate-200"><X size={14} /></button></div>
                              ) : confirmDel && confirmDel.tipo === 'campanha' && confirmDel.id === c.id ? (
                                <div className="flex items-center gap-1.5 text-xs shrink-0"><span className="text-slate-500">Remover e apagar vendas?</span><button onClick={() => { delCampanha(c.id); setConfirmDel(null); }} className="p-1.5 rounded bg-rose-50 text-rose-600 hover:bg-rose-100"><Check size={14} /></button><button onClick={() => setConfirmDel(null)} className="p-1.5 rounded bg-slate-100 text-slate-500 hover:bg-slate-200"><X size={14} /></button></div>
                              ) : (
                                <div className="flex items-center gap-2 shrink-0">
                                  {campanhas.length > 1 && (
                                    <select value="" onChange={(e) => e.target.value && setMergePending({ from: c.id, to: e.target.value })} className="inp !w-auto text-xs !py-1 text-slate-500" title="Mesclar duplicado em outro anúncio">
                                      <option value="">Mesclar em…</option>
                                      {campanhas.filter((x) => x.id !== c.id).map((x) => <option key={x.id} value={x.id}>{x.nome}</option>)}
                                    </select>
                                  )}
                                  <button onClick={() => setConfirmDel({ tipo: 'campanha', id: c.id })} className="text-slate-300 hover:text-rose-500 transition" aria-label="Remover"><Trash2 size={15} /></button>
                                </div>
                              )}
                            </div>
                          ))}
                        </div>
                      </>
                    )}
                  </div>
                </Card>
              </div>
            </div>
          </div>
        )}

        {aba === 'modelos' && (
          <div className="space-y-6">
            {/* Mais vendidos */}
            <Card icon={<Award size={16} className="text-amber-500" />} title={`Mais vendidos · ${per.label}`}>
              {modelosRank.list.every((x) => x.n === 0) ? (
                <div className="p-8 text-center text-slate-500 text-sm">Nenhuma venda com modelo neste período.{modelosRank.semModelo > 0 && <><br />{modelosRank.semModelo} venda(s) sem modelo definido.</>}</div>
              ) : (
                <div className="overflow-x-auto">
                  <table className="w-full text-sm min-w-[620px]">
                    <thead><tr className="text-left text-xs text-slate-500 uppercase tracking-wide border-b border-slate-100">
                      <th className="px-4 sm:px-5 py-2.5 font-medium">#</th>
                      <th className="px-3 py-2.5 font-medium">Modelo</th>
                      <th className="px-3 py-2.5 font-medium">Fornecedor</th>
                      <th className="px-3 py-2.5 font-medium text-right">Vendas</th>
                      <th className="px-3 py-2.5 font-medium text-right">Receita</th>
                      <th className="px-4 sm:px-5 py-2.5 font-medium text-right">Lucro produto</th>
                    </tr></thead>
                    <tbody className="divide-y divide-slate-100">
                      {modelosRank.list.map((x, i) => (
                        <tr key={x.m.id} className="hover:bg-slate-50/60">
                          <td className="px-4 sm:px-5 py-3 tabular-nums text-slate-400">{i + 1}</td>
                          <td className="px-3 py-3 font-medium text-slate-800">{x.m.nome}</td>
                          <td className="px-3 py-3 text-slate-500">{x.m.fornecedor || '—'}</td>
                          <td className="px-3 py-3 text-right tabular-nums font-semibold">{x.n}</td>
                          <td className="px-3 py-3 text-right tabular-nums">{brl(x.receita)}</td>
                          <td className="px-4 sm:px-5 py-3 text-right tabular-nums"><span className={x.lucro > 0 ? 'text-emerald-600' : x.lucro < 0 ? 'text-rose-600' : 'text-slate-500'}>{brl(x.lucro)}</span></td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                  {modelosRank.semModelo > 0 && <p className="px-4 sm:px-5 py-3 text-xs text-slate-400">+ {modelosRank.semModelo} venda(s) sem modelo definido no período.</p>}
                </div>
              )}
            </Card>

            {/* Cadastro de modelos */}
            <Card icon={<Package size={16} className="text-slate-600" />} title="Cadastro de modelos">
              <div className="p-4 sm:p-5">
                <div className="grid grid-cols-2 sm:grid-cols-6 gap-3 items-end">
                  <Field label="Nome do modelo" className="col-span-2 sm:col-span-1"><input value={mNome} onChange={(e) => setMNome(e.target.value)} placeholder="Ex.: Sofá Roma 2,20m" className="inp" /></Field>
                  <Field label="Preço de venda"><input value={mPreco} onChange={(e) => setMPreco(e.target.value)} placeholder="0,00" inputMode="decimal" className="inp" /></Field>
                  <Field label="Custo"><input value={mCusto} onChange={(e) => setMCusto(e.target.value)} placeholder="0,00" inputMode="decimal" className="inp" /></Field>
                  <Field label="Frete"><input value={mFrete} onChange={(e) => setMFrete(e.target.value)} placeholder="0,00" inputMode="decimal" className="inp" /></Field>
                  <Field label="Fornecedor"><input value={mFornecedor} onChange={(e) => setMFornecedor(e.target.value)} placeholder="Ex.: Benini" className="inp" /></Field>
                  <button onClick={salvarModelo} disabled={!mNome.trim()} className="h-[38px] rounded-lg bg-slate-900 text-white text-sm font-medium hover:bg-slate-800 disabled:opacity-40 transition flex items-center justify-center gap-1.5">{editModelo ? <><Check size={16} /> Salvar</> : <><Plus size={16} /> Cadastrar</>}</button>
                </div>
                {editModelo && <button onClick={() => { setEditModelo(null); setMNome(''); setMPreco(''); setMCusto(''); setMFrete(''); setMFornecedor(''); }} className="text-xs text-slate-400 hover:text-slate-600 mt-2">cancelar edição</button>}
                {modelos.length > 0 && (
                  <div className="mt-4 overflow-x-auto">
                    <table className="w-full text-sm min-w-[560px]">
                      <thead><tr className="text-left text-xs text-slate-500 uppercase tracking-wide border-b border-slate-100">
                        <th className="py-2 font-medium">Modelo</th>
                        <th className="py-2 font-medium">Fornecedor</th>
                        <th className="py-2 font-medium text-right">Preço</th>
                        <th className="py-2 font-medium text-right">Custo</th>
                        <th className="py-2 font-medium text-right">Frete</th>
                        <th className="py-2 font-medium text-right">Margem real</th>
                        <th className="py-2 font-medium text-right"></th>
                      </tr></thead>
                      <tbody className="divide-y divide-slate-100">
                        {modelos.map((m) => (
                          <tr key={m.id}>
                            <td className="py-2.5 font-medium text-slate-800">{m.nome}</td>
                            <td className="py-2.5 text-slate-500 flex items-center gap-1"><Truck size={12} className="text-slate-300" />{m.fornecedor || '—'}</td>
                            <td className="py-2.5 text-right tabular-nums">{brl(m.preco)}</td>
                            <td className="py-2.5 text-right tabular-nums text-slate-500">{brl(m.custo)}</td>
                            <td className="py-2.5 text-right tabular-nums text-slate-500">{brl(m.frete || 0)}</td>
                            <td className="py-2.5 text-right tabular-nums font-medium"><span className={(m.preco - m.custo - (m.frete || 0)) >= 0 ? 'text-emerald-600' : 'text-rose-600'}>{brl(m.preco - m.custo - (m.frete || 0))}</span></td>
                            <td className="py-2.5 text-right"><div className="flex items-center justify-end gap-2"><button onClick={() => startEditModelo(m)} className="text-slate-300 hover:text-slate-600" aria-label="Editar"><Pencil size={14} /></button><button onClick={() => delModelo(m.id)} className="text-slate-300 hover:text-rose-500" aria-label="Excluir"><Trash2 size={15} /></button></div></td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </div>
            </Card>
          </div>
        )}

        {aba === 'organico' && (
          <div className="space-y-6">
            <div className="grid grid-cols-3 gap-3">
              <Kpi icon={<Users size={16} />} label="Vendas orgânicas" value={num(orgResumo.n, 0)} />
              <Kpi icon={<Receipt size={16} />} label="Receita orgânica" value={brl(orgResumo.receita)} />
              <Kpi icon={orgResumo.lucro >= 0 ? <TrendingUp size={16} /> : <TrendingDown size={16} />} label="Lucro orgânico" value={brl(orgResumo.lucro)} tone={orgResumo.lucro > 0 ? 'emerald' : orgResumo.lucro < 0 ? 'rose' : 'slate'} />
            </div>
            <Card icon={<PieChart size={16} className="text-slate-600" />} title={`Por origem · ${per.label}`}>
              {orgPorOrigem.length === 0 ? (
                <div className="p-8 text-center text-slate-500 text-sm">Nenhuma venda orgânica no período.</div>
              ) : (
                <div className="overflow-x-auto">
                  <table className="w-full text-sm min-w-[520px]">
                    <thead><tr className="text-left text-xs text-slate-500 uppercase tracking-wide border-b border-slate-100"><th className="px-4 sm:px-5 py-2.5 font-medium">Origem</th><th className="px-3 py-2.5 font-medium text-right">Vendas</th><th className="px-3 py-2.5 font-medium text-right">Receita</th><th className="px-3 py-2.5 font-medium text-right">Custo</th><th className="px-4 sm:px-5 py-2.5 font-medium text-right">Lucro</th></tr></thead>
                    <tbody className="divide-y divide-slate-100">
                      {orgPorOrigem.map((o) => (
                        <tr key={o.origem} className="hover:bg-slate-50/60"><td className="px-4 sm:px-5 py-3 font-medium text-slate-800">{o.origem}</td><td className="px-3 py-3 text-right tabular-nums">{o.n}</td><td className="px-3 py-3 text-right tabular-nums">{brl(o.receita)}</td><td className="px-3 py-3 text-right tabular-nums text-slate-500">{brl(o.custo)}</td><td className="px-4 sm:px-5 py-3 text-right tabular-nums font-semibold"><span className={o.lucro > 0 ? 'text-emerald-600' : o.lucro < 0 ? 'text-rose-600' : 'text-slate-500'}>{brl(o.lucro)}</span></td></tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </Card>
            {recentesAba.length > 0 && (
              <Card icon={<Receipt size={16} className="text-slate-600" />} title={`Vendas orgânicas · ${per.label}`} defaultOpen={false}>
                <div className="p-4 sm:p-5 flex flex-col divide-y divide-slate-100">{recentesAba.map(renderVenda)}</div>
              </Card>
            )}
          </div>
        )}

        <p className="text-center text-xs text-slate-400 pb-4">CPA real = gasto (com imposto) ÷ vendas de anúncio &nbsp;·&nbsp; ROAS = receita ÷ gasto &nbsp;·&nbsp; Lucro = receita − custo − gasto. Dados salvos automaticamente.</p>
      </main>

      <style>{`
        .inp { width:100%; border:1px solid rgb(203 213 225); border-radius:0.5rem; padding:0.5rem 0.625rem; font-size:0.875rem; background:#fff; outline:none; }
        .inp:focus { border-color:rgb(100 116 139); box-shadow:0 0 0 3px rgb(148 163 184 / 0.15); }
      `}</style>
    </div>
  );
}

function Card({ icon, title, right, children, defaultOpen = true, onMoveUp, onMoveDown }) {
  const [open, setOpen] = useState(defaultOpen);
  const showMove = onMoveUp !== undefined || onMoveDown !== undefined;
  return (
    <section className="bg-white border border-slate-200 rounded-xl shadow-sm">
      <div className="px-4 sm:px-5 py-3 border-b border-slate-100 flex items-center justify-between gap-3">
        <div className="flex items-center gap-2 min-w-0">
          {showMove && (
            <span className="flex flex-col shrink-0 -my-1">
              <button onClick={onMoveUp || undefined} disabled={!onMoveUp} className="text-slate-300 hover:text-slate-600 disabled:opacity-25 disabled:hover:text-slate-300 leading-none" aria-label="Mover bloco para cima"><ChevronUp size={15} /></button>
              <button onClick={onMoveDown || undefined} disabled={!onMoveDown} className="text-slate-300 hover:text-slate-600 disabled:opacity-25 disabled:hover:text-slate-300 leading-none" aria-label="Mover bloco para baixo"><ChevronDown size={15} /></button>
            </span>
          )}
          <button onClick={() => setOpen((o) => !o)} className="flex items-center gap-2 min-w-0 text-left">
            <ChevronDown size={16} className={`text-slate-400 transition-transform ${open ? '' : '-rotate-90'}`} />
            {icon}<h2 className="font-semibold text-slate-800 truncate">{title}</h2>
          </button>
        </div>
        {right && <div className="shrink-0">{right}</div>}
      </div>
      {open && <div>{children}</div>}
    </section>
  );
}
function TabBtn({ active, onClick, children }) {
  return <button onClick={onClick} className={`px-4 py-2.5 text-sm font-medium -mb-px border-b-2 transition flex items-center ${active ? 'border-slate-900 text-slate-900' : 'border-transparent text-slate-400 hover:text-slate-600'}`}>{children}</button>;
}
function Kpi({ icon, label, value, tone }) {
  const tones = { slate: 'text-slate-800', emerald: 'text-emerald-600', rose: 'text-rose-600' };
  return (
    <div className="bg-white border border-slate-200 rounded-xl shadow-sm p-3.5">
      <div className="flex items-center gap-1.5 text-slate-400 text-xs mb-1.5">{icon}<span className="truncate">{label}</span></div>
      <div className={`text-xl sm:text-2xl font-semibold tabular-nums ${tones[tone] || tones.slate}`}>{value}</div>
    </div>
  );
}
function MiniStat({ label, value, sub, tone }) {
  const tones = { slate: 'text-slate-800', emerald: 'text-emerald-600', rose: 'text-rose-600' };
  return (
    <div className="rounded-lg bg-slate-50 border border-slate-100 p-3">
      <div className="text-xs text-slate-400 mb-1">{label}</div>
      <div className={`text-lg font-semibold tabular-nums ${tones[tone] || tones.slate}`}>{value}</div>
      {sub && <div className="text-[11px] text-slate-400 mt-0.5 tabular-nums">{sub}</div>}
    </div>
  );
}
function Field({ label, children, className = '' }) {
  return <label className={`flex flex-col gap-1 ${className}`}><span className="text-xs text-slate-500">{label}</span>{children}</label>;
}


createRoot(document.getElementById('root')).render(<App />);
