/* global React, ReactDOM */
const { useState, useEffect, useRef, useMemo } = React;

/* ===========================================================
   HOOK: Persistência automática via localStorage
=========================================================== */
const useLocalStorage = (key, initial) => {
  const [state, setState] = useState(() => {
    try {
      const raw = localStorage.getItem(key);
      return raw !== null ? JSON.parse(raw) : initial;
    } catch { return initial; }
  });
  useEffect(() => {
    try { localStorage.setItem(key, JSON.stringify(state)); }
    catch { /* Quota exceeded - silencioso */ }
  }, [key, state]);
  return [state, setState];
};
window.useLocalStorage = useLocalStorage;

/* ===========================================================
   TWEAKS DEFAULTS
=========================================================== */
const TWEAK_DEFAULTS = {
  "accent": "#3D8BFF",
  "density": "comfortable",
  "showCircuitry": true,
  "monoReadouts": true
};

const ACCENT_MAP = {
  "#3D8BFF": { primary: "oklch(72% 0.18 245)", glow: "oklch(72% 0.22 245 / 0.35)", soft: "oklch(72% 0.18 245 / 0.12)" },
  "#3DD6E6": { primary: "oklch(82% 0.14 200)", glow: "oklch(82% 0.18 200 / 0.40)", soft: "oklch(82% 0.14 200 / 0.12)" },
  "#5BE38C": { primary: "oklch(84% 0.18 145)", glow: "oklch(84% 0.22 145 / 0.35)", soft: "oklch(84% 0.18 145 / 0.12)" },
  "#F2B043": { primary: "oklch(80% 0.16 75)",  glow: "oklch(80% 0.20 75 / 0.35)",  soft: "oklch(80% 0.16 75 / 0.12)" },
};

/* ===========================================================
   ICONS — minimal stroke icons
=========================================================== */
const Dropdown = ({ value, onChange, options }) => {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDocClick = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDocClick);
    return () => document.removeEventListener("mousedown", onDocClick);
  }, [open]);
  const current = options.find(o => o.value === value) || options[0];
  return (
    <div className={"vl-dd " + (open ? "is-open" : "")} ref={ref}>
      <button type="button" className="vl-dd-trigger" onClick={() => setOpen(o => !o)}>
        <span>{current?.label}</span>
        <span className="vl-dd-chev"/>
      </button>
      {open && (
        <div className="vl-dd-menu">
          {options.map(o => (
            <div
              key={o.value}
              className={"vl-dd-opt " + (o.value === value ? "is-sel" : "")}
              onClick={() => { onChange(o.value); setOpen(false); }}
            >{o.label}</div>
          ))}
        </div>
      )}
    </div>
  );
};

const Icon = ({ name, size = 18, stroke = 1.5 }) => {
  const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" };
  const paths = {
    dashboard: <><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></>,
    calc: <><rect x="4" y="3" width="16" height="18" rx="2"/><line x1="4" y1="9" x2="20" y2="9"/><line x1="9" y1="14" x2="9" y2="14"/><line x1="12" y1="14" x2="12" y2="14"/><line x1="15" y1="14" x2="15" y2="14"/><line x1="9" y1="17" x2="15" y2="17"/></>,
    ruler: <><path d="M3 17L17 3l4 4L7 21z"/><path d="M7.5 12.5l2 2M10 10l2 2M12.5 7.5l2 2"/></>,
    bolt: <><path d="M13 2L4 14h7l-2 8 9-12h-7z"/></>,
    wave: <><path d="M2 12c2 0 2-6 4-6s2 12 4 12 2-12 4-12 2 6 4 6 2-3 4-3"/></>,
    pipe: <><path d="M3 8h12a3 3 0 013 3v0a3 3 0 01-3 3H3"/><path d="M3 8v8"/><circle cx="18" cy="11" r="0.5"/></>,
    cable: <><path d="M4 4c4 0 4 8 8 8s4-8 8-8"/><path d="M4 20c4 0 4-8 8-8s4 8 8 8"/></>,
    flash: <><circle cx="12" cy="12" r="9"/><path d="M13 7l-4 7h3l-1 4 4-7h-3z"/></>,
    shield: <><path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z"/><path d="M9 12l2 2 4-4"/></>,
    transformer: <><circle cx="8" cy="12" r="4"/><circle cx="16" cy="12" r="4"/><line x1="3" y1="12" x2="4" y2="12"/><line x1="20" y1="12" x2="21" y2="12"/></>,
    sigma: <><path d="M18 4H6l6 8-6 8h12"/></>,
    chart: <><path d="M3 3v18h18"/><path d="M7 14l3-3 3 3 5-6"/></>,
    bulb: <><path d="M9 21h6"/><path d="M10 18h4"/><path d="M12 3a6 6 0 00-4 10.5c1 1 1.5 2 1.5 3.5h5c0-1.5.5-2.5 1.5-3.5A6 6 0 0012 3z"/></>,
    diagram: <><rect x="3" y="3" width="6" height="6"/><rect x="15" y="3" width="6" height="6"/><rect x="9" y="15" width="6" height="6"/><path d="M6 9v3h12v3M12 12v3"/></>,
    refresh: <><path d="M21 12a9 9 0 11-3-6.7L21 8"/><path d="M21 3v5h-5"/></>,
    settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 00.3 1.8l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.8-.3 1.7 1.7 0 00-1 1.5V21a2 2 0 11-4 0v-.1a1.7 1.7 0 00-1.1-1.5 1.7 1.7 0 00-1.8.3l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.7 1.7 0 00.3-1.8 1.7 1.7 0 00-1.5-1H3a2 2 0 110-4h.1a1.7 1.7 0 001.5-1.1 1.7 1.7 0 00-.3-1.8l-.1-.1a2 2 0 112.8-2.8l.1.1a1.7 1.7 0 001.8.3H9a1.7 1.7 0 001-1.5V3a2 2 0 114 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.8-.3l.1-.1a2 2 0 112.8 2.8l-.1.1a1.7 1.7 0 00-.3 1.8V9a1.7 1.7 0 001.5 1H21a2 2 0 110 4h-.1a1.7 1.7 0 00-1.5 1z"/></>,
    arrow: <><line x1="5" y1="12" x2="19" y2="12"/><polyline points="13 6 19 12 13 18"/></>,
    arrowL: <><line x1="19" y1="12" x2="5" y2="12"/><polyline points="11 6 5 12 11 18"/></>,
    check: <><polyline points="20 6 9 17 4 12"/></>,
    plus: <><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></>,
    user: <><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 4-7 8-7s8 3 8 7"/></>,
    search: <><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.5" y2="16.5"/></>,
    bell: <><path d="M18 16v-5a6 6 0 10-12 0v5l-2 2h16z"/><path d="M10 21h4"/></>,
    download: <><path d="M12 3v12"/><polyline points="7 10 12 15 17 10"/><line x1="4" y1="21" x2="20" y2="21"/></>,
    spark: <><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M5.6 18.4l2.8-2.8M15.6 8.4l2.8-2.8"/></>,
    grid: <><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></>,
    lock: <><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V8a4 4 0 018 0v3"/></>,
    mail: <><rect x="3" y="5" width="18" height="14" rx="2"/><polyline points="3 7 12 13 21 7"/></>,
    eye: <><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></>,
  };
  return <svg {...common}>{paths[name] || null}</svg>;
};

/* ===========================================================
   BACKGROUND — animated circuitry SVG layer
=========================================================== */
const Circuitry = ({ show }) => {
  if (!show) return null;
  return (
    <svg className="circuitry" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
      <defs>
        <linearGradient id="lineGrad" x1="0" x2="1" y1="0" y2="0">
          <stop offset="0%"  stopColor="var(--accent)" stopOpacity="0"/>
          <stop offset="50%" stopColor="var(--accent)" stopOpacity="1"/>
          <stop offset="100%" stopColor="var(--accent)" stopOpacity="0"/>
        </linearGradient>
        <radialGradient id="nodeGlow" r="0.5">
          <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.9"/>
          <stop offset="100%" stopColor="var(--accent)" stopOpacity="0"/>
        </radialGradient>
      </defs>
      <g className="grid-lines" stroke="currentColor" strokeWidth="0.5" opacity="0.06">
        {Array.from({length: 16}).map((_,i) => <line key={"v"+i} x1={i*100} y1="0" x2={i*100} y2="900"/>)}
        {Array.from({length: 10}).map((_,i) => <line key={"h"+i} x1="0" y1={i*100} x2="1600" y2={i*100}/>)}
      </g>
      <g fill="none" stroke="currentColor" strokeWidth="1" opacity="0.18">
        <path d="M0,200 L300,200 L320,220 L600,220 L620,200 L900,200"/>
        <path d="M200,0 L200,150 L220,170 L220,400 L240,420 L240,700"/>
        <path d="M1600,300 L1300,300 L1280,320 L1000,320 L980,300 L800,300"/>
        <path d="M1100,900 L1100,700 L1120,680 L1120,500 L1140,480 L1140,300"/>
        <path d="M400,800 L800,800 L820,780 L1100,780"/>
        <path d="M50,500 L50,700 L70,720 L300,720"/>
      </g>
      <g fill="currentColor">
        {[[300,200],[600,220],[900,200],[220,400],[240,700],[1000,320],[800,300],[1100,700],[1100,500],[1140,300],[820,780],[70,720]].map(([x,y], i) => (
          <circle key={i} cx={x} cy={y} r="2.5" opacity="0.45"/>
        ))}
      </g>
      <g>
        <line className="pulse pulse-1" x1="0" x2="220" y1="200" y2="200" stroke="url(#lineGrad)" strokeWidth="1.5"/>
        <line className="pulse pulse-2" x1="1600" x2="1380" y1="300" y2="300" stroke="url(#lineGrad)" strokeWidth="1.5"/>
        <line className="pulse pulse-3" x1="400" x2="620" y1="800" y2="800" stroke="url(#lineGrad)" strokeWidth="1.5"/>
        <circle className="ping ping-1" cx="600" cy="220" r="3" fill="var(--accent)"/>
        <circle className="ping ping-2" cx="1100" cy="700" r="3" fill="var(--accent)"/>
        <circle className="ping ping-3" cx="240" cy="700" r="3" fill="var(--accent)"/>
      </g>
    </svg>
  );
};

/* ===========================================================
   BRAND MARK — logo "V" (volt) bicolor, segue o --accent do tema
=========================================================== */
const BrandMark = ({ size = 28 }) => (
  <span className="brand-logo" style={{ width: size, height: size }} aria-hidden="true">
    <svg viewBox="0 0 32 32" width={size} height={size} fill="none">
      <rect x="1.25" y="1.25" width="29.5" height="29.5" rx="8.5"
        fill="oklch(15% 0.02 245)" stroke="var(--accent)" strokeOpacity="0.4" strokeWidth="1"/>
      <rect x="4.75" y="4.75" width="22.5" height="22.5" rx="6"
        stroke="var(--accent)" strokeOpacity="0.13" strokeWidth="1"/>
      <path d="M9 9.5 L16 21.4" stroke="var(--accent)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
      <path d="M16 21.4 L23 9.5" stroke="var(--accent-2)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
      <circle cx="9" cy="9.5" r="1.7" fill="var(--fg)"/>
      <circle cx="23" cy="9.5" r="1.7" fill="var(--fg)"/>
      <circle cx="16" cy="21.4" r="1.25" fill="var(--accent)"/>
    </svg>
  </span>
);
window.VL_BrandMark = BrandMark;

/* ===========================================================
   LANDING / LOGIN / CADASTRO
=========================================================== */
const Landing = ({ onEnter, onGuest, showCircuitry }) => {
  const [pwVisible, setPwVisible] = useState(false);
  const [mode, setMode] = useState("login"); // "login" | "register" | "verify" | "forgot"

  const [email, setEmail] = useState("");
  const [senha, setSenha] = useState("");
  const [nome, setNome] = useState("");
  const [codigo, setCodigo] = useState("");
  const [manterSessao, setManterSessao] = useState(true);
  const [erro, setErro] = useState("");
  const [busy, setBusy] = useState(false);
  const fpRef = useRef("");

  useEffect(() => {
    if (window.VL_fingerprint) {
      window.VL_fingerprint().then(fp => { fpRef.current = fp; });
    }
  }, []);

  const concluirLogin = (res) => {
    window.VL_AUTH.setToken(res.token, manterSessao);
    window.VL_SESSION = { token: res.token, user: res.user, plan: res.plan, fingerprint: fpRef.current };
    onEnter(); 
  };

  const handleLogin = async (e) => {
    e.preventDefault();
    setErro("");
    if (!window.VL_AUTH) { onEnter(); return; }
    if (!email || !senha) { setErro("Preencha e-mail e senha."); return; }
    setBusy(true);
    const res = await window.VL_AUTH.login({
      email: email.trim().toLowerCase(),
      senha,
      fingerprint: fpRef.current,
      remember: manterSessao,
    });
    setBusy(false);
    if (!res.ok) { setErro(res.error); return; }
    concluirLogin(res);
  };

  const handleRegister = async (e) => {
    e.preventDefault();
    setErro("");
    if (!window.VL_AUTH) { onEnter(); return; }
    if (!nome.trim()) { setErro("Informe seu nome completo."); return; }
    if (!email.includes("@")) { setErro("E-mail inválido."); return; }
    if (senha.length < 6) { setErro("A senha deve ter ao menos 6 caracteres."); return; }
    
    setBusy(true);
    const emailNorm = email.trim().toLowerCase();
    const res = await window.VL_AUTH.requestRegistrationCode({ nome: nome.trim(), email: emailNorm, senha });
    setBusy(false);
    
    if (!res.ok) { setErro(res.error); return; }
    
    alert(`VoltLab — Verificação de conta\n\nEnviamos um código de confirmação para ${emailNorm}.\n\nSeu código é: ${res.codeForTesting}\n\nDigite-o na próxima tela para concluir o cadastro.`);
    setMode("verify");
  };

  const handleVerify = async (e) => {
    e.preventDefault();
    setErro("");
    if (!codigo) { setErro("Informe o código de 6 dígitos."); return; }
    
    setBusy(true);
    const emailNorm = email.trim().toLowerCase();
    
    const reg = await window.VL_AUTH.verifyAndRegister({ email: emailNorm, code: codigo });
    if (!reg.ok) { setBusy(false); setErro(reg.error); return; }
    
    const res = await window.VL_AUTH.login({ email: emailNorm, senha, fingerprint: fpRef.current, remember: manterSessao });
    setBusy(false);
    if (!res.ok) { setErro(res.error); return; }
    concluirLogin(res);
  };

  const handleForgot = (e) => {
    e.preventDefault();
    alert("Se o e-mail estiver cadastrado, um link de recuperação foi enviado.");
    setMode("login");
  };

  return (
    <div className="landing">
      <div className="landing-bg" aria-hidden="true">
        <Circuitry show={showCircuitry} />
        <div className="landing-vignette" />
        <div className="landing-orb landing-orb-a" />
        <div className="landing-orb landing-orb-b" />
      </div>

      <header className="landing-top">
        <div className="brand">
          <BrandMark/>
          <div className="brand-name">VOLTLAB<span className="brand-dot">.</span><em>eng</em></div>
        </div>
        <nav className="landing-nav">
          <a href="#" onClick={(e) => { e.preventDefault(); setMode("login"); }}>Fazer Login</a>
          <a href="#" onClick={(e) => { e.preventDefault(); setMode("register"); }}>Criar Conta</a>
        </nav>
      </header>

      <main className="landing-grid">
        <section className="landing-hero">
          <div className="hero-tag">
            <span className="hero-tag-line" /> v 4.2 — ENGINEERING SUITE
          </div>
          <h1 className="hero-title">
            Plataforma <em>inteligente</em><br/>
            de engenharia <span className="hero-emph">elétrica</span>
          </h1>
          <p className="hero-sub">
            Dimensionamento normativo, análise de circuitos e ferramentas técnicas
            em um único ambiente — projetado para engenheiros que exigem precisão.
          </p>
        </section>

        <section className="login-card">
          <div className="login-frame">
            <div className="login-corner login-corner-tl"/>
            <div className="login-corner login-corner-tr"/>
            <div className="login-corner login-corner-bl"/>
            <div className="login-corner login-corner-br"/>

            {/* MODO DE ACESSO — sem conta */}
            {mode === "login" && (
              <>
                <div className="login-head">
                  <div className="login-eyebrow">ACESSO LIVRE · SEM CADASTRO</div>
                  <h2>Entrar na plataforma</h2>
                  <p>Acesse o ambiente de projetos diretamente — sem conta e sem senha. Seus dados ficam salvos apenas neste navegador.</p>
                </div>

                <div className="login-form">
                  <button type="button" className="btn btn-primary btn-block" onClick={() => (onGuest || onEnter)()}>
                    Acessar plataforma <Icon name="arrow" size={16}/>
                  </button>

                  <div className="login-foot" style={{marginTop: 16, textAlign: "center", lineHeight: 1.6}}>
                    <span className="dim">Todos os módulos técnicos liberados. Nenhum dado é enviado para servidores.</span>
                  </div>
                </div>
              </>
            )}

            {/* MODO DE CADASTRO */}
            {mode === "register" && (
              <>
                <div className="login-head">
                  <div className="login-eyebrow">NOVA CONTA</div>
                  <h2>Criar Conta</h2>
                  <p>Crie sua conta para obter acesso aos módulos técnicos.</p>
                </div>

                <form className="login-form" onSubmit={handleRegister}>
                  <label className="field">
                    <span className="field-label">Nome Completo</span>
                    <span className="field-input">
                      <Icon name="user" size={16} />
                      <input type="text" placeholder="Como deseja ser chamado" required
                        value={nome} onChange={e => { setNome(e.target.value); setErro(""); }} />
                    </span>
                  </label>
                  <label className="field">
                    <span className="field-label">E-mail</span>
                    <span className="field-input">
                      <Icon name="mail" size={16} />
                      <input type="email" placeholder="email@empresa.com.br" required
                        value={email} onChange={e => { setEmail(e.target.value); setErro(""); }} />
                    </span>
                  </label>
                  <label className="field">
                    <span className="field-label">Criar Senha</span>
                    <span className="field-input">
                      <Icon name="lock" size={16} />
                      <input type={pwVisible ? "text" : "password"} placeholder="Mínimo 6 caracteres" required
                        value={senha} onChange={e => { setSenha(e.target.value); setErro(""); }} />
                      <button type="button" className="field-action" onClick={() => setPwVisible(v => !v)}>
                        <Icon name="eye" size={16}/>
                      </button>
                    </span>
                  </label>

                  {erro && <div className="login-error" role="alert">{erro}</div>}

                  <button type="submit" className="btn btn-primary btn-block" style={{marginTop: 15}} disabled={busy}>
                    {busy ? "Enviando código…" : <>Prosseguir <Icon name="arrow" size={16}/></>}
                  </button>

                  <div className="login-foot" style={{marginTop: 15, textAlign: "center"}}>
                    <span className="dim">Já tem uma conta?</span> <button type="button" className="btn-link" onClick={() => setMode("login")}>Fazer login</button>
                  </div>
                </form>
              </>
            )}

            {/* MODO VERIFICAR CÓDIGO */}
            {mode === "verify" && (
              <>
                <div className="login-head">
                  <div className="login-eyebrow">VERIFICAÇÃO DE SEGURANÇA</div>
                  <h2>Confirme seu e-mail</h2>
                  <p>Enviamos um código de 6 dígitos para <b>{email}</b>. Insira-o abaixo para liberar seu acesso.</p>
                </div>

                <form className="login-form" onSubmit={handleVerify}>
                  <label className="field">
                    <span className="field-label">Código de verificação</span>
                    <span className="field-input">
                      <Icon name="lock" size={16} />
                      <input type="text" placeholder="000000" maxLength={6} required
                        value={codigo} onChange={e => { setCodigo(e.target.value.replace(/\D/g, '')); setErro(""); }} 
                        style={{ letterSpacing: "0.4em", fontSize: "18px", fontWeight: "bold", textAlign: "center" }}/>
                    </span>
                  </label>

                  {erro && <div className="login-error" role="alert">{erro}</div>}

                  <button type="submit" className="btn btn-primary btn-block" style={{marginTop: 15}} disabled={busy}>
                    {busy ? "Validando…" : <>Confirmar e entrar <Icon name="check" size={16}/></>}
                  </button>

                  <div className="login-foot" style={{marginTop: 15, textAlign: "center"}}>
                    <button type="button" className="btn-link" onClick={() => setMode("register")}>Voltar para o cadastro</button>
                  </div>
                </form>
              </>
            )}

            {/* MODO RECUPERAÇÃO DE SENHA */}
            {mode === "forgot" && (
              <>
                <div className="login-head">
                  <div className="login-eyebrow">RECUPERAÇÃO DE ACESSO</div>
                  <h2>Redefinir senha</h2>
                  <p>Informe o e-mail cadastrado e enviaremos um link seguro para você criar uma nova senha.</p>
                </div>

                <form className="login-form" onSubmit={handleForgot}>
                  <label className="field">
                    <span className="field-label">E-mail da conta</span>
                    <span className="field-input">
                      <Icon name="mail" size={16} />
                      <input type="email" placeholder="engenheiro@empresa.com.br" required />
                    </span>
                  </label>

                  <button type="submit" className="btn btn-primary btn-block" style={{marginTop: 20}}>
                    Enviar link de recuperação
                  </button>

                  <button type="button" className="btn btn-ghost btn-block" onClick={() => setMode("login")} style={{marginTop: 10}}>
                    Voltar para o login
                  </button>
                </form>
              </>
            )}
          </div>
        </section>
      </main>
    </div>
  );
};

/* ===========================================================
   SIDEBAR
=========================================================== */
const NAV = [
  { id: "dashboard",   label: "Dashboard",       icon: "dashboard", section: "PRINCIPAL" },
  { id: "calculators", label: "Calculadoras",    icon: "calc",      section: "PRINCIPAL" },
  { id: "current",     label: "Corrente Elétrica", icon: "bolt",    section: "MÓDULOS TÉCNICOS", badge: "NOVO" },
  { id: "drop",        label: "Queda de Tensão", icon: "wave",      section: "MÓDULOS TÉCNICOS", badge: "NOVO" },
  { id: "cables",      label: "Dimensionamento", icon: "ruler",     section: "MÓDULOS TÉCNICOS", badge: "NOVO" },
  { id: "secao",       label: "Seção do Condutor", icon: "cable",   section: "MÓDULOS TÉCNICOS", badge: "NOVO" },
  { id: "eletroduto",  label: "Taxa de Ocupação", icon: "pipe",     section: "MÓDULOS TÉCNICOS", badge: "ATIVO" },
  { id: "fp",          label: "Banco Capacitor", icon: "sigma",    section: "MÓDULOS TÉCNICOS", badge: "NOVO" },
  { id: "short",       label: "Curto-Circuito",  icon: "flash",     section: "MÓDULOS TÉCNICOS" },
  { id: "spda",        label: "SPDA",            icon: "shield",    section: "MÓDULOS TÉCNICOS" },
  { id: "trafo",       label: "Transformadores", icon: "transformer", section: "MÓDULOS TÉCNICOS" },
  { id: "motores",     label: "Quadro de Motores", icon: "bolt",     section: "MÓDULOS TÉCNICOS", badge: "NOVO" },
  { id: "demand",      label: "Demandas",        icon: "chart",     section: "MÓDULOS TÉCNICOS" },
  { id: "light",       label: "Iluminação",      icon: "bulb",      section: "MÓDULOS TÉCNICOS" },
  { id: "aterramento", label: "Aterramento",     icon: "spark",    section: "MÓDULOS TÉCNICOS" },
  { id: "quadros",     label: "Quadros & Partidas",   icon: "diagram", section: "FERRAMENTAS", badge: "NOVO" },
  { id: "montagem",    label: "Montagem de Quadros",  icon: "grid",    section: "FERRAMENTAS", badge: "NOVO" },
  { id: "infra",       label: "Infraestrutura",       icon: "pipe",    section: "FERRAMENTAS", badge: "NOVO" },
  { id: "cad",         label: "Desenho Técnico",      icon: "ruler",   section: "FERRAMENTAS", badge: "NOVO" },
  { id: "diagrams",    label: "Diagramas Unifilares",  icon: "diagram", section: "FERRAMENTAS" },
  { id: "simulador",   label: "Simulador de Circuitos", icon: "flash",  section: "FERRAMENTAS", badge: "NOVO" },
  { id: "convert",     label: "Conversores",     icon: "refresh",   section: "FERRAMENTAS" },
  { id: "settings",    label: "Configurações",   icon: "settings",  section: "SISTEMA" },
  { id: "minha-conta", label: "Minha Conta",    icon: "user",      section: "CONTA" },
];

const Sidebar = ({ current, onNav, onLogout }) => {
  const isAdmin = window.VL_SESSION?.user?.role === 'ADMIN';
  const sections = useMemo(() => {
    const map = {};
    NAV
      .filter(n => !n.adminOnly || isAdmin)
      .forEach(n => { (map[n.section] = map[n.section] || []).push(n); });
    return map;
  }, [isAdmin]);
  return (
    <aside className="sidebar">
      <div className="sidebar-brand">
        <BrandMark size={24} />
        <div className="brand-name">VOLTLAB<span className="brand-dot">.</span><em>eng</em></div>
      </div>

      <div className="sidebar-search">
        <Icon name="search" size={14}/>
        <input placeholder="Buscar módulo, norma, fórmula…" />
        <kbd>⌘K</kbd>
      </div>

      <nav className="sidebar-nav">
        {Object.entries(sections).map(([title, items]) => (
          <div className="nav-section" key={title}>
            <div className="nav-section-title">{title}</div>
            {items.map(it => (
              <button
                key={it.id}
                className={"nav-item " + (current === it.id ? "is-active" : "")}
                onClick={() => onNav(it.id)}
              >
                <Icon name={it.icon} size={16}/>
                <span>{it.label}</span>
                {it.badge && <span className="nav-badge">{it.badge}</span>}
                {current === it.id && <span className="nav-active-mark" />}
              </button>
            ))}
          </div>
        ))}
      </nav>

      <div className="sidebar-foot">
        <div className="sys-card">
          <div className="sys-row">
            <span className="status-dot status-ok" /> SISTEMA OPERACIONAL
          </div>
          <div className="sys-row sys-row-meta">
            <span>CPU 14%</span><span>RAM 312MB</span>
          </div>
          <div className="sys-bar"><span style={{width: "14%"}} /></div>
        </div>
      </div>
    </aside>
  );
};

/* ===========================================================
   APP HEADER
=========================================================== */
const AppHeader = ({ title, eyebrow, crumbs, onAction, actionLabel = "Novo cálculo", current, onExportReport, onHeaderNav, onMenu }) => (
  <header className="app-header">
    <button className="hamburger" aria-label="Abrir menu" onClick={onMenu}><span></span><span></span><span></span></button>
    <div className="app-header-l">
      <div className="crumbs">
        {crumbs.map((c, i) => (
          <React.Fragment key={i}>
            <span className={"crumb " + (i === crumbs.length - 1 ? "is-last" : "")}>{c}</span>
            {i < crumbs.length - 1 && <span className="crumb-sep">/</span>}
          </React.Fragment>
        ))}
      </div>
      <div className="app-eyebrow">{eyebrow}</div>
      <h1 className="app-title">{title}</h1>
    </div>
    <div className="app-header-r">
      <button className="icon-btn" aria-label="notif"><Icon name="bell" size={16}/><span className="dot-mark"/></button>
      <button className="icon-btn" aria-label="settings" onClick={() => onHeaderNav && onHeaderNav("settings")} title="Configurações"><Icon name="settings" size={16}/></button>
      
      {["current","drop","cables","fp"].includes(current) && onExportReport && (
        <div style={{display:"flex",gap:6}}>
          <button className="btn btn-ghost" onClick={() => onExportReport("json")} title="Exportar JSON">
            <Icon name="download" size={14}/> JSON
          </button>
          <button className="btn btn-ghost" onClick={() => onExportReport("csv")} title="Exportar CSV">
            <Icon name="download" size={14}/> CSV
          </button>
        </div>
      )}

      <button className="btn btn-primary" onClick={onAction}>
        <Icon name="plus" size={14}/> {actionLabel}
      </button>
    </div>
  </header>
);

/* ===========================================================
   DASHBOARD
=========================================================== */
const KPI = ({ label, value, unit, delta, trend, spark }) => (
  <div className="kpi">
    <div className="kpi-head">
      <span className="kpi-label">{label}</span>
      <span className={"kpi-delta " + (trend === "up" ? "is-up" : trend === "down" ? "is-down" : "")}>{delta}</span>
    </div>
    <div className="kpi-value">
      <span className="readout">{value}</span>
      <span className="kpi-unit">{unit}</span>
    </div>
    <svg className="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none">
      <polyline points={spark} fill="none" stroke="var(--accent)" strokeWidth="1.5"/>
      <polyline points={spark} fill="none" stroke="var(--accent)" strokeWidth="6" opacity="0.18"/>
    </svg>
  </div>
);

const Dashboard = ({ onOpenCalc }) => {
  const userName = window.VL_SESSION?.user?.nome?.split(' ')[0] || "Engenheiro";
  const userAcessos = window.VL_SESSION?.user?.acessos || 1;

  const getGreeting = () => {
    const hour = new Date().getHours();
    if (hour >= 5 && hour < 12) return "Bom dia";
    if (hour >= 12 && hour < 18) return "Boa tarde";
    return "Boa noite";
  };
  
  const greeting = getGreeting();

  return (
    <div className="dashboard">
      <section className="d-hero">
        <div className="d-hero-bg"><Circuitry show={true}/></div>
        <div className="d-hero-content">
          <div className="d-hero-eyebrow"><span className="hero-tag-line"/> AMBIENTE DE TRABALHO · {userName.toUpperCase()}</div>
          <h2 className="d-hero-title">
            {greeting}, {userName}. <em>Seu ambiente está pronto.</em>
          </h2>
          <p className="d-hero-sub">
            Você já acessou a plataforma <b>{userAcessos} {userAcessos === 1 ? 'vez' : 'vezes'}</b>.
          </p>
          <div className="d-hero-actions">
            <button className="btn btn-primary" onClick={() => onOpenCalc("eletroduto")}>
              Abrir calculadora de eletroduto <Icon name="arrow" size={14}/>
            </button>
            <button className="btn btn-ghost">Ver meus projetos</button>
          </div>
        </div>
      </section>

      <section className="d-kpis">
        <KPI label="CÁLCULOS / 30 DIAS" value="0" unit="" delta="novo" trend=""
             spark="0,30 120,30"/>
        <KPI label="QUEDA DE TENSÃO MÉD." value="0,0" unit="%" delta="novo" trend=""
             spark="0,30 120,30"/>
        <KPI label="OCUPAÇÃO ELETRODUTO" value="0,0" unit="%" delta="novo" trend=""
             spark="0,30 120,30"/>
        <KPI label="DEMANDA INSTALADA" value="0,0" unit="kVA" delta="novo" trend=""
             spark="0,30 120,30"/>
      </section>

      <section className="d-grid">
        <div className="panel panel-recent">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">RECENTES</div>
              <h3>Cálculos do projeto atual</h3>
            </div>
          </div>
          <div className="recent-table">
            <div className="rt-head">
              <span>ID</span><span>Módulo</span><span>Projeto</span><span>Resultado</span><span>Status</span>
            </div>
            <div style={{ padding: '34px 20px', textAlign: 'center', color: 'var(--fg-mute)', fontSize: '13px' }}>
              Nenhum cálculo realizado recentemente.<br/>
              Acesse as calculadoras pelo menu lateral para começar.
            </div>
          </div>
        </div>

        <div className="panel panel-quick">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ATALHOS</div>
              <h3>Módulos frequentes</h3>
            </div>
          </div>
          <div className="quick-grid">
            {[
              ["eletroduto","Eletroduto","pipe","NBR 5410"],
              ["drop","Queda de Tensão","wave","≤ 4%"],
              ["short","Curto-Circuito","flash","Icc·t²"],
              ["cables","Cabos","cable","Ampacidade"],
              ["spda","SPDA","shield","NBR 5419"],
              ["montagem","Montagem de Quadros","grid","Layout DIN"],
              ["light","Iluminação","bulb","8995-1"],
              ["aterramento","Aterramento","spark","R ≤ 10Ω"],
            ].map(([id, label, icon, sub]) => (
              <button key={id} className="quick-card" onClick={() => onOpenCalc(id)}>
                <div className="quick-icon"><Icon name={icon} size={20}/></div>
                <div className="quick-meta">
                  <b>{label}</b>
                  <em>{sub}</em>
                </div>
                <Icon name="arrow" size={14}/>
              </button>
            ))}
          </div>
        </div>

        <div className="panel panel-chart">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">CURVA DE DEMANDA · 24H</div>
              <h3>Geral — 13.8/0.38 kV</h3>
            </div>
            <div className="legend">
              <span><i className="lg lg-a"/>Demanda</span>
              <span><i className="lg lg-b"/>Reativa</span>
              <span><i className="lg lg-c"/>Limite</span>
            </div>
          </div>
          <div className="chart-wrap" style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '240px', color: 'var(--fg-mute)', fontSize: '13px', border: '1px dashed var(--border-2)', borderRadius: '8px' }}>
            A curva será gerada assim que houver dados de demanda.
          </div>
        </div>

        <div className="panel panel-notes">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">SISTEMA</div>
              <h3>Avisos técnicos</h3>
            </div>
          </div>
          <ul className="notice-list">
            <li>
              <span className="status-dot status-ok"/>
              <div>
                <b>Conta conectada</b>
                <em>Bem-vindo ao VoltLab! Seu ambiente está sincronizado com o servidor seguro.</em>
              </div>
            </li>
          </ul>
        </div>
      </section>
    </div>
  );
};

/* ===========================================================
   CALCULATORS GRID
=========================================================== */
const CALCS = [
  { id: "eletroduto",  icon: "pipe",       name: "Eletroduto",         norm: "NBR 5410 — Anexo H",   tag: "Dimensionamento", desc: "Cálculo de ocupação e bitola mínima de eletroduto para múltiplos condutores." },
  { id: "drop",        icon: "wave",       name: "Queda de Tensão",    norm: "NBR 5410 6.2.7",       tag: "Análise",        desc: "Cálculo de ΔV em circuitos monofásicos, bifásicos e trifásicos." },
  { id: "current",     icon: "bolt",       name: "Corrente Nominal",   norm: "IEC 60364",            tag: "Análise",        desc: "Determinação da corrente de projeto a partir da carga e tensão." },
  { id: "cables",      icon: "cable",      name: "Dimensionamento de Cabos", norm: "NBR 5410 — Tabela 36", tag: "Dimensionamento", desc: "Bitola por ampacidade, queda de tensão e curto-circuito." },
  { id: "secao",       icon: "cable",      name: "Seção do Condutor",   norm: "NBR 5410 — item 6.2", tag: "Dimensionamento", desc: "Seção por todos os critérios: ampacidade, queda, seção mínima, sobrecarga e curto." },
  { id: "short",       icon: "flash",      name: "Corrente de Curto-Circuito", norm: "IEC 60909", tag: "Proteção", desc: "Cálculo de Icc simétrica e assimétrica em barramentos." },
  { id: "spda",        icon: "shield",     name: "SPDA",               norm: "NBR 5419",            tag: "Proteção",        desc: "Classificação do SPDA, malha e número de captores." },
  { id: "trafo",       icon: "transformer", name: "Transformadores",   norm: "NBR 5440",            tag: "Equipamento",     desc: "Dimensionamento de potência e correntes primária/secundária." },
  { id: "motores",     icon: "bolt",       name: "Quadro de Motores",  norm: "WEG · NBR 5410",      tag: "Equipamento",     desc: "Lista de motores: corrente nominal, fator de partida e dimensionamento de cabo." },
  { id: "fp",          icon: "sigma",      name: "Banco de Capacitores",  norm: "ANEEL 414/2010", tag: "Qualidade", desc: "Dimensionamento do banco capacitivo para correção de fator de potência." },
  { id: "demand",      icon: "chart",      name: "Demandas",           norm: "Concessionárias",     tag: "Projeto",         desc: "Demanda provável por tipologia de unidade consumidora." },
  { id: "light",       icon: "bulb",       name: "Iluminação",         norm: "NBR ISO 8995",        tag: "Conforto",        desc: "Método dos lumens, fator de utilização e densidade luminosa." },
  { id: "quadros",     icon: "diagram",    name: "Quadros & Partidas", norm: "WEG · IEC 60947", tag: "Ferramentas", desc: "Diagrama interativo de quadros de partida (direta e estrela-triângulo) com componentes WEG." },
  { id: "cad",         icon: "ruler",      name: "Desenho Técnico",    norm: "CAD 2D",          tag: "Ferramentas", desc: "Editor CAD com pan/zoom, snap-grid, ferramentas de desenho, biblioteca de símbolos e camadas." },
  { id: "diagrams",    icon: "diagram",    name: "Diagramas Unifilares", norm: "—",                 tag: "Ferramentas",     desc: "Editor para diagramas unifilares e multifilares simplificados." },
  { id: "simulador",   icon: "flash",      name: "Simulador de Circuitos", norm: "MNA · Transitório", tag: "Ferramentas", desc: "Simulação interativa de circuitos (estilo Falstad) com análise nodal e transitória." },
  { id: "convert",     icon: "refresh",    name: "Conversores",        norm: "SI · USCS",          tag: "Ferramentas",     desc: "Conversão entre unidades elétricas, mecânicas e térmicas." },
  { id: "infra",       icon: "pipe",       name: "Infraestrutura",     norm: "Quantitativo / BOM", tag: "Ferramentas",     desc: "Quantitativo de eletrocalhas, leitos, perfilados e eletrodutos por distância." },
];

const CALC_TAGS = {
  "Dimensionamento": { hue: 245, icon: "pipe" },
  "Análise":         { hue: 200, icon: "wave" },
  "Proteção":        { hue: 45,  icon: "shield" },
  "Equipamento":     { hue: 290, icon: "transformer" },
  "Qualidade":       { hue: 150, icon: "sigma" },
  "Projeto":         { hue: 330, icon: "chart" },
  "Conforto":        { hue: 95,  icon: "bulb" },
  "Ferramentas":     { hue: 265, icon: "diagram" },
};
const tagTone = (tag) => `oklch(74% 0.135 ${(CALC_TAGS[tag]?.hue ?? 245)})`;
const tagSoft = (tag) => `oklch(74% 0.135 ${(CALC_TAGS[tag]?.hue ?? 245)} / 0.13)`;

const Calculators = ({ onOpen }) => {
  const [filter, setFilter] = useState("Todos");
  const [query, setQuery] = useState("");
  const tags = ["Todos", ...Array.from(new Set(CALCS.map(c => c.tag)))];

  const list = CALCS.filter(c => {
    const okTag = filter === "Todos" || c.tag === filter;
    const q = query.trim().toLowerCase();
    const okQuery = !q || [c.name, c.norm, c.desc, c.tag].join(" ").toLowerCase().includes(q);
    return okTag && okQuery;
  });

  const tagCount = (t) => t === "Todos" ? CALCS.length : CALCS.filter(c => c.tag === t).length;

  return (
    <div className="calculators">
      <div className="catalog-head">
        <div className="catalog-head-l">
          <div className="catalog-eyebrow">BIBLIOTECA DE MÓDULOS</div>
          <h2 className="catalog-title">
            {list.length} {list.length === 1 ? "ferramenta disponível" : "ferramentas disponíveis"}
          </h2>
        </div>
        <div className="catalog-search">
          <Icon name="search" size={15}/>
          <input
            value={query}
            onChange={e => setQuery(e.target.value)}
            placeholder="Buscar por nome, norma ou categoria…"
          />
          {query && <button className="catalog-search-clear" onClick={() => setQuery("")} aria-label="limpar">×</button>}
        </div>
      </div>

      <div className="catalog-tabs">
        {tags.map(t => (
          <button
            key={t}
            className={"cat-tab " + (filter === t ? "is-active" : "")}
            onClick={() => setFilter(t)}
            style={t !== "Todos" ? { "--cat": tagTone(t), "--cat-soft": tagSoft(t) } : undefined}
          >
            {t !== "Todos" && <span className="cat-tab-dot"/>}
            <span>{t}</span>
            <span className="cat-tab-count">{tagCount(t)}</span>
          </button>
        ))}
      </div>

      {list.length === 0 ? (
        <div className="catalog-empty">
          <div className="catalog-empty-icon"><Icon name="search" size={26}/></div>
          <h4>Nenhum módulo encontrado</h4>
          <p>Tente outro termo ou limpe o filtro de categoria.</p>
        </div>
      ) : (
        <div className="calc-grid">
          {list.map((c, i) => (
            <button
              key={c.id}
              className="calc-card"
              onClick={() => onOpen(c.id)}
              style={{ "--cat": tagTone(c.tag), "--cat-soft": tagSoft(c.tag), "--i": i }}
            >
              <div className="calc-card-top">
                <div className="calc-card-icon"><Icon name={c.icon} size={22}/></div>
                <span className="calc-card-tag">{c.tag}</span>
              </div>
              <div className="calc-card-body">
                <h4>{c.name}</h4>
                <p>{c.desc}</p>
              </div>
              <div className="calc-card-foot">
                <span className="calc-card-norm mono">{c.norm}</span>
                <span className="calc-card-cta">
                  Abrir <Icon name="arrow" size={14}/>
                </span>
              </div>
              <div className="calc-card-glow"/>
            </button>
          ))}
        </div>
      )}
    </div>
  );
};

/* ===========================================================
   TAXA DE OCUPAÇÃO — eletrodutos, eletrocalhas e leitos
=========================================================== */
const INFRA_TYPES = [
  { id: "ELETRODUTO",  label: "Eletroduto",   shape: "circle" },
  { id: "ELETROCALHA", label: "Eletrocalha",  shape: "rect" },
  { id: "LEITO",       label: "Leito",        shape: "rect" },
];
const CABLE_BITOLAS = ["1.5","2.5","4","6","10","16","25","35","50","70","95","120","150","185","240"];

const Eletroduto = () => {
  const D = window.VL_DATA;
  const [rows, setRows] = useLocalStorage("vl_eletroduto_rows", [
    { bit: "2.5", qty: 3, iso: "PVC" },
    { bit: "4",   qty: 2, iso: "PVC" },
    { bit: "10",  qty: 1, iso: "PVC" },
  ]);
  const [infra, setInfra] = useLocalStorage("vl_eletroduto_infra", "ELETRODUTO");
  const [material, setMaterial] = useLocalStorage("vl_eletroduto_material", "PVC");
  const [dim, setDim] = useLocalStorage("vl_eletroduto_dim", "");

  const infraType = INFRA_TYPES.find(t => t.id === infra);

  const dimOptions = useMemo(() => {
    if (!D) return [];
    if (infra === "ELETRODUTO") {
      const obj = D.conduits[material] || {};
      return Object.entries(obj).map(([k,area]) => ({ key: k, area, label: k }));
    }
    if (infra === "ELETROCALHA") return Object.entries(D.eletrocalhas).map(([k,v]) => ({ key: k, ...v, label: k + " mm" }));
    return Object.entries(D.leitos).map(([k,v]) => ({ key: k, ...v, label: k + " mm" }));
  }, [infra, material, D]);

  const totalCond = rows.reduce((s,r) => s + r.qty, 0);
  const cableList = useMemo(() => {
    if (!D) return [];
    return rows.flatMap(r => {
      const d = D.cableDiameters[r.bit]?.[r.iso] || 0;
      const a = Math.PI * (d/2)**2;
      return Array.from({length: r.qty}, () => ({ bit: r.bit, iso: r.iso, d, a }));
    });
  }, [rows, D]);
  
  const totalArea = cableList.reduce((s,c) => s + c.a, 0);

  const limitPct = useMemo(() => {
    if (infra === "ELETRODUTO") return totalCond === 1 ? 53 : totalCond <= 3 ? 31 : 40;
    return 40;
  }, [infra, totalCond]);

  const autoDim = useMemo(() => {
    if (!dimOptions.length) return null;
    const required = totalArea / (limitPct/100);
    return dimOptions.find(d => d.area >= required) || dimOptions[dimOptions.length - 1];
  }, [dimOptions, totalArea, limitPct]);

  const selectedDim = useMemo(() => {
    if (!dim) return autoDim;
    return dimOptions.find(d => d.key === dim) || autoDim;
  }, [dim, dimOptions, autoDim]);

  const occupancyPct = selectedDim ? (totalArea / selectedDim.area) * 100 : 0;
  const status = occupancyPct <= limitPct ? "ok" : "warn";

  const updateRow = (i, patch) => setRows(rs => rs.map((r,idx) => idx===i ? {...r, ...patch} : r));
  const removeRow = (i) => setRows(rs => rs.filter((_,idx) => idx!==i));
  const addRow = () => setRows(rs => [...rs, { bit: "2.5", qty: 1, iso: "PVC" }]);

  if (!D) return <div style={{padding: 20}}>Carregando dados normativos...</div>;

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel el-inputs">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ENTRADA · INFRAESTRUTURA E CABOS</div>
              <h3>Configuração da bandeja, leito ou eletroduto</h3>
            </div>
            <div className="status-chip"><span className="status-dot status-ok"/>AUTO-CÁLCULO</div>
          </div>

          <div className="form-row form-row-2">
            <div className="field-block">
              <label>Tipo de infraestrutura</label>
              <div className="seg">
                {INFRA_TYPES.map(t => (
                  <button key={t.id} className={infra===t.id ? "is-active":""} onClick={() => { setInfra(t.id); setDim(""); }}>{t.label}</button>
                ))}
              </div>
            </div>
            {infra === "ELETRODUTO" ? (
              <div className="field-block">
                <label>Material do eletroduto</label>
                <div className="seg">
                  {Object.entries(D.conduitMaterials).filter(([k]) => D.conduits[k]).map(([k,label]) => (
                    <button key={k} className={material===k ? "is-active":""} onClick={() => { setMaterial(k); setDim(""); }}>{label}</button>
                  ))}
                </div>
              </div>
            ) : (
              <div className="field-block">
                <label>Limite NBR aplicado</label>
                <div className="vl-info-card">
                  <span className="readout">40%</span>
                  <em>Eletrocalhas e leitos · NBR 5410</em>
                </div>
              </div>
            )}
          </div>

          <div className="cond-table">
            <div className="ct-head">
              <span>#</span>
              <span>Bitola</span>
              <span>Isolação</span>
              <span>Quantidade</span>
              <span>Área unit.</span>
              <span/>
            </div>
            {rows.map((r,i) => {
              const d = D.cableDiameters[r.bit]?.[r.iso] || 0;
              const unit = Math.PI * (d/2)**2;
              return (
                <div className="ct-row" key={i}>
                  <span className="mono dim">{String(i+1).padStart(2,"0")}</span>
                  <span>
                    <Dropdown
                      value={r.bit}
                      onChange={(v) => updateRow(i, { bit: v })}
                      options={CABLE_BITOLAS.map(b => ({ value: b, label: `${b} mm²` }))}
                    />
                  </span>
                  <span>
                    <Dropdown
                      value={r.iso}
                      onChange={(v) => updateRow(i, { iso: v })}
                      options={[
                        { value: "PVC", label: "PVC" },
                        { value: "EPR", label: "EPR" },
                        { value: "XLPE", label: "XLPE" },
                      ]}
                    />
                  </span>
                  <span className="qty">
                    <button onClick={() => updateRow(i, { qty: Math.max(1, r.qty - 1) })}>−</button>
                    <span className="mono">{String(r.qty).padStart(2,"0")}</span>
                    <button onClick={() => updateRow(i, { qty: r.qty + 1 })}>+</button>
                  </span>
                  <span className="mono">
                    <span className="dim">Ø{d.toFixed(1)}</span> · {(unit*r.qty).toFixed(1)} mm²
                  </span>
                  <button className="ct-remove" onClick={() => removeRow(i)} aria-label="remover">×</button>
                </div>
              );
            })}
            <button className="ct-add" onClick={addRow}>
              <Icon name="plus" size={14}/> Adicionar condutor
            </button>
          </div>

          <div className="summary-grid">
            <div>
              <span>Total condutores</span>
              <b className="readout">{String(totalCond).padStart(2,"0")}</b>
            </div>
            <div>
              <span>Área total ocupada</span>
              <b className="readout">{totalArea.toFixed(1)} <em>mm²</em></b>
            </div>
            <div>
              <span>Limite NBR aplicado</span>
              <b className="readout">{limitPct} <em>%</em></b>
            </div>
            <div>
              <span>Área mínima necessária</span>
              <b className="readout">{(totalArea/(limitPct/100)).toFixed(1)} <em>mm²</em></b>
            </div>
          </div>
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">RESULTADO · INFRAESTRUTURA RECOMENDADA</div>
              <h3>{infra === "ELETRODUTO" ? "Eletroduto recomendado" : infra === "ELETROCALHA" ? "Eletrocalha recomendada" : "Leito recomendado"}</h3>
            </div>
          </div>

          <div className="result-hero">
            <div className="result-corner result-corner-tl"/>
            <div className="result-corner result-corner-tr"/>
            <div className="result-corner result-corner-bl"/>
            <div className="result-corner result-corner-br"/>

            <div className="result-eyebrow">
              {infra === "ELETRODUTO" ? "DIÂMETRO NOMINAL" : "DIMENSÃO COMERCIAL"}
            </div>
            <div className="result-value">
              <span className="readout">{infra === "ELETRODUTO" ? selectedDim?.label : selectedDim?.label?.replace(" mm","")}</span>
              <em>{infra === "ELETRODUTO" ? "" : "mm"}</em>
            </div>
            <div className="result-meta">
              {infra === "ELETRODUTO" ? (
                <>
                  <span>Material: <b>{D.conduitMaterials[material]}</b></span>
                  <span>Área útil: <b>{selectedDim?.area} mm²</b></span>
                </>
              ) : (
                <>
                  <span>L × A: <b>{selectedDim?.largura}×{selectedDim?.altura} mm</b></span>
                  <span>Área útil: <b>{selectedDim?.area} mm²</b></span>
                </>
              )}
            </div>

            {infraType.shape === "circle"
              ? <ConduitDiagram totalArea={totalArea} pipeArea={selectedDim?.area || 1} cables={cableList}/>
              : <TrayDiagram dims={selectedDim} cables={cableList}/>
            }

            <div className="result-bar">
              <div className="result-bar-track">
                <span style={{ width: Math.min(100, occupancyPct/limitPct*100) + "%" }} className={"bar-fill bar-" + status}/>
                <span className="bar-limit" style={{ left: "100%" }}/>
              </div>
              <div className="result-bar-meta">
                <span><b className="readout">{occupancyPct.toFixed(1)}%</b> ocupado</span>
                <span className="dim">limite {limitPct}%</span>
              </div>
            </div>

            <div className={"result-status status-" + status}>
              <span className="status-dot"/>
              {status === "ok" ? "Dentro do limite normativo · NBR 5410" : `Excedido em ${(occupancyPct-limitPct).toFixed(1)}pp — selecionar maior`}
            </div>
          </div>
        </aside>
      </div>

      <section className="panel el-reference">
        <div className="panel-head">
          <div>
            <div className="panel-eyebrow">REFERÊNCIA TÉCNICA · DIMENSÕES DISPONÍVEIS</div>
            <h3>
              {infra === "ELETRODUTO" ? `Eletroduto ${D.conduitMaterials[material]}` : infra === "ELETROCALHA" ? "Eletrocalhas perfuradas" : "Leitos para cabos"}
            </h3>
          </div>
          <span className="dim mono small">Fonte: NBR 5410 / catálogos técnicos</span>
        </div>
        <div className="ref-table">
          <div className="ref-head">
            <span>{infra === "ELETRODUTO" ? "NOMINAL" : "L×A (mm)"}</span>
            <span>ÁREA ÚTIL (mm²)</span>
            <span>ÁREA NECESSÁRIA</span>
            <span>STATUS</span>
            <span>UTILIZAÇÃO</span>
          </div>
          {dimOptions.map(c => {
            const required = totalArea/(limitPct/100);
            const ok = c.area >= required;
            const isSel = selectedDim && c.key === selectedDim.key;
            const util = (totalArea / c.area) * 100;
            return (
              <div key={c.key} className={"ref-row " + (isSel ? "is-sel" : "")} onClick={() => setDim(c.key)} style={{cursor:"pointer"}}>
                <span className="mono">{c.label}</span>
                <span className="mono">{c.area}</span>
                <span className="mono dim">{required.toFixed(0)} mm²</span>
                <span className={"pill pill-" + (ok ? "ok" : "warn")}>{ok ? "Atende" : "Insuficiente"}</span>
                <span className="ref-util">
                  <span className="util-bar"><span style={{width: Math.min(100,util)+"%"}}/></span>
                  <span className="mono">{util.toFixed(0)}%</span>
                </span>
              </div>
            );
          })}
        </div>
      </section>
    </div>
  );
};

const ConduitDiagram = ({ totalArea, pipeArea, cables }) => {
  const R = 90;
  const pipeArea_px = Math.PI * R * R;
  const scale = pipeArea_px / pipeArea;
  const list = cables.map(c => ({ rad: Math.sqrt((c.a * scale) / Math.PI), bit: c.bit }));
  list.sort((a,b) => b.rad - a.rad);
  const placed = [];
  list.forEach(c => {
    if (placed.length === 0) {
      placed.push({ x: 0, y: 0, rad: c.rad });
      return;
    }
    let placedOk = false;
    const maxRingR = R - c.rad - 1;
    for (let ringR = c.rad + 2; ringR <= maxRingR && !placedOk; ringR += 1) {
      const steps = Math.max(8, Math.floor((2*Math.PI*ringR) / (c.rad*1.4)));
      for (let i = 0; i < steps; i++) {
        const ang = (i / steps) * Math.PI * 2;
        const x = Math.cos(ang) * ringR;
        const y = Math.sin(ang) * ringR;
        const ok = placed.every(p => {
          const dx = p.x - x, dy = p.y - y;
          return Math.sqrt(dx*dx + dy*dy) >= (p.rad + c.rad) * 1.01;
        });
        if (ok) {
          placed.push({ x, y, rad: c.rad });
          placedOk = true;
          break;
        }
      }
    }
  });

  return (
    <svg className="conduit-svg" viewBox="-110 -110 220 220">
      <defs>
        <radialGradient id="pipeShade" r="0.6">
          <stop offset="0%" stopColor="var(--bg-1)"/>
          <stop offset="100%" stopColor="var(--bg-0)"/>
        </radialGradient>
      </defs>
      <circle cx="0" cy="0" r={R+6} fill="none" stroke="var(--border-2)" strokeWidth="1" strokeDasharray="2 4"/>
      <circle cx="0" cy="0" r={R} fill="url(#pipeShade)" stroke="var(--border-2)" strokeWidth="1.2"/>
      <circle cx="0" cy="0" r={R-2} fill="none" stroke="var(--accent)" strokeWidth="0.5" opacity="0.4"/>
      {placed.map((p, i) => (
        <g key={i}>
          <circle cx={p.x} cy={p.y} r={p.rad} fill="var(--accent-soft)" stroke="var(--accent)" strokeWidth="0.8"/>
          <circle cx={p.x} cy={p.y} r={p.rad*0.35} fill="var(--accent)"/>
        </g>
      ))}
      <line x1={R} y1="0" x2={R+18} y2="0" stroke="var(--fg-dim)" strokeWidth="0.6"/>
      <line x1={R+18} y1="0" x2={R+18} y2="-20" stroke="var(--fg-dim)" strokeWidth="0.6"/>
      <text x={R+20} y="-22" fill="var(--fg-dim)" fontSize="7" fontFamily="JetBrains Mono">Ø interno</text>
    </svg>
  );
};

const TrayDiagram = ({ dims, cables }) => {
  if (!dims) return null;
  const VBW = 240, VBH = 130;
  const padX = 14, padY = 12;
  const innerW = VBW - padX*2 - 12;
  const aspect = dims.largura / dims.altura;
  let trayW = innerW, trayH = trayW / aspect;
  if (trayH > VBH - padY*2 - 12) {
    trayH = VBH - padY*2 - 12;
    trayW = trayH * aspect;
  }
  const trayX = (VBW - trayW)/2;
  const trayY = (VBH - trayH)/2;
  const trayAreaPx = trayW * trayH;
  const trayAreaMm = dims.area;
  const scale = trayAreaPx / trayAreaMm;
  const list = cables.map(c => ({ rad: Math.sqrt((c.a * scale) / Math.PI) }));
  list.sort((a,b) => b.rad - a.rad);
  const placed = [];
  let x = trayX + 4, y = trayY + trayH - 4 - (list[0]?.rad || 0);
  let rowH = 0;
  list.forEach(c => {
    if (x + c.rad*2 > trayX + trayW - 4) {
      x = trayX + 4;
      y -= rowH*2 + 2;
      rowH = 0;
    }
    placed.push({ x: x + c.rad, y: y, rad: c.rad });
    x += c.rad*2 + 2;
    if (c.rad > rowH) rowH = c.rad;
  });
  return (
    <svg className="conduit-svg" viewBox={`0 0 ${VBW} ${VBH}`} style={{height: 200}}>
      <defs>
        <linearGradient id="trayShade" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor="var(--bg-1)"/>
          <stop offset="100%" stopColor="var(--bg-0)"/>
        </linearGradient>
      </defs>
      <rect x={trayX-4} y={trayY-4} width={trayW+8} height={trayH+8} rx="3" fill="none" stroke="var(--border-2)" strokeDasharray="2 4"/>
      <rect x={trayX} y={trayY} width={trayW} height={trayH} rx="2" fill="url(#trayShade)" stroke="var(--border-2)" strokeWidth="1"/>
      <g fill="var(--border-2)" opacity="0.4">
        {Array.from({length: Math.floor(trayW/12)}).map((_,i) => (
          <circle key={i} cx={trayX + 6 + i*12} cy={trayY + 3} r="0.8"/>
        ))}
      </g>
      {placed.map((p, i) => (
        <g key={i}>
          <circle cx={p.x} cy={p.y} r={p.rad} fill="var(--accent-soft)" stroke="var(--accent)" strokeWidth="0.8"/>
          <circle cx={p.x} cy={p.y} r={p.rad*0.35} fill="var(--accent)"/>
        </g>
      ))}
      <line x1={trayX} y1={trayY+trayH+10} x2={trayX+trayW} y2={trayY+trayH+10} stroke="var(--fg-dim)" strokeWidth="0.5"/>
      <text x={trayX+trayW/2} y={trayY+trayH+18} textAnchor="middle" fill="var(--fg-dim)" fontSize="7" fontFamily="JetBrains Mono">{dims.largura} mm</text>
    </svg>
  );
};

/* ===========================================================
   PLACEHOLDER VIEW
=========================================================== */
const Placeholder = ({ name }) => (
  <div className="placeholder-panel panel">
    <div className="ph-icon"><Icon name="spark" size={28}/></div>
    <h3>Módulo "{name}"</h3>
    <p>Esta calculadora segue a mesma arquitetura visual e técnica da calculadora de eletroduto. Disponível em breve no protótipo.</p>
    <span className="dim mono small">MÓDULO EM CONFIGURAÇÃO · NBR ASSOCIADA</span>
  </div>
);

/* ===========================================================
   APP ROOT
=========================================================== */
const APP_TITLES = {
  dashboard:   { eyebrow: "VISÃO GERAL",         title: "Workspace de engenharia",   crumbs: ["VOLTLAB","Dashboard"] },
  calculators: { eyebrow: "BIBLIOTECA",          title: "Catálogo de calculadoras",  crumbs: ["VOLTLAB","Calculadoras"] },
  eletroduto:  { eyebrow: "INFRAESTRUTURA · NBR 5410", title: "Taxa de ocupação", crumbs: ["VOLTLAB","Calculadoras","Taxa de Ocupação"] },
  current:     { eyebrow: "CIRCUITOS · NBR 5410",      title: "Corrente elétrica", crumbs: ["VOLTLAB","Calculadoras","Corrente"] },
  drop:        { eyebrow: "CIRCUITOS · NBR 5410",      title: "Queda de tensão",   crumbs: ["VOLTLAB","Calculadoras","Queda de Tensão"] },
  cables:      { eyebrow: "DIMENSIONAMENTO · NBR 5410", title: "Dimensionamento de cabos", crumbs: ["VOLTLAB","Calculadoras","Cabos"] },
  fp:          { eyebrow: "QUALIDADE DE ENERGIA · ANEEL 414", title: "Banco de capacitores", crumbs: ["VOLTLAB","Calculadoras","Banco de Capacitores"] },
  quadros:     { eyebrow: "FERRAMENTAS · DIMENSIONAMENTO WEG", title: "Quadros & Diagramas de Partidas", crumbs: ["VOLTLAB","Ferramentas","Quadros & Partidas"] },
  cad:         { eyebrow: "FERRAMENTAS · DESENHO 2D",          title: "Editor CAD", crumbs: ["VOLTLAB","Ferramentas","Desenho Técnico"] },
  light:       { eyebrow: "ILUMINAÇÃO · NBR ISO/CIE 8995-1", title: "Dimensionamento de Iluminação", crumbs: ["VOLTLAB","Calculadoras","Iluminação"] },
  aterramento: { eyebrow: "ATERRAMENTO · MÉTODO DAS RESISTÊNCIAS MÚTUAS", title: "Resistência de Aterramento", crumbs: ["VOLTLAB","Calculadoras","Aterramento"] },
  montagem:    { eyebrow: "FERRAMENTAS · MONTAGEM DE QUADROS ELÉTRICOS", title: "Montagem de Quadros — Layout DIN", crumbs: ["VOLTLAB","Ferramentas","Montagem de Quadros"] },
  secao:       { eyebrow: "DIMENSIONAMENTO · NBR 5410 (item 6.2)", title: "Seção do Condutor", crumbs: ["VOLTLAB","Calculadoras","Seção do Condutor"] },
  simulador:   { eyebrow: "FERRAMENTAS · SIMULAÇÃO DE CIRCUITOS", title: "Simulador de Circuitos", crumbs: ["VOLTLAB","Ferramentas","Simulador"] },
  demand:      { eyebrow: "MÓDULOS TÉCNICOS", title: "Cálculo de Demandas", crumbs: ["VOLTLAB","Calculadoras","Demandas"] },
  motores:     { eyebrow: "EQUIPAMENTOS · MOTORES", title: "Quadro de Motores", crumbs: ["VOLTLAB","Calculadoras","Quadro de Motores"] },
  convert:     { eyebrow: "FERRAMENTAS", title: "Conversores Elétricos", crumbs: ["VOLTLAB","Ferramentas","Conversores"] },
  infra:       { eyebrow: "FERRAMENTAS · INFRAESTRUTURA", title: "Cálculo de Infraestrutura", crumbs: ["VOLTLAB","Ferramentas","Infraestrutura"] },
  settings:    { eyebrow: "SISTEMA · PREFERÊNCIAS", title: "Configurações", crumbs: ["VOLTLAB","Sistema","Configurações"] },
};

