// Shared components: Sidebar, Topbar, KPI cards, charts, modals
// All styles read from CSS variables defined in index.html

const { useState, useEffect, useRef, useMemo } = React;

// ─────────────────────────────────────────────────────────────────────────────
// Formatters
// ─────────────────────────────────────────────────────────────────────────────
const fmtBRL = (n) => "R$ " + (n || 0).toLocaleString("pt-BR", { maximumFractionDigits: 0 });
const fmtBRLshort = (n) => {
  if (n == null) return "—";
  const abs = Math.abs(n);
  if (abs >= 1_000_000) return "R$ " + (n / 1_000_000).toFixed(1).replace(".", ",") + "M";
  if (abs >= 1_000) return "R$ " + (n / 1_000).toFixed(0) + "k";
  return "R$ " + n;
};
const fmtPct = (n) => (n >= 0 ? "+" : "") + (n * 100).toFixed(1).replace(".", ",") + "%";
const fmtInt = (n) => (n || 0).toLocaleString("pt-BR");

// ─────────────────────────────────────────────────────────────────────────────
// Logo
// ─────────────────────────────────────────────────────────────────────────────
// Logo oficial CEFEQ Ferramentas (PNG real do cliente)
const CEFEQ_LOGO_SRC = "/mockup/assets/cefeq-logo.png";

// Logo CEFEQ pós-processamento: 540×157 (ratio 3.44:1, wide)
const LOGO_RATIO = 540 / 157;

function CefeqMark({ height = 36 }) {
  return (
    <img
      src={CEFEQ_LOGO_SRC}
      alt="CEFEQ Ferramentas"
      style={{
        height,
        width: height * LOGO_RATIO,
        objectFit: "contain",
        display: "block",
        flexShrink: 0,
      }}
    />
  );
}

function CefeqLogo({ collapsed = false, size = "md" }) {
  // collapsed: ícone só (height 28). expanded: logo grande (height 36 sidebar, 56 hero)
  if (collapsed) {
    return (
      <div style={{
        width: 32, height: 32, borderRadius: 6,
        background: "var(--cefeq-yellow)",
        display: "grid", placeItems: "center",
        fontWeight: 900, fontSize: 18, color: "var(--cefeq-blue)",
        border: "1.5px solid var(--cefeq-blue)",
        fontFamily: "var(--font-display)",
      }}>C</div>
    );
  }
  const h = size === "lg" ? 56 : 36;
  // Logo CEFEQ tem ratio ~3.44:1 (540×157). Slogan centralizado abaixo, com mesma largura da logo.
  const logoWidth = h * (540 / 157);
  return (
    <div style={{ display: "inline-flex", flexDirection: "column", alignItems: "center", padding: "2px 0", gap: 6, width: logoWidth }}>
      <CefeqMark height={h} />
      <div className="cefeq-slogan" style={{
        fontSize: size === "lg" ? 12 : 9,
        fontWeight: 700,
        letterSpacing: "0.02em",
        color: "var(--cefeq-blue)",
        lineHeight: 1.2,
        fontStyle: "italic",
        textAlign: "center",
        width: "100%",
        whiteSpace: "nowrap",
      }}>
        Equipando Quem Constrói o Futuro!
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Icons (inline SVG, single stroke style)
// ─────────────────────────────────────────────────────────────────────────────
function Icon({ name, size = 18, style }) {
  const s = { width: size, height: size, strokeWidth: 1.6, fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", ...style };
  const paths = {
    overview:   <><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></>,
    brands:     <><path d="M3 9l9-6 9 6v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M9 21v-7h6v7"/></>,
    sectors:    <><circle cx="12" cy="12" r="9"/><path d="M12 3v9l7 4"/></>,
    sellers:    <><circle cx="9" cy="8" r="3.5"/><path d="M3 21c0-3.3 2.7-6 6-6s6 2.7 6 6"/><circle cx="17" cy="8" r="2.5"/><path d="M17 14.5c2.5 0 4.5 1.8 4.5 4.5"/></>,
    inactive:   <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/><path d="M3.5 16.5l3-1.5"/></>,
    recurring:  <><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 4v5h-5"/></>,
    admin:      <><circle cx="12" cy="8" r="3.5"/><path d="M5 21c0-3.5 3-6 7-6s7 2.5 7 6"/><path d="M18 14l1.5 1.5L22 13"/></>,
    bell:       <><path d="M6 8a6 6 0 1 1 12 0c0 5 2 7 2 7H4s2-2 2-7"/><path d="M10 19a2 2 0 0 0 4 0"/></>,
    search:     <><circle cx="11" cy="11" r="7"/><path d="M20 20l-4-4"/></>,
    sun:        <><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.5 1.5M17.6 17.6l1.5 1.5M2 12h2M20 12h2M4.9 19.1l1.5-1.5M17.6 6.4l1.5-1.5"/></>,
    moon:       <><path d="M21 12.8A8.5 8.5 0 1 1 11.2 3a6.7 6.7 0 0 0 9.8 9.8z"/></>,
    chevron:    <><path d="M9 6l6 6-6 6"/></>,
    chevronDown:<><path d="M6 9l6 6 6-6"/></>,
    settings:   <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1A1.7 1.7 0 0 0 4.6 9a1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></>,
    logout:     <><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5"/><path d="M21 12H9"/></>,
    download:   <><path d="M12 3v12"/><path d="M7 10l5 5 5-5"/><path d="M5 21h14"/></>,
    printer:    <><path d="M6 9V2h12v7"/><rect x="3" y="9" width="18" height="9" rx="2"/><path d="M6 14h12v8H6z"/><circle cx="18" cy="12" r="0.5"/></>,
    filter:     <><path d="M3 5h18l-7 8v6l-4 2v-8z"/></>,
    arrowUp:    <><path d="M12 19V5"/><path d="M5 12l7-7 7 7"/></>,
    arrowDown:  <><path d="M12 5v14"/><path d="M5 12l7 7 7-7"/></>,
    plus:       <><path d="M12 5v14M5 12h14"/></>,
    mail:       <><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></>,
    whatsapp:   <><path d="M21 12a9 9 0 1 1-3.8-7.3L21 4l-1 4.5A9 9 0 0 1 21 12z"/><path d="M8 10c.5 2.5 3.5 5 6 5"/></>,
    close:      <><path d="M18 6L6 18M6 6l12 12"/></>,
    eye:        <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></>,
    user:       <><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 4-7 8-7s8 3 8 7"/></>,
    check:      <><path d="M5 12l5 5L20 7"/></>,
    flag:       <><path d="M4 21V4h12l-2 4 2 4H4"/></>,
    dots:       <><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></>,
    phone:      <><rect x="6" y="2" width="12" height="20" rx="2.5"/><path d="M10 18h4"/><path d="M11 5h2"/></>,
  };
  return <svg viewBox="0 0 24 24" style={s}>{paths[name] || null}</svg>;
}

// ─────────────────────────────────────────────────────────────────────────────
// Sidebar
// ─────────────────────────────────────────────────────────────────────────────
function Sidebar({ current, onNavigate, layout = "expanded", onToggle, onSwitchView }) {
  const collapsed = layout === "icons";
  const items = [
    { key: "overview",  label: "Visão Geral",      icon: "overview" },
    { key: "brands",    label: "Marcas",           icon: "brands" },
    { key: "sectors",   label: "Setores",          icon: "sectors" },
    { key: "sellers",   label: "Vendedores",       icon: "sellers" },
    { key: "inactive",  label: "Clientes Inativos", icon: "inactive" },
    { key: "recurring", label: "Recorrentes",      icon: "recurring" },
  ];
  const financeItems = [
    { key: "dre",       label: "DRE",            icon: "overview" },
    { key: "cashflow",  label: "Fluxo de Caixa", icon: "recurring" },
    { key: "forecast",  label: "Previsão de Vendas", icon: "arrowUp" },
    // Nota: "Fechamento Diário" virou aba dentro da Visão Geral
  ];
  const ecomItems = [
    { key: "ecommerce", label: "E-commerce",     icon: "recurring" },
  ];

  return (
    <aside className={`sidebar ${collapsed ? "collapsed" : ""}`}>
      <div className="sidebar-header">
        <CefeqLogo collapsed={collapsed} />
        <button className="sidebar-toggle" onClick={onToggle} title={collapsed ? "Expandir" : "Recolher"}>
          <Icon name="chevron" size={14} style={{ transform: collapsed ? "none" : "rotate(180deg)" }}/>
        </button>
      </div>

      {!collapsed && (
        <button
          className="sidebar-search sidebar-search-btn"
          type="button"
          onClick={() => window.openSearchHelp && window.openSearchHelp()}
          title="Abrir busca rápida (Shift+K)"
        >
          <Icon name="search" size={14} />
          <span style={{ flex: 1, textAlign: "left", color: "var(--text-muted)", fontSize: 13 }}>Buscar...</span>
          <span className="kbd">Shift K</span>
        </button>
      )}

      <nav className="sidebar-nav">
        {!collapsed && <div className="nav-section">Análises</div>}
        {items.map(it => (
          <button key={it.key}
            className={`nav-item ${current === it.key ? "active" : ""}`}
            onClick={() => onNavigate(it.key)}
            title={collapsed ? it.label : undefined}
          >
            <Icon name={it.icon} size={17} />
            {!collapsed && <span>{it.label}</span>}
            {current === it.key && <span className="nav-bar" />}
          </button>
        ))}

        {!collapsed && <div className="nav-section" style={{ marginTop: 16 }}>Financeiro</div>}
        {financeItems.map(it => (
          <button key={it.key}
            className={`nav-item ${current === it.key ? "active" : ""}`}
            onClick={() => onNavigate(it.key)}
            title={collapsed ? it.label : undefined}
          >
            <Icon name={it.icon} size={17} />
            {!collapsed && <span>{it.label}</span>}
            {current === it.key && <span className="nav-bar" />}
          </button>
        ))}

        {!collapsed && <div className="nav-section" style={{ marginTop: 16 }}>E-commerce</div>}
        {ecomItems.map(it => (
          <button key={it.key}
            className={`nav-item ${current === it.key ? "active" : ""}`}
            onClick={() => onNavigate(it.key)}
            title={collapsed ? it.label : undefined}
          >
            <Icon name={it.icon} size={17} />
            {!collapsed && <span>{it.label}</span>}
            {current === it.key && <span className="nav-bar" />}
          </button>
        ))}
      </nav>

      <div className="sidebar-foot">
        <button className="sidebar-mobile-btn" onClick={onSwitchView} title="Visualizar versão mobile">
          <Icon name="phone" size={15}/>
          {!collapsed && <span>Visualizar versão mobile</span>}
        </button>
        {!collapsed && (
          <div className="period-card">
            <div className="period-label">Período</div>
            <div className="period-value">Ano fiscal 2026</div>
            <div className="period-sub">Jan — Set (parcial)</div>
          </div>
        )}
      </div>
    </aside>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Topbar
// ─────────────────────────────────────────────────────────────────────────────
function Topbar({ title, breadcrumb, dark, onToggleTheme, onNavigate, screenKey, onOpenNotifs, onSwitchView }) {
  const [menuOpen, setMenuOpen] = useState(false);
  const menuRef = useRef(null);
  useEffect(() => {
    function onClick(e) { if (menuRef.current && !menuRef.current.contains(e.target)) setMenuOpen(false); }
    document.addEventListener("mousedown", onClick);
    return () => document.removeEventListener("mousedown", onClick);
  }, []);

  return (
    <header className="topbar">
      <div className="topbar-left">
        <div className="breadcrumb">
          {breadcrumb.map((b, i) => (
            <React.Fragment key={i}>
              {i > 0 && <Icon name="chevron" size={12} style={{ opacity: 0.4 }} />}
              <span className={i === breadcrumb.length - 1 ? "crumb-current" : "crumb"}>{b}</span>
            </React.Fragment>
          ))}
        </div>
        <h1 className="page-title">{title}</h1>
      </div>

      <div className="topbar-right">
        <button className="icon-btn" title="Notificações" onClick={onOpenNotifs}><Icon name="bell" size={17} /><span className="badge-dot"></span></button>
        <button className="icon-btn" title="Trocar tema" onClick={onToggleTheme}>
          <Icon name={dark ? "sun" : "moon"} size={17} />
        </button>
        <div className="profile-wrap" ref={menuRef}>
          <button className="profile-btn" onClick={() => setMenuOpen(v => !v)}>
            <div className="avatar">{(window.MOCK?.currentUser?.initials) || "FS"}</div>
            <div className="profile-meta">
              <div className="profile-name">{(window.MOCK?.currentUser?.name) || "Felipe Sergio"}</div>
              <div className="profile-role">
                {(window.MOCK?.currentUser?.role) || "CEO"}
                {window.MOCK?.currentUser?.scope && window.MOCK.currentUser.scope !== "Tudo" && (
                  <span style={{ opacity: 0.7 }}> · {window.MOCK.currentUser.scope}</span>
                )}
              </div>
            </div>
            <Icon name="chevronDown" size={14} />
          </button>
          {menuOpen && (
            <div className="profile-menu">
              <div className="pm-header">
                <div className="avatar lg">{(window.MOCK?.currentUser?.initials) || "FS"}</div>
                <div>
                  <div className="pm-name">{(window.MOCK?.currentUser?.name) || "Felipe Sergio"}</div>
                  <div className="pm-email">{(window.MOCK?.currentUser?.email) || "felipe.sergio@cefeq.com.br"}</div>
                  <div className="pm-role-pill">{(window.MOCK?.currentUser?.role) || "CEO"}</div>
                </div>
              </div>
              <div className="pm-divider"/>
              <button className="pm-item"><Icon name="user" size={15}/> Meu perfil</button>
              <button className="pm-item"><Icon name="settings" size={15}/> Preferências</button>
              <button className="pm-item" onClick={() => { setMenuOpen(false); onSwitchView && onSwitchView(); }}>
                <Icon name="phone" size={15}/> Visualizar versão mobile
              </button>
              <div className="pm-divider"/>
              <button className="pm-item" onClick={() => { setMenuOpen(false); onNavigate("admin"); }}>
                <Icon name="admin" size={15}/> Administração
              </button>
              <button className="pm-item" onClick={() => window.openPrintPreview()}><Icon name="printer" size={15}/> Imprimir PDF da tela</button>
              <div className="pm-divider"/>
              <button className="pm-item danger" onClick={() => onNavigate("login")}>
                <Icon name="logout" size={15}/> Sair
              </button>
              <div className="pm-foot">v1.0 · MVP · {new Date().getFullYear()}</div>
            </div>
          )}
        </div>
      </div>
    </header>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// KPI Card
// ─────────────────────────────────────────────────────────────────────────────
// Tooltip helper — usa <span title> base + ícone "?" pra dar dica visual
function InfoTip({ text }) {
  return (
    <span className="info-tip" title={text} aria-label={text}>
      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" style={{ verticalAlign: "middle" }}>
        <circle cx="12" cy="12" r="10"/>
        <path d="M12 16v-4"/>
        <circle cx="12" cy="8" r="0.5"/>
      </svg>
    </span>
  );
}

// Dicionário de tooltips por label comum — aplicado automaticamente
const KPI_TOOLTIPS = {
  "LTV": "Lifetime Value: faturamento total que o cliente já trouxe desde o primeiro pedido.",
  "LTV total": "Soma do faturamento histórico de todos os clientes do recorte.",
  "Ticket médio": "Faturamento total dividido pelo número de pedidos.",
  "Margem média": "Margem de contribuição ponderada — quanto sobra após CMV em média.",
  "Margem bruta": "% de lucro bruto sobre faturamento (Receita − CMV) / Receita.",
  "EBITDA": "Lucro antes de juros, impostos, depreciação e amortização. Indica geração operacional de caixa.",
  "Lucro Líquido": "Resultado final após todos os custos, despesas, impostos e resultado financeiro.",
  "YoY": "Year-over-Year — comparação com o mesmo período do ano anterior.",
  "MRR": "Receita recorrente mensal — apenas pra clientes recorrentes confirmados.",
};

// Procura no label se contém alguma das keys do dicionário e retorna tooltip se sim
function getTooltipForLabel(label) {
  if (!label || typeof label !== "string") return null;
  const lower = label.toLowerCase();
  for (const key of Object.keys(KPI_TOOLTIPS)) {
    if (lower.includes(key.toLowerCase())) return KPI_TOOLTIPS[key];
  }
  return null;
}

function KPI({ label, value, delta, sub, accent, sparkline, big = false, tooltip }) {
  const positive = delta == null ? null : delta >= 0;
  const finalTooltip = tooltip || (typeof label === "string" ? getTooltipForLabel(label) : null);
  return (
    <div className={`kpi ${big ? "kpi-big" : ""}`}>
      <div className="kpi-label">
        {label}
        {finalTooltip && <InfoTip text={finalTooltip} />}
      </div>
      <div className="kpi-value" style={accent ? { color: accent } : undefined}>{value}</div>
      <div className="kpi-foot">
        {delta != null && (
          <span className={`kpi-delta ${positive ? "up" : "down"}`} title={positive ? "Crescimento vs período anterior" : "Queda vs período anterior"}>
            <Icon name={positive ? "arrowUp" : "arrowDown"} size={11} />
            {fmtPct(delta)}
          </span>
        )}
        {sub && <span className="kpi-sub">{sub}</span>}
      </div>
      {sparkline && <Sparkline data={sparkline} color={accent || "var(--cefeq-blue)"} />}
    </div>
  );
}

// Disponibiliza globalmente pra outros componentes usarem
window.InfoTip = InfoTip;

// ─────────────────────────────────────────────────────────────────────────────
// Sparkline (mini line)
// ─────────────────────────────────────────────────────────────────────────────
function Sparkline({ data, color = "var(--cefeq-blue)", height = 36 }) {
  const w = 140, h = height, pad = 2;
  const vals = data.filter(v => v != null);
  const min = Math.min(...vals), max = Math.max(...vals);
  const range = max - min || 1;
  const pts = data.map((v, i) => {
    if (v == null) return null;
    const x = pad + (i / (data.length - 1)) * (w - 2 * pad);
    const y = h - pad - ((v - min) / range) * (h - 2 * pad);
    return [x, y];
  }).filter(Boolean);
  const d = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(" ");
  return (
    <svg className="sparkline" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <path d={d} stroke={color} strokeWidth="1.6" fill="none" />
      <path d={d + ` L${pts[pts.length-1][0]},${h} L${pts[0][0]},${h} Z`} fill={color} opacity="0.08" />
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Bar chart (vertical, comparative y25 vs y26)
// ─────────────────────────────────────────────────────────────────────────────
function GrowthBars({ data }) {
  const maxV = Math.max(...data.flatMap(d => [d.y25, d.y26].filter(v => v != null)));
  return (
    <div className="growth-bars">
      {data.map((d, i) => {
        const h25 = (d.y25 / maxV) * 100;
        const h26 = d.y26 != null ? (d.y26 / maxV) * 100 : 0;
        return (
          <div key={i} className="gb-col">
            <div className="gb-stack">
              {d.y26 != null && (
                <div className="gb-bar gb-26" style={{ height: `${h26}%` }} title={`2026: ${fmtBRLshort(d.y26)}`}>
                  <span className="gb-tip gb-tip-26">{fmtBRLshort(d.y26)}</span>
                </div>
              )}
              <div className="gb-bar gb-25" style={{ height: `${h25}%` }} title={`2025: ${fmtBRLshort(d.y25)}`}>
                <span className="gb-tip gb-tip-25">{fmtBRLshort(d.y25)}</span>
              </div>
            </div>
            <div className="gb-lbl">{d.m}</div>
          </div>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Horizontal bar list (ranking)
// ─────────────────────────────────────────────────────────────────────────────
function RankBars({ items, valueKey = "rev", labelKey = "name", color, format = fmtBRLshort, secondaryKey, secondaryFormat = fmtPct }) {
  const maxV = Math.max(...items.map(it => it[valueKey]));
  return (
    <div className="rank-bars">
      {items.map((it, i) => {
        const pct = (it[valueKey] / maxV) * 100;
        return (
          <div key={i} className="rb-row">
            <div className="rb-rank">{String(i + 1).padStart(2, "0")}</div>
            <div className="rb-meta">
              <div className="rb-name">{it[labelKey]}</div>
              <div className="rb-bar"><span style={{ width: `${pct}%`, background: it.color || color || "var(--cefeq-blue)" }}/></div>
            </div>
            <div className="rb-val">
              <div className="rb-val-main">{format(it[valueKey])}</div>
              {secondaryKey && (
                <div className={`rb-val-sub ${it[secondaryKey] >= 0 ? "up" : "down"}`}>
                  {secondaryFormat(it[secondaryKey])}
                </div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Donut chart
// ─────────────────────────────────────────────────────────────────────────────
function Donut({ data, size = 200, thick = 32, label }) {
  const total = data.reduce((s, d) => s + d.value, 0);
  const r = size / 2 - thick / 2;
  const C = 2 * Math.PI * r;
  let offset = 0;
  return (
    <div className="donut-wrap">
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--border)" strokeWidth={thick} />
        {data.map((d, i) => {
          const len = (d.value / total) * C;
          const seg = <circle key={i} cx={size/2} cy={size/2} r={r} fill="none"
            stroke={d.color} strokeWidth={thick} strokeDasharray={`${len} ${C - len}`}
            strokeDashoffset={-offset} transform={`rotate(-90 ${size/2} ${size/2})`} />;
          offset += len;
          return seg;
        })}
      </svg>
      <div className="donut-center">
        <div className="donut-total">{fmtBRLshort(total)}</div>
        <div className="donut-label">{label}</div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Modal (generic)
// ─────────────────────────────────────────────────────────────────────────────
function Modal({ open, onClose, title, subtitle, children, footer, wide = false }) {
  useEffect(() => {
    function onKey(e) { if (e.key === "Escape") onClose(); }
    if (open) document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className={`modal ${wide ? "wide" : ""}`} onClick={e => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <h3>{title}</h3>
            {subtitle && <div className="modal-sub">{subtitle}</div>}
          </div>
          <button className="icon-btn" onClick={onClose}><Icon name="close" size={16} /></button>
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Pill / Badge
// ─────────────────────────────────────────────────────────────────────────────
function Pill({ children, variant = "neutral", icon }) {
  return (
    <span className={`pill pill-${variant}`}>
      {icon && <Icon name={icon} size={11} />}
      {children}
    </span>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Toast (simple, ephemeral)
// ─────────────────────────────────────────────────────────────────────────────
function useToast() {
  const [toast, setToast] = useState(null);
  function show(msg, variant = "success") {
    setToast({ msg, variant, id: Date.now() });
    setTimeout(() => setToast(null), 2400);
  }
  const node = toast ? (
    <div className={`toast toast-${toast.variant}`} key={toast.id}>
      <Icon name={toast.variant === "success" ? "check" : "bell"} size={14}/>
      {toast.msg}
    </div>
  ) : null;
  return [node, show];
}

Object.assign(window, {
  CefeqLogo, CefeqMark, Icon,
  Sidebar, Topbar, KPI, Sparkline, GrowthBars, RankBars, Donut, Modal, Pill,
  useToast, fmtBRL, fmtBRLshort, fmtPct, fmtInt,
});
