/* global React */
/* ===========================================================
   VOLTLAB · Calculation Modules — Corrente, Queda, Dimensionamento
   Logic adapted from technical reference (NBR 5410).
=========================================================== */
const { useState, useMemo, useEffect } = React;

const D = window.VL_DATA;


// =====================================================
// HOOKS E LÓGICA DE EXPORTAÇÃO (JSON/CSV)
// =====================================================
const usePersist = (key, initial) => {
  if (window.useLocalStorage) return window.useLocalStorage(key, initial);
  return React.useState(initial); // fallback
};

const buildReport = (moduleName, inputs, result) => ({
  modulo: moduleName, norma: "NBR 5410 / ANEEL 414",
  geradoEm: new Date().toLocaleString("pt-BR"), entradas: inputs, resultado: result,
});

const downloadBlob = (content, filename, mime) => {
  const blob = new Blob([content], { type: mime });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = filename; a.click();
  URL.revokeObjectURL(url);
};

window.VL_exportReport = (format) => {
  if (!window._VL_lastExport) return;
  const report = window._VL_lastExport();
  if (!report) return;
  
  if (format === "csv") {
    const rows = [
      ["Campo", "Valor"], ["Módulo", report.modulo], ["Gerado em", report.geradoEm],
      ["---ENTRADAS---", ""], ...Object.entries(report.entradas).map(([k, v]) => [k, v]),
      ["---RESULTADO---", ""], ...Object.entries(report.resultado).map(([k, v]) => [k, typeof v === "object" ? JSON.stringify(v) : v])
    ];
    const csv = rows.map(r => r.map(c => `"${String(c).replace(/"/g,'""')}"`).join(";")).join("\n");
    downloadBlob(csv, `voltlab-${report.modulo}.csv`, "text/csv;charset=utf-8");
  } else {
    downloadBlob(JSON.stringify(report, null, 2), `voltlab-${report.modulo}.json`, "application/json");
  }
};


/* Small shared atoms ---------------------------------------- */
const VL_Icon = ({ name, size = 18 }) => {
  const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" };
  const paths = {
    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"/>,
    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"/></>,
    pipe: <><path d="M3 8h12a3 3 0 013 3v0a3 3 0 01-3 3H3"/><path d="M3 8v8"/></>,
    refresh: <><path d="M21 12a9 9 0 11-3-6.7L21 8"/><path d="M21 3v5h-5"/></>,
    download: <><path d="M12 3v12"/><polyline points="7 10 12 15 17 10"/><line x1="4" y1="21" x2="20" y2="21"/></>,
    plus: <><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></>,
    check: <polyline points="20 6 9 17 4 12"/>,
    warn: <><path d="M10.3 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></>,
    info: <><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></>,
  };
  return <svg {...props}>{paths[name]}</svg>;
};

const ResultBig = ({ label, value, unit, status }) => (
  <div className={"vl-result-big " + (status ? "vl-result-" + status : "")}>
    <div className="vl-result-corner vl-result-corner-tl"/>
    <div className="vl-result-corner vl-result-corner-tr"/>
    <div className="vl-result-corner vl-result-corner-bl"/>
    <div className="vl-result-corner vl-result-corner-br"/>
    <div className="vl-result-label">{label}</div>
    <div className="vl-result-row">
      <span className="readout vl-result-val">{value}</span>
      <em>{unit}</em>
    </div>
  </div>
);

const MetricCell = ({ label, value, unit, status, big }) => (
  <div className={"vl-metric " + (status ? "vl-metric-" + status : "")}>
    <div className="vl-metric-label">{label}</div>
    <div className={"vl-metric-value " + (big ? "is-big" : "")}>
      <span className="readout">{value}</span>
      {unit && <em>{unit}</em>}
    </div>
  </div>
);

const StatusBanner = ({ kind, children }) => (
  <div className={"vl-banner vl-banner-" + kind}>
    <VL_Icon name={kind === "ok" ? "check" : kind === "warn" ? "warn" : kind === "danger" ? "warn" : "info"} size={16}/>
    <span>{children}</span>
  </div>
);

const MemoryStep = ({ n, title, children, isFormula }) => (
  <div className="vl-mem-step">
    <div className="vl-mem-step-head">
      <span className="vl-mem-step-n">{String(n).padStart(2, "0")}</span>
      <span className="vl-mem-step-title">{title}</span>
    </div>
    <div className={"vl-mem-step-body " + (isFormula ? "is-formula" : "")}>{children}</div>
  </div>
);

const FieldBlock = ({ label, hint, children }) => (
  <div className="vl-field">
    <label className="vl-field-label">
      <span>{label}</span>
      {hint && <span className="vl-field-hint">{hint}</span>}
    </label>
    {children}
  </div>
);

const NumberInput = ({ value, onChange, suffix, step, min, max, placeholder }) => (
  <div className="vl-input">
    <input
      type="number"
      value={value}
      onChange={e => onChange(e.target.value)}
      step={step ?? "0.01"}
      min={min}
      max={max}
      placeholder={placeholder ?? "0"}
    />
    {suffix && <span className="vl-input-suffix">{suffix}</span>}
  </div>
);

const SelectInput = ({ value, onChange, children, options }) => {
  if (options && window.Dropdown_VL) {
    return <window.Dropdown_VL value={value} onChange={onChange} options={options}/>;
  }
  return (
    <div className="vl-input">
      <select value={value} onChange={e => onChange(e.target.value)}>{children}</select>
    </div>
  );
};

const Seg = ({ value, onChange, options }) => (
  <div className="seg">
    {options.map(o => (
      <button key={o.value} className={value === o.value ? "is-active" : ""} onClick={() => onChange(o.value)}>
        {o.label}
      </button>
    ))}
  </div>
);

/* ===========================================================
   1. CORRENTE ELÉTRICA
=========================================================== */
const Corrente = () => {
  const [potencia, setPotencia] = useState("50");
  const [unidade, setUnidade] = useState("kW");
  const [tensao, setTensao] = useState("380");
  const [sistema, setSistema] = useState("trifasico");
  const [decimais, setDecimais] = useState("3");

  const calc = useMemo(() => {
    const P = parseFloat(potencia);
    const V = parseFloat(tensao);
    const d = parseInt(decimais);
    if (!P || !V || P <= 0 || V <= 0) return null;
    let Pw;
    if (unidade === "W") Pw = P;
    else if (unidade === "kW") Pw = P * 1000;
    else Pw = P * 735.5; // CV
    let I, formula, sub;
    if (sistema === "trifasico") {
      I = Pw / (V * Math.sqrt(3));
      formula = "I = P / (V · √3)";
      sub = `I = ${Pw.toLocaleString("pt-BR")} / (${V} · 1,732)`;
    } else {
      I = Pw / V;
      formula = "I = P / V";
      sub = `I = ${Pw.toLocaleString("pt-BR")} / ${V}`;
    }
    return { I, Pw, formula, sub, d };
  }, [potencia, unidade, tensao, sistema, decimais]);

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ENTRADA · POTÊNCIA E TENSÃO</div>
              <h3>Dados do circuito</h3>
            </div>
            <div className="status-chip"><span className="status-dot status-ok"/>AUTO-CÁLCULO</div>
          </div>

          {window.VL_ProjetoSync && <window.VL_ProjetoSync
            source="Corrente"
            reads={["tensao","sistema"]}
            pull={(s)=>{ const t=s.get("tensao"); if(t!=null) setTensao(String(t)); const sis=s.get("sistema"); if(sis) setSistema(sis); }}
            push={()=>({ tensao: parseFloat(tensao), sistema, corrente: calc? +calc.I.toFixed(2): undefined, potencia: calc? +(calc.Pw/1000).toFixed(3): undefined })}
          />}

          <div className="form-row form-row-2">
            <FieldBlock label="Potência">
              <NumberInput value={potencia} onChange={setPotencia} suffix={unidade}/>
            </FieldBlock>
            <FieldBlock label="Unidade">
              <Seg value={unidade} onChange={setUnidade} options={[
                {value: "W", label: "W"},
                {value: "kW", label: "kW"},
                {value: "CV", label: "CV"},
              ]}/>
            </FieldBlock>
          </div>

          <div className="form-row form-row-2">
            <FieldBlock label="Tensão de operação">
              <NumberInput value={tensao} onChange={setTensao} suffix="V"/>
            </FieldBlock>
            <FieldBlock label="Casas decimais">
              <Seg value={decimais} onChange={setDecimais} options={[
                {value: "1", label: "1"},
                {value: "2", label: "2"},
                {value: "3", label: "3"},
                {value: "4", label: "4"},
              ]}/>
            </FieldBlock>
          </div>

          <FieldBlock label="Tipo de sistema">
            <Seg value={sistema} onChange={setSistema} options={[
              {value: "monofasico", label: "Monofásico"},
              {value: "bifasico", label: "Bifásico"},
              {value: "trifasico", label: "Trifásico"},
            ]}/>
          </FieldBlock>

          <div className="vl-quick-stats">
            <div><span>Sistema</span><b>{sistema === "trifasico" ? "3F" : sistema === "bifasico" ? "2F" : "1F"} · {tensao || 0} V</b></div>
            <div><span>Potência ativa</span><b className="readout">{(calc?.Pw ?? 0).toLocaleString("pt-BR", {maximumFractionDigits: 1})} W</b></div>
            <div><span>Conversão</span><b className="readout">{unidade} → W</b></div>
          </div>
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">RESULTADO · CORRENTE NOMINAL</div>
              <h3>Corrente elétrica calculada</h3>
            </div>
          </div>

          <ResultBig
            label="CORRENTE NOMINAL · I"
            value={calc ? calc.I.toFixed(calc.d) : "—"}
            unit="A"
            status="ok"
          />

          {calc ? (
            <>
              <StatusBanner kind="ok">Cálculo concluído · sistema {sistema === "trifasico" ? "trifásico" : sistema === "bifasico" ? "bifásico" : "monofásico"}</StatusBanner>

              <div className="vl-memory">
                <div className="vl-memory-head">
                  <div className="vl-memory-eyebrow">MEMÓRIA DE CÁLCULO</div>
                </div>
                <MemoryStep n={1} title="Potência convertida">
                  {potencia} {unidade} → <b className="readout">{calc.Pw.toLocaleString("pt-BR")} W</b>
                </MemoryStep>
                <MemoryStep n={2} title="Fórmula aplicada" isFormula>
                  {calc.formula}
                </MemoryStep>
                <MemoryStep n={3} title="Substituição" isFormula>
                  {calc.sub}
                </MemoryStep>
                <MemoryStep n={4} title="Resultado">
                  I = <b className="readout">{calc.I.toFixed(calc.d)} A</b>
                </MemoryStep>
              </div>
            </>
          ) : (
            <StatusBanner kind="info">Informe potência e tensão para calcular</StatusBanner>
          )}
        </aside>
      </div>
    </div>
  );
};

/* ===========================================================
   2. QUEDA DE TENSÃO
=========================================================== */
const QuedaTensao = () => {
  const [dist, setDist]         = usePersist("vl_queda_dist", "265");
  const [tensao, setTensao]     = usePersist("vl_queda_tensao", "380");
  const [corrente, setCorrente] = usePersist("vl_queda_corrente", "16.05");
  const [secao, setSecao]       = usePersist("vl_queda_secao", "10");
  const [sistema, setSistema]   = usePersist("vl_queda_sistema", "trifasico");
  const [material, setMaterial] = usePersist("vl_queda_material", "0.0175");

  const calc = useMemo(() => {
    const L = parseFloat(dist), V = parseFloat(tensao), I = parseFloat(corrente), S = parseFloat(secao);
    const rho = parseFloat(material);
    if (!L || !V || !I || !S || L<=0 || V<=0 || I<=0 || S<=0) return null;
    let dV, formula, sub;
    if (sistema === "monofasico") {
      dV = (2 * rho * L * I) / S;
      formula = "ΔV = 2 · ρ · L · I / S";
      sub = `ΔV = 2 · ${rho} · ${L} · ${I} / ${S}`;
    } else {
      dV = (Math.sqrt(3) * rho * L * I) / S;
      formula = "ΔV = √3 · ρ · L · I / S";
      sub = `ΔV = 1,732 · ${rho} · ${L} · ${I} / ${S}`;
    }
    const pct = (dV / V) * 100;
    const limite = 4;
    const status = pct > limite ? "danger" : pct > 3 ? "warn" : "ok";
    return { dV, pct, limite, status, formula, sub, rho, L, V, I, S };
  }, [dist, tensao, corrente, secao, sistema, material]);

useEffect(() => {
    window._VL_lastExport = () => calc ? buildReport("queda-tensao", {
      distancia_m: dist, tensao_V: tensao, corrente_A: corrente, secao_mm2: secao, sistema, material: material === "0.0175" ? "Cobre" : "Alumínio",
    }, {
      queda_V: calc.dV.toFixed(3), queda_pct: calc.pct.toFixed(2), status: calc.status, limite_pct: calc.limite,
    }) : null;
    return () => { window._VL_lastExport = null; };
  }, [calc]);

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ENTRADA · PARÂMETROS DO CIRCUITO</div>
              <h3>Configuração do trecho</h3>
            </div>
            <div className="status-chip"><span className="status-dot status-ok"/>AUTO-CÁLCULO</div>
          </div>

          {window.VL_ProjetoSync && <window.VL_ProjetoSync
            source="Queda de Tensão"
            reads={["corrente","tensao","secao","sistema"]}
            pull={(s)=>{ const c=s.get("corrente"); if(c!=null) setCorrente(String(c)); const t=s.get("tensao"); if(t!=null) setTensao(String(t)); const sec=s.get("secao"); if(sec!=null) setSecao(String(sec)); const sis=s.get("sistema"); if(sis&&sis!=="bifasico") setSistema(sis); }}
            push={()=>({ tensao: parseFloat(tensao), corrente: parseFloat(corrente), secao: parseFloat(secao), sistema })}
          />}

          <div className="form-row form-row-2">
            <FieldBlock label="Distância do trecho">
              <NumberInput value={dist} onChange={setDist} suffix="m" step="0.1"/>
            </FieldBlock>
            <FieldBlock label="Tensão de operação">
              <NumberInput value={tensao} onChange={setTensao} suffix="V" step="0.1"/>
            </FieldBlock>
          </div>

          <div className="form-row form-row-2">
            <FieldBlock label="Corrente de projeto">
              <NumberInput value={corrente} onChange={setCorrente} suffix="A" step="0.01"/>
            </FieldBlock>
            <FieldBlock label="Seção do condutor">
              <SelectInput value={secao} onChange={setSecao} options={
                [1.5,2.5,4,6,10,16,25,35,50,70,95,120,150,185,240].map(s => ({ value: String(s), label: `${s} mm²` }))
              }/>
            </FieldBlock>
          </div>

          <FieldBlock label="Sistema">
            <Seg value={sistema} onChange={setSistema} options={[
              {value: "monofasico", label: "Monofásico"},
              {value: "trifasico", label: "Trifásico"},
            ]}/>
          </FieldBlock>

          <FieldBlock label="Material condutor">
            <Seg value={material} onChange={setMaterial} options={[
              {value: "0.0175", label: "Cobre · 0,0175 Ω·mm²/m"},
              {value: "0.0278", label: "Alumínio · 0,0278 Ω·mm²/m"},
            ]}/>
          </FieldBlock>

          <div className="vl-quick-stats">
            <div><span>L · I</span><b className="readout">{(parseFloat(dist)||0) * (parseFloat(corrente)||0)}</b></div>
            <div><span>Sistema</span><b>{sistema === "trifasico" ? "Trifásico" : "Monofásico"}</b></div>
            <div><span>Limite NBR</span><b className="readout">≤ 4%</b></div>
          </div>
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">RESULTADO · QUEDA DE TENSÃO</div>
              <h3>Análise normativa</h3>
            </div>
          </div>

          <ResultBig
            label="QUEDA PERCENTUAL · ΔV%"
            value={calc ? calc.pct.toFixed(2) : "—"}
            unit="%"
            status={calc?.status}
          />

          {calc && (
            <div className="vl-bar-wrap">
              <div className="vl-bar-track">
                <span style={{ width: Math.min(100, calc.pct / calc.limite * 100) + "%" }} className={"bar-fill bar-" + calc.status}/>
                <span className="bar-limit" style={{ left: "100%" }}/>
              </div>
              <div className="result-bar-meta">
                <span><b className="readout">{calc.dV.toFixed(3)} V</b> de queda</span>
                <span className="dim">limite {calc.limite}%</span>
              </div>
            </div>
          )}

          {calc ? (
            <>
              <StatusBanner kind={calc.status}>
                {calc.status === "ok" && "Dentro do limite normativo NBR 5410 · 4%"}
                {calc.status === "warn" && "Atenção: queda próxima do limite (≥ 3%)"}
                {calc.status === "danger" && `Excedido o limite — aumentar bitola ou reduzir distância (Δ ${(calc.pct - calc.limite).toFixed(2)}pp)`}
              </StatusBanner>

              <div className="vl-memory">
                <div className="vl-memory-eyebrow">MEMÓRIA DE CÁLCULO</div>
                <MemoryStep n={1} title="Dados do circuito">
                  {sistema === "trifasico" ? "Trifásico" : "Monofásico"} · {material === "0.0175" ? "Cobre" : "Alumínio"}<br/>
                  L = <b className="readout">{calc.L} m</b> · V = <b className="readout">{calc.V} V</b><br/>
                  I = <b className="readout">{calc.I} A</b> · S = <b className="readout">{calc.S} mm²</b>
                </MemoryStep>
                <MemoryStep n={2} title="Fórmula aplicada" isFormula>{calc.formula}</MemoryStep>
                <MemoryStep n={3} title="Substituição" isFormula>{calc.sub}</MemoryStep>
                <MemoryStep n={4} title="Resultado">
                  ΔV = <b className="readout">{calc.dV.toFixed(3)} V</b><br/>
                  Queda % = (ΔV / V) · 100 = <b className="readout">{calc.pct.toFixed(3)} %</b>
                </MemoryStep>
              </div>
            </>
          ) : (
            <StatusBanner kind="info">Informe os dados do trecho para calcular</StatusBanner>
          )}
        </aside>
      </div>
    </div>
  );
};

/* ===========================================================
   3. DIMENSIONAMENTO DE CABOS
=========================================================== */
const Dimensionamento = () => {
  const [tipo, setTipo] = useState("3CA");
  const [tempAmb, setTempAmb] = useState("40");
  const [dist, setDist] = useState("300");
  const [tensao, setTensao] = useState("380");
  const [potencia, setPotencia] = useState("150");
  const [quedaMax, setQuedaMax] = useState("5");
  const [fp, setFp] = useState("0.8");
  const [rend, setRend] = useState("90");
  const [isolacao, setIsolacao] = useState("PVC");
  const [agrup, setAgrup] = useState("1");

  // adjust defaults when type changes
  useEffect(() => {
    if (tipo === "CC")       { setPotencia("20");   setTensao("24");  setDist("100"); }
    else if (tipo === "3CA") { setPotencia("150");  setTensao("380"); setDist("300"); }
    else                     { setPotencia("7000"); setTensao("220"); setDist("300"); }
  }, [tipo]);

  const result = useMemo(() => {
    const L = parseFloat(dist), V = parseFloat(tensao), P = parseFloat(potencia);
    const qMax = parseFloat(quedaMax) / 100;
    if (!L || !V || !P || !qMax) return null;

    const rho20 = 0.0175;
    const alpha = 0.00393;
    const rho = rho20 * (1 + alpha * (parseFloat(tempAmb) - 20));

    let corrente, table = [];
    let secaoQueda = null, secaoAmpacidade = null;
    const sections = D.commercialSections;
    const fpN = parseFloat(fp), rendN = parseFloat(rend) / 100;

    if (tipo === "CC") {
      const Rl = (V * V) / P;
      corrente = P / V;
      sections.forEach(s => {
        const Rcond = rho * L / s;
        const Rcirc = Rl + 2 * Rcond;
        const Vf = (Rl / Rcirc) * V;
        const qV = V - Vf;
        const qPct = (qV / V) * 100;
        table.push({ s, Rcond, qV, qPct });
        if (!secaoQueda && (qPct / 100) <= qMax) secaoQueda = s;
      });
    } else if (tipo === "3CA") {
      const Pkw = P * 0.736; // CV → kW
      corrente = (Pkw * 1000) / (Math.sqrt(3) * V * rendN * fpN);
      const sinFi = Math.sin(Math.acos(fpN));
      const X = 0.08 * L / 1000;
      sections.forEach(s => {
        const Rcond = rho * L / s;
        const qV = Math.sqrt(3) * corrente * (Rcond * fpN + X * sinFi);
        const qPct = (qV / V) * 100;
        table.push({ s, Rcond, qV, qPct });
        if (!secaoQueda && (qPct / 100) <= qMax) secaoQueda = s;
      });
      const fctT = D.getTempFactor(parseFloat(tempAmb), isolacao);
      const fctA = D.getAgrupFactor(parseInt(agrup));
      const iBase = corrente / (fctT * fctA);
      secaoAmpacidade = D.getSectionByAmpacity(iBase, isolacao, true);
    } else { // 1CA
      corrente = P / V;
      sections.forEach(s => {
        const Rcond = rho * L / s;
        const qV = 2 * Rcond * corrente;
        const qPct = (qV / V) * 100;
        table.push({ s, Rcond, qV, qPct });
        if (!secaoQueda && (qPct / 100) <= qMax) secaoQueda = s;
      });
      const fctT = D.getTempFactor(parseFloat(tempAmb), isolacao);
      const fctA = D.getAgrupFactor(parseInt(agrup));
      const iBase = corrente / (fctT * fctA);
      secaoAmpacidade = D.getSectionByAmpacity(iBase, isolacao, false);
    }

    const secaoFinal = Math.max(secaoQueda || 300, secaoAmpacidade || 0);
    const final = table.find(t => t.s === secaoFinal);
    return { corrente, table, secaoQueda, secaoAmpacidade, secaoFinal, final, rho };
  }, [tipo, tempAmb, dist, tensao, potencia, quedaMax, fp, rend, isolacao, agrup]);

  const isCA = tipo !== "CC";
  const potLabel = tipo === "3CA" ? "Potência (CV)" : "Potência (W)";

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ENTRADA · DIMENSIONAMENTO NBR 5410</div>
              <h3>Parâmetros do sistema e da instalação</h3>
            </div>
            <div className="status-chip"><span className="status-dot status-ok"/>AUTO-CÁLCULO</div>
          </div>

          {window.VL_ProjetoSync && <window.VL_ProjetoSync
            source="Dimensionamento"
            reads={["tensao"]}
            pull={(s)=>{ const t=s.get("tensao"); if(t!=null) setTensao(String(t)); }}
            push={()=>({ tensao: parseFloat(tensao), corrente: result? +result.corrente.toFixed(2): undefined, secao: result? result.secaoFinal: undefined })}
          />}

          <FieldBlock label="Tipo de sistema">
            <Seg value={tipo} onChange={setTipo} options={[
              {value: "3CA", label: "Trifásico CA"},
              {value: "1CA", label: "Monofásico CA"},
              {value: "CC",  label: "CC"},
            ]}/>
          </FieldBlock>

          <div className="form-row form-row-2">
            <FieldBlock label="Temperatura ambiente">
              <NumberInput value={tempAmb} onChange={setTempAmb} suffix="°C" step="5" min="20" max="60"/>
            </FieldBlock>
            <FieldBlock label="Distância fonte–carga">
              <NumberInput value={dist} onChange={setDist} suffix="m" step="0.1"/>
            </FieldBlock>
          </div>

          <div className="form-row form-row-2">
            <FieldBlock label="Tensão de operação">
              <NumberInput value={tensao} onChange={setTensao} suffix="V"/>
            </FieldBlock>
            <FieldBlock label={potLabel}>
              <NumberInput value={potencia} onChange={setPotencia}/>
            </FieldBlock>
          </div>

          <FieldBlock label="Queda máxima admitida">
            <NumberInput value={quedaMax} onChange={setQuedaMax} suffix="%" step="0.1" min="0" max="10"/>
          </FieldBlock>

          {isCA && (
            <>
              <div className="form-row form-row-2">
                <FieldBlock label="Fator de potência">
                  <NumberInput value={fp} onChange={setFp} step="0.01" min="0" max="1"/>
                </FieldBlock>
                <FieldBlock label="Rendimento">
                  <NumberInput value={rend} onChange={setRend} suffix="%" step="0.1" min="0" max="100"/>
                </FieldBlock>
              </div>

              <div className="form-row form-row-2">
                <FieldBlock label="Isolação do cabo">
                  <Seg value={isolacao} onChange={setIsolacao} options={[
                    {value: "PVC", label: "PVC 70°C"},
                    {value: "EPR", label: "EPR 90°C"},
                  ]}/>
                </FieldBlock>
                <FieldBlock label="Circuitos agrupados">
                  <NumberInput value={agrup} onChange={setAgrup} step="1" min="1" max="20"/>
                </FieldBlock>
              </div>
            </>
          )}
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">RESULTADO · SEÇÃO RECOMENDADA</div>
              <h3>Cabo mínimo dimensionado</h3>
            </div>
          </div>

          <ResultBig
            label="SEÇÃO MÍNIMA · S"
            value={result ? result.secaoFinal : "—"}
            unit="mm²"
            status="ok"
          />

          {result && (
            <>
              <div className="vl-mini-grid">
                <MetricCell label="CORRENTE NOMINAL" value={result.corrente.toFixed(2)} unit="A"/>
                <MetricCell label="QUEDA REAL" value={result.final ? result.final.qPct.toFixed(2) : "—"} unit="%" status="ok"/>
                <MetricCell label="POR QUEDA" value={result.secaoQueda ?? "—"} unit="mm²"/>
                {isCA && <MetricCell label="POR AMPACIDADE" value={result.secaoAmpacidade ?? "—"} unit="mm²"/>}
              </div>

              <StatusBanner kind="ok">Dimensionamento concluído conforme NBR 5410</StatusBanner>

              <div className="result-actions">
                <button className="btn btn-ghost"><VL_Icon name="refresh" size={14}/> Recalcular</button>
                <button className="btn btn-primary"><VL_Icon name="download" size={14}/> Memorial técnico</button>
              </div>
            </>
          )}
        </aside>
      </div>

      {result && (
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">TABELA COMPLETA DE SEÇÕES</div>
              <h3>Iteração por bitola comercial</h3>
            </div>
            <span className="dim mono small">ρ corrigida = {result.rho.toFixed(6)} Ω·mm²/m</span>
          </div>
          <div className="ref-table">
            <div className="ref-head">
              <span>SEÇÃO (mm²)</span>
              <span>R CONDUTOR (Ω)</span>
              <span>QUEDA (V)</span>
              <span>QUEDA (%)</span>
              <span>STATUS</span>
            </div>
            {result.table.map(r => {
              const isSel = r.s === result.secaoFinal;
              const ok = r.qPct <= parseFloat(quedaMax);
              return (
                <div key={r.s} className={"ref-row " + (isSel ? "is-sel" : "")}>
                  <span className="mono"><b>{r.s}</b></span>
                  <span className="mono dim">{r.Rcond.toFixed(4)}</span>
                  <span className="mono">{r.qV.toFixed(3)} V</span>
                  <span className="mono">{r.qPct.toFixed(2)} %</span>
                  <span className={"pill pill-" + (ok ? "ok" : "warn")}>{ok ? "Atende" : "Não atende"}</span>
                </div>
              );
            })}
          </div>
        </section>
      )}
    </div>
  );
};

/* ===========================================================
   4. BANCO DE CAPACITORES — correção de fator de potência
=========================================================== */
// Bancos comerciais (kVAr) — degraus padrão
const CAP_STEPS_BT = [2.5, 5, 7.5, 10, 12.5, 15, 20, 25, 30, 37.5, 50, 60, 75, 100];
const CAP_STEPS_MT = [50, 75, 100, 150, 200, 300, 400, 500, 750, 1000];

const Capacitor = () => {
  const [pAtiva, setPAtiva] = useState("100");
  const [fpAtual, setFpAtual] = useState("0.75");
  const [fpDesejado, setFpDesejado] = useState("0.92");
  const [tensao, setTensao] = useState("380");
  const [sistema, setSistema] = useState("trifasico");
  const [freq, setFreq] = useState("60");
  const [classe, setClasse] = useState("BT"); // BT ou MT

  const calc = useMemo(() => {
    const P = parseFloat(pAtiva);
    const fp1 = parseFloat(fpAtual);
    const fp2 = parseFloat(fpDesejado);
    const V = parseFloat(tensao);
    const f = parseFloat(freq);
    if (!P || !fp1 || !fp2 || !V || P <= 0 || fp1 <= 0 || fp1 > 1 || fp2 <= 0 || fp2 > 1) return null;
    if (fp2 <= fp1) return { error: "FP desejado deve ser maior que o atual" };

    const phi1 = Math.acos(fp1);
    const phi2 = Math.acos(fp2);
    const tan1 = Math.tan(phi1);
    const tan2 = Math.tan(phi2);

    // Qc em kVAr
    const Qc = P * (tan1 - tan2);

    // Antes
    const S1 = P / fp1;
    const Q1 = P * tan1;
    const I1 = sistema === "trifasico"
      ? (S1 * 1000) / (Math.sqrt(3) * V)
      : (S1 * 1000) / V;

    // Depois
    const S2 = P / fp2;
    const Q2 = P * tan2;
    const I2 = sistema === "trifasico"
      ? (S2 * 1000) / (Math.sqrt(3) * V)
      : (S2 * 1000) / V;

    // Redução de corrente / perdas
    const redCorrente = ((I1 - I2) / I1) * 100;
    const redPerdas = (1 - Math.pow(I2 / I1, 2)) * 100;

    // Capacitância equivalente (μF) — banco delta trifásico
    const omega = 2 * Math.PI * f;
    let cap_uF;
    if (sistema === "trifasico") {
      // Delta: C = Qc / (3 · ω · V²) — kVAr e V em SI
      cap_uF = (Qc * 1000) / (3 * omega * V * V) * 1e6;
    } else {
      cap_uF = (Qc * 1000) / (omega * V * V) * 1e6;
    }

    // Bancos comerciais — proposta de degraus
    const steps = classe === "MT" ? CAP_STEPS_MT : CAP_STEPS_BT;
    // pick smallest single step >= Qc, OR closest combination of equal steps
    const singleStep = steps.find(s => s >= Qc) ?? steps[steps.length - 1];
    // best combination: try 1-6 steps of each commercial value
    let best = { step: singleStep, n: 1, total: singleStep, sobra: singleStep - Qc };
    steps.forEach(s => {
      for (let n = 1; n <= 8; n++) {
        const total = s * n;
        if (total >= Qc) {
          const sobra = total - Qc;
          if (sobra < best.sobra || (sobra === best.sobra && n < best.n)) {
            best = { step: s, n, total, sobra };
          }
          break;
        }
      }
    });

    // Multa ANEEL — referência 414/2010 (FP < 0,92)
    const limite = 0.92;
    const multa = fp1 < limite;

    return {
      P, fp1, fp2, V, f,
      Qc, S1, S2, Q1, Q2, I1, I2,
      redCorrente, redPerdas, cap_uF,
      singleStep, best, multa, limite,
      tan1, tan2, phi1, phi2,
    };
  }, [pAtiva, fpAtual, fpDesejado, tensao, sistema, freq, classe]);

  const fpClass = (fp) => fp >= 0.92 ? "ok" : fp >= 0.85 ? "warn" : "danger";

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ENTRADA · CORREÇÃO DE FATOR DE POTÊNCIA</div>
              <h3>Dados da carga e meta de FP</h3>
            </div>
            <div className="status-chip"><span className="status-dot status-ok"/>ANEEL 414</div>
          </div>

          <div className="form-row form-row-2">
            <FieldBlock label="Potência ativa da carga">
              <NumberInput value={pAtiva} onChange={setPAtiva} suffix="kW" step="0.1"/>
            </FieldBlock>
            <FieldBlock label="Tensão de operação">
              <NumberInput value={tensao} onChange={setTensao} suffix="V"/>
            </FieldBlock>
          </div>

          <div className="form-row form-row-2">
            <FieldBlock label="FP atual (medido)" hint={`cos φ₁ · ${(parseFloat(fpAtual)*100).toFixed(0)}%`}>
              <NumberInput value={fpAtual} onChange={setFpAtual} step="0.01" min="0.1" max="1"/>
            </FieldBlock>
            <FieldBlock label="FP desejado (meta)" hint={`cos φ₂ · ${(parseFloat(fpDesejado)*100).toFixed(0)}%`}>
              <NumberInput value={fpDesejado} onChange={setFpDesejado} step="0.01" min="0.1" max="1"/>
            </FieldBlock>
          </div>

          <FieldBlock label="Configuração do sistema">
            <Seg value={sistema} onChange={setSistema} options={[
              {value: "trifasico", label: "Trifásico"},
              {value: "monofasico", label: "Monofásico"},
            ]}/>
          </FieldBlock>

          <div className="form-row form-row-2">
            <FieldBlock label="Classe de tensão">
              <Seg value={classe} onChange={setClasse} options={[
                {value: "BT", label: "Baixa Tensão"},
                {value: "MT", label: "Média Tensão"},
              ]}/>
            </FieldBlock>
            <FieldBlock label="Frequência">
              <Seg value={freq} onChange={setFreq} options={[
                {value: "50", label: "50 Hz"},
                {value: "60", label: "60 Hz"},
              ]}/>
            </FieldBlock>
          </div>

          {/* Quick comparison */}
          <div className="vl-fp-compare">
            <div className="vl-fp-side">
              <div className="vl-fp-label">ANTES</div>
              <div className="vl-fp-meter">
                <FPDial fp={parseFloat(fpAtual) || 0} status={fpClass(parseFloat(fpAtual) || 0)}/>
                <span className="readout vl-fp-val">{parseFloat(fpAtual || 0).toFixed(2)}</span>
              </div>
            </div>
            <div className="vl-fp-arrow">→</div>
            <div className="vl-fp-side">
              <div className="vl-fp-label">DEPOIS</div>
              <div className="vl-fp-meter">
                <FPDial fp={parseFloat(fpDesejado) || 0} status={fpClass(parseFloat(fpDesejado) || 0)}/>
                <span className="readout vl-fp-val">{parseFloat(fpDesejado || 0).toFixed(2)}</span>
              </div>
            </div>
          </div>
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">RESULTADO · POTÊNCIA REATIVA</div>
              <h3>Banco de capacitores</h3>
            </div>
          </div>

          {calc?.error ? (
            <>
              <ResultBig label="POTÊNCIA REATIVA · Qc" value="—" unit="kVAr" status="danger"/>
              <StatusBanner kind="danger">{calc.error}</StatusBanner>
            </>
          ) : calc ? (
            <>
              <ResultBig
                label="POTÊNCIA REATIVA · Qc"
                value={calc.Qc.toFixed(2)}
                unit="kVAr"
                status="ok"
              />

              <div className="vl-mini-grid vl-mini-grid-3">
                <MetricCell label="CAPACITÂNCIA" value={calc.cap_uF.toFixed(1)} unit="μF"/>
                <MetricCell label="REDUÇÃO I" value={"−" + calc.redCorrente.toFixed(1)} unit="%" status="ok"/>
                <MetricCell label="REDUÇÃO PERDAS" value={"−" + calc.redPerdas.toFixed(1)} unit="%" status="ok"/>
              </div>

              <div className="vl-cap-suggestion">
                <div className="vl-cap-eyebrow">SUGESTÃO COMERCIAL · {classe === "BT" ? "Baixa Tensão" : "Média Tensão"}</div>
                <div className="vl-cap-row">
                  <div className="vl-cap-steps">
                    {Array.from({length: calc.best.n}).map((_,i) => (
                      <div key={i} className="vl-cap-step">
                        <div className="vl-cap-step-icon">
                          <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5">
                            <line x1="3" y1="12" x2="9" y2="12"/>
                            <line x1="15" y1="12" x2="21" y2="12"/>
                            <line x1="9" y1="6" x2="9" y2="18"/>
                            <line x1="15" y1="6" x2="15" y2="18"/>
                          </svg>
                        </div>
                        <span className="readout">{calc.best.step}</span>
                        <em>kVAr</em>
                      </div>
                    ))}
                  </div>
                  <div className="vl-cap-formula">
                    <span>{calc.best.n} × {calc.best.step} kVAr</span>
                    <b className="readout">= {calc.best.total} kVAr</b>
                    {calc.best.sobra > 0 && <em>+{calc.best.sobra.toFixed(1)} kVAr de margem</em>}
                  </div>
                </div>
              </div>

              {calc.multa && (
                <StatusBanner kind="warn">
                  FP atual {calc.fp1.toFixed(2)} &lt; 0,92 — sujeito a tarifa de excedente reativo (ANEEL 414/2010)
                </StatusBanner>
              )}
              <StatusBanner kind="ok">
                Correção {((calc.fp2 - calc.fp1)/calc.fp1*100).toFixed(1)}% no fator de potência
              </StatusBanner>
            </>
          ) : (
            <>
              <ResultBig label="POTÊNCIA REATIVA · Qc" value="—" unit="kVAr"/>
              <StatusBanner kind="info">Informe potência ativa e FPs para calcular</StatusBanner>
            </>
          )}
        </aside>
      </div>

      {calc && !calc.error && (
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ANÁLISE DETALHADA · ANTES × DEPOIS</div>
              <h3>Impacto da correção no sistema</h3>
            </div>
            <span className="dim mono small">Frequência: {calc.f} Hz</span>
          </div>

          <div className="vl-fp-table">
            <div className="vl-fp-tr vl-fp-th">
              <span>GRANDEZA</span>
              <span>SÍMBOLO</span>
              <span className="dim">ANTES</span>
              <span className="vl-fp-after">DEPOIS</span>
              <span>VARIAÇÃO</span>
            </div>
            <FpRow label="Potência ativa"    sym="P"  unit="kW"   before={calc.P.toFixed(2)}  after={calc.P.toFixed(2)}  delta="—"/>
            <FpRow label="Potência aparente" sym="S"  unit="kVA"  before={calc.S1.toFixed(2)} after={calc.S2.toFixed(2)} delta={"−"+((calc.S1-calc.S2)/calc.S1*100).toFixed(1)+"%"} good/>
            <FpRow label="Potência reativa"  sym="Q"  unit="kVAr" before={calc.Q1.toFixed(2)} after={calc.Q2.toFixed(2)} delta={"−"+((calc.Q1-calc.Q2)/calc.Q1*100).toFixed(1)+"%"} good/>
            <FpRow label="Fator de potência" sym="cos φ" unit="" before={calc.fp1.toFixed(3)} after={calc.fp2.toFixed(3)} delta={"+"+((calc.fp2-calc.fp1)*100).toFixed(1)+"pp"} good/>
            <FpRow label="Corrente de linha" sym="I"  unit="A"    before={calc.I1.toFixed(2)} after={calc.I2.toFixed(2)} delta={"−"+calc.redCorrente.toFixed(1)+"%"} good/>
            <FpRow label="Ângulo de defasagem" sym="φ" unit="°"  before={(calc.phi1*180/Math.PI).toFixed(2)} after={(calc.phi2*180/Math.PI).toFixed(2)} delta={"−"+((calc.phi1-calc.phi2)*180/Math.PI).toFixed(2)+"°"} good/>
          </div>

          <div className="vl-memory" style={{marginTop: 22}}>
            <div className="vl-memory-eyebrow">MEMÓRIA DE CÁLCULO</div>
            <MemoryStep n={1} title="Ângulos de defasagem">
              φ₁ = arccos({calc.fp1.toFixed(2)}) = <b className="readout">{(calc.phi1*180/Math.PI).toFixed(2)}°</b><br/>
              φ₂ = arccos({calc.fp2.toFixed(2)}) = <b className="readout">{(calc.phi2*180/Math.PI).toFixed(2)}°</b>
            </MemoryStep>
            <MemoryStep n={2} title="Fórmula aplicada" isFormula>
              Qc = P · (tan φ₁ − tan φ₂)
            </MemoryStep>
            <MemoryStep n={3} title="Substituição" isFormula>
              Qc = {calc.P} · ({calc.tan1.toFixed(4)} − {calc.tan2.toFixed(4)})
            </MemoryStep>
            <MemoryStep n={4} title="Potência reativa necessária">
              Qc = <b className="readout">{calc.Qc.toFixed(2)} kVAr</b>
            </MemoryStep>
            <MemoryStep n={5} title="Capacitância equivalente" isFormula>
              {sistema === "trifasico" ? "C = Qc / (3 · ω · V²)" : "C = Qc / (ω · V²)"}
              {"  →  "}
              <span className="readout">{calc.cap_uF.toFixed(2)} μF</span>
            </MemoryStep>
          </div>
        </section>
      )}
    </div>
  );
};

const FPDial = ({ fp, status }) => {
  const R = 38, C = 2 * Math.PI * R;
  const pct = Math.max(0, Math.min(1, fp));
  const dash = pct * C;
  const color = status === "ok" ? "var(--ok)" : status === "warn" ? "var(--warn)" : "var(--danger)";
  return (
    <svg viewBox="0 0 100 100" className="vl-fp-dial">
      <circle cx="50" cy="50" r={R} fill="none" stroke="var(--border-2)" strokeWidth="6"/>
      <circle cx="50" cy="50" r={R} fill="none" stroke={color} strokeWidth="6"
              strokeDasharray={`${dash} ${C}`} strokeLinecap="round"
              transform="rotate(-90 50 50)"/>
    </svg>
  );
};

const FpRow = ({ label, sym, unit, before, after, delta, good }) => (
  <div className="vl-fp-tr">
    <span>{label}</span>
    <span className="mono dim">{sym}</span>
    <span className="mono dim">{before} {unit}</span>
    <span className="mono vl-fp-after"><b>{after}</b> {unit}</span>
    <span className={"mono " + (good ? "vl-fp-good" : "")}>{delta}</span>
  </div>
);

/* ===========================================================
   5. TRANSFORMADORES
=========================================================== */
const Transformador = () => {
  const [potencia, setPotencia] = usePersist("vl_tr_pot", "500");
  const [vPrim, setVPrim] = usePersist("vl_tr_vp", "13.8");
  const [vSec, setVSec] = usePersist("vl_tr_vs", "380");

  const calc = useMemo(() => {
    const S = parseFloat(potencia), Vp = parseFloat(vPrim), Vs = parseFloat(vSec);
    if (!S || !Vp || !Vs) return null;
    
    // I = S / (√3 * V)
    const ip = (S * 1000) / (Math.sqrt(3) * Vp * 1000);
    const is = (S * 1000) / (Math.sqrt(3) * Vs);
    
    // Dimensionamento rápido de proteção (1.25x In para Trafo)
    const djSec = is * 1.25;

    return { S, Vp, Vs, ip, is, djSec };
  }, [potencia, vPrim, vSec]);

  useEffect(() => {
    window._VL_lastExport = () => calc ? buildReport("transformador", {
      potencia_kVA: potencia, tensao_primaria_kV: vPrim, tensao_secundaria_V: vSec
    }, {
      corrente_primaria_A: calc.ip.toFixed(2), corrente_secundaria_A: calc.is.toFixed(2)
    }) : null;
    return () => { window._VL_lastExport = null; };
  }, [calc]);

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">DADOS DE ENTRADA · NBR 5440</div>
              <h3>Especificações do Transformador</h3>
            </div>
          </div>
          <div className="form-row form-row-2">
            <FieldBlock label="Potência Nominal">
              <NumberInput value={potencia} onChange={setPotencia} suffix="kVA"/>
            </FieldBlock>
            <FieldBlock label="Tensão Primária (AT)">
              <NumberInput value={vPrim} onChange={setVPrim} suffix="kV"/>
            </FieldBlock>
          </div>
          <FieldBlock label="Tensão Secundária (BT)">
            <Seg value={vSec} onChange={setVSec} options={[
              {value: "220", label: "220/127 V"},
              {value: "380", label: "380/220 V"},
              {value: "440", label: "440/254 V"},
            ]}/>
          </FieldBlock>
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div><div className="panel-eyebrow">RESULTADO · CORRENTES</div></div>
          </div>
          {calc ? (
            <>
              <ResultBig label="CORRENTE SECUNDÁRIA (BT)" value={calc.is.toFixed(1)} unit="A" status="ok"/>
              <div className="vl-mini-grid">
                <MetricCell label="CORRENTE PRIMÁRIA" value={calc.ip.toFixed(2)} unit="A"/>
                <MetricCell label="DISJUNTOR BT REC." value={calc.djSec.toFixed(0)} unit="A"/>
              </div>
              <StatusBanner kind="ok">As correntes nominais foram calculadas utilizando o sistema trifásico.</StatusBanner>
            </>
          ) : <StatusBanner kind="info">Informe os dados para calcular.</StatusBanner>}
        </aside>
      </div>
    </div>
  );
};

/* ===========================================================
   6. CURTO-CIRCUITO (MÉTODO INFINITO / IMPEDÂNCIA)
=========================================================== */
const CurtoCircuito = () => {
  const [potencia, setPotencia] = usePersist("vl_cc_pot", "500");
  const [z, setZ] = usePersist("vl_cc_z", "4.5");
  const [tensao, setTensao] = usePersist("vl_cc_v", "380");

  const calc = useMemo(() => {
    const S = parseFloat(potencia), imp = parseFloat(z), V = parseFloat(tensao);
    if (!S || !imp || !V) return null;
    
    // Corrente Nominal
    const In = (S * 1000) / (Math.sqrt(3) * V);
    // Corrente de Curto-Circuito Simétrica (Icc = In / Z%)
    const Icc = In / (imp / 100);
    const Icc_kA = Icc / 1000;
    // Corrente Assimétrica de pico (Aprox 2.5x Icc simétrica em BT)
    const Icc_pico = Icc_kA * 2.5;

    return { In, Icc, Icc_kA, Icc_pico, imp };
  }, [potencia, z, tensao]);

  useEffect(() => {
    window._VL_lastExport = () => calc ? buildReport("curto-circuito", {
      potencia_trafo_kVA: potencia, impedancia_pct: z, tensao_V: tensao
    }, {
      icc_simetrica_kA: calc.Icc_kA.toFixed(2), icc_pico_kA: calc.Icc_pico.toFixed(2)
    }) : null;
    return () => { window._VL_lastExport = null; };
  }, [calc]);

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">DADOS DE ENTRADA · IEC 60909</div>
              <h3>Parâmetros da Fonte (Transformador)</h3>
            </div>
          </div>
          <div className="form-row form-row-2">
            <FieldBlock label="Potência do Trafo">
              <NumberInput value={potencia} onChange={setPotencia} suffix="kVA"/>
            </FieldBlock>
            <FieldBlock label="Tensão Secundária">
              <NumberInput value={tensao} onChange={setTensao} suffix="V"/>
            </FieldBlock>
          </div>
          <FieldBlock label="Impedância do Trafo (Z%)">
            <NumberInput value={z} onChange={setZ} suffix="%" step="0.1"/>
          </FieldBlock>
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div><div className="panel-eyebrow">RESULTADO · TERMINAIS DO TRAFO</div></div>
          </div>
          {calc ? (
            <>
              <ResultBig label="ICC SIMÉTRICA (TRIFÁSICA)" value={calc.Icc_kA.toFixed(2)} unit="kA" status="danger"/>
              <div className="vl-mini-grid">
                <MetricCell label="CORRENTE NOMINAL" value={calc.In.toFixed(0)} unit="A"/>
                <MetricCell label="PICO ASSIMÉTRICO" value={calc.Icc_pico.toFixed(2)} unit="kA" status="warn"/>
              </div>
              <StatusBanner kind="warn">Corrente de curto-circuito presumida nos terminais do secundário. Utilize este valor para especificar a capacidade de ruptura (Icu) dos disjuntores gerais.</StatusBanner>
            </>
          ) : <StatusBanner kind="info">Informe a potência e impedância.</StatusBanner>}
        </aside>
      </div>
    </div>
  );
};

/* ===========================================================
   7. SPDA (SISTEMA DE PROTEÇÃO CONTRA DESCARGAS ATMOSFÉRICAS)
   Baseado na NBR 5419-3:2015 (Tabelas 2 e 4)
=========================================================== */
const SPDA = () => {
  const [classe, setClasse] = usePersist("vl_spda_classe", "III");
  const [altura, setAltura] = usePersist("vl_spda_h", "15");
  const [comprimento, setComprimento] = usePersist("vl_spda_c", "30");
  const [largura, setLargura] = usePersist("vl_spda_l", "20");

  const calc = useMemo(() => {
    const h = parseFloat(altura), c = parseFloat(comprimento), l = parseFloat(largura);
    if (!h || !c || !l) return null;

    // Parâmetros NBR 5419-3:2015 (Tabelas 2 e 4)
    // r: Raio da Esfera Rolante (m) | malha: Tamanho da Malha (m) | descida: Espaçamento médio (m)
    const param = {
      "I":   { r: 20, malha: 5,  descida: 10 },
      "II":  { r: 30, malha: 10, descida: 10 },
      "III": { r: 45, malha: 15, descida: 15 },
      "IV":  { r: 60, malha: 20, descida: 20 }
    }[classe];

    const perimetro = 2 * (c + l);
    
    // NBR 5419-3: O número mínimo de condutores de descida é 2, posicionados no perímetro
    let nDescidas = Math.ceil(perimetro / param.descida);
    if (nDescidas < 2) nDescidas = 2;

    // Aplicação do Método do Ângulo de Proteção (Franklin)
    // Só é válido se a altura da edificação for menor ou igual ao raio da esfera da classe escolhida.
    const franklinAplicavel = h <= param.r;

    return { h, c, l, perimetro, param, nDescidas, franklinAplicavel };
  }, [classe, altura, comprimento, largura]);

  useEffect(() => {
    window._VL_lastExport = () => calc ? buildReport("spda", {
      classe_protecao: classe, altura_m: altura, comprimento_m: comprimento, largura_m: largura
    }, {
      raio_esfera_rolante_m: calc.param.r, 
      malha_captores_m: `${calc.param.malha} x ${calc.param.malha}`, 
      descidas_minimas: calc.nDescidas,
      espacamento_descidas_m: calc.param.descida
    }) : null;
    return () => { window._VL_lastExport = null; };
  }, [calc, classe, altura, comprimento, largura]);

  return (
    <div className="eletroduto">
      <div className="el-grid">
        <section className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">DADOS DE ENTRADA · NBR 5419-3:2015</div>
              <h3>Geometria e Nível de Proteção</h3>
            </div>
            <div className="status-chip"><span className="status-dot status-ok"/>ATUALIZADO</div>
          </div>
          
          <FieldBlock label="Nível de Proteção (Classe do SPDA)">
            <Seg value={classe} onChange={setClasse} options={[
              {value: "I",   label: "Classe I (Rigoroso)"},
              {value: "II",  label: "Classe II"},
              {value: "III", label: "Classe III (Comum)"},
              {value: "IV",  label: "Classe IV (Básico)"},
            ]}/>
          </FieldBlock>

          <div className="form-row form-row-2">
            <FieldBlock label="Altura da edificação (h)">
              <NumberInput value={altura} onChange={setAltura} suffix="m"/>
            </FieldBlock>
            <FieldBlock label="Comprimento">
              <NumberInput value={comprimento} onChange={setComprimento} suffix="m"/>
            </FieldBlock>
          </div>
          
          <div className="form-row form-row-2">
            <FieldBlock label="Largura">
              <NumberInput value={largura} onChange={setLargura} suffix="m"/>
            </FieldBlock>
            <FieldBlock label="Perímetro (Automático)">
              <div className="vl-input"><input type="text" disabled value={calc ? `${calc.perimetro} m` : "—"} /></div>
            </FieldBlock>
          </div>
        </section>

        <aside className="panel el-result">
          <div className="panel-head">
            <div><div className="panel-eyebrow">RESULTADO · PARÂMETROS DA MALHA E DESCIDA</div></div>
          </div>
          {calc ? (
            <>
              <ResultBig 
                label="ESFERA ROLANTE · RAIO (R)" 
                value={calc.param.r} 
                unit="metros" 
                status="ok"
              />
              <div className="vl-mini-grid vl-mini-grid-3">
                <MetricCell label="MALHA MÁXIMA" value={`${calc.param.malha}×${calc.param.malha}`} unit="m"/>
                <MetricCell label="ESPAÇAMENTO DESCIDAS" value={`≤ ${calc.param.descida}`} unit="m"/>
                <MetricCell label="MÍNIMO DE DESCIDAS" value={calc.nDescidas} unit="un." status="ok"/>
              </div>

              {!calc.franklinAplicavel && (
                <StatusBanner kind="warn">
                  Atenção: A altura ({calc.h}m) é maior que o raio da esfera da Classe {classe} ({calc.param.r}m). O método do Ângulo de Proteção (Haste de Franklin) <b>NÃO é aplicável</b> para o topo desta estrutura. Utilize malha ou esfera rolante.
                </StatusBanner>
              )}
              {calc.franklinAplicavel && (
                <StatusBanner kind="ok">
                  O método do Ângulo de Proteção (Franklin) pode ser aplicado para proteção de elementos na cobertura.
                </StatusBanner>
              )}

              <div className="vl-memory">
                <div className="vl-memory-eyebrow">MEMÓRIA NORMATIVA</div>
                <MemoryStep n={1} title={`Parâmetros Classe ${classe}`}>
                  Extraídos das Tabelas 2 e 4 da NBR 5419-3:2015.
                </MemoryStep>
                <MemoryStep n={2} title="Distribuição das Descidas">
                  P = {calc.perimetro}m. <br/>
                  N = Perímetro / Espaçamento ({calc.param.descida}m) = <b className="readout">{calc.nDescidas}</b> descidas bem distribuídas no perímetro (máx. variação de ±20%).
                </MemoryStep>
              </div>
            </>
          ) : <StatusBanner kind="info">Informe a geometria da edificação.</StatusBanner>}
        </aside>
      </div>
    </div>
  );
};

/* Export to window for app.jsx to use */
Object.assign(window, {
  VL_Corrente: Corrente,
  VL_QuedaTensao: QuedaTensao,
  VL_Dimensionamento: Dimensionamento,
  VL_Capacitor: Capacitor,
  VL_Transformador: Transformador,
  VL_CurtoCircuito: CurtoCircuito,

  // ADICIONE ESTA LINHA:
  VL_SPDA: SPDA,
  
  VL_Icon, VL_ResultBig: ResultBig, VL_MetricCell: MetricCell,
  // ... resto do código
});