const App = () => {
  const t = window.useTweaks ? window.useTweaks(TWEAK_DEFAULTS) : [TWEAK_DEFAULTS, () => {}];
  const [tweaks, setTweak] = t;

  useEffect(() => { window.Dropdown_VL = Dropdown; }, []);

  const [screen, setScreen] = useState(() => window.location.hash === "#app" ? "app" : "landing");
  const [current, setCurrent] = useState("dashboard");
  const [mobileNav, setMobileNav] = useState(false);
  const [guest, setGuest] = useState(false);

  useEffect(() => {
    const a = ACCENT_MAP[tweaks.accent] || ACCENT_MAP["#3D8BFF"];
    document.documentElement.style.setProperty("--accent", a.primary);
    document.documentElement.style.setProperty("--accent-glow", a.glow);
    document.documentElement.style.setProperty("--accent-soft", a.soft);
    document.documentElement.style.setProperty("--accent-2", "oklch(82% 0.14 200)");
    document.documentElement.dataset.density = tweaks.density;
    document.documentElement.dataset.mono = tweaks.monoReadouts ? "on" : "off";
  }, [tweaks]);

  const goCalc = (id) => {
    setCurrent(id);
  };

  const enterApp = () => {
    window.location.hash = "#app";
    setScreen("app");
  };
  const enterGuest = () => {
    window.VL_SESSION = { token: "guest", user: { nome: "Visitante", email: "", role: "GUEST" }, plan: null, guest: true };
    setGuest(true);
    enterApp();
  };
  const goLanding = () => {
    try { history.replaceState(null, "", window.location.pathname + window.location.search); }
    catch { window.location.hash = ""; }
    setScreen("landing");
  };
  const doLogout = () => {
    if (window.VL_AUTH) window.VL_AUTH.logout();
    window.VL_SESSION = null;
    setGuest(false);
    goLanding();
  };

  const renderView = () => {
    const guard = (id, component) => {
      if (!window.VL_moduloLiberado || window.VL_moduloLiberado(id)) return component;
      if (window.VL_ModuloBloqueado) {
        return <window.VL_ModuloBloqueado
          moduloId={id}
          onUpgrade={() => window.VL_goUpgrade && window.VL_goUpgrade(id)}
        />;
      }
      return component;
    };

    if (current === "dashboard")   return <Dashboard onOpenCalc={goCalc}/>;
    if (current === "calculators") return <Calculators onOpen={goCalc}/>;
    if (current === "settings" && window.VL_Settings) return <window.VL_Settings tweaks={tweaks} setTweak={setTweak} onNav={setCurrent}/>;

    if (current === "minha-conta" && window.VL_UserPanel && window.VL_SESSION)
      return <window.VL_UserPanel session={window.VL_SESSION} onLogout={doLogout} onClose={() => setCurrent("dashboard")} />;

    if (current === "eletroduto")  return guard("eletroduto",  <Eletroduto/>);
    if (current === "current"  && window.VL_Corrente)        return guard("current",  <window.VL_Corrente/>);
    if (current === "drop"     && window.VL_QuedaTensao)     return guard("drop",     <window.VL_QuedaTensao/>);
    if (current === "cables"   && window.VL_Dimensionamento) return guard("cables",   <window.VL_Dimensionamento/>);
    if (current === "fp"       && window.VL_Capacitor)       return guard("fp",       <window.VL_Capacitor/>);
    if (current === "quadros"  && window.VL_Quadros)         return guard("quadros",  <window.VL_Quadros/>);
    if (current === "cad"      && window.VL_CAD)             return guard("cad",      <window.VL_CAD/>);
    if (current === "diagrams" && window.VL_Unifilar)        return guard("diagrams", <window.VL_Unifilar/>);
    if (current === "demand"   && window.VL_Demandas)        return guard("demand",   <window.VL_Demandas/>);
    if (current === "convert"  && window.VL_Conversores)     return guard("convert",  <window.VL_Conversores/>);
    if (current === "infra"    && window.VL_Infraestrutura)  return guard("infra",    <window.VL_Infraestrutura/>);
    if (current === "trafo"    && window.VL_Transformador)   return guard("trafo",    <window.VL_Transformador/>);
    if (current === "motores"  && window.VL_QuadroMotores)   return guard("motores",  <window.VL_QuadroMotores/>);
    if (current === "short"    && window.VL_CurtoCircuito)   return guard("short",    <window.VL_CurtoCircuito/>);
    if (current === "spda"     && window.VL_SPDA)            return guard("spda",     <window.VL_SPDA/>);
    if (current === "light"    && window.VL_Iluminacao)      return guard("light",    <window.VL_Iluminacao/>);
    if (current === "aterramento" && window.ModuloAterramento) return guard("aterramento", <window.ModuloAterramento/>);
    if (current === "montagem" && window.VL_QuadroMontagem)  return guard("montagem", <window.VL_QuadroMontagem/>);
    if (current === "secao"     && window.VL_SecaoCondutor)   return guard("secao",     <window.VL_SecaoCondutor/>);
    if (current === "simulador" && window.SimuladorCircuitos) return guard("simulador", <window.SimuladorCircuitos/>);

    const found = NAV.find(n => n.id === current);
    return <Placeholder name={found ? found.label : current}/>;
  };

  if (screen === "landing") {
    return (
      <>
        <Landing onEnter={enterApp} onGuest={enterGuest} showCircuitry={tweaks.showCircuitry}/>
        {window.TweaksPanel && (
          <window.TweaksPanel title="Tweaks">
            <TweaksContent tweaks={tweaks} setTweak={setTweak}/>
          </window.TweaksPanel>
        )}
      </>
    );
  }

  const meta = APP_TITLES[current] || { eyebrow: "MÓDULO", title: NAV.find(n=>n.id===current)?.label || "", crumbs: ["VOLTLAB","Módulos", NAV.find(n=>n.id===current)?.label || ""] };

  const appShell = (
    <div className={"shell" + (mobileNav ? " nav-open" : "")} data-screen-label={"App · " + current}>
      <button className="nav-scrim" aria-label="Fechar menu" onClick={() => setMobileNav(false)}></button>
      <Sidebar current={current} onNav={(id) => { setCurrent(id); setMobileNav(false); }} onLogout={doLogout}/>
      <main className="main">
        <AppHeader
          eyebrow={meta.eyebrow}
          title={meta.title}
          crumbs={meta.crumbs}
          current={current}
          onExportReport={window.VL_exportReport}
          onHeaderNav={setCurrent}
          onMenu={() => setMobileNav(v => !v)}
          onAction={() => setCurrent("eletroduto")}
          actionLabel="Novo cálculo"
        />
        <div className="main-scroll">
          {renderView()}
        </div>
      </main>
      {window.VL_ProjectBar && <window.VL_ProjectBar/>}
    </div>
  );

  return (window.VL_AuthGuard && !guest)
    ? <window.VL_AuthGuard onUnauth={goLanding}>{appShell}</window.VL_AuthGuard>
    : appShell;
};

const TweaksContent = ({ tweaks, setTweak }) => {
  const T = window;
  return (
    <>
      <T.TweakSection label="Aparência">
        <T.TweakColor
          label="Cor de acento"
          value={tweaks.accent}
          onChange={(v) => setTweak("accent", v)}
          options={Object.keys(ACCENT_MAP)}
        />
        <T.TweakRadio
          label="Densidade"
          value={tweaks.density}
          onChange={(v) => setTweak("density", v)}
          options={[{value:"comfortable",label:"Conforto"},{value:"compact",label:"Compacta"}]}
        />
      </T.TweakSection>
      <T.TweakSection label="Detalhes">
        <T.TweakToggle label="Circuitos animados" value={tweaks.showCircuitry} onChange={(v) => setTweak("showCircuitry", v)}/>
        <T.TweakToggle label="Readouts monoespaçados" value={tweaks.monoReadouts} onChange={(v) => setTweak("monoReadouts", v)}/>
      </T.TweakSection>
    </>
  );
};

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