const { useState, useEffect, useMemo } = React;

/* ---------- utilidades ---------- */
const uid = () => Math.random().toString(36).slice(2, 9);
const pad = n => String(n).padStart(2, "0");
const ymd = d => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
const parse = s => { const [y, m, d] = s.split("-").map(Number); return new Date(y, m - 1, d); };
const addDays = (n, base = new Date()) => { const d = new Date(base); d.setDate(d.getDate() + n); return ymd(d); };
const TODAY = ymd(new Date());
const brl = v => v.toLocaleString("pt-BR", { style: "currency", currency: "BRL", maximumFractionDigits: 0 });
const fmtDay = s => parse(s).toLocaleDateString("pt-BR", { day: "2-digit", month: "short" }).replace(".", "");
const MONTHS = ["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"];
const WEEK = ["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"];
const weekRange = () => { const d = new Date(); const s = new Date(d); s.setDate(d.getDate() - d.getDay()); const e = new Date(s); e.setDate(s.getDate() + 6); return [ymd(s), ymd(e)]; };

const EVENT_TYPES = {
  "Produção":   { c: "var(--ocean)", bg: "var(--ocean-bg)" },
  "Fornecedor": { c: "var(--warn)",  bg: "var(--warn-bg)" },
  "Gravação":   { c: "var(--shell)", bg: "var(--shell-bg)" },
  "Entrega":    { c: "var(--sage)",  bg: "var(--ok-bg)" },
  "Pessoal":    { c: "var(--muted)", bg: "var(--raised)" },
};
const STAGES = ["Ideia", "Roteiro", "Gravar", "Edição", "Publicado"];
const FORMATS = ["Reels", "Carrossel", "Stories", "TikTok", "Foto"];
const KINDS = ["Comercial", "Posicionamento de marca"];
const kindStyle = { "Comercial": { color: "var(--warn)", background: "var(--warn-bg)" }, "Posicionamento de marca": { color: "var(--ocean)", background: "var(--ocean-bg)" } };
const kindShort = k => k === "Posicionamento de marca" ? "Posicionamento" : k;

/* ---------- dados de exemplo ---------- */
function seed() {
  return {
    tasks: [
      { id: uid(), text: "Conferir corte das peças da legging nova", done: false },
      { id: uid(), text: "Responder directs de trocas pendentes", done: true },
      { id: uid(), text: "Separar looks para a gravação de amanhã", done: false },
      { id: uid(), text: "Postar 3 stories com a coleção Verão", done: false },
    ],
    suppliers: [
      { id: uid(), name: "Malharia Atlântica", cat: "Tecido UV50+", contact: "Rogério", phone: "(11) 98812-4410", lead: 15, status: "Ativo", rating: 5, notes: "Lote mínimo 30 m por cor. Prazo aperta em novembro." },
      { id: uid(), name: "Tecelagem Ritmo", cat: "Suplex e poliamida fitness", contact: "Débora", phone: "(11) 97455-2031", lead: 12, status: "Ativo", rating: 4, notes: "Melhor compressão para legging cintura alta." },
      { id: uid(), name: "Aviamentos Costa Sul", cat: "Bojos, alças, argolas", contact: "Sr. Paulo", phone: "(13) 99610-7782", lead: 7, status: "Ativo", rating: 4, notes: "Argolas douradas esgotam rápido." },
      { id: uid(), name: "Estamparia Maré", cat: "Sublimação", contact: "Luana", phone: "(11) 96320-1188", lead: 10, status: "Em negociação", rating: 3, notes: "Pedir prova da estampa folhagem antes de fechar." },
      { id: uid(), name: "Etiquetas Brisa", cat: "Tags e embalagens", contact: "Fábio", phone: "(11) 95544-9020", lead: 20, status: "Pausado", rating: 4, notes: "Nova embalagem kraft em orçamento." },
    ],
    products: [
      { id: uid(), sku: "SOL-BW-01", name: "Biquíni Cortininha Duna", line: "Beach", price: 189, stock: 14, color: "#C99368", supplier: "Malharia Atlântica" },
      { id: uid(), sku: "SOL-BW-02", name: "Maiô Maré Alta UV50+", line: "Beach", price: 289, stock: 4, color: "#1F5F66", supplier: "Malharia Atlântica" },
      { id: uid(), sku: "SOL-BW-03", name: "Saída de Linho Brisa", line: "Beach", price: 219, stock: 9, color: "#E4D8C4", supplier: "Estamparia Maré" },
      { id: uid(), sku: "SOL-BW-04", name: "Camisa UV Horizonte", line: "Beach", price: 239, stock: 6, color: "#86B9AC", supplier: "Malharia Atlântica" },
      { id: uid(), sku: "SOL-FT-01", name: "Top Pulso", line: "Fitness", price: 129, stock: 22, color: "#2B3A3D", supplier: "Tecelagem Ritmo" },
      { id: uid(), sku: "SOL-FT-02", name: "Legging Ritmo Cintura Alta", line: "Fitness", price: 199, stock: 3, color: "#6E7F5C", supplier: "Tecelagem Ritmo" },
      { id: uid(), sku: "SOL-FT-03", name: "Short Tempo", line: "Fitness", price: 149, stock: 11, color: "#C47F76", supplier: "Tecelagem Ritmo" },
      { id: uid(), sku: "SOL-FT-04", name: "Conjunto Corrida Areia", line: "Fitness", price: 279, stock: 0, color: "#D2B48C", supplier: "Tecelagem Ritmo" },
    ],
    clients: [
      { id: uid(), name: "Mariana Lopes", phone: "(11) 99231-5520", city: "Santo André", tag: "VIP", channel: "Instagram", notes: "Veste P no top e M na calcinha. Ama cores terrosas.",
        orders: [o(-3, "Maiô Maré Alta + Saída Brisa", 508), o(-41, "Biquíni Duna", 189), o(-96, "Camisa UV Horizonte", 239), o(-150, "Kit 2 biquínis", 360)] },
      { id: uid(), name: "Camila Ferreira", phone: "(11) 98470-3312", city: "São Bernardo do Campo", tag: "Recorrente", channel: "WhatsApp", notes: "Treina crossfit. Pediu aviso quando a legging oliva voltar.",
        orders: [o(-8, "Top Pulso + Short Tempo", 278), o(-62, "Legging Ritmo", 199)] },
      { id: uid(), name: "Juliana Prado", phone: "(11) 97781-0045", city: "São Paulo", tag: "Nova", channel: "Site", notes: "Primeira compra veio pelo anúncio de UV50+.",
        orders: [o(-15, "Camisa UV Horizonte", 239)] },
      { id: uid(), name: "Beatriz Nunes", phone: "(13) 99102-7764", city: "Guarujá", tag: "VIP", channel: "Instagram", notes: "Revende para amigas da praia. Prefere pagar no Pix.",
        orders: [o(-1, "Kit 4 biquínis Duna", 680), o(-33, "2 Saídas Brisa", 438), o(-75, "Maiô Maré Alta", 289), o(-122, "Kit verão", 540)] },
      { id: uid(), name: "Renata Okamoto", phone: "(11) 96655-2189", city: "Diadema", tag: "Recorrente", channel: "WhatsApp", notes: "Pediu troca de tamanho na última compra (M → G).",
        orders: [o(-27, "Conjunto Corrida Areia", 279), o(-88, "Top Pulso", 129)] },
      { id: uid(), name: "Patrícia Vidal", phone: "(11) 95420-6631", city: "Santo André", tag: "Inativa", channel: "Instagram", notes: "Sem compras há mais de 5 meses. Enviar cupom.",
        orders: [o(-170, "Biquíni Duna", 189)] },
    ],
    events: [
      { id: uid(), date: addDays(0), time: "10:00", title: "Prova de modelagem da legging nova", type: "Produção" },
      { id: uid(), date: addDays(0), time: "15:30", title: "Ligar Malharia Atlântica sobre prazo UV50+", type: "Fornecedor" },
      { id: uid(), date: addDays(1), time: "08:00", title: "Gravação Reels coleção Verão na praia", type: "Gravação" },
      { id: uid(), date: addDays(3), time: "11:00", title: "Postagem dos pedidos da semana", type: "Entrega" },
      { id: uid(), date: addDays(5), time: "14:00", title: "Visita Estamparia Maré: prova de estampa", type: "Fornecedor" },
      { id: uid(), date: addDays(-2), time: "09:00", title: "Corte do lote de maiôs", type: "Produção" },
      { id: uid(), date: addDays(9), time: "07:30", title: "Fotos do lookbook fitness", type: "Gravação" },
      { id: uid(), date: addDays(14), time: "19:00", title: "Lançamento da coleção Verão", type: "Produção" },
      { id: uid(), date: addDays(6), time: "18:00", title: "Pilates", type: "Pessoal" },
    ],
    content: [
      { id: uid(), title: "Bastidores: corte do tecido UV", kind: "Posicionamento de marca", format: "Reels", stage: "Gravar", date: addDays(1), notes: "Close na tesoura, som ambiente." },
      { id: uid(), title: "Teste de proteção UV na prática", kind: "Comercial", format: "Reels", stage: "Gravar", date: addDays(2), notes: "Cartão UV ao sol com e sem tecido." },
      { id: uid(), title: "Provador: legging cintura alta", kind: "Comercial", format: "TikTok", stage: "Gravar", date: addDays(4), notes: "Agachamento para mostrar que não fica transparente." },
      { id: uid(), title: "Como escolher o tamanho do maiô", kind: "Comercial", format: "Carrossel", stage: "Roteiro", date: addDays(6), notes: "Tabela de medidas + 3 erros comuns." },
      { id: uid(), title: "Do mar ao treino com uma peça só", kind: "Posicionamento de marca", format: "Reels", stage: "Ideia", date: "", notes: "Transição praia → academia." },
      { id: uid(), title: "Perguntas da semana nos stories", kind: "Posicionamento de marca", format: "Stories", stage: "Ideia", date: "", notes: "" },
      { id: uid(), title: "Unboxing da embalagem nova", kind: "Posicionamento de marca", format: "Reels", stage: "Edição", date: addDays(-1), notes: "Falta legenda e capa." },
      { id: uid(), title: "Provador: maiô Maré Alta", kind: "Comercial", format: "Reels", stage: "Publicado", date: addDays(-4), notes: "" },
    ],
    inspo: [
      { id: uid(), title: "Luz de fim de tarde na areia", note: "Gravar entre 16h30 e 17h15, contra a luz.", tag: "Luz", tone: "#A39382" },
      { id: uid(), title: "Tecido molhado x seco", note: "Mostrar que a cor não muda depois do mergulho.", tag: "Produto", tone: "#685D54" },
      { id: uid(), title: "Paleta areia + oliva", note: "Para o feed de novembro.", tag: "Paleta", tone: "#E5DED2" },
      { id: uid(), title: "Mãos costurando em câmera lenta", note: "Reforça a fabricação própria.", tag: "Bastidores", tone: "#B58C7A" },
    ],
    extraSales: [
      { id: uid(), date: addDays(-5), client: "Venda avulsa", channel: "Feira", items: "2 Tops Pulso", value: 258 },
    ],
    defaultGoal: 3000,
    goals: {},
    calc: { cost: 58, pkg: 4.5, tag: 1.2, ship: 6, mode: "margem", margin: 45, markup: 2.5, fees: 5 },
    brand: { logo: "", manualName: "", manualLink: "", fontFiles: "", fontsLink: "" },
  };
  function o(d, items, value) { return { id: uid(), date: addDays(d), items, value }; }
}

const KEY = "qg-solare-v1";
const load = () => { try { const r = localStorage.getItem(KEY); return r ? JSON.parse(r) : null; } catch { return null; } };
const save = s => { try { localStorage.setItem(KEY, JSON.stringify(s)); } catch {} };

/* ---------- ícones ---------- */
const I = ({ d, s = 18 }) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">{d}</svg>;
const icons = {
  home: <I d={<><path d="M3 12h4l3-8 4 16 3-8h4"/></>} />,
  box: <I d={<><path d="M21 8 12 3 3 8v8l9 5 9-5V8Z"/><path d="m3 8 9 5 9-5M12 13v8"/></>} />,
  users: <I d={<><circle cx="9" cy="8" r="3.5"/><path d="M2.5 20c.8-3.5 3.4-5.5 6.5-5.5s5.7 2 6.5 5.5"/><path d="M16 4.5a3.5 3.5 0 0 1 0 7M18.5 14.8c1.6.8 2.6 2.6 3 5.2"/></>} />,
  cal: <I d={<><rect x="3" y="4.5" width="18" height="16" rx="2.5"/><path d="M3 9.5h18M8 3v3M16 3v3"/></>} />,
  cam: <I d={<><rect x="2.5" y="6" width="14" height="12" rx="2.5"/><path d="m16.5 10.5 5-3v9l-5-3"/></>} />,
  plus: <I s={16} d={<path d="M12 5v14M5 12h14"/>} />,
  x: <I s={16} d={<path d="M6 6l12 12M18 6 6 18"/>} />,
  search: <I s={16} d={<><circle cx="11" cy="11" r="6.5"/><path d="m20 20-4-4"/></>} />,
  left: <I s={16} d={<path d="m15 6-6 6 6 6"/>} />,
  right: <I s={16} d={<path d="m9 6 6 6-6 6"/>} />,
  coin: <I d={<><path d="M3 17l5-5 4 3 8-8"/><path d="M15 7h5v5"/></>} />,
  tick: <I s={13} d={<path d="m5 12 4.5 4.5L19 7"/>} />,
  trash: <I s={15} d={<><path d="M4 7h16M9 7V4.5h6V7M6.5 7l1 13h9l1-13"/></>} />,
  sun: <I s={16} d={<><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></>} />,
  moon: <I s={16} d={<path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5Z"/>} />,
};

/* ---------- peças comuns ---------- */
function Modal({ title, onClose, children, wide }) {
  useEffect(() => { const k = e => e.key === "Escape" && onClose(); window.addEventListener("keydown", k); return () => window.removeEventListener("keydown", k); }, []);
  return (
    <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4" style={{ background: "rgba(8,20,22,.45)" }} onClick={onClose}>
      <div className={"card w-full p-5 fade max-h-[90vh] overflow-y-auto " + (wide ? "max-w-2xl" : "max-w-md")} style={{ boxShadow: "0 20px 60px rgba(0,0,0,.25)" }} onClick={e => e.stopPropagation()} role="dialog" aria-label={title}>
        <div className="flex items-center justify-between mb-4">
          <h3 className="display text-2xl">{title}</h3>
          <button onClick={onClose} className="btn btn-ghost !p-2" aria-label="Fechar">{icons.x}</button>
        </div>
        {children}
      </div>
    </div>
  );
}
function Field({ label, children }) { return <label className="flex flex-col gap-1.5"><span className="label">{label}</span>{children}</label>; }
function Form({ fields, initial = {}, onSubmit, submit = "Salvar" }) {
  const [v, setV] = useState(() => Object.fromEntries(fields.map(f => [f.k, initial[f.k] ?? f.def ?? ""])));
  return (
    <form className="flex flex-col gap-3" onSubmit={e => { e.preventDefault(); if (fields.some(f => f.req && !String(v[f.k]).trim())) return; onSubmit(v); }}>
      <div className="grid grid-cols-2 gap-3">
        {fields.map(f => (
          <div key={f.k} className={f.half ? "col-span-1" : "col-span-2"}>
            <Field label={f.label + (f.req ? " *" : "")}>
              {f.opts ? (
                <select id={"f-" + f.k} className="input" value={v[f.k]} onChange={e => setV({ ...v, [f.k]: e.target.value })}>{f.opts.map(o => <option key={o}>{o}</option>)}</select>
              ) : f.area ? (
                <textarea id={"f-" + f.k} className="input" rows="3" value={v[f.k]} onChange={e => setV({ ...v, [f.k]: e.target.value })} />
              ) : (
                <input id={"f-" + f.k} className="input" type={f.type || "text"} value={v[f.k]} onChange={e => setV({ ...v, [f.k]: e.target.value })} />
              )}
            </Field>
          </div>
        ))}
      </div>
      <button className="btn btn-primary self-end mt-1" type="submit">{submit}</button>
    </form>
  );
}
function SectionHead({ eyebrow, title, children }) {
  return (
    <div className="flex flex-wrap items-end justify-between gap-3 mb-6">
      <div><div className="label mb-1">{eyebrow}</div><h1 className="display text-4xl sm:text-5xl leading-none">{title}</h1></div>
      <div className="flex flex-wrap gap-2">{children}</div>
    </div>
  );
}
function Check({ on, onClick, label }) {
  return <span role="checkbox" aria-checked={on} aria-label={label} tabIndex="0" className="check" onClick={onClick} onKeyDown={e => (e.key === " " || e.key === "Enter") && (e.preventDefault(), onClick())}>{on && icons.tick}</span>;
}
const tagStyle = {
  VIP: { color: "var(--sun)", background: "var(--sun-bg)" },
  Recorrente: { color: "var(--ok)", background: "var(--ok-bg)" },
  Nova: { color: "var(--ocean)", background: "var(--ocean-bg)" },
  Inativa: { color: "var(--muted)", background: "var(--raised)" },
};
const statusStyle = {
  "Ativo": { color: "var(--ok)", background: "var(--ok-bg)" },
  "Em negociação": { color: "var(--warn)", background: "var(--warn-bg)" },
  "Pausado": { color: "var(--muted)", background: "var(--raised)" },
};
const allSales = db => [
  ...db.clients.flatMap(c => c.orders.map(o => ({ ...o, client: c.name, channel: c.channel }))),
  ...(db.extraSales || []),
];
const goalOf = (db, k) => db.goals?.[k] ?? db.defaultGoal ?? 0;
const brl2 = v => v.toLocaleString("pt-BR", { style: "currency", currency: "BRL", minimumFractionDigits: 2, maximumFractionDigits: 2 });
const BRAND_COLORS = [
  { n: "Milk", h: "#FBF7F4" }, { n: "Oat", h: "#E5DED2" }, { n: "Taupe", h: "#A39382" },
  { n: "Mocha", h: "#685D54" }, { n: "Charcoal", h: "#232323", note: "só texto e subtexto" },
];
const stockState = s => s === 0 ? { t: "Esgotado", c: "var(--crit)", bg: "var(--crit-bg)" } : s <= 5 ? { t: "Baixo", c: "var(--warn)", bg: "var(--warn-bg)" } : { t: "Ok", c: "var(--ok)", bg: "var(--ok-bg)" };

/* ---------- 1. Visão geral ---------- */
function Overview({ db, set, go }) {
  const [t, setT] = useState("");
  const now = new Date();
  const monthKey = TODAY.slice(0, 7);
  const allOrders = allSales(db);
  const goal = goalOf(db, TODAY.slice(0, 7));
  const monthOrders = allOrders.filter(o => o.date.startsWith(monthKey));
  const revenue = monthOrders.reduce((a, o) => a + o.value, 0);
  const low = db.products.filter(p => p.stock <= 5);
  const [ws, we] = weekRange();
  const toRecord = db.content.filter(c => c.stage === "Gravar" && c.date && c.date >= ws && c.date <= we);
  const todayEvents = db.events.filter(e => e.date === TODAY).sort((a, b) => a.time.localeCompare(b.time));
  const upcoming = db.events.filter(e => e.date > TODAY).sort((a, b) => (a.date + a.time).localeCompare(b.date + b.time)).slice(0, 4);

  const months = [...Array(6)].map((_, i) => { const d = new Date(now.getFullYear(), now.getMonth() - 5 + i, 1); const k = `${d.getFullYear()}-${pad(d.getMonth() + 1)}`; return { k, l: MONTHS[d.getMonth()].slice(0, 3), v: allOrders.filter(o => o.date.startsWith(k)).reduce((a, o) => a + o.value, 0) }; });
  const max = Math.max(...months.map(m => m.v), 1);
  const hour = now.getHours();
  const greet = hour < 12 ? "Bom dia" : hour < 18 ? "Boa tarde" : "Boa noite";
  const done = db.tasks.filter(x => x.done).length;

  const metrics = [
    { l: "Faturamento do mês", v: brl(revenue), s: `${monthOrders.length} pedidos · ${goal ? Math.round(revenue / goal * 100) : 0}% da meta`, to: "vendas" },
    { l: "Estoque em alerta", v: low.length, s: `${low.filter(p => p.stock === 0).length} esgotado`, to: "produtos", warn: low.length > 0 },
    { l: "Gravações da semana", v: toRecord.length, s: "pendentes de gravar", to: "marketing" },
    { l: "Compromissos hoje", v: todayEvents.length, s: upcoming[0] ? `próximo: ${fmtDay(upcoming[0].date)}` : "agenda livre", to: "calendario" },
  ];

  return (
    <div className="fade">
      <div className="mb-8">
        <div className="label mb-2">{now.toLocaleDateString("pt-BR", { weekday: "long", day: "numeric", month: "long" })}</div>
        <h1 className="display text-5xl sm:text-6xl leading-[.95]">{greet}, Ana. <span style={{ color: "var(--sea)" }}>Maré boa hoje.</span></h1>
      </div>

      <div className="grid grid-cols-2 lg:grid-cols-4 gap-3 mb-6">
        {metrics.map(m => (
          <button key={m.l} onClick={() => go(m.to)} className="card p-4 text-left rowhover transition-colors">
            <div className="label">{m.l}</div>
            <div className="mono text-2xl sm:text-3xl mt-2 font-medium" style={{ color: m.warn ? "var(--warn)" : "var(--ink)" }}>{m.v}</div>
            <div className="text-xs mt-1" style={{ color: "var(--muted)" }}>{m.s}</div>
          </button>
        ))}
      </div>

      <div className="grid lg:grid-cols-5 gap-4">
        <div className="card p-5 lg:col-span-3 min-w-0">
          <div className="flex items-center justify-between mb-3">
            <h2 className="display text-2xl">Avisos do dia</h2>
            <span className="mono text-xs" style={{ color: "var(--muted)" }}>{done}/{db.tasks.length} feitos</span>
          </div>
          <div className="h-1.5 rounded-full mb-4 overflow-hidden" style={{ background: "var(--raised)" }}>
            <div className="h-full rounded-full transition-all" style={{ width: `${db.tasks.length ? done / db.tasks.length * 100 : 0}%`, background: "var(--sea)" }} />
          </div>
          <ul className="flex flex-col">
            {todayEvents.map(e => (
              <li key={e.id} className="flex items-center gap-3 py-2.5 border-b" style={{ borderColor: "var(--line)" }}>
                <span className="w-1 h-7 rounded-full" style={{ background: EVENT_TYPES[e.type].c }} />
                <span className="mono text-xs w-11" style={{ color: "var(--muted)" }}>{e.time}</span>
                <span className="flex-1 min-w-0 font-medium">{e.title}</span>
                <span className="chip" style={{ color: EVENT_TYPES[e.type].c, background: EVENT_TYPES[e.type].bg }}>{e.type}</span>
              </li>
            ))}
            {db.tasks.map(x => (
              <li key={x.id} className="group flex items-center gap-3 py-2.5 border-b" style={{ borderColor: "var(--line)" }}>
                <Check on={x.done} label={x.text} onClick={() => set({ tasks: db.tasks.map(y => y.id === x.id ? { ...y, done: !y.done } : y) })} />
                <span className="flex-1 min-w-0" style={{ color: x.done ? "var(--muted)" : "var(--ink)", textDecoration: x.done ? "line-through" : "none" }}>{x.text}</span>
                <button className="opacity-0 group-hover:opacity-100 focus:opacity-100" style={{ color: "var(--muted)" }} onClick={() => set({ tasks: db.tasks.filter(y => y.id !== x.id) })} aria-label="Remover aviso">{icons.trash}</button>
              </li>
            ))}
          </ul>
          <form className="flex gap-2 mt-3" onSubmit={e => { e.preventDefault(); if (!t.trim()) return; set({ tasks: [...db.tasks, { id: uid(), text: t.trim(), done: false }] }); setT(""); }}>
            <input id="new-task" className="input" placeholder="Novo aviso para hoje" value={t} onChange={e => setT(e.target.value)} />
            <button className="btn btn-primary" type="submit">{icons.plus}</button>
          </form>
        </div>

        <div className="lg:col-span-2 flex flex-col gap-4 min-w-0">
          <div className="card p-5">
            <div className="flex items-baseline justify-between mb-4">
              <h2 className="display text-2xl">Vendas</h2>
              <span className="label">últimos 6 meses</span>
            </div>
            <div className="flex items-end gap-2 h-32">
              {months.map((m, i) => (
                <div key={m.k} className="flex-1 flex flex-col items-center gap-1.5 h-full justify-end">
                  <span className="mono text-[10px]" style={{ color: i === 5 ? "var(--ink)" : "var(--muted)" }}>{m.v ? (m.v / 1000).toFixed(1) + "k" : "–"}</span>
                  <div className="w-full rounded-t-md" style={{ height: `${Math.max(m.v / max * 100, 3)}%`, background: i === 5 ? "var(--ocean)" : "var(--sea-bg)" }} />
                  <span className="text-[11px]" style={{ color: "var(--muted)" }}>{m.l}</span>
                </div>
              ))}
            </div>
          </div>

          <div className="card p-5">
            <div className="flex items-center justify-between mb-2">
              <h2 className="display text-2xl">Repor estoque</h2>
              <button className="text-xs font-semibold" style={{ color: "var(--ocean)" }} onClick={() => go("produtos")}>Ver catálogo</button>
            </div>
            {low.length === 0 && <p style={{ color: "var(--muted)" }}>Tudo em dia.</p>}
            {low.map(p => { const s = stockState(p.stock); return (
              <div key={p.id} className="flex items-center gap-3 py-2">
                <span className="w-3 h-3 rounded-full flex-none" style={{ background: p.color }} />
                <span className="flex-1 min-w-0 truncate">{p.name}</span>
                <span className="mono text-xs">{p.stock} un</span>
                <span className="chip" style={{ color: s.c, background: s.bg }}>{s.t}</span>
              </div>); })}
          </div>

          <div className="card p-5">
            <h2 className="display text-2xl mb-2">Próximos dias</h2>
            {upcoming.map(e => (
              <div key={e.id} className="flex items-center gap-3 py-2">
                <span className="mono text-xs w-14 flex-none" style={{ color: "var(--muted)" }}>{fmtDay(e.date)}</span>
                <span className="w-2 h-2 rounded-full flex-none" style={{ background: EVENT_TYPES[e.type].c }} />
                <span className="flex-1 min-w-0 truncate">{e.title}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

/* ---------- 2. Fornecedores & Produtos ---------- */
function Products({ db, set }) {
  const [view, setView] = useState("produtos");
  const [line, setLine] = useState("Todas");
  const [q, setQ] = useState("");
  const [modal, setModal] = useState(null);
  const [open, setOpen] = useState(null);

  const list = db.products.filter(p => (line === "Todas" || p.line === line) && (p.name + p.sku).toLowerCase().includes(q.toLowerCase()));
  const stockValue = db.products.reduce((a, p) => a + p.price * p.stock, 0);
  const adj = (id, d) => set({ products: db.products.map(p => p.id === id ? { ...p, stock: Math.max(0, p.stock + d) } : p) });

  return (
    <div className="fade">
      <SectionHead eyebrow="Operação" title="Fornecedores & Produtos">
        <div className="flex p-1 rounded-full border" style={{ borderColor: "var(--line)", background: "var(--surface)" }}>
          {["produtos", "fornecedores", "calculadora"].map(v => (
            <button key={v} onClick={() => setView(v)} className="px-4 py-1.5 rounded-full text-sm font-semibold capitalize" style={view === v ? { background: "var(--ocean)", color: "var(--on-accent)" } : { color: "var(--muted)" }}>{v}</button>
          ))}
        </div>
        {view !== "calculadora" && <button className="btn btn-primary" onClick={() => setModal(view)}>{icons.plus} {view === "produtos" ? "Produto" : "Fornecedor"}</button>}
      </SectionHead>

      {view === "calculadora" ? <Calculator db={db} set={set} /> : view === "produtos" ? (
        <>
          <div className="flex flex-wrap items-center gap-2 mb-4">
            <div className="relative flex-1 min-w-[180px] max-w-xs">
              <span className="absolute left-3 top-1/2 -translate-y-1/2" style={{ color: "var(--muted)" }}>{icons.search}</span>
              <input id="prod-search" className="input !pl-9" placeholder="Buscar peça ou SKU" value={q} onChange={e => setQ(e.target.value)} />
            </div>
            {["Todas", "Beach", "Fitness"].map(l => (
              <button key={l} onClick={() => setLine(l)} className="btn btn-ghost" style={line === l ? { background: "var(--ocean)", color: "var(--on-accent)", borderColor: "var(--ocean)" } : {}}>{l}</button>
            ))}
            <span className="ml-auto text-xs" style={{ color: "var(--muted)" }}>Valor em estoque <span className="mono" style={{ color: "var(--ink)" }}>{brl(stockValue)}</span></span>
          </div>
          <div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-3">
            {list.map(p => { const s = stockState(p.stock); return (
              <div key={p.id} className="card overflow-hidden flex flex-col">
                <div className="h-24 relative" style={{ background: p.color }}>
                  <span className="absolute top-3 left-3 chip" style={{ background: "rgba(255,255,255,.85)", color: "#232323" }}>{p.line}</span>
                  <span className="absolute top-3 right-3 chip" style={{ color: s.c, background: s.bg }}>{s.t}</span>
                </div>
                <div className="p-4 flex flex-col gap-1 flex-1">
                  <span className="mono text-[11px]" style={{ color: "var(--muted)" }}>{p.sku}</span>
                  <span className="font-semibold leading-snug">{p.name}</span>
                  <span className="text-xs" style={{ color: "var(--muted)" }}>{p.supplier}</span>
                  <div className="flex items-center justify-between mt-auto pt-3">
                    <span className="mono font-medium">{brl(p.price)}</span>
                    <div className="flex items-center gap-1">
                      <button className="btn btn-ghost !px-2.5 !py-1" onClick={() => adj(p.id, -1)} aria-label="Diminuir estoque">−</button>
                      <span className="mono w-8 text-center">{p.stock}</span>
                      <button className="btn btn-ghost !px-2.5 !py-1" onClick={() => adj(p.id, 1)} aria-label="Aumentar estoque">+</button>
                    </div>
                  </div>
                </div>
              </div>); })}
            {list.length === 0 && <p style={{ color: "var(--muted)" }}>Nenhuma peça encontrada.</p>}
          </div>
        </>
      ) : (
        <div className="grid sm:grid-cols-2 xl:grid-cols-3 gap-3">
          {db.suppliers.map(s => (
            <div key={s.id} className="card p-5 flex flex-col gap-3">
              <div className="flex items-start justify-between gap-2">
                <div className="min-w-0">
                  <div className="display text-2xl leading-tight">{s.name}</div>
                  <div className="text-sm" style={{ color: "var(--muted)" }}>{s.cat}</div>
                </div>
                <span className="chip" style={statusStyle[s.status]}>{s.status}</span>
              </div>
              <div className="grid grid-cols-3 gap-2 text-center">
                <div className="rounded-lg py-2" style={{ background: "var(--raised)" }}><div className="mono text-lg">{s.lead}d</div><div className="label !text-[9px]">prazo</div></div>
                <div className="rounded-lg py-2" style={{ background: "var(--raised)" }}><div className="mono text-lg">{db.products.filter(p => p.supplier === s.name).length}</div><div className="label !text-[9px]">peças</div></div>
                <div className="rounded-lg py-2" style={{ background: "var(--raised)" }}><div className="text-lg" style={{ color: "var(--sun)" }}>{"●".repeat(s.rating)}<span style={{ color: "var(--line)" }}>{"●".repeat(5 - s.rating)}</span></div><div className="label !text-[9px]">avaliação</div></div>
              </div>
              <div className="text-sm"><span style={{ color: "var(--muted)" }}>Contato:</span> {s.contact} · <span className="mono select-all">{s.phone}</span></div>
              {open === s.id ? (
                <textarea id={"notes-" + s.id} className="input text-sm" rows="3" value={s.notes} onChange={e => set({ suppliers: db.suppliers.map(x => x.id === s.id ? { ...x, notes: e.target.value } : x) })} onBlur={() => setOpen(null)} autoFocus />
              ) : (
                <button className="text-sm text-left rounded-lg p-3 rowhover" style={{ background: "var(--raised)", color: "var(--muted)" }} onClick={() => setOpen(s.id)}>{s.notes || "Adicionar anotação"}</button>
              )}
            </div>
          ))}
        </div>
      )}

      {modal === "produtos" && <Modal title="Novo produto" onClose={() => setModal(null)}>
        <Form fields={[
          { k: "name", label: "Nome", req: true }, { k: "sku", label: "SKU", half: true }, { k: "line", label: "Linha", opts: ["Beach", "Fitness"], half: true },
          { k: "price", label: "Preço (R$)", type: "number", half: true, req: true }, { k: "stock", label: "Estoque", type: "number", half: true, def: 0 },
          { k: "color", label: "Cor", type: "color", half: true, def: "#A39382" }, { k: "supplier", label: "Fornecedor", opts: db.suppliers.map(s => s.name), half: true },
        ]} onSubmit={v => { set({ products: [...db.products, { ...v, id: uid(), price: +v.price, stock: +v.stock || 0 }] }); setModal(null); }} />
      </Modal>}
      {modal === "fornecedores" && <Modal title="Novo fornecedor" onClose={() => setModal(null)}>
        <Form fields={[
          { k: "name", label: "Nome", req: true }, { k: "cat", label: "O que fornece" },
          { k: "contact", label: "Contato", half: true }, { k: "phone", label: "Telefone", half: true },
          { k: "lead", label: "Prazo (dias)", type: "number", half: true, def: 10 }, { k: "status", label: "Status", opts: ["Ativo", "Em negociação", "Pausado"], half: true },
          { k: "notes", label: "Anotações", area: true },
        ]} onSubmit={v => { set({ suppliers: [...db.suppliers, { ...v, id: uid(), lead: +v.lead || 0, rating: 4 }] }); setModal(null); }} />
      </Modal>}
    </div>
  );
}

/* ---------- 3. Clientes ---------- */
function Clients({ db, set }) {
  const [q, setQ] = useState("");
  const [tag, setTag] = useState("Todas");
  const [sel, setSel] = useState(db.clients[0]?.id);
  const [modal, setModal] = useState(null);

  const enriched = db.clients.map(c => {
    const sorted = [...c.orders].sort((a, b) => b.date.localeCompare(a.date));
    return { ...c, orders: sorted, total: c.orders.reduce((a, o) => a + o.value, 0), last: sorted[0]?.date };
  });
  const list = enriched.filter(c => (tag === "Todas" || c.tag === tag) && (c.name + c.city).toLowerCase().includes(q.toLowerCase())).sort((a, b) => (b.last || "").localeCompare(a.last || ""));
  const c = enriched.find(x => x.id === sel);
  const daysSince = d => d ? Math.round((parse(TODAY) - parse(d)) / 864e5) : null;

  return (
    <div className="fade">
      <SectionHead eyebrow="Relacionamento" title="Clientes">
        <button className="btn btn-primary" onClick={() => setModal("client")}>{icons.plus} Cliente</button>
      </SectionHead>
      <div className="flex flex-wrap items-center gap-2 mb-4">
        <div className="relative flex-1 min-w-[180px] max-w-xs">
          <span className="absolute left-3 top-1/2 -translate-y-1/2" style={{ color: "var(--muted)" }}>{icons.search}</span>
          <input id="cli-search" className="input !pl-9" placeholder="Buscar por nome ou cidade" value={q} onChange={e => setQ(e.target.value)} />
        </div>
        {["Todas", "VIP", "Recorrente", "Nova", "Inativa"].map(t => (
          <button key={t} onClick={() => setTag(t)} className="btn btn-ghost" style={tag === t ? { background: "var(--ocean)", color: "var(--on-accent)", borderColor: "var(--ocean)" } : {}}>{t}</button>
        ))}
      </div>

      <div className="grid lg:grid-cols-5 gap-4">
        <div className="card lg:col-span-3 min-w-0 scroll-x">
          <table className="w-full text-sm" style={{ minWidth: 520 }}>
            <thead><tr className="text-left">{["Cliente", "Perfil", "Último pedido", "Total"].map(h => <th key={h} className="label px-4 py-3 font-semibold">{h}</th>)}</tr></thead>
            <tbody>
              {list.map(x => (
                <tr key={x.id} onClick={() => setSel(x.id)} className="cursor-pointer rowhover border-t" style={{ borderColor: "var(--line)", background: sel === x.id ? "var(--raised)" : undefined }}>
                  <td className="px-4 py-3"><div className="font-semibold">{x.name}</div><div className="text-xs" style={{ color: "var(--muted)" }}>{x.city}</div></td>
                  <td className="px-4 py-3"><span className="chip" style={tagStyle[x.tag]}>{x.tag}</span></td>
                  <td className="px-4 py-3 mono text-xs">{x.last ? `${fmtDay(x.last)} · ${daysSince(x.last)}d` : "–"}</td>
                  <td className="px-4 py-3 mono">{brl(x.total)}</td>
                </tr>
              ))}
            </tbody>
          </table>
          {list.length === 0 && <p className="p-4" style={{ color: "var(--muted)" }}>Ninguém com esse filtro.</p>}
        </div>

        {c && <div className="card p-5 lg:col-span-2 min-w-0 flex flex-col gap-4 self-start">
          <div className="flex items-start justify-between gap-2">
            <div>
              <div className="display text-3xl leading-tight">{c.name}</div>
              <div className="text-sm" style={{ color: "var(--muted)" }}>{c.city} · via {c.channel}</div>
            </div>
            <select id="cli-tag" className="input !w-auto !py-1 text-xs" value={c.tag} onChange={e => set({ clients: db.clients.map(x => x.id === c.id ? { ...x, tag: e.target.value } : x) })}>
              {["VIP", "Recorrente", "Nova", "Inativa"].map(t => <option key={t}>{t}</option>)}
            </select>
          </div>
          <div className="grid grid-cols-3 gap-2">
            {[["Total", brl(c.total)], ["Pedidos", c.orders.length], ["Ticket", brl(c.orders.length ? c.total / c.orders.length : 0)]].map(([l, v]) => (
              <div key={l} className="rounded-lg p-3" style={{ background: "var(--raised)" }}><div className="label !text-[9px]">{l}</div><div className="mono mt-1">{v}</div></div>
            ))}
          </div>
          <div className="text-sm">Telefone <span className="mono select-all">{c.phone}</span></div>
          <Field label="Anotações">
            <textarea id="cli-notes" className="input text-sm" rows="2" value={c.notes} onChange={e => set({ clients: db.clients.map(x => x.id === c.id ? { ...x, notes: e.target.value } : x) })} />
          </Field>
          <div>
            <div className="flex items-center justify-between mb-2"><span className="label">Histórico</span>
              <button className="text-xs font-semibold" style={{ color: "var(--ocean)" }} onClick={() => setModal("order")}>+ Registrar pedido</button></div>
            <ol className="relative flex flex-col gap-3 pl-4 border-l" style={{ borderColor: "var(--line)" }}>
              {c.orders.map(o => (
                <li key={o.id} className="relative">
                  <span className="absolute -left-[21px] top-1.5 w-2.5 h-2.5 rounded-full" style={{ background: "var(--sea)", boxShadow: "0 0 0 3px var(--surface)" }} />
                  <div className="flex justify-between gap-2"><span className="text-sm">{o.items}</span><span className="mono text-sm">{brl(o.value)}</span></div>
                  <div className="mono text-[11px]" style={{ color: "var(--muted)" }}>{parse(o.date).toLocaleDateString("pt-BR")}</div>
                </li>
              ))}
            </ol>
          </div>
        </div>}
      </div>

      {modal === "client" && <Modal title="Nova cliente" onClose={() => setModal(null)}>
        <Form fields={[
          { k: "name", label: "Nome", req: true }, { k: "phone", label: "Telefone", half: true }, { k: "city", label: "Cidade", half: true },
          { k: "tag", label: "Perfil", opts: ["Nova", "Recorrente", "VIP", "Inativa"], half: true }, { k: "channel", label: "Canal", opts: ["Instagram", "WhatsApp", "Site", "Loja"], half: true },
          { k: "notes", label: "Anotações", area: true },
        ]} onSubmit={v => { const id = uid(); set({ clients: [...db.clients, { ...v, id, orders: [] }] }); setSel(id); setModal(null); }} />
      </Modal>}
      {modal === "order" && c && <Modal title={`Pedido de ${c.name.split(" ")[0]}`} onClose={() => setModal(null)}>
        <Form fields={[
          { k: "items", label: "Peças", req: true }, { k: "value", label: "Valor (R$)", type: "number", half: true, req: true }, { k: "date", label: "Data", type: "date", half: true, def: TODAY },
        ]} onSubmit={v => { set({ clients: db.clients.map(x => x.id === c.id ? { ...x, orders: [...x.orders, { id: uid(), items: v.items, value: +v.value, date: v.date }] } : x) }); setModal(null); }} />
      </Modal>}
    </div>
  );
}

/* ---------- 4. Calendário ---------- */
function Calendar({ db, set }) {
  const now = new Date();
  const [ym, setYm] = useState([now.getFullYear(), now.getMonth()]);
  const [sel, setSel] = useState(TODAY);
  const [modal, setModal] = useState(false);
  const [filter, setFilter] = useState(Object.keys(EVENT_TYPES));
  const [y, m] = ym;
  const first = new Date(y, m, 1);
  const cells = [...Array(42)].map((_, i) => { const d = new Date(y, m, 1 - first.getDay() + i); return { k: ymd(d), day: d.getDate(), inMonth: d.getMonth() === m }; });
  const visible = db.events.filter(e => filter.includes(e.type));
  const byDay = k => visible.filter(e => e.date === k).sort((a, b) => a.time.localeCompare(b.time));
  const move = d => { const n = new Date(y, m + d, 1); setYm([n.getFullYear(), n.getMonth()]); };
  const trimWeeks = cells.slice(35).every(c => !c.inMonth) ? cells.slice(0, 35) : cells;

  return (
    <div className="fade">
      <SectionHead eyebrow="Agenda" title="Calendário & Avisos">
        <button className="btn btn-primary" onClick={() => setModal(true)}>{icons.plus} Compromisso</button>
      </SectionHead>
      <div className="flex flex-wrap gap-2 mb-4">
        {Object.entries(EVENT_TYPES).map(([t, s]) => { const on = filter.includes(t); return (
          <button key={t} onClick={() => setFilter(on ? filter.filter(x => x !== t) : [...filter, t])} className="chip !py-1 !px-3 border" style={on ? { color: s.c, background: s.bg, borderColor: "transparent" } : { color: "var(--muted)", borderColor: "var(--line)" }}>
            <span className="w-2 h-2 rounded-full" style={{ background: on ? s.c : "var(--line)" }} />{t}</button>); })}
      </div>

      <div className="grid xl:grid-cols-4 gap-4">
        <div className="card p-4 xl:col-span-3 min-w-0">
          <div className="flex items-center justify-between mb-3">
            <h2 className="display text-3xl">{MONTHS[m]} <span style={{ color: "var(--muted)" }}>{y}</span></h2>
            <div className="flex gap-1">
              <button className="btn btn-ghost !p-2" onClick={() => move(-1)} aria-label="Mês anterior">{icons.left}</button>
              <button className="btn btn-ghost" onClick={() => { setYm([now.getFullYear(), now.getMonth()]); setSel(TODAY); }}>Hoje</button>
              <button className="btn btn-ghost !p-2" onClick={() => move(1)} aria-label="Próximo mês">{icons.right}</button>
            </div>
          </div>
          <div className="grid grid-cols-7 gap-px rounded-xl overflow-hidden" style={{ background: "var(--line)", border: "1px solid var(--line)" }}>
            {WEEK.map(w => <div key={w} className="label text-center py-2" style={{ background: "var(--surface)" }}>{w}</div>)}
            {trimWeeks.map(c => { const evs = byDay(c.k); const isT = c.k === TODAY, isS = c.k === sel; return (
              <button key={c.k} onClick={() => setSel(c.k)} className="calcell text-left p-1.5 flex flex-col gap-1 transition-colors" style={{ background: isS ? "var(--raised)" : "var(--surface)", opacity: c.inMonth ? 1 : .45, outline: isS ? "2px solid var(--sea)" : "none", outlineOffset: -2 }}>
                <span className="mono text-xs w-6 h-6 grid place-items-center rounded-full" style={isT ? { background: "var(--ocean)", color: "var(--on-accent)" } : {}}>{c.day}</span>
                <span className="hidden sm:flex flex-col gap-0.5 w-full">
                  {evs.slice(0, 2).map(e => <span key={e.id} className="truncate text-[11px] rounded px-1.5 py-0.5" style={{ background: EVENT_TYPES[e.type].bg, color: EVENT_TYPES[e.type].c }}>{e.title}</span>)}
                  {evs.length > 2 && <span className="text-[10px] px-1" style={{ color: "var(--muted)" }}>+{evs.length - 2}</span>}
                </span>
                <span className="flex sm:hidden gap-0.5">{evs.slice(0, 3).map(e => <span key={e.id} className="w-1.5 h-1.5 rounded-full" style={{ background: EVENT_TYPES[e.type].c }} />)}</span>
              </button>); })}
          </div>
        </div>

        <div className="card p-5 self-start min-w-0">
          <div className="label">{parse(sel).toLocaleDateString("pt-BR", { weekday: "long" })}</div>
          <div className="display text-3xl mb-3">{parse(sel).toLocaleDateString("pt-BR", { day: "numeric", month: "long" })}</div>
          {byDay(sel).length === 0 && <p className="text-sm mb-3" style={{ color: "var(--muted)" }}>Nada marcado.</p>}
          <div className="flex flex-col gap-2">
            {byDay(sel).map(e => (
              <div key={e.id} className="group rounded-xl p-3 flex gap-3" style={{ background: EVENT_TYPES[e.type].bg }}>
                <span className="w-1 rounded-full flex-none" style={{ background: EVENT_TYPES[e.type].c }} />
                <div className="flex-1 min-w-0">
                  <div className="mono text-[11px]" style={{ color: EVENT_TYPES[e.type].c }}>{e.time} · {e.type}</div>
                  <div className="text-sm font-medium">{e.title}</div>
                </div>
                <button className="opacity-0 group-hover:opacity-100 focus:opacity-100 self-start" style={{ color: "var(--muted)" }} onClick={() => set({ events: db.events.filter(x => x.id !== e.id) })} aria-label="Excluir compromisso">{icons.trash}</button>
              </div>
            ))}
          </div>
          <button className="btn btn-ghost mt-4 w-full justify-center" onClick={() => setModal(true)}>{icons.plus} Adicionar neste dia</button>
        </div>
      </div>

      {modal && <Modal title="Novo compromisso" onClose={() => setModal(false)}>
        <Form fields={[
          { k: "title", label: "O quê", req: true }, { k: "date", label: "Data", type: "date", half: true, def: sel }, { k: "time", label: "Hora", type: "time", half: true, def: "09:00" },
          { k: "type", label: "Tipo", opts: Object.keys(EVENT_TYPES) },
        ]} onSubmit={v => { set({ events: [...db.events, { ...v, id: uid() }] }); setSel(v.date); const d = parse(v.date); setYm([d.getFullYear(), d.getMonth()]); setModal(false); }} />
      </Modal>}
    </div>
  );
}

/* ---------- 5. Marketing & Gravações ---------- */
function Marketing({ db, set }) {
  const [kind, setKind] = useState("Todos");
  const [modal, setModal] = useState(null);
  const [ws, we] = weekRange();
  const week = db.content.filter(c => c.date && c.date >= ws && c.date <= we && ["Gravar", "Edição", "Publicado"].includes(c.stage)).sort((a, b) => a.date.localeCompare(b.date));
  const step = (id, d) => set({ content: db.content.map(c => c.id === id ? { ...c, stage: STAGES[Math.min(STAGES.length - 1, Math.max(0, STAGES.indexOf(c.stage) + d))] } : c) });
  const stageColor = { "Ideia": "var(--muted)", "Roteiro": "var(--sun)", "Gravar": "var(--shell)", "Edição": "var(--ocean)", "Publicado": "var(--ok)" };

  return (
    <div className="fade">
      <SectionHead eyebrow="@solareswim" title="Marketing & Gravações">
        <button className="btn btn-ghost" onClick={() => setModal("inspo")}>{icons.plus} Referência</button>
        <button className="btn btn-primary" onClick={() => setModal("content")}>{icons.plus} Conteúdo</button>
      </SectionHead>

      <div className="card p-5 mb-4 waves" style={{ backgroundColor: "var(--side)", color: "var(--side-ink)", borderColor: "transparent" }}>
        <div className="flex flex-wrap items-baseline justify-between gap-2 mb-3">
          <h2 className="display text-3xl">O que gravar esta semana</h2>
          <span className="mono text-xs" style={{ color: "var(--side-muted)" }}>{fmtDay(ws)} – {fmtDay(we)}</span>
        </div>
        {week.length === 0 && <p style={{ color: "var(--side-muted)" }}>Nenhuma gravação com data nesta semana. Coloque uma data nos cards da etapa Gravar.</p>}
        <div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-2">
          {week.map(c => { const rec = c.stage !== "Gravar"; return (
            <div key={c.id} className="flex items-center gap-3 rounded-xl p-3" style={{ background: "var(--side-hover)" }}>
              <span role="checkbox" aria-checked={rec} aria-label={"Gravado: " + c.title} tabIndex="0" className="check" style={rec ? { background: "var(--ocean)", borderColor: "var(--ocean)", color: "var(--on-accent)" } : { borderColor: "var(--side-muted)" }}
                onClick={() => step(c.id, rec ? -(STAGES.indexOf(c.stage) - 2) : 1)} onKeyDown={e => (e.key === " " || e.key === "Enter") && (e.preventDefault(), step(c.id, rec ? -(STAGES.indexOf(c.stage) - 2) : 1))}>{rec && icons.tick}</span>
              <div className="min-w-0 flex-1">
                <div className="text-sm font-semibold truncate" style={{ textDecoration: rec ? "line-through" : "none", opacity: rec ? .6 : 1 }}>{c.title}</div>
                <div className="mono text-[11px]" style={{ color: "var(--side-muted)" }}>{parse(c.date).toLocaleDateString("pt-BR", { weekday: "short", day: "2-digit" })} · {c.format}{c.kind ? ` · ${kindShort(c.kind)}` : ""}</div>
              </div>
            </div>); })}
        </div>
      </div>

      <div className="flex flex-wrap items-center gap-2 mb-3">
        {["Todos", ...KINDS].map(k => (
          <button key={k} onClick={() => setKind(k)} className="btn btn-ghost" style={kind === k ? { background: "var(--ocean)", color: "var(--on-accent)", borderColor: "var(--ocean)" } : {}}>{k === "Todos" ? "Todos" : kindShort(k)}</button>
        ))}
        {(() => { const total = db.content.filter(c => c.kind).length; const com = db.content.filter(c => c.kind === "Comercial").length; return total ? (
          <div className="ml-auto flex items-center gap-2 text-xs" style={{ color: "var(--muted)" }}>
            <span>Comercial <span className="mono" style={{ color: "var(--ink)" }}>{com}</span></span>
            <span className="w-24 h-1.5 rounded-full overflow-hidden flex" style={{ background: "var(--ocean-bg)" }}><span style={{ width: `${com / total * 100}%`, background: "var(--warn)" }} /><span style={{ flex: 1, background: "var(--ocean)" }} /></span>
            <span>Posicionamento <span className="mono" style={{ color: "var(--ink)" }}>{total - com}</span></span>
          </div>) : null; })()}
      </div>
      <div className="scroll-x pb-2 mb-6">
        <div className="grid grid-cols-5 gap-3" style={{ minWidth: 980 }}>
          {STAGES.map(s => { const items = db.content.filter(c => c.stage === s && (kind === "Todos" || c.kind === kind)); return (
            <div key={s} className="rounded-2xl p-3 flex flex-col gap-2" style={{ background: "var(--raised)" }}>
              <div className="flex items-center justify-between px-1 mb-1">
                <span className="flex items-center gap-2 font-semibold text-sm"><span className="w-2 h-2 rounded-full" style={{ background: stageColor[s] }} />{s}</span>
                <span className="mono text-xs" style={{ color: "var(--muted)" }}>{items.length}</span>
              </div>
              {items.map(c => (
                <div key={c.id} className="card p-3 flex flex-col gap-2 group">
                  <div className="flex items-start justify-between gap-2">
                    <span className="text-sm font-semibold leading-snug">{c.title}</span>
                    <button className="opacity-0 group-hover:opacity-100 focus:opacity-100 flex-none" style={{ color: "var(--muted)" }} onClick={() => set({ content: db.content.filter(x => x.id !== c.id) })} aria-label="Excluir">{icons.trash}</button>
                  </div>
                  {c.notes && <p className="text-xs" style={{ color: "var(--muted)" }}>{c.notes}</p>}
                  <div className="flex items-center gap-1.5 flex-wrap">
                    {c.kind && <span className="chip" style={kindStyle[c.kind]}>{kindShort(c.kind)}</span>}
                    <span className="chip" style={{ background: "var(--raised)", color: "var(--ink)" }}>{c.format}</span>
                    {c.date && <span className="mono text-[11px]" style={{ color: c.date < TODAY && s !== "Publicado" ? "var(--crit)" : "var(--muted)" }}>{fmtDay(c.date)}</span>}
                    <span className="ml-auto flex gap-0.5">
                      <button disabled={s === STAGES[0]} className="btn btn-ghost !p-1 disabled:opacity-30" onClick={() => step(c.id, -1)} aria-label="Voltar etapa">{icons.left}</button>
                      <button disabled={s === STAGES[4]} className="btn btn-ghost !p-1 disabled:opacity-30" onClick={() => step(c.id, 1)} aria-label="Avançar etapa">{icons.right}</button>
                    </span>
                  </div>
                </div>
              ))}
            </div>); })}
        </div>
      </div>

      <h2 className="display text-3xl mb-3">Referências</h2>
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
        {db.inspo.map(i => (
          <div key={i.id} className="card overflow-hidden group">
            <div className="h-20 relative" style={{ background: `linear-gradient(135deg, ${i.tone}, ${i.tone}99)` }}>
              <span className="absolute bottom-2 left-3 chip" style={{ background: "rgba(255,255,255,.85)", color: "#232323" }}>{i.tag}</span>
              <button className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 focus:opacity-100 rounded-full p-1.5" style={{ background: "rgba(255,255,255,.85)", color: "#232323" }} onClick={() => set({ inspo: db.inspo.filter(x => x.id !== i.id) })} aria-label="Excluir referência">{icons.trash}</button>
            </div>
            <div className="p-4"><div className="font-semibold">{i.title}</div><p className="text-sm mt-1" style={{ color: "var(--muted)" }}>{i.note}</p></div>
          </div>
        ))}
      </div>

      {modal === "content" && <Modal title="Novo conteúdo" onClose={() => setModal(null)}>
        <Form fields={[
          { k: "title", label: "Ideia", req: true }, { k: "kind", label: "Tipo de conteúdo", opts: KINDS },
          { k: "format", label: "Formato", opts: FORMATS, half: true }, { k: "stage", label: "Etapa", opts: STAGES, half: true },
          { k: "date", label: "Data de gravação", type: "date" }, { k: "notes", label: "Notas de roteiro", area: true },
        ]} onSubmit={v => { set({ content: [...db.content, { ...v, id: uid() }] }); setModal(null); }} />
      </Modal>}
      {modal === "inspo" && <Modal title="Nova referência" onClose={() => setModal(null)}>
        <Form fields={[
          { k: "title", label: "Título", req: true }, { k: "tag", label: "Tag", half: true, def: "Referência" }, { k: "tone", label: "Cor", type: "color", half: true, def: "#A39382" },
          { k: "note", label: "Nota", area: true },
        ]} onSubmit={v => { set({ inspo: [...db.inspo, { ...v, id: uid() }] }); setModal(null); }} />
      </Modal>}
    </div>
  );
}

function MoneyField({ id, label, hint, value, onChange }) {
  return (
    <Field label={label}>
      <div className="relative">
        <span className="absolute left-3 top-1/2 -translate-y-1/2 text-sm" style={{ color: "var(--muted)" }}>R$</span>
        <input id={id} className="input mono !pl-10" type="number" step="0.01" min="0" value={value} onChange={e => onChange(e.target.value)} />
      </div>
      {hint && <span className="text-[11px]" style={{ color: "var(--muted)" }}>{hint}</span>}
    </Field>
  );
}
function BrandSlot({ title, desc, done, children }) {
  return (
    <div className="rounded-xl p-4 flex flex-col gap-3" style={{ background: "var(--raised)" }}>
      <div className="flex items-start justify-between gap-2">
        <div><div className="font-semibold">{title}</div><div className="text-xs" style={{ color: "var(--muted)" }}>{desc}</div></div>
        <span className="chip" style={done ? { color: "var(--ok)", background: "var(--ok-bg)" } : { color: "var(--muted)", background: "var(--surface)" }}>{done ? "Anexado" : "Pendente"}</span>
      </div>
      {children}
    </div>
  );
}

/* ---------- 6. Vendas ---------- */
function Sales({ db, set }) {
  const now = new Date();
  const mk = TODAY.slice(0, 7);
  const [modal, setModal] = useState(false);
  const [editGoal, setEditGoal] = useState(false);
  const sales = allSales(db);
  const month = sales.filter(o => o.date.startsWith(mk)).sort((a, b) => b.date.localeCompare(a.date));
  const revenue = month.reduce((a, o) => a + o.value, 0);
  const goal = goalOf(db, mk);
  const dim = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
  const day = now.getDate();
  const projection = day ? revenue / day * dim : 0;
  const left = Math.max(goal - revenue, 0);
  const perDay = left / Math.max(dim - day + 1, 1);
  const pct = goal ? revenue / goal : 0;
  const prevK = (() => { const d = new Date(now.getFullYear(), now.getMonth() - 1, 1); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}`; })();
  const prev = sales.filter(o => o.date.startsWith(prevK)).reduce((a, o) => a + o.value, 0);
  const delta = prev ? (revenue - prev) / prev : null;

  const months = [...Array(6)].map((_, i) => { const d = new Date(now.getFullYear(), now.getMonth() - 5 + i, 1); const k = `${d.getFullYear()}-${pad(d.getMonth() + 1)}`; const list = sales.filter(o => o.date.startsWith(k)); return { k, l: MONTHS[d.getMonth()].slice(0, 3), v: list.reduce((a, o) => a + o.value, 0), n: list.length, g: goalOf(db, k) }; });
  const top = Math.max(...months.map(m => Math.max(m.v, m.g)), 1);
  const channels = Object.entries(month.reduce((a, o) => ({ ...a, [o.channel || "Outro"]: (a[o.channel || "Outro"] || 0) + o.value }), {})).sort((a, b) => b[1] - a[1]);
  const chTop = Math.max(...channels.map(c => c[1]), 1);
  const status = pct >= 1 ? { t: "Meta batida", c: "var(--ok)", bg: "var(--ok-bg)" } : projection >= goal ? { t: "No ritmo", c: "var(--ok)", bg: "var(--ok-bg)" } : { t: "Abaixo do ritmo", c: "var(--warn)", bg: "var(--warn-bg)" };

  const addSale = v => {
    const value = +v.value;
    if (v.client === "Venda avulsa") set({ extraSales: [...(db.extraSales || []), { id: uid(), date: v.date, client: "Venda avulsa", channel: v.channel, items: v.items, value }] });
    else set({ clients: db.clients.map(c => c.name === v.client ? { ...c, orders: [...c.orders, { id: uid(), date: v.date, items: v.items, value }] } : c) });
    setModal(false);
  };

  return (
    <div className="fade">
      <SectionHead eyebrow={`${MONTHS[now.getMonth()]} ${now.getFullYear()}`} title="Vendas">
        <button className="btn btn-primary" onClick={() => setModal(true)}>{icons.plus} Venda</button>
      </SectionHead>

      <div className="card p-5 sm:p-6 mb-4">
        <div className="flex flex-wrap items-start justify-between gap-4 mb-5">
          <div>
            <div className="label">Faturamento do mês</div>
            <div className="mono text-4xl sm:text-5xl mt-2">{brl(revenue)}</div>
            <div className="text-sm mt-1" style={{ color: "var(--muted)" }}>
              {delta === null ? "Sem vendas no mês anterior para comparar" : <>{delta >= 0 ? "+" : ""}{Math.round(delta * 100)}% vs. {MONTHS[(now.getMonth() + 11) % 12].toLowerCase()}</>}
            </div>
          </div>
          <div className="text-right">
            <div className="label">Meta do mês</div>
            {editGoal ? (
              <form className="flex gap-2 mt-2" onSubmit={e => { e.preventDefault(); setEditGoal(false); }}>
                <input id="goal-input" className="input mono !w-32" type="number" min="0" value={goal} autoFocus onChange={e => set({ goals: { ...db.goals, [mk]: +e.target.value || 0 } })} />
                <button className="btn btn-primary" type="submit">Ok</button>
              </form>
            ) : (
              <button className="mono text-2xl mt-2 underline decoration-dotted underline-offset-4" onClick={() => setEditGoal(true)} title="Editar meta">{brl(goal)}</button>
            )}
            <div className="mt-2"><span className="chip" style={{ color: status.c, background: status.bg }}>{status.t}</span></div>
          </div>
        </div>
        <div className="relative h-3 rounded-full" style={{ background: "var(--raised)" }}>
          <div className="absolute inset-y-0 left-0 rounded-full transition-all" style={{ width: `${Math.min(pct, 1) * 100}%`, background: "var(--ocean)" }} />
          {goal > 0 && projection > revenue && <div className="absolute top-1/2 -translate-y-1/2 w-0.5 h-5 rounded" title="Projeção" style={{ left: `${Math.min(projection / goal, 1) * 100}%`, background: "var(--gold)" }} />}
        </div>
        <div className="flex justify-between mt-2 text-xs" style={{ color: "var(--muted)" }}>
          <span className="mono">{Math.round(pct * 100)}% da meta</span>
          <span><span className="inline-block w-2 h-2 rounded-full mr-1" style={{ background: "var(--gold)" }} />Projeção: <span className="mono">{brl(projection)}</span></span>
        </div>
      </div>

      <div className="grid grid-cols-2 lg:grid-cols-4 gap-3 mb-4">
        {[["Pedidos no mês", month.length], ["Ticket médio", brl(month.length ? revenue / month.length : 0)], ["Falta para a meta", brl(left)], ["Vender por dia", left ? brl(perDay) : "–"]].map(([l, v]) => (
          <div key={l} className="card p-4"><div className="label">{l}</div><div className="mono text-2xl mt-2">{v}</div></div>
        ))}
      </div>

      <div className="grid lg:grid-cols-5 gap-4 mb-4">
        <div className="card p-5 lg:col-span-3 min-w-0">
          <div className="flex items-baseline justify-between mb-4">
            <h2 className="display text-2xl">Faturamento x meta</h2>
            <span className="text-xs flex items-center gap-1.5" style={{ color: "var(--muted)" }}><span className="w-3 h-0.5" style={{ background: "var(--gold)" }} />meta</span>
          </div>
          <div className="flex items-end gap-3 h-44">
            {months.map((m, i) => (
              <div key={m.k} className="flex-1 flex flex-col items-center gap-1.5 h-full justify-end">
                <span className="mono text-[10px]" style={{ color: i === 5 ? "var(--ink)" : "var(--muted)" }}>{m.v ? (m.v / 1000).toFixed(1) + "k" : "–"}</span>
                <div className="relative w-full flex-1 flex items-end">
                  <div className="w-full rounded-t-md" style={{ height: `${Math.max(m.v / top * 100, 2)}%`, background: m.v >= m.g ? "var(--sea)" : i === 5 ? "var(--ocean)" : "var(--ocean-bg)" }} />
                  {m.g > 0 && <div className="absolute left-[-3px] right-[-3px] h-0.5" style={{ bottom: `${m.g / top * 100}%`, background: "var(--gold)" }} />}
                </div>
                <span className="text-[11px]" style={{ color: "var(--muted)" }}>{m.l}</span>
                <span className="mono text-[10px]" style={{ color: "var(--muted)" }}>{m.n} ped.</span>
              </div>
            ))}
          </div>
        </div>
        <div className="card p-5 lg:col-span-2 min-w-0">
          <h2 className="display text-2xl mb-4">Por canal</h2>
          {channels.length === 0 && <p style={{ color: "var(--muted)" }}>Nenhuma venda este mês ainda.</p>}
          <div className="flex flex-col gap-3">
            {channels.map(([ch, v]) => (
              <div key={ch}>
                <div className="flex justify-between text-sm mb-1"><span>{ch}</span><span className="mono">{brl(v)}</span></div>
                <div className="h-2 rounded-full" style={{ background: "var(--raised)" }}><div className="h-full rounded-full" style={{ width: `${v / chTop * 100}%`, background: "var(--sea)" }} /></div>
              </div>
            ))}
          </div>
          <div className="mt-5 pt-4 border-t text-sm flex items-center justify-between gap-2" style={{ borderColor: "var(--line)" }}>
            <span style={{ color: "var(--muted)" }}>Meta padrão dos próximos meses</span>
            <input id="default-goal" className="input mono !w-28 !py-1" type="number" min="0" value={db.defaultGoal} onChange={e => set({ defaultGoal: +e.target.value || 0 })} />
          </div>
        </div>
      </div>

      <div className="card min-w-0 scroll-x">
        <div className="px-5 pt-5 pb-2"><h2 className="display text-2xl">Pedidos do mês</h2></div>
        <table className="w-full text-sm" style={{ minWidth: 520 }}>
          <thead><tr className="text-left">{["Data", "Cliente", "Peças", "Canal", "Valor"].map(h => <th key={h} className="label px-5 py-2 font-semibold">{h}</th>)}</tr></thead>
          <tbody>
            {month.map(o => (
              <tr key={o.id} className="border-t" style={{ borderColor: "var(--line)" }}>
                <td className="px-5 py-3 mono text-xs">{fmtDay(o.date)}</td>
                <td className="px-5 py-3 font-medium">{o.client}</td>
                <td className="px-5 py-3" style={{ color: "var(--muted)" }}>{o.items}</td>
                <td className="px-5 py-3"><span className="chip" style={{ background: "var(--raised)", color: "var(--ink)" }}>{o.channel || "Outro"}</span></td>
                <td className="px-5 py-3 mono">{brl(o.value)}</td>
              </tr>
            ))}
          </tbody>
        </table>
        {month.length === 0 && <p className="px-5 pb-5" style={{ color: "var(--muted)" }}>Registre a primeira venda do mês no botão Venda.</p>}
      </div>

      {modal && <Modal title="Registrar venda" onClose={() => setModal(false)}>
        <Form fields={[
          { k: "client", label: "Cliente", opts: ["Venda avulsa", ...db.clients.map(c => c.name)] },
          { k: "items", label: "Peças", req: true },
          { k: "value", label: "Valor (R$)", type: "number", half: true, req: true }, { k: "date", label: "Data", type: "date", half: true, def: TODAY },
          { k: "channel", label: "Canal (venda avulsa)", opts: ["Instagram", "WhatsApp", "Site", "Loja", "Feira"] },
        ]} onSubmit={addSale} />
      </Modal>}
    </div>
  );
}

/* ---------- calculadora de preço ---------- */
function Calculator({ db, set }) {
  const c = db.calc;
  const [target, setTarget] = useState(db.products[0]?.id || "");
  const [msg, setMsg] = useState("");
  const up = (k, v) => set({ calc: { ...c, [k]: v } });
  const n = x => parseFloat(String(x).replace(",", ".")) || 0;
  const extras = n(c.pkg) + n(c.tag) + n(c.ship);
  const cost = n(c.cost) + extras;
  const t = n(c.fees) / 100;
  const m = n(c.margin) / 100;
  let price = null, error = "";
  if (c.mode === "margem") { if (m + t >= 1) error = "Margem + taxas precisam somar menos de 100%."; else price = cost / (1 - m - t); }
  else { if (n(c.markup) <= 0) error = "Informe um markup maior que zero."; else price = cost * n(c.markup); }
  const profitAt = p => p - cost - p * t;
  const profit = price ? profitAt(price) : 0;
  const rounded = price ? (Math.floor(price) + 0.9 >= price ? Math.floor(price) + 0.9 : Math.ceil(price) + 0.9) : 0;
  const parts = price ? [["Custo", cost / price, "var(--ocean)"], ["Taxas", t, "var(--shell)"], ["Lucro", Math.max(profit, 0) / price, "var(--side-ink)"]] : [];

  const Money = ({ k, label, hint }) => <MoneyField id={"calc-" + k} label={label} hint={hint} value={c[k]} onChange={v => up(k, v)} />;

  return (
    <div className="grid lg:grid-cols-5 gap-4 fade">
      <div className="card p-5 sm:p-6 lg:col-span-3 flex flex-col gap-6 min-w-0">
        <section>
          <h2 className="display text-2xl mb-1">Custos da peça</h2>
          <p className="text-sm mb-4" style={{ color: "var(--muted)" }}>Tudo o que sai do caixa para uma unidade chegar à cliente.</p>
          <div className="grid sm:grid-cols-2 gap-3">
            <div className="sm:col-span-2">{Money({ k: "cost", label: "Custo da peça", hint: "Matéria-prima, aviamentos e costura ou valor pago ao fornecedor" })}</div>
            {Money({ k: "pkg", label: "Embalagem" })}
            {Money({ k: "tag", label: "Etiqueta e tag" })}
            <div className="sm:col-span-2">{Money({ k: "ship", label: "Frete proporcional", hint: "Frete do lote dividido pelo número de peças, ou frete grátis embutido" })}</div>
          </div>
          <div className="flex justify-between mt-4 pt-3 border-t text-sm" style={{ borderColor: "var(--line)" }}>
            <span style={{ color: "var(--muted)" }}>Custos adicionais <span className="mono">{brl2(extras)}</span></span>
            <span>Custo total <span className="mono font-medium">{brl2(cost)}</span></span>
          </div>
        </section>

        <section>
          <div className="flex flex-wrap items-center justify-between gap-2 mb-4">
            <h2 className="display text-2xl">Precificação</h2>
            <div className="flex p-1 rounded-full border" style={{ borderColor: "var(--line)" }}>
              {[["margem", "Margem %"], ["markup", "Markup"]].map(([v, l]) => (
                <button key={v} onClick={() => up("mode", v)} className="px-4 py-1.5 rounded-full text-sm font-semibold" style={c.mode === v ? { background: "var(--ocean)", color: "var(--on-accent)" } : { color: "var(--muted)" }}>{l}</button>
              ))}
            </div>
          </div>
          <div className="grid sm:grid-cols-2 gap-4">
            {c.mode === "margem" ? (
              <Field label={`Margem de lucro desejada · ${n(c.margin)}%`}>
                <input id="calc-margin-range" type="range" min="0" max="80" step="1" value={c.margin} onChange={e => up("margin", e.target.value)} style={{ accentColor: "var(--ocean)" }} />
                <input id="calc-margin" className="input mono" type="number" min="0" max="95" value={c.margin} onChange={e => up("margin", e.target.value)} />
                <span className="text-[11px]" style={{ color: "var(--muted)" }}>Calculada sobre o preço de venda.</span>
              </Field>
            ) : (
              <Field label={`Markup · ${n(c.markup).toFixed(2).replace(".", ",")}x`}>
                <input id="calc-markup-range" type="range" min="1" max="5" step="0.1" value={c.markup} onChange={e => up("markup", e.target.value)} style={{ accentColor: "var(--ocean)" }} />
                <input id="calc-markup" className="input mono" type="number" min="0" step="0.1" value={c.markup} onChange={e => up("markup", e.target.value)} />
                <span className="text-[11px]" style={{ color: "var(--muted)" }}>Preço = custo total × markup.</span>
              </Field>
            )}
            <Field label="Taxas sobre a venda (%)">
              <input id="calc-fees" className="input mono" type="number" min="0" step="0.5" value={c.fees} onChange={e => up("fees", e.target.value)} />
              <span className="text-[11px]" style={{ color: "var(--muted)" }}>Maquininha, plataforma, impostos. Use 0 se não quiser considerar.</span>
            </Field>
          </div>
        </section>
      </div>

      <div className="lg:col-span-2 flex flex-col gap-4 min-w-0">
        <div className="card p-6 waves" style={{ backgroundColor: "var(--side)", color: "var(--side-ink)", borderColor: "transparent" }}>
          <div className="label" style={{ color: "var(--side-muted)" }}>Preço de venda sugerido</div>
          {error ? <p className="mt-3 text-sm" style={{ color: "var(--crit)" }}>{error}</p> : <>
            <div className="mono text-5xl mt-2">{brl2(price)}</div>
            <div className="text-sm mt-1" style={{ color: "var(--side-muted)" }}>Arredondado para vitrine: <span className="mono" style={{ color: "var(--side-ink)" }}>{brl2(rounded)}</span></div>
            <div className="grid grid-cols-2 gap-3 mt-6">
              <div className="rounded-xl p-3" style={{ background: "var(--side-hover)" }}>
                <div className="label !text-[10px]" style={{ color: "var(--side-muted)" }}>Lucro líquido</div>
                <div className="mono text-2xl mt-1" style={{ color: profit >= 0 ? "var(--side-ink)" : "var(--crit)" }}>{brl2(profit)}</div>
                <div className="text-[11px]" style={{ color: "var(--side-muted)" }}>por peça</div>
              </div>
              <div className="rounded-xl p-3" style={{ background: "var(--side-hover)" }}>
                <div className="label !text-[10px]" style={{ color: "var(--side-muted)" }}>No preço arredondado</div>
                <div className="mono text-2xl mt-1">{brl2(profitAt(rounded))}</div>
                <div className="text-[11px]" style={{ color: "var(--side-muted)" }}>margem {Math.round(profitAt(rounded) / rounded * 100)}%</div>
              </div>
            </div>
            <div className="mt-6">
              <div className="flex h-2.5 rounded-full overflow-hidden">{parts.map(([l, v, col]) => <div key={l} style={{ width: `${v * 100}%`, background: col === "var(--ocean)" ? "var(--sea)" : col }} />)}</div>
              <div className="flex justify-between mt-2 text-[11px]" style={{ color: "var(--side-muted)" }}>
                {parts.map(([l, v]) => <span key={l}>{l} <span className="mono">{Math.round(v * 100)}%</span></span>)}
              </div>
            </div>
            <div className="text-xs mt-4" style={{ color: "var(--side-muted)" }}>Markup equivalente <span className="mono">{(price / cost || 0).toFixed(2).replace(".", ",")}x</span> · margem real <span className="mono">{Math.round(profit / price * 100)}%</span></div>
          </>}
        </div>

        {!error && db.products.length > 0 && <div className="card p-5">
          <div className="label mb-2">Aplicar no catálogo</div>
          <div className="flex gap-2">
            <select id="calc-target" className="input" value={target} onChange={e => { setTarget(e.target.value); setMsg(""); }}>
              {db.products.map(p => <option key={p.id} value={p.id}>{p.name} · {brl(p.price)}</option>)}
            </select>
            <button className="btn btn-primary whitespace-nowrap" onClick={() => { set({ products: db.products.map(p => p.id === target ? { ...p, price: +rounded.toFixed(2) } : p) }); setMsg(`Preço atualizado para ${brl2(rounded)}.`); }}>Aplicar</button>
          </div>
          {msg && <p className="text-sm mt-2" style={{ color: "var(--ok)" }}>{msg}</p>}
        </div>}
      </div>
    </div>
  );
}

/* ---------- identidade visual ---------- */
function BrandModal({ db, set, onClose }) {
  const b = db.brand;
  const [note, setNote] = useState("");
  const upB = patch => set({ brand: { ...b, ...patch } });
  const copy = h => { try { navigator.clipboard.writeText(h).then(() => setNote(`${h} copiado.`), () => setNote(`Selecione e copie: ${h}`)); } catch { setNote(`Selecione e copie: ${h}`); } };
  const onLogo = e => {
    const f = e.target.files[0]; if (!f) return;
    if (f.size > 1.5e6) { setNote("Logo acima de 1,5 MB. Exporte uma versão menor (PNG ou SVG) e tente de novo."); return; }
    const r = new FileReader(); r.onload = () => { upB({ logo: r.result }); setNote("Logo aplicado na barra lateral."); }; r.readAsDataURL(f);
  };
  return (
    <Modal title="Identidade Visual Solare" onClose={onClose} wide>
      <div className="flex flex-col gap-6">
        <section>
          <div className="label mb-3">Paleta</div>
          <div className="grid grid-cols-3 sm:grid-cols-5 gap-2">
            {BRAND_COLORS.map(c => (
              <button key={c.h} onClick={() => copy(c.h)} className="text-left group">
                <div className="h-16 rounded-lg mb-1.5" style={{ background: c.h, border: "1px solid var(--line)" }} />
                <div className="text-xs font-medium">{c.n}</div>
                <div className="mono text-[11px] select-all" style={{ color: "var(--muted)" }}>{c.h}</div>
                {c.note && <div className="text-[10px]" style={{ color: "var(--muted)" }}>{c.note}</div>}
              </button>
            ))}
          </div>
          {note && <p className="text-xs mt-2" style={{ color: "var(--ok)" }}>{note}</p>}
        </section>
        <section className="grid sm:grid-cols-2 gap-3">
          <div className="rounded-xl p-4" style={{ border: "1px solid var(--line)" }}>
            <div className="label mb-2">Logotipo</div>
            <div className="text-2xl font-semibold">TAN MonCheri</div>
            <div className="text-sm mt-1" style={{ color: "var(--muted)" }}>Exclusiva da logo, sempre em preto puro <span className="mono select-all">#000000</span>. Sem versão negativa: sobre fundo escuro, usar plaquinha Milk ou Oat.</div>
            <div className="flex gap-2 mt-3">
              <span className="plaque wordmark text-xs">SOLARE</span>
              <span className="plaque wordmark text-xs" style={{ background: "#E5DED2" }}>SOLARE</span>
            </div>
          </div>
          <div className="rounded-xl p-4" style={{ border: "1px solid var(--line)" }}>
            <div className="label mb-2">Complementar</div>
            <div className="text-2xl font-semibold">Montserrat</div>
            <div className="text-sm mt-1" style={{ color: "var(--muted)" }}>Demais usos textuais, incluindo todo este painel.</div>
          </div>
          <div className="rounded-xl p-4 sm:col-span-2 flex items-center gap-4" style={{ border: "1px solid var(--line)" }}>
            <div className="w-20 h-14 rounded-lg flex-none waves" style={{ backgroundColor: "#E5DED2" }} />
            <div><div className="label mb-1">Elemento gráfico oficial</div><div className="text-sm">Textura de areia. Aparece na barra lateral e nos blocos de destaque.</div></div>
          </div>
        </section>
        <section className="flex flex-col gap-3">
          <div className="label">Anexos</div>
          <BrandSlot title="Logotipo" desc="PNG ou SVG em preto, fundo transparente, até 1,5 MB. Aparece no topo da barra lateral." done={!!b.logo}>
            <div className="flex items-center gap-3 flex-wrap">
              {b.logo && <div className="plaque" style={{ background: "#E5DED2" }}><img src={b.logo} alt="Logotipo atual" className="h-8 w-auto" /></div>}
              <label className="btn btn-ghost cursor-pointer">{b.logo ? "Trocar" : "Escolher arquivo"}<input id="brand-logo" type="file" accept="image/*" className="hidden" onChange={onLogo} /></label>
              {b.logo && <button className="text-xs underline" style={{ color: "var(--muted)" }} onClick={() => upB({ logo: "" })}>Remover</button>}
            </div>
          </BrandSlot>
          <BrandSlot title="Manual da marca" desc="Registre o arquivo e cole o link de onde ele está guardado para abrir de qualquer aparelho." done={!!(b.manualName || b.manualLink)}>
            <div className="flex items-center gap-3 flex-wrap">
              <label className="btn btn-ghost cursor-pointer">Escolher arquivo<input id="brand-manual" type="file" accept=".pdf,.png,.jpg,.key,.pptx" className="hidden" onChange={e => e.target.files[0] && upB({ manualName: e.target.files[0].name })} /></label>
              {b.manualName && <span className="text-sm mono truncate">{b.manualName}</span>}
            </div>
            <input id="brand-manual-link" className="input" placeholder="Link do manual (Drive, Canva...)" value={b.manualLink} onChange={e => upB({ manualLink: e.target.value })} />
            {/^https?:\/\//.test(b.manualLink) && <a href={b.manualLink} target="_blank" rel="noopener" className="text-sm font-semibold" style={{ color: "var(--ocean)" }}>Abrir manual</a>}
          </BrandSlot>
          <BrandSlot title="Fontes oficiais" desc="Arquivos .otf ou .ttf da marca e o link da pasta onde estão." done={!!(b.fontFiles || b.fontsLink)}>
            <div className="flex items-center gap-3 flex-wrap">
              <label className="btn btn-ghost cursor-pointer">Escolher arquivos<input id="brand-fonts" type="file" multiple accept=".otf,.ttf,.woff,.woff2,.zip" className="hidden" onChange={e => upB({ fontFiles: [...e.target.files].map(f => f.name).join(", ") })} /></label>
              {b.fontFiles && <span className="text-sm mono truncate min-w-0">{b.fontFiles}</span>}
            </div>
            <input id="brand-fonts-link" className="input" placeholder="Link da pasta de fontes" value={b.fontsLink} onChange={e => upB({ fontsLink: e.target.value })} />
          </BrandSlot>
          <p className="text-xs" style={{ color: "var(--muted)" }}>Enquanto não houver logo anexado, o painel mostra o nome em Montserrat no lugar. O logo fica salvo neste navegador. Do manual e das fontes, o painel guarda o nome do arquivo e o link.</p>
        </section>
      </div>
    </Modal>
  );
}

/* ---------- app ---------- */
const TABS = [
  { id: "visao", label: "Visão Geral", icon: icons.home },
  { id: "produtos", label: "Fornecedores & Produtos", short: "Produtos", icon: icons.box },
  { id: "vendas", label: "Vendas", icon: icons.coin },
  { id: "clientes", label: "Clientes", icon: icons.users },
  { id: "calendario", label: "Calendário & Avisos", short: "Agenda", icon: icons.cal },
  { id: "marketing", label: "Marketing & Gravações", short: "Marketing", icon: icons.cam },
];

function App() {
  const [db, setDb] = useState(() => { const s = seed(), l = load(); return l ? { ...s, ...l, brand: { ...s.brand, ...(l.brand || {}) } } : s; });
  const [brandOpen, setBrandOpen] = useState(false);
  const [tab, setTab] = useState(() => { const h = location.hash.slice(1); return TABS.some(t => t.id === h) ? h : "visao"; });
  const [theme, setTheme] = useState(() => document.documentElement.dataset.theme || "");
  const [confirmReset, setConfirmReset] = useState(false);
  useEffect(() => save(db), [db]);
  useEffect(() => { if (theme) document.documentElement.dataset.theme = theme; }, [theme]);
  const set = patch => setDb(d => ({ ...d, ...patch }));
  const go = t => { setTab(t); window.scrollTo({ top: 0 }); };
  const isDark = theme ? theme === "dark" : matchMedia("(prefers-color-scheme: dark)").matches;
  const pending = db.tasks.filter(t => !t.done).length + db.events.filter(e => e.date === TODAY).length;

  const View = { visao: Overview, vendas: Sales, produtos: Products, clientes: Clients, calendario: Calendar, marketing: Marketing }[tab];

  return (
    <div className="lg:flex min-h-full">
      <aside className="lg:w-64 lg:flex-none lg:h-screen lg:sticky lg:top-0 lg:overflow-y-auto flex flex-col waves" style={{ backgroundColor: "var(--side)", color: "var(--side-ink)" }}>
        <div className="gutter lg:!px-6 pt-5 pb-3 lg:pt-8 lg:pb-5 flex items-center justify-between">
          <div>
            <div className={isDark ? "plaque" : ""}>
              {db.brand.logo
                ? <img src={db.brand.logo} alt="Logotipo Solare" className="h-9 w-auto object-contain" />
                : <div className="wordmark text-xl leading-none">SOLARE</div>}
            </div>
            <div className="label !text-[10px] mt-1.5" style={{ color: "var(--side-muted)" }}>QG · beachwear & fitness</div>
          </div>
          <div className="flex lg:hidden items-center gap-1">
            <button className="chip !py-1.5 !px-3" style={{ border: "1px solid var(--side-hover)", color: "var(--side-ink)" }} onClick={() => setBrandOpen(true)}>Identidade</button>
            <button className="rounded-full p-2" style={{ color: "var(--side-muted)" }} onClick={() => setTheme(isDark ? "light" : "dark")} aria-label="Alternar tema">{isDark ? icons.sun : icons.moon}</button>
          </div>
        </div>
        <div className="hidden lg:block px-3 pb-5">
          <button onClick={() => setBrandOpen(true)} className="w-full text-left rounded-xl p-4 transition-colors" style={{ border: "1px solid var(--side-hover)", background: "var(--bg)" }}>
            <div className="label !text-[10px]" style={{ color: "var(--ink)" }}>Identidade Visual Solare</div>
            <div className="flex mt-3 mb-3">{BRAND_COLORS.map((c, i) => <span key={c.h} className="w-6 h-6 rounded-full" style={{ background: c.h, marginLeft: i ? -6 : 0, boxShadow: "0 0 0 2px var(--bg)" }} />)}</div>
            <div className="text-xs" style={{ color: "var(--muted)" }}>
              {[db.brand.logo, db.brand.manualName || db.brand.manualLink, db.brand.fontFiles || db.brand.fontsLink].filter(Boolean).length} de 3 anexos · logo, manual e fontes
            </div>
          </button>
        </div>
        <nav className="flex lg:flex-col gap-1 gutter lg:!px-3 pb-3 overflow-x-auto" aria-label="Seções">
          {TABS.map(t => (
            <button key={t.id} className="navbtn whitespace-nowrap !w-auto lg:!w-full" aria-current={tab === t.id ? "page" : undefined} onClick={() => go(t.id)}>
              {t.icon}<span className="hidden lg:inline">{t.label}</span><span className="lg:hidden">{t.short || t.label}</span>
              {t.id === "visao" && pending > 0 && <span className="mono text-[10px] rounded-full px-1.5" style={{ background: "var(--ocean)", color: "var(--on-accent)" }}>{pending}</span>}
              <span className="dot hidden lg:block" />
            </button>
          ))}
        </nav>
        <div className="hidden lg:flex flex-col gap-2 mt-auto p-6 text-xs" style={{ color: "var(--side-muted)" }}>
          <button className="flex items-center gap-2 hover:opacity-80" onClick={() => setTheme(isDark ? "light" : "dark")}>{isDark ? icons.sun : icons.moon} {isDark ? "Tema claro" : "Tema escuro"}</button>
          {confirmReset ? (
            <span className="flex items-center gap-2">Apagar tudo?
              <button className="underline" style={{ color: "var(--sun)" }} onClick={() => { setDb({ ...seed(), brand: db.brand }); setConfirmReset(false); }}>Sim</button>
              <button className="underline" onClick={() => setConfirmReset(false)}>Não</button></span>
          ) : (
            <button className="text-left hover:opacity-80" onClick={() => setConfirmReset(true)}>Restaurar dados de exemplo</button>
          )}
          <span className="opacity-70">Dados salvos neste navegador.</span>
        </div>
      </aside>
      <main className="flex-1 min-w-0 gutter py-6 lg:py-10 lg:!px-10">
        <div className="max-w-6xl mx-auto"><View db={db} set={set} go={go} key={tab} /></div>
      </main>
      {brandOpen && <BrandModal db={db} set={set} onClose={() => setBrandOpen(false)} />}
    </div>
  );
}

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