/* ============================================================================
   VOLTLAB · Seção do Condutor (NBR 5410)
   ----------------------------------------------------------------------------
   Dimensionamento de condutores por TODOS os critérios da NBR 5410 (item 6.2):

     1) Capacidade de condução de corrente (ampacidade) — Tab. 36/37
     2) Queda de tensão                                   — Tab. 9
     3) Seção mínima por aplicação                        — Tab. 47
     4) Proteção contra sobrecargas                       — item 5.3.4.1
     5) Proteção contra curto-circuito                    — item 5.3.5

   Cada critério é ATIVÁVEL individualmente. A seção final é o MAIOR valor
   entre todos os critérios ligados (regra clássica da NBR 5410).

   Métodos de entrada da corrente de projeto (Ip):
     - Direta · Mono P · Bi P · Tri P · Mono S · Tri S

   Expõe: window.VL_SecaoCondutor  (componente React)
   ============================================================================ */

(function () {
  const { useState, useMemo, useEffect } = React;

  /* ------------------------------ Paleta --------------------------------- */
  const C = {
    bg:      '#0C1018',
    panel:   '#121826',
    panel2:  '#0F1420',
    border:  'rgba(61,139,255,0.16)',
    soft:    'rgba(61,139,255,0.08)',
    text:    '#E8EDF5',
    dim:     '#8FA3BF',
    blue:    '#3D8BFF',
    cyan:    '#57D8E6',
    amber:   '#FFB84D',
    red:     '#FF6B6B',
    green:   '#5CE0A1',
    purple:  '#9B8CFF',
    copper:  '#D08658',
    aluminum:'#C4CCD6',
  };
  /* cor por critério (usada nos badges e cards) */
  const CRIT_COR = {
    ampacidade:  C.amber,
    queda:       C.cyan,
    minima:      C.green,
    sobrecarga:  C.blue,
    curto:       C.red,
  };

  /* ---------- Seções comerciais (mm²) — NBR 5410 ------------------------- */
  const SECOES_TAB = [1.5, 2.5, 4, 6, 10, 16, 25, 35, 50, 70, 95, 120, 150, 185, 240];

  /* ---------- Métodos de instalação (Tab. 33) ---------------------------- */
  const METODOS = [
    { id: 'A1', desc: 'Condutores isolados em eletroduto embutido em parede termicamente isolante' },
    { id: 'A2', desc: 'Cabo multipolar em eletroduto embutido em parede termicamente isolante' },
    { id: 'B1', desc: 'Condutores isolados em eletroduto aparente sobre parede' },
    { id: 'B2', desc: 'Cabo multipolar em eletroduto aparente sobre parede' },
    { id: 'C',  desc: 'Cabos uni/multipolares fixados sobre parede ou teto' },
    { id: 'D',  desc: 'Cabo multipolar em eletroduto enterrado no solo' },
    { id: 'E',  desc: 'Cabo multipolar ao ar livre, afastado' },
    { id: 'F',  desc: 'Cabos unipolares ao ar livre, justapostos (trifólio)' },
  ];

  /* ---------- Tabelas 36 e 37 (ampères) — Cu/Al × PVC/EPR × 2/3 cond ----- */
  const TAB = {
    Cu_PVC_2: {
      A1: [14.5, 19.5, 26,  34,  46,  61,  80,  99,  119, 151, 182, 210, 240, 273, 320],
      A2: [14,   18.5, 25,  32,  43,  57,  75,  92,  110, 139, 167, 192, 219, 248, 291],
      B1: [17.5, 24,   32,  41,  57,  76,  101, 125, 151, 192, 232, 269, 309, 353, 415],
      B2: [16.5, 23,   30,  38,  52,  69,  90,  111, 133, 168, 201, 232, 265, 300, 351],
      C:  [19.5, 27,   36,  46,  63,  85,  112, 138, 168, 213, 258, 299, 344, 392, 461],
      D:  [22,   29,   38,  47,  63,  81,  104, 125, 148, 183, 216, 246, 278, 312, 361],
      E:  [22,   30,   40,  51,  70,  94,  119, 148, 180, 232, 282, 328, 379, 434, 514],
      F:  [null, null, null,null,null,null, 131, 162, 196, 251, 304, 352, 406, 463, 546],
    },
    Cu_PVC_3: {
      A1: [13.5, 18,   24,  31,  42,  56,  73,  89,  108, 136, 164, 188, 216, 245, 286],
      A2: [13,   17.5, 23,  29,  39,  52,  68,  83,  99,  125, 150, 172, 196, 223, 261],
      B1: [15.5, 21,   28,  36,  50,  68,  89,  111, 134, 171, 207, 239, 275, 314, 369],
      B2: [15,   20,   27,  34,  46,  62,  80,  99,  118, 149, 179, 206, 236, 268, 313],
      C:  [17.5, 24,   32,  41,  57,  76,  96,  119, 144, 184, 223, 259, 299, 341, 403],
      D:  [18,   24,   31,  39,  52,  67,  86,  103, 122, 151, 179, 203, 230, 258, 297],
      E:  [18.5, 25,   34,  43,  60,  80,  101, 126, 153, 196, 238, 276, 319, 364, 430],
      F:  [null, null, null,null,null,null, 114, 141, 172, 218, 264, 308, 356, 405, 477],
    },
    Al_PVC_2: {
      A1: [null, null, 21,  28,  36,  49,  64,  77,  94,  118, 144, 167, 191, 218, 256],
      A2: [null, null, 19.5,26,  33,  45,  59,  71,  86,  109, 130, 150, 172, 195, 229],
      B1: [null, null, 25,  33,  44,  60,  79,  97,  118, 150, 181, 210, 241, 275, 324],
      B2: [null, null, 23,  30,  41,  55,  71,  87,  104, 131, 157, 181, 206, 234, 274],
      C:  [null, null, 28,  36,  49,  66,  86,  107, 130, 165, 200, 232, 267, 305, 359],
      D:  [null, null, 30,  37,  49,  63,  80,  96,  114, 141, 167, 190, 215, 241, 280],
      E:  [null, null, 31,  39,  54,  73,  92,  115, 140, 180, 218, 254, 293, 336, 397],
      F:  [null, null, null,null,null,null, 101, 126, 152, 195, 236, 273, 315, 359, 424],
    },
    Al_PVC_3: {
      A1: [null, null, 19,  25,  33,  45,  58,  71,  86,  108, 130, 150, 172, 196, 229],
      A2: [null, null, 18,  23,  31,  41,  54,  66,  79,  100, 119, 137, 157, 178, 209],
      B1: [null, null, 22,  28,  39,  53,  70,  86,  104, 133, 161, 186, 214, 244, 287],
      B2: [null, null, 21,  27,  36,  48,  62,  77,  92,  116, 139, 160, 183, 208, 243],
      C:  [null, null, 25,  32,  44,  59,  73,  90,  110, 140, 170, 197, 227, 259, 305],
      D:  [null, null, 24,  30,  40,  52,  66,  80,  94,  117, 138, 157, 178, 200, 230],
      E:  [null, null, 26,  33,  46,  61,  78,  96,  117, 150, 183, 212, 245, 280, 330],
      F:  [null, null, null,null,null,null, 87,  109, 133, 173, 212, 247, 287, 330, 389],
    },
    Cu_EPR_2: {
      A1: [19,   26,   35,  45,  61,  81,  106, 131, 158, 200, 241, 278, 318, 362, 424],
      A2: [18.5, 25,   33,  42,  57,  76,  99,  121, 145, 183, 220, 253, 290, 329, 386],
      B1: [23,   31,   42,  54,  75,  100, 133, 164, 198, 253, 306, 354, 407, 464, 546],
      B2: [22,   30,   40,  51,  69,  91,  119, 146, 175, 221, 265, 305, 348, 394, 461],
      C:  [24,   33,   45,  58,  80,  107, 138, 171, 209, 269, 328, 382, 441, 506, 599],
      D:  [26,   34,   44,  56,  73,  95,  121, 146, 173, 213, 252, 287, 324, 363, 419],
      E:  [26,   36,   49,  63,  86,  115, 149, 185, 225, 289, 352, 410, 473, 542, 641],
      F:  [null, null, null,null,null,null, 161, 200, 242, 310, 377, 437, 504, 575, 679],
    },
    Cu_EPR_3: {
      A1: [17,   23,   31,  40,  54,  73,  95,  117, 141, 179, 216, 249, 285, 324, 380],
      A2: [16.5, 22,   30,  38,  51,  68,  89,  109, 130, 164, 197, 227, 259, 295, 346],
      B1: [20,   28,   37,  48,  66,  88,  117, 144, 175, 222, 269, 312, 358, 408, 481],
      B2: [19.5, 26,   35,  44,  60,  80,  105, 128, 154, 194, 233, 268, 307, 348, 407],
      C:  [22,   30,   40,  52,  71,  96,  119, 147, 179, 229, 278, 322, 371, 424, 500],
      D:  [21,   28,   36,  44,  58,  75,  96,  115, 135, 167, 197, 223, 251, 281, 324],
      E:  [23,   32,   42,  54,  75,  100, 127, 158, 192, 246, 298, 346, 399, 456, 538],
      F:  [null, null, null,null,null,null, 135, 169, 207, 268, 328, 383, 444, 510, 607],
    },
    Al_EPR_2: {
      A1: [null, null, 27,  35,  48,  64,  84,  103, 125, 158, 191, 220, 253, 288, 338],
      A2: [null, null, 26,  33,  44,  59,  77,  94,  113, 142, 171, 197, 226, 256, 300],
      B1: [null, null, 32,  42,  58,  78,  103, 127, 155, 197, 238, 275, 316, 361, 425],
      B2: [null, null, 31,  39,  53,  71,  92,  114, 137, 173, 207, 239, 274, 312, 365],
      C:  [null, null, 36,  47,  64,  86,  112, 138, 169, 217, 263, 305, 351, 401, 472],
      D:  [null, null, 34,  43,  56,  73,  93,  112, 132, 163, 193, 220, 249, 279, 322],
      E:  [null, null, 39,  50,  70,  93,  121, 150, 184, 237, 289, 337, 389, 447, 530],
      F:  [null, null, null,null,null,null, 130, 162, 197, 254, 311, 362, 419, 480, 569],
    },
    Al_EPR_3: {
      A1: [null, null, 25,  32,  43,  57,  75,  92,  112, 142, 171, 197, 226, 257, 302],
      A2: [null, null, 23,  30,  39,  53,  69,  84,  101, 128, 153, 176, 201, 229, 268],
      B1: [null, null, 29,  37,  51,  69,  91,  112, 136, 174, 211, 244, 280, 320, 377],
      B2: [null, null, 27,  35,  47,  63,  82,  101, 121, 153, 184, 212, 242, 275, 322],
      C:  [null, null, 32,  41,  57,  76,  98,  121, 147, 188, 228, 264, 305, 348, 410],
      D:  [null, null, 28,  35,  46,  59,  75,  90,  106, 130, 154, 174, 197, 220, 253],
      E:  [null, null, 35,  45,  62,  84,  101, 126, 154, 198, 241, 280, 324, 371, 439],
      F:  [null, null, null,null,null,null, 110, 137, 167, 216, 264, 308, 356, 409, 485],
    },
  };

  /* ---------- Tab. 40 — fatores de correção por temperatura -------------- */
  const K_TEMP_PVC = {
    10:1.22, 15:1.17, 20:1.12, 25:1.06, 30:1.00, 35:0.94, 40:0.87,
    45:0.79, 50:0.71, 55:0.61, 60:0.50,
  };
  const K_TEMP_EPR = {
    10:1.15, 15:1.12, 20:1.08, 25:1.04, 30:1.00, 35:0.96, 40:0.91,
    45:0.87, 50:0.82, 55:0.76, 60:0.71, 65:0.65, 70:0.58, 75:0.50,
  };

  /* ---------- Tab. 42 — fator de agrupamento ----------------------------- */
  const K_AGRUP = {
    1:1.00, 2:0.80, 3:0.70, 4:0.65, 5:0.60, 6:0.57, 7:0.54, 8:0.52,
    9:0.50, 10:0.49, 12:0.45, 14:0.43, 16:0.41, 18:0.39, 20:0.38,
  };

  /* ---------- Resistividade (Ω·mm²/m) na temperatura de regime ----------- */
  /* Cu @70°C ≈ 0,0225 · Cu @90°C ≈ 0,0246 · Al @70°C ≈ 0,036 · Al @90°C ≈ 0,041 */
  const RHO = {
    Cu_PVC: 0.0225,
    Cu_EPR: 0.0246,
    Al_PVC: 0.0360,
    Al_EPR: 0.0410,
  };

  /* ---------- Tab. 27 — constante K p/ critério curto-circuito ----------- */
  const K_CURTO = {
    Cu_PVC: 115,
    Cu_EPR: 143,
    Al_PVC: 76,
    Al_EPR: 94,
  };

  /* ---------- Tab. 47 — seção mínima por aplicação ----------------------- */
  /* Alumínio na NBR 5410 só é permitido a partir de 16 mm²                 */
  const SECAO_MIN_APLIC = {
    iluminacao:  { rotulo: 'Circuito de iluminação',         Cu: 1.5, Al: 16 },
    tomadas:     { rotulo: 'Circuito de tomadas (TUG/TUE)',  Cu: 2.5, Al: 16 },
    forca:       { rotulo: 'Circuitos de força/motor',       Cu: 2.5, Al: 16 },
    alimentador: { rotulo: 'Alimentador (entrada/quadros)',  Cu: 10,  Al: 16 },
    controle:    { rotulo: 'Sinalização / controle',          Cu: 0.5, Al: 16 },
  };

  /* ---------- Diâmetros aproximados (para o desenho) --------------------- */
  const D_EXT = {
    1.5:3.4, 2.5:3.9, 4:4.5, 6:5.1, 10:6.6, 16:7.7, 25:9.6, 35:10.8,
    50:12.2, 70:14.0, 95:16.0, 120:17.6, 150:19.3, 185:21.4, 240:24.0,
    300:26.3, 400:29.5, 500:32.4,
  };

  /* ============================ Utilitários ============================== */
  function fmt(v, casas) {
    if (!isFinite(v) || v == null) return '—';
    const n = casas == null ? 2 : casas;
    return v.toFixed(n).replace(/\.?0+$/, '');
  }
  function interp(map, x) {
    const keys = Object.keys(map).map(Number).sort((a,b) => a-b);
    if (x <= keys[0]) return map[keys[0]];
    if (x >= keys[keys.length-1]) return map[keys[keys.length-1]];
    for (let i = 0; i < keys.length-1; i++) {
      const a = keys[i], b = keys[i+1];
      if (x >= a && x <= b) {
        const t = (x - a) / (b - a);
        return map[a] + t * (map[b] - map[a]);
      }
    }
    return 1;
  }
  function fatorAgrupamento(n) {
    if (n <= 1) return 1.0;
    const keys = Object.keys(K_AGRUP).map(Number).sort((a,b) => a-b);
    let best = keys[0];
    for (const k of keys) { if (k <= n) best = k; }
    return K_AGRUP[best];
  }
  /* Primeira seção da lista que satisfaz cond(secao, capacidade) */
  function buscarSecao(linha, cond) {
    if (!linha) return null;
    for (let i = 0; i < SECOES_TAB.length; i++) {
      if (linha[i] == null) continue;
      if (cond(SECOES_TAB[i], linha[i])) {
        return { secao: SECOES_TAB[i], capacidade: linha[i] };
      }
    }
    return null;
  }
  /* Primeira seção comercial ≥ valor */
  function arredondaParaSecaoComercial(v) {
    for (const s of SECOES_TAB) if (s >= v) return s;
    return SECOES_TAB[SECOES_TAB.length - 1];
  }


  /* ============================ Corrente de projeto ====================== */
  function calcCorrente(modo, p) {
    const V = +p.V || 0, FP = +p.FP || 1;
    const Pp = +p.P || 0, S = +p.S || 0, Id = +p.I || 0;
    if (V <= 0 && modo !== 'direta') return 0;
    switch (modo) {
      case 'direta':     return Math.max(0, Id);
      case 'mono_P':     return Pp / (V * Math.max(0.01, FP));
      case 'bi_P':       return Pp / (V * Math.max(0.01, FP));
      case 'tri_P':      return Pp / (Math.sqrt(3) * V * Math.max(0.01, FP));
      case 'mono_S':     return S  / V;
      case 'tri_S':      return S  / (Math.sqrt(3) * V);
      default:           return 0;
    }
  }

  /* ============================ Critérios ================================ */

  /* (1) Capacidade de condução de corrente (ampacidade) */
  function critAmpacidade({ Ip, material, isolacao, ncond, metodo, tempAmb, nCircuitos }) {
    const tabMap = isolacao === 'PVC' ? K_TEMP_PVC : K_TEMP_EPR;
    const k1 = interp(tabMap, tempAmb);
    const k2 = fatorAgrupamento(nCircuitos);
    const Ic = Ip / (k1 * k2);
    const linha = TAB[`${material}_${isolacao}_${ncond}`]?.[metodo];
    if (!linha) return { ok:false, msg:'Combinação sem dados na tabela', k1, k2, Ic };
    const esc = buscarSecao(linha, (_, cap) => cap >= Ic);
    return {
      ok: !!esc,
      secao: esc?.secao || null,
      capacidade: esc?.capacidade || null,
      Ip, k1, k2, Ic,
      detalhe: `Iz ≥ Ip/(K1·K2) = ${fmt(Ip,1)} / (${fmt(k1,2)}·${fmt(k2,2)}) = ${fmt(Ic,1)} A`,
    };
  }

  /* (2) Queda de tensão (despreza X, suficiente para BT até ~70 mm²)
        ΔV% = k · ρ · L · I · cosφ · 100 / (S · V_ref)
        k: 2 (mono), 2 (bi), √3 (tri)
        Inverte: S_min = k · ρ · L · I · cosφ · 100 / (ΔV%_max · V_ref)
  */
  function critQueda({ Ip, material, isolacao, modo, V, FP, L_m, dV_max_pct }) {
    const rho = RHO[`${material}_${isolacao}`];
    if (!(L_m > 0) || !(dV_max_pct > 0)) {
      return { ok:false, msg:'Defina L e ΔV% máxima' };
    }
    if (!(Ip > 0)) return { ok:false, msg:'Ip não definida' };
    const cosphi = (modo === 'mono_S' || modo === 'tri_S') ? 1 : Math.max(0.01, FP);

    let k = 2, V_ref = V;                 /* monofásico default */
    if (modo === 'tri_P' || modo === 'tri_S') { k = Math.sqrt(3); V_ref = V; }
    else if (modo === 'bi_P')                 { k = 2;            V_ref = V; }
    if (V_ref <= 0) return { ok:false, msg:'V inválida' };

    const S_min = (k * rho * L_m * Ip * cosphi * 100) / (dV_max_pct * V_ref);
    const secao = arredondaParaSecaoComercial(S_min);

    /* ΔV% real para a seção comercial escolhida */
    const dV_real = (k * rho * L_m * Ip * cosphi * 100) / (secao * V_ref);

    return {
      ok: secao != null,
      secao, capacidade: null,
      S_calc: S_min, dV_real, k, rho, L_m, dV_max_pct, V_ref,
      detalhe: `ΔV% = ${k === 2 ? '2' : '√3'} · ρ · L · I · cosφ · 100 / (S · V)
S_min = ${k === 2 ? '2' : '√3'}·${fmt(rho,4)}·${fmt(L_m,1)}·${fmt(Ip,1)}·${fmt(cosphi,2)}·100 / (${fmt(dV_max_pct,2)}·${fmt(V_ref,0)})
S_min teórica = ${fmt(S_min,2)} mm²  →  comercial = ${secao} mm² (ΔV ≈ ${fmt(dV_real,2)}%)`,
    };
  }

  /* (3) Seção mínima por aplicação (Tab. 47) */
  function critMinima({ material, aplicacao }) {
    const ap = SECAO_MIN_APLIC[aplicacao];
    if (!ap) return { ok:false, msg:'Aplicação não definida' };
    const sec = ap[material];
    if (sec == null) return { ok:false, msg:'Sem mínima definida para este material' };
    return {
      ok: true, secao: sec, capacidade: null,
      detalhe: `${ap.rotulo} · mínimo NBR 5410 = ${sec} mm² (${material})`,
    };
  }

  /* (4) Proteção contra sobrecargas — Iz(S) ≥ In/(K1·K2) */
  function critSobrecarga({ In, material, isolacao, ncond, metodo, tempAmb, nCircuitos }) {
    if (!(In > 0)) return { ok:false, msg:'Defina In (corrente nominal do dispositivo)' };
    const tabMap = isolacao === 'PVC' ? K_TEMP_PVC : K_TEMP_EPR;
    const k1 = interp(tabMap, tempAmb);
    const k2 = fatorAgrupamento(nCircuitos);
    const I_alvo = In / (k1 * k2);
    const linha = TAB[`${material}_${isolacao}_${ncond}`]?.[metodo];
    if (!linha) return { ok:false, msg:'Sem dados na tabela' };
    const esc = buscarSecao(linha, (_, cap) => cap >= I_alvo);
    return {
      ok: !!esc, secao: esc?.secao || null, capacidade: esc?.capacidade || null,
      In, k1, k2, I_alvo,
      detalhe: `Iz ≥ In/(K1·K2) = ${fmt(In,1)} / (${fmt(k1,2)}·${fmt(k2,2)}) = ${fmt(I_alvo,1)} A`,
    };
  }

  /* (5) Curto-circuito — S_min = I_cc · √t / K */
  function critCurto({ I_cc_kA, t_s, material, isolacao }) {
    if (!(I_cc_kA > 0) || !(t_s > 0)) return { ok:false, msg:'Defina I_cc e t' };
    const K = K_CURTO[`${material}_${isolacao}`];
    const I_cc = I_cc_kA * 1000;
    const S_min = (I_cc * Math.sqrt(t_s)) / K;
    const secao = arredondaParaSecaoComercial(S_min);
    return {
      ok: true, secao, capacidade: null,
      S_calc: S_min, K, I_cc, t_s,
      detalhe: `S_min = I_cc·√t / K = ${fmt(I_cc,0)}·√${fmt(t_s,2)} / ${K}
S_min teórica = ${fmt(S_min,2)} mm²  →  comercial = ${secao} mm²`,
    };
  }

  /* ============================ Orquestrador ============================= */
  function dimensionar(params) {
    const { ativos, Ip } = params;
    const resultados = {};
    if (ativos.ampacidade) resultados.ampacidade = critAmpacidade(params);
    if (ativos.queda)      resultados.queda      = critQueda(params);
    if (ativos.minima)     resultados.minima     = critMinima(params);
    if (ativos.sobrecarga) resultados.sobrecarga = critSobrecarga(params);
    if (ativos.curto)      resultados.curto      = critCurto(params);

    /* Vencedor: maior seção entre os critérios OK */
    let vencedor = null;
    let secaoVencedora = 0;
    for (const [k, r] of Object.entries(resultados)) {
      if (r.ok && r.secao != null && r.secao > secaoVencedora) {
        secaoVencedora = r.secao; vencedor = k;
      }
    }

    /* Capacidade real do cabo escolhido (ampacidade real do vencedor) */
    let capacidadeReal = null;
    if (secaoVencedora) {
      const idx = SECOES_TAB.indexOf(secaoVencedora);
      const linha = TAB[`${params.material}_${params.isolacao}_${params.ncond}`]?.[params.metodo];
      if (linha && idx >= 0) capacidadeReal = linha[idx];
    }

    return { Ip, resultados, vencedor, secaoVencedora, capacidadeReal };
  }


  /* ===================== Desenho da seção do condutor ===================== */
  function ConductorSVG({ secao, material, isolacao, ncond, capacidade, vencedorCor }) {
    const dExt = D_EXT[secao] || (2 * Math.sqrt(secao / Math.PI) + 3);
    const dCore = 2 * Math.sqrt(secao / Math.PI);

    const VB = 320;
    const maxExt = 24;
    const px = (VB * 0.82) / maxExt;
    const cx = VB / 2, cy = VB / 2;
    const rExt  = (dExt / 2) * px;
    const rIso  = rExt - Math.max(6, rExt * 0.10);
    const rCore = (dCore / 2) * px;

    const corNucleo = material === 'Cu' ? C.copper : C.aluminum;
    const corIso    = isolacao === 'PVC' ? '#1a4d8f' : '#1a8f6b';

    const arranjo = (() => {
      if (ncond === 1) return [{ x: cx, y: cy }];
      if (ncond === 2) {
        const d = rIso - rCore - 4;
        return [{ x: cx - d/2, y: cy }, { x: cx + d/2, y: cy }];
      }
      if (ncond === 3) {
        const R = (rIso - rCore) - 4;
        const a = -Math.PI / 2;
        return [0,1,2].map(i => ({
          x: cx + R * Math.cos(a + i * 2 * Math.PI / 3),
          y: cy + R * Math.sin(a + i * 2 * Math.PI / 3),
        }));
      }
      const R = (rIso - rCore) - 6;
      return Array.from({ length: ncond }, (_, i) => {
        const a = -Math.PI / 2 + (i * 2 * Math.PI / ncond);
        return { x: cx + R * Math.cos(a), y: cy + R * Math.sin(a) };
      });
    })();

    const isMulti = ncond >= 2;
    const rCoreMulti = isMulti ? Math.max(8, rCore * 0.6) : rCore;
    const rIsoMulti  = isMulti ? rCoreMulti + Math.max(4, rCoreMulti * 0.45) : rIso;
    const rExtMulti  = isMulti
      ? Math.max(...arranjo.map(p => Math.hypot(p.x - cx, p.y - cy))) + rIsoMulti + 8
      : rExt;

    const coresVeias = ncond === 2
      ? ['#1f6dd6', '#222']
      : ncond === 3
        ? ['#222', '#1f6dd6', '#2fa256']
        : ['#222', '#c33', '#888', '#1f6dd6', '#2fa256'];

    return (
      <svg viewBox={`0 0 ${VB} ${VB}`} className="vlsec-svg">
        <defs>
          <radialGradient id="vlsec-core" cx="35%" cy="35%" r="65%">
            <stop offset="0%"  stopColor={material === 'Cu' ? '#F0AA77' : '#E2E6EB'} />
            <stop offset="60%" stopColor={corNucleo} />
            <stop offset="100%" stopColor={material === 'Cu' ? '#8C5128' : '#7E8896'} />
          </radialGradient>
          <radialGradient id="vlsec-iso" cx="50%" cy="40%" r="70%">
            <stop offset="0%" stopColor={isolacao === 'PVC' ? '#3B7DD8' : '#3DB489'} stopOpacity="0.95"/>
            <stop offset="100%" stopColor={corIso} />
          </radialGradient>
          <radialGradient id="vlsec-capa" cx="50%" cy="40%" r="75%">
            <stop offset="0%"  stopColor="#2A3344" />
            <stop offset="100%" stopColor="#1f2735" />
          </radialGradient>
          <filter id="vlsec-shadow" x="-20%" y="-20%" width="140%" height="140%">
            <feGaussianBlur in="SourceAlpha" stdDeviation="6"/>
            <feOffset dx="0" dy="6" result="off"/>
            <feComponentTransfer><feFuncA type="linear" slope="0.45"/></feComponentTransfer>
            <feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
          </filter>
        </defs>

        {/* Anel de critério vencedor (cor) */}
        <circle cx={cx} cy={cy} r={rExtMulti + 14}
                fill="none" stroke={vencedorCor || C.border} strokeWidth="2"
                strokeDasharray="3 5" opacity="0.7"/>

        <g filter="url(#vlsec-shadow)">
          <circle cx={cx} cy={cy} r={rExtMulti} fill="url(#vlsec-capa)"
                  stroke="#0a0e16" strokeWidth="2"/>
        </g>

        {isMulti
          ? arranjo.map((p, i) => (
              <g key={i}>
                <circle cx={p.x} cy={p.y} r={rIsoMulti}
                        fill={coresVeias[i % coresVeias.length]} opacity="0.92"
                        stroke="rgba(0,0,0,0.35)" strokeWidth="1"/>
                <circle cx={p.x} cy={p.y} r={rCoreMulti} fill="url(#vlsec-core)"
                        stroke="rgba(0,0,0,0.45)" strokeWidth="1"/>
                <circle cx={p.x - rCoreMulti*0.3} cy={p.y - rCoreMulti*0.3}
                        r={rCoreMulti*0.25} fill="#fff" opacity="0.32"/>
              </g>
            ))
          : (
            <g>
              <circle cx={cx} cy={cy} r={rIso} fill="url(#vlsec-iso)"
                      stroke="rgba(0,0,0,0.35)" strokeWidth="1"/>
              <circle cx={cx} cy={cy} r={rCore} fill="url(#vlsec-core)"
                      stroke="rgba(0,0,0,0.45)" strokeWidth="1"/>
              <circle cx={cx - rCore*0.3} cy={cy - rCore*0.3}
                      r={rCore*0.25} fill="#fff" opacity="0.32"/>
            </g>
          )
        }

        <g fontFamily="JetBrains Mono, monospace" fontSize="14" fill={C.dim}>
          <line x1={cx + rExtMulti + 6} y1={cy} x2={cx + rExtMulti + 26} y2={cy}
                stroke={C.dim} strokeWidth="1"/>
          <text x={cx + rExtMulti + 32} y={cy + 5}>Ø {fmt(dExt, 1)} mm</text>
        </g>
        <g fontFamily="JetBrains Mono, monospace" fontSize="11" fill={C.cyan} textAnchor="middle">
          <text x={cx} y={VB - 14}>{secao} mm² · {ncond}× · {material === 'Cu' ? 'Cobre' : 'Alumínio'} · {isolacao}</text>
        </g>
        {capacidade && (
          <g fontFamily="Space Grotesk, sans-serif" textAnchor="middle">
            <text x={cx} y={28} fontSize="11" fill={C.dim} letterSpacing="1.5">CAPACIDADE Iz</text>
            <text x={cx} y={50} fontSize="20" fill={C.amber} fontWeight="600">{fmt(capacidade,0)} A</text>
          </g>
        )}
      </svg>
    );
  }


  /* ============================ Sub-componentes ========================== */
  function Field({ label, hint, children }) {
    return (
      <label className="vlsec-field">
        <div className="vlsec-field-head">
          <span>{label}</span>
          {hint && <span className="vlsec-field-hint">{hint}</span>}
        </div>
        {children}
      </label>
    );
  }
  function Pill({ active, onClick, children, title }) {
    return (
      <button type="button" title={title}
        className={'vlsec-pill' + (active ? ' is-active' : '')}
        onClick={onClick}>{children}</button>
    );
  }
  function Stat({ rotulo, valor, unidade, accent }) {
    return (
      <div className="vlsec-stat">
        <div className="vlsec-stat-rot">{rotulo}</div>
        <div className="vlsec-stat-val" style={accent ? { color: accent } : null}>
          <span>{valor}</span>{unidade && <small>{unidade}</small>}
        </div>
      </div>
    );
  }
  function Switch({ on, onChange, cor }) {
    return (
      <button type="button"
        className={'vlsec-switch' + (on ? ' is-on' : '')}
        style={on && cor ? { background: cor + '33', borderColor: cor } : null}
        onClick={() => onChange(!on)}
        aria-pressed={on}>
        <span className="vlsec-switch-knob"
              style={on && cor ? { background: cor } : null}/>
      </button>
    );
  }
  function CriterioCard({ id, titulo, ativo, onToggle, status, secaoCalc,
                          msg, detalhe, vencedor, children }) {
    const cor = CRIT_COR[id];
    return (
      <div className={
          'vlsec-crit' +
          (ativo ? ' is-on' : ' is-off') +
          (vencedor ? ' is-vencedor' : '')
        }
        style={ativo ? { borderColor: cor + '55' } : null}>
        <header className="vlsec-crit-head">
          <div className="vlsec-crit-title">
            <span className="vlsec-crit-dot" style={{ background: cor }}/>
            <h3>{titulo}</h3>
            {vencedor && <span className="vlsec-crit-tag">CRITÉRIO VENCEDOR</span>}
          </div>
          <Switch on={ativo} onChange={onToggle} cor={cor}/>
        </header>
        {ativo && (
          <div className="vlsec-crit-body">
            {children}
            <div className="vlsec-crit-out">
              {status === 'ok' && secaoCalc != null && (
                <div className="vlsec-crit-secao" style={{ color: cor }}>
                  <span className="vlsec-crit-num">{secaoCalc}</span>
                  <span className="vlsec-crit-uni">mm²</span>
                </div>
              )}
              {status === 'erro' && (
                <div className="vlsec-crit-erro">⚠ {msg}</div>
              )}
              {detalhe && status === 'ok' && (
                <pre className="vlsec-crit-detalhe">{detalhe}</pre>
              )}
            </div>
          </div>
        )}
      </div>
    );
  }

  /* ============================ Componente principal ===================== */
  function SecaoCondutor() {
    /* corrente */
    const [modo, setModo]    = useState('tri_P');
    const [V, setV]          = useState(380);
    const [P, setP]          = useState(7500);
    const [S, setS]          = useState(10000);
    const [FP, setFP]        = useState(0.92);
    const [Idir, setIdir]    = useState(20);

    /* cabo / instalação */
    const [material, setMaterial] = useState('Cu');
    const [isolacao, setIsolacao] = useState('PVC');
    const [ncond, setNcond]       = useState(3);
    const [metodo, setMetodo]     = useState('B1');
    const [tempAmb, setTempAmb]   = useState(30);
    const [nCircuitos, setNCirc]  = useState(1);

    /* critérios ativos */
    const [ativos, setAtivos] = useState({
      ampacidade: true,
      queda:      false,
      minima:     false,
      sobrecarga: false,
      curto:      false,
    });

    /* parâmetros dos critérios opcionais */
    const [L_m, setL]         = useState(30);
    const [dV_max, setDV]     = useState(4);
    const [aplicacao, setAp]  = useState('tomadas');
    const [In, setIn]         = useState(20);
    const [I_cc_kA, setIcc]   = useState(3);
    const [t_s, setT]         = useState(0.1);

    /* override manual do desenho */
    const [overrideSecao, setOverr] = useState(null);

    /* corrente de projeto */
    const Ip = useMemo(() => calcCorrente(modo, { V, P, S, FP, I: Idir }),
                       [modo, V, P, S, FP, Idir]);

    /* cálculo consolidado */
    const dim = useMemo(() => dimensionar({
      ativos, Ip,
      material, isolacao, ncond, metodo, tempAmb, nCircuitos,
      modo, V, FP,
      L_m, dV_max_pct: dV_max,
      aplicacao,
      In,
      I_cc_kA, t_s,
    }), [ativos, Ip, material, isolacao, ncond, metodo, tempAmb, nCircuitos,
         modo, V, FP, L_m, dV_max, aplicacao, In, I_cc_kA, t_s]);

    /* seção apresentada no desenho */
    const secaoMostrada = overrideSecao != null
      ? overrideSecao
      : (dim.secaoVencedora || null);

    /* capacidade real do cabo (na seção mostrada) */
    const capMostrada = useMemo(() => {
      if (!secaoMostrada) return null;
      const idx = SECOES_TAB.indexOf(secaoMostrada);
      const linha = TAB[`${material}_${isolacao}_${ncond}`]?.[metodo];
      return linha && idx >= 0 ? linha[idx] : null;
    }, [secaoMostrada, material, isolacao, ncond, metodo]);

    useEffect(() => { setOverr(null); },
             [material, isolacao, ncond, metodo, tempAmb, nCircuitos, modo, ativos]);

    function exportarJSON() {
      const data = {
        modulo: 'secao_condutor-nbr5410', criado_em: new Date().toISOString(),
        entrada: { modo, V, P, S, FP, I: Idir },
        cabo: { material, isolacao, ncond, metodo, tempAmb, nCircuitos },
        criterios_ativos: ativos,
        parametros: { L_m, dV_max, aplicacao, In, I_cc_kA, t_s },
        resultados: dim.resultados,
        vencedor: dim.vencedor,
        secao_final_mm2: dim.secaoVencedora,
        capacidade_Iz_A: dim.capacidadeReal,
      };
      const blob = new Blob([JSON.stringify(data, null, 2)], { type:'application/json' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = `secao_condutor_${Date.now()}.json`;
      a.click();
      setTimeout(() => URL.revokeObjectURL(a.href), 1000);
    }

    const modoInfo = {
      direta:  { label: 'Direta',          formula: 'I = valor digitado' },
      mono_P:  { label: 'Mono · P',        formula: 'I = P / (V · FP)' },
      bi_P:    { label: 'Bifásico · P',    formula: 'I = P / (V_ff · FP)' },
      tri_P:   { label: 'Trifásico · P',   formula: 'I = P / (√3 · V_ff · FP)' },
      mono_S:  { label: 'Mono · S',        formula: 'I = S / V' },
      tri_S:   { label: 'Trifásico · S',   formula: 'I = S / (√3 · V_ff)' },
    };

    const toggleAtivo = (k) => setAtivos(prev => ({ ...prev, [k]: !prev[k] }));

    /* lista para a tabela comparativa */
    const linhaComp = (id, titulo) => {
      const r = dim.resultados[id];
      if (!ativos[id]) return null;
      if (!r) return null;
      const isVenc = dim.vencedor === id;
      return (
        <tr key={id} className={
              (isVenc ? 'is-vencedor ' : '') +
              (r.ok ? 'is-passa' : 'is-falha')}>
          <td>
            <span className="vlsec-table-dot" style={{ background: CRIT_COR[id] }}/>
            {titulo}
          </td>
          <td>{r.ok ? `${r.secao} mm²` : '—'}</td>
          <td>{r.ok ? (isVenc ? '✓ vencedor' : 'OK') : '✗ ' + (r.msg || '')}</td>
        </tr>
      );
    };

    return (
      <div className="vlsec">
        <div className="vlsec-topbar">
          <span className="panel-eyebrow">Dimensionamento · NBR 5410 (Item 6.2)</span>
          <button className="btn btn-ghost" style={{fontSize:12}} onClick={exportarJSON}>Exportar JSON</button>
        </div>

        <div className="vlsec-body">

          {/* COL 1 — Entradas */}
          <section className="vlsec-col vlsec-col-in panel">
            <h2 className="vlsec-col-title">Corrente de projeto</h2>
            <div className="vlsec-pills">
              {Object.entries(modoInfo).map(([k, v]) =>
                <Pill key={k} active={modo === k}
                      title={v.formula}
                      onClick={() => setModo(k)}>{v.label}</Pill>
              )}
            </div>
            <div className="vlsec-formula">{modoInfo[modo].formula}</div>

            {modo === 'direta' && (
              <Field label="Corrente (A)">
                <input type="number" min="0" step="0.1" value={Idir}
                       onChange={e => setIdir(+e.target.value)}/>
              </Field>
            )}
            {(modo === 'mono_P' || modo === 'tri_P' || modo === 'bi_P') && (<>
              <Field label="Potência ativa P (W)">
                <input type="number" min="0" step="1" value={P}
                       onChange={e => setP(+e.target.value)}/>
              </Field>
              <Field label={modo === 'mono_P' ? 'Tensão (fase-neutro)' : 'Tensão V_ff'} hint="V">
                <input type="number" min="0" step="1" value={V}
                       onChange={e => setV(+e.target.value)}/>
              </Field>
              <Field label="Fator de potência" hint="cosφ">
                <input type="number" min="0" max="1" step="0.01" value={FP}
                       onChange={e => setFP(+e.target.value)}/>
              </Field>
            </>)}
            {(modo === 'mono_S' || modo === 'tri_S') && (<>
              <Field label="Potência aparente S (VA)">
                <input type="number" min="0" step="1" value={S}
                       onChange={e => setS(+e.target.value)}/>
              </Field>
              <Field label={modo === 'mono_S' ? 'Tensão (fase-neutro)' : 'Tensão V_ff'} hint="V">
                <input type="number" min="0" step="1" value={V}
                       onChange={e => setV(+e.target.value)}/>
              </Field>
            </>)}

            <div className="vlsec-ip-box">
              <span>Ip calculada</span>
              <strong>{fmt(Ip, 1)} A</strong>
            </div>

            <hr className="vlsec-sep"/>

            <h2 className="vlsec-col-title">Cabo & instalação</h2>

            <Field label="Material">
              <div className="vlsec-toggle">
                <Pill active={material === 'Cu'} onClick={() => setMaterial('Cu')}>
                  <i style={{ background: C.copper }}/>Cobre
                </Pill>
                <Pill active={material === 'Al'} onClick={() => setMaterial('Al')}>
                  <i style={{ background: C.aluminum }}/>Alumínio
                </Pill>
              </div>
            </Field>
            <Field label="Isolação">
              <div className="vlsec-toggle">
                <Pill active={isolacao === 'PVC'} onClick={() => setIsolacao('PVC')}>
                  PVC <small>70°C</small>
                </Pill>
                <Pill active={isolacao === 'EPR'} onClick={() => setIsolacao('EPR')}>
                  EPR/XLPE <small>90°C</small>
                </Pill>
              </div>
            </Field>
            <Field label="Condutores carregados">
              <div className="vlsec-toggle">
                <Pill active={ncond === 2} onClick={() => setNcond(2)}>2 cond.</Pill>
                <Pill active={ncond === 3} onClick={() => setNcond(3)}>3 cond.</Pill>
              </div>
            </Field>
            <Field label="Método de instalação" hint="Tab. 33">
              <select value={metodo} onChange={e => setMetodo(e.target.value)}>
                {METODOS.map(m =>
                  <option key={m.id} value={m.id}>{m.id} · {m.desc}</option>
                )}
              </select>
            </Field>
            <div className="vlsec-row2">
              <Field label="T. ambiente (°C)" hint="K1">
                <input type="number" min="10" max="75" step="1" value={tempAmb}
                       onChange={e => setTempAmb(+e.target.value)}/>
              </Field>
              <Field label="Circuitos agrupados" hint="K2">
                <input type="number" min="1" max="20" step="1" value={nCircuitos}
                       onChange={e => setNCirc(+e.target.value)}/>
              </Field>
            </div>
          </section>

          <div className="vlsec-right">
          {/* Critérios */}
          <section className="vlsec-col vlsec-col-mid panel">
            <h2 className="vlsec-col-title">Critérios de dimensionamento</h2>

            {/* (1) AMPACIDADE */}
            <CriterioCard id="ampacidade" titulo="1. Capacidade de condução (ampacidade)"
              ativo={ativos.ampacidade} onToggle={() => toggleAtivo('ampacidade')}
              status={dim.resultados.ampacidade?.ok ? 'ok' : 'erro'}
              secaoCalc={dim.resultados.ampacidade?.secao}
              msg={dim.resultados.ampacidade?.msg}
              detalhe={dim.resultados.ampacidade?.detalhe}
              vencedor={dim.vencedor === 'ampacidade'}>
              <div className="vlsec-mini-stats">
                <span>K1 = {fmt(dim.resultados.ampacidade?.k1, 2)}</span>
                <span>K2 = {fmt(dim.resultados.ampacidade?.k2, 2)}</span>
                <span>Ic = {fmt(dim.resultados.ampacidade?.Ic, 1)} A</span>
              </div>
            </CriterioCard>

            {/* (2) QUEDA DE TENSÃO */}
            <CriterioCard id="queda" titulo="2. Queda de tensão"
              ativo={ativos.queda} onToggle={() => toggleAtivo('queda')}
              status={dim.resultados.queda?.ok ? 'ok' : 'erro'}
              secaoCalc={dim.resultados.queda?.secao}
              msg={dim.resultados.queda?.msg}
              detalhe={dim.resultados.queda?.detalhe}
              vencedor={dim.vencedor === 'queda'}>
              <div className="vlsec-row2">
                <Field label="Comprimento L (m)">
                  <input type="number" min="0" step="0.5" value={L_m}
                         onChange={e => setL(+e.target.value)}/>
                </Field>
                <Field label="ΔV% máxima" hint="Tab. 9">
                  <select value={dV_max} onChange={e => setDV(+e.target.value)}>
                    <option value="4">4% (terminais)</option>
                    <option value="5">5% (iluminação)</option>
                    <option value="7">7% (alimentador)</option>
                  </select>
                </Field>
              </div>
            </CriterioCard>

            {/* (3) SEÇÃO MÍNIMA */}
            <CriterioCard id="minima" titulo="3. Seção mínima por aplicação"
              ativo={ativos.minima} onToggle={() => toggleAtivo('minima')}
              status={dim.resultados.minima?.ok ? 'ok' : 'erro'}
              secaoCalc={dim.resultados.minima?.secao}
              msg={dim.resultados.minima?.msg}
              detalhe={dim.resultados.minima?.detalhe}
              vencedor={dim.vencedor === 'minima'}>
              <Field label="Aplicação" hint="Tab. 47">
                <select value={aplicacao} onChange={e => setAp(e.target.value)}>
                  {Object.entries(SECAO_MIN_APLIC).map(([k, v]) =>
                    <option key={k} value={k}>{v.rotulo}</option>
                  )}
                </select>
              </Field>
            </CriterioCard>

            {/* (4) SOBRECARGA */}
            <CriterioCard id="sobrecarga" titulo="4. Proteção contra sobrecargas"
              ativo={ativos.sobrecarga} onToggle={() => toggleAtivo('sobrecarga')}
              status={dim.resultados.sobrecarga?.ok ? 'ok' : 'erro'}
              secaoCalc={dim.resultados.sobrecarga?.secao}
              msg={dim.resultados.sobrecarga?.msg}
              detalhe={dim.resultados.sobrecarga?.detalhe}
              vencedor={dim.vencedor === 'sobrecarga'}>
              <Field label="In do dispositivo (A)"
                     hint="corrente nominal do disjuntor / fusível">
                <input type="number" min="0" step="1" value={In}
                       onChange={e => setIn(+e.target.value)}/>
              </Field>
            </CriterioCard>

            {/* (5) CURTO-CIRCUITO */}
            <CriterioCard id="curto" titulo="5. Curto-circuito"
              ativo={ativos.curto} onToggle={() => toggleAtivo('curto')}
              status={dim.resultados.curto?.ok ? 'ok' : 'erro'}
              secaoCalc={dim.resultados.curto?.secao}
              msg={dim.resultados.curto?.msg}
              detalhe={dim.resultados.curto?.detalhe}
              vencedor={dim.vencedor === 'curto'}>
              <div className="vlsec-row2">
                <Field label="I_cc presumida (kA)">
                  <input type="number" min="0" step="0.1" value={I_cc_kA}
                         onChange={e => setIcc(+e.target.value)}/>
                </Field>
                <Field label="Tempo de atuação t (s)" hint="típico 0,1 s">
                  <input type="number" min="0" max="5" step="0.01" value={t_s}
                         onChange={e => setT(+e.target.value)}/>
                </Field>
              </div>
              <div className="vlsec-mini-stats">
                <span>K = {K_CURTO[`${material}_${isolacao}`]}</span>
              </div>
            </CriterioCard>

            {/* COMPARATIVO */}
            <h3 className="vlsec-sub-title">Comparativo entre critérios</h3>
            <div className="vlsec-table-wrap">
              <table className="vlsec-table">
                <thead><tr>
                  <th>Critério</th><th>Seção mín.</th><th>Status</th>
                </tr></thead>
                <tbody>
                  {linhaComp('ampacidade', 'Ampacidade')}
                  {linhaComp('queda',      'Queda de tensão')}
                  {linhaComp('minima',     'Seção mínima')}
                  {linhaComp('sobrecarga', 'Sobrecarga')}
                  {linhaComp('curto',      'Curto-circuito')}
                </tbody>
              </table>
            </div>
          </section>

          {/* COL 3 — Resultado final + Desenho */}
          <section className="vlsec-col vlsec-col-svg panel">
            <h2 className="vlsec-col-title">Seção final</h2>

            {dim.secaoVencedora ? (
              <div className="vlsec-final"
                   style={{ borderColor: CRIT_COR[dim.vencedor] + '66' }}>
                <div className="vlsec-final-head">RESULTADO</div>
                <div className="vlsec-final-main">
                  <span className="vlsec-final-num"
                        style={{ color: CRIT_COR[dim.vencedor] }}>
                    {dim.secaoVencedora}
                  </span>
                  <span className="vlsec-final-unit">mm²</span>
                </div>
                <div className="vlsec-final-sub">
                  vencedor: <b>{
                    {ampacidade:'Ampacidade', queda:'Queda de tensão',
                     minima:'Seção mínima', sobrecarga:'Sobrecarga',
                     curto:'Curto-circuito'}[dim.vencedor]
                  }</b>
                </div>
                {dim.capacidadeReal && (
                  <div className="vlsec-final-cap">
                    Iz = {fmt(dim.capacidadeReal, 0)} A
                  </div>
                )}
              </div>
            ) : (
              <div className="vlsec-warn">
                Ative ao menos um critério para obter resultado.
              </div>
            )}

            <div className="vlsec-svg-wrap">
              {secaoMostrada
                ? <ConductorSVG secao={secaoMostrada} material={material}
                                isolacao={isolacao} ncond={ncond}
                                capacidade={capMostrada}
                                vencedorCor={CRIT_COR[dim.vencedor]}/>
                : <div className="vlsec-svg-empty">Sem seção definida</div>
              }
            </div>

            <div className="vlsec-legend">
              <div><i style={{ background: material === 'Cu' ? C.copper : C.aluminum }}/>
                {material === 'Cu' ? 'Cobre' : 'Alumínio'}</div>
              <div><i style={{ background: isolacao === 'PVC' ? '#1f6dd6' : '#2fa256' }}/>
                isolação {isolacao}</div>
              <div><i style={{ background: '#1f2735' }}/>capa</div>
            </div>

            {overrideSecao && (
              <button className="vlsec-btn vlsec-btn-ghost"
                      onClick={() => setOverr(null)}>
                Voltar à seção calculada
              </button>
            )}

            <div className="vlsec-foot">
              <div><b>Resumo</b></div>
              <div>Ip = {fmt(Ip, 1)} A</div>
              {Object.entries(dim.resultados).map(([k, r]) =>
                ativos[k] && r.ok && (
                  <div key={k}>
                    <span style={{ color: CRIT_COR[k] }}>●</span> {k}: {r.secao} mm²
                  </div>
                )
              )}
              {dim.secaoVencedora && (
                <div style={{ marginTop: 6 }}>
                  → final: <b>{ncond}× {dim.secaoVencedora} mm² {material} {isolacao}</b>
                </div>
              )}
            </div>
          </section>

          </div>{/* /vlsec-right */}
        </div>
      </div>
    );
  }


  /* ================================ CSS ================================== */
  const CSS = `
  .vlsec{display:flex;flex-direction:column;min-height:100%;color:var(--fg);
    font-family:var(--ff-body)}
  .vlsec *{box-sizing:border-box}
  .vlsec h1,.vlsec h2,.vlsec h3{font-family:var(--ff-display);margin:0}

  .vlsec-topbar{display:flex;align-items:center;justify-content:space-between;
    margin-bottom:16px;gap:12px}

  .vlsec-body{display:grid;grid-template-columns:360px 1fr;gap:var(--gap-grid);
    align-items:start;flex:1}

  .vlsec-right{display:grid;grid-template-columns:1fr 280px;gap:var(--gap-grid);
    align-items:start}

  .vlsec-col{display:flex;flex-direction:column;gap:12px;overflow-y:auto}
  .vlsec-col.panel{padding:var(--pad-panel)}
  .vlsec-col-svg.panel{background:var(--bg-2)}

  .vlsec-col-title{font-size:10px;font-weight:600;letter-spacing:1.6px;
    text-transform:uppercase;color:var(--fg-mute);margin:0 0 6px}
  .vlsec-sub-title{font-size:10px;font-weight:600;letter-spacing:1.6px;
    text-transform:uppercase;color:var(--fg-mute);margin:16px 0 6px}
  .vlsec-sep{border:none;border-top:1px solid var(--border);margin:8px 0 4px}

  .vlsec-pills{display:flex;flex-wrap:wrap;gap:6px}
  .vlsec-pill{background:var(--bg-2);color:var(--fg-mute);border:1px solid var(--border);
    padding:6px 11px;border-radius:var(--r-pill);cursor:pointer;
    font:500 11.5px var(--ff-body);letter-spacing:.2px;transition:all .12s ease;
    display:inline-flex;align-items:center;gap:6px}
  .vlsec-pill:hover{color:var(--fg);border-color:var(--border-2)}
  .vlsec-pill.is-active{background:var(--accent-soft);color:var(--fg);
    border-color:var(--accent);box-shadow:0 0 0 1px var(--accent-soft) inset}
  .vlsec-pill small{color:var(--fg-mute);font-size:10.5px;margin-left:3px}
  .vlsec-pill i{width:10px;height:10px;border-radius:50%;display:inline-block;
    border:1px solid rgba(0,0,0,0.3)}
  .vlsec-toggle{display:flex;gap:6px;flex-wrap:wrap}

  .vlsec-formula{font:13px var(--ff-mono);color:var(--accent-2);
    background:oklch(72% 0.14 200/0.07);border:1px solid oklch(72% 0.14 200/0.20);
    padding:8px 12px;border-radius:var(--r-2)}

  .vlsec-field{display:flex;flex-direction:column;gap:5px}
  .vlsec-field-head{display:flex;justify-content:space-between;align-items:baseline;
    font-size:11.5px;color:var(--fg-mute);font-weight:500;letter-spacing:.3px}
  .vlsec-field-hint{font-size:10.5px;color:var(--fg-mute);opacity:.7}
  .vlsec-field input,.vlsec-field select{
    background:var(--bg-2);color:var(--fg);border:1px solid var(--border);
    border-radius:var(--r-2);padding:8px 11px;font:14px var(--ff-mono);
    outline:none;transition:border .12s;width:100%}
  .vlsec-field input:focus,.vlsec-field select:focus{border-color:var(--accent)}
  .vlsec-row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}

  .vlsec-ip-box{display:flex;justify-content:space-between;align-items:center;
    padding:8px 14px;background:var(--bg-2);border:1px solid var(--border);
    border-radius:var(--r-2);margin-top:4px}
  .vlsec-ip-box span{font-size:11px;color:var(--fg-mute);letter-spacing:.5px;text-transform:uppercase}
  .vlsec-ip-box strong{font:600 18px var(--ff-mono);color:var(--accent-2)}

  /* ----- cards de critério ----- */
  .vlsec-crit{background:var(--bg-2);border:1px solid var(--border);border-radius:var(--r-3);
    overflow:hidden;transition:border-color .15s}
  .vlsec-crit.is-ativo{border-color:var(--border-2)}
  .vlsec-crit.is-vencedor{border-color:var(--accent)!important;
    box-shadow:0 0 0 1px var(--accent-soft) inset}
  .vlsec-crit-head{display:flex;align-items:center;justify-content:space-between;
    padding:10px 14px;gap:10px;cursor:pointer}
  .vlsec-crit-title{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
  .vlsec-crit-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
  .vlsec-crit-badge{font:600 9.5px var(--ff-mono);letter-spacing:.8px;padding:2px 7px;
    border-radius:var(--r-pill);text-transform:uppercase}
  .vlsec-crit-name{font:600 12px var(--ff-display)}
  .vlsec-crit-body{padding:12px 14px;display:flex;flex-direction:column;gap:10px}
  .vlsec-crit-secao{display:flex;align-items:baseline;gap:5px;
    font-family:var(--ff-display)}
  .vlsec-crit-secao-num{font-size:26px;font-weight:700;line-height:1}
  .vlsec-crit-secao-unit{font-size:14px;color:var(--fg-mute)}
  .vlsec-crit-msg{font-size:12px;color:var(--fg-mute);font-family:var(--ff-mono);
    background:var(--bg-0);padding:6px 10px;border-radius:var(--r-2)}
  .vlsec-mini-stats{display:flex;gap:14px;flex-wrap:wrap;
    font:11.5px var(--ff-mono);color:var(--fg-mute)}

  /* ----- tabela comparativa ----- */
  .vlsec-table-wrap{border:1px solid var(--border);border-radius:var(--r-2);overflow:hidden}
  .vlsec-table{width:100%;border-collapse:collapse;font-size:12px}
  .vlsec-table th{padding:7px 10px;text-align:left;font:600 9.5px var(--ff-mono);
    letter-spacing:.8px;text-transform:uppercase;color:var(--fg-mute);
    background:var(--bg-2);border-bottom:1px solid var(--border)}
  .vlsec-table td{padding:8px 10px;border-bottom:1px solid var(--border);color:var(--fg-dim)}
  .vlsec-table tr:last-child td{border-bottom:none}
  .vlsec-table tr.is-vencedor td{color:var(--fg);font-weight:600;background:var(--accent-soft)}
  .vlsec-table tr.is-falha td{opacity:.5}
  .vlsec-table-dot{display:inline-block;width:7px;height:7px;border-radius:50%;
    margin-right:7px;vertical-align:middle}

  /* ----- toggle switch ----- */
  .vlsec-switch{position:relative;width:32px;height:18px;flex-shrink:0}
  .vlsec-switch input{opacity:0;width:0;height:0}
  .vlsec-switch-track{position:absolute;inset:0;border-radius:var(--r-pill);
    background:var(--bg-3);border:1px solid var(--border);
    transition:background .2s,border-color .2s;cursor:pointer}
  .vlsec-switch input:checked + .vlsec-switch-track{background:var(--accent);
    border-color:var(--accent)}
  .vlsec-switch-track::after{content:'';position:absolute;top:2px;left:2px;
    width:12px;height:12px;border-radius:50%;background:#fff;
    transition:transform .2s;box-shadow:0 1px 3px rgba(0,0,0,.4)}
  .vlsec-switch input:checked + .vlsec-switch-track::after{transform:translateX(14px)}

  /* ----- painel resultado ----- */
  .vlsec-final{border:1px solid var(--border);border-radius:var(--r-3);
    padding:16px;display:flex;flex-direction:column;align-items:center;gap:5px;
    text-align:center;background:var(--bg-0);transition:border-color .3s}
  .vlsec-final-head{font:600 9px var(--ff-mono);letter-spacing:1.8px;
    text-transform:uppercase;color:var(--fg-mute)}
  .vlsec-final-main{display:flex;align-items:baseline;gap:5px}
  .vlsec-final-num{font:700 44px var(--ff-display);line-height:1;letter-spacing:-1px}
  .vlsec-final-unit{font-size:20px;color:var(--fg-mute)}
  .vlsec-final-sub{font-size:12px;color:var(--fg-mute)}
  .vlsec-final-sub b{color:var(--fg)}
  .vlsec-final-cap{font:600 11px var(--ff-mono);color:var(--ok);margin-top:2px;
    letter-spacing:.5px}

  .vlsec-warn{font-size:12px;color:var(--fg-mute);padding:12px;
    background:var(--bg-2);border:1px solid var(--border);border-radius:var(--r-2);
    text-align:center}
  .vlsec-svg-wrap{display:flex;justify-content:center;padding:8px 0}
  .vlsec-svg-empty{height:120px;display:flex;align-items:center;justify-content:center;
    color:var(--fg-mute);font-size:12px}
  .vlsec-legend{display:flex;flex-wrap:wrap;justify-content:center;
    gap:12px;font-size:11.5px;color:var(--fg-mute);margin:4px 0}
  .vlsec-legend i{width:12px;height:12px;border-radius:50%;display:inline-block;
    margin-right:5px;vertical-align:middle;border:1px solid rgba(0,0,0,0.2)}
  .vlsec-foot{margin-top:auto;padding:12px 14px;background:var(--bg-0);
    border:1px solid var(--border);border-radius:var(--r-2);
    font:12px var(--ff-mono);color:var(--fg-mute);line-height:1.7}
  .vlsec-foot b{color:var(--fg);font-family:var(--ff-display);font-size:11px;
    letter-spacing:1px;text-transform:uppercase;display:block;margin-bottom:4px}

  @media (max-width:1100px){
    .vlsec-body{grid-template-columns:1fr}
    .vlsec-right{grid-template-columns:1fr}
  }
  @media (max-width:760px){
    .vlsec-row2{grid-template-columns:1fr}
    .vlsec-svg-wrap{max-width:280px;margin:0 auto}
  }
  `;

  if (!document.getElementById('vl-secao-condutor-css')) {
    const s = document.createElement('style');
    s.id = 'vl-secao-condutor-css';
    s.textContent = CSS;
    document.head.appendChild(s);
  }

  /* ============================ Registro global ========================== */
  window.VL_SecaoCondutor = SecaoCondutor;
  if (window.VOLTLAB_MODULES && Array.isArray(window.VOLTLAB_MODULES)) {
    window.VOLTLAB_MODULES.push({
      id: 'secao_condutor',
      nome: 'Seção do Condutor',
      descricao: 'Dimensionamento por 5 critérios da NBR 5410 (ampacidade, queda, mínima, sobrecarga, curto)',
      component: SecaoCondutor,
    });
  }
})();
