/* global React */
/* ===========================================================
   VOLTLAB · ATERRAMENTO v2.1 (bugfix)
   Resistência de Aterramento · Método das Resistências Mútuas
=========================================================== */
const { useState, useRef, useEffect, useCallback } = React;

// ─── Cálculo ─────────────────────────────────────────────────────────────────

function resistenciaPropria(rho, L, d) {
  return (rho / (2 * Math.PI * L)) * Math.log(4 * L / d);
}
function resistenciaMutua(rho, Lm, b) {
  if (b <= Lm) return 0;
  return 0.183 * (rho / Lm) * Math.log10((b + Lm) / (b - Lm));
}
function calcularSistema(hastes, rho) {
  const keys = Object.keys(hastes);
  const n = keys.length;
  if (n === 0) return null;
  const matriz = Array.from({ length: n }, () => Array(n).fill(0));
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      const hi = hastes[keys[i]], hj = hastes[keys[j]];
      if (i === j) {
        matriz[i][j] = resistenciaPropria(rho, hi.L, hi.D);
      } else {
        const e = Math.sqrt((hi.X - hj.X) ** 2 + (hi.Y - hj.Y) ** 2);
        const b = Math.sqrt(hj.L ** 2 + e ** 2);
        matriz[i][j] = resistenciaMutua(rho, hj.L, b);
      }
    }
  }
  const resPorHaste = matriz.map(row => row.reduce((a, v) => a + v, 0));
  const somaRecip = resPorHaste.reduce((a, v) => (v > 0 ? a + 1 / v : a), 0);
  const resTotal = somaRecip > 0 ? 1 / somaRecip : 0;
  return { matriz, resPorHaste, resTotal, keys };
}

// ─── CSV parser ───────────────────────────────────────────────────────────────

function parseCSV(text) {
  const lines = text.replace(/\r/g, '').split('\n').filter(Boolean);
  const header = lines[0].split(',').map(h => h.trim().replace(/^\uFEFF/, ''));
  const rows = lines.slice(1).map(line => {
    const vals = line.split(',');
    return Object.fromEntries(header.map((h, i) => [h, (vals[i] || '').trim()]));
  });
  const round = v => parseFloat(v.toFixed(4));
  const hastes = {}, linhas = {}, mapaXY = {};
  let cH = 1, cL = 1;
  for (const row of rows) {
    if (row['Name'] === 'Circle') {
      const nome = 'haste_' + cH++;
      const X = round(parseFloat(row['Center X']));
      const Y = round(parseFloat(row['Center Y']));
      hastes[nome] = { X, Y };
      mapaXY[X + ',' + Y] = nome;
    }
    if (row['Name'] === 'Line') {
      const nome = 'cabo_' + cL++;
      const sx = round(parseFloat(row['Start X'])), sy = round(parseFloat(row['Start Y']));
      const ex = round(parseFloat(row['End X'])),   ey = round(parseFloat(row['End Y']));
      linhas[nome] = { P_INICIAL: [sx, sy], P_FINAL: [ex, ey], COMPRIMENTO: parseFloat(row['Length']) };
    }
  }
  for (const cabo of Object.values(linhas)) {
    cabo.HASTE_DE   = mapaXY[cabo.P_INICIAL[0] + ',' + cabo.P_INICIAL[1]] || null;
    cabo.HASTE_PARA = mapaXY[cabo.P_FINAL[0]   + ',' + cabo.P_FINAL[1]]   || null;
  }
  return { hastes, linhas };
}

// ─── Classify (FORA do componente) ───────────────────────────────────────────

function classify(r) {
  if (r <= 1)  return { label: 'Excelente', pill: 'ok',   col: 'var(--ok)'     };
  if (r <= 5)  return { label: 'Bom',       pill: 'ok',   col: 'var(--ok)'     };
  if (r <= 10) return { label: 'Aceitável', pill: 'warn', col: 'var(--warn)'   };
  return             { label: 'Verificar',  pill: 'warn', col: 'var(--danger)' };
}

// ─── Canvas (FORA do componente) ─────────────────────────────────────────────

function GradeCanvas(props) {
  var hastes = props.hastes, linhas = props.linhas, resPorHaste = props.resPorHaste, keys = props.keys;
  var canvasRef = useRef(null);
  useEffect(function() {
    var canvas = canvasRef.current;
    if (!canvas) return;
    var ctx = canvas.getContext('2d');
    var W = canvas.width, H = canvas.height;
    ctx.clearRect(0, 0, W, H);
    var hasteList = Object.values(hastes);
    if (!hasteList.length) return;
    var xs = hasteList.map(function(h) { return h.X; });
    var ys = hasteList.map(function(h) { return h.Y; });
    var minX = Math.min.apply(null, xs), maxX = Math.max.apply(null, xs);
    var minY = Math.min.apply(null, ys), maxY = Math.max.apply(null, ys);
    var pad = 52, rangeX = maxX - minX || 1, rangeY = maxY - minY || 1;
    var scale = Math.min((W - pad * 2) / rangeX, (H - pad * 2) / rangeY);
    function toC(x, y) { return [pad + (x - minX) * scale, H - pad - (y - minY) * scale]; }

    // Grid
    ctx.strokeStyle = 'rgba(61,139,255,0.07)'; ctx.lineWidth = 1;
    for (var i = 0; i <= 10; i++) {
      var cx = pad + (i / 10) * (W - pad * 2);
      ctx.beginPath(); ctx.moveTo(cx, 0); ctx.lineTo(cx, H); ctx.stroke();
      var cy = pad + (i / 10) * (H - pad * 2);
      ctx.beginPath(); ctx.moveTo(0, cy); ctx.lineTo(W, cy); ctx.stroke();
    }
    // Cabos
    var linhaVals = Object.values(linhas);
    for (var li = 0; li < linhaVals.length; li++) {
      var cabo = linhaVals[li];
      var p1 = toC(cabo.P_INICIAL[0], cabo.P_INICIAL[1]);
      var p2 = toC(cabo.P_FINAL[0], cabo.P_FINAL[1]);
      ctx.beginPath(); ctx.moveTo(p1[0], p1[1]); ctx.lineTo(p2[0], p2[1]);
      ctx.strokeStyle = '#f59e0b'; ctx.lineWidth = 2;
      ctx.setLineDash([6, 3]); ctx.stroke(); ctx.setLineDash([]);
    }
    // Hastes
    var hasteKeys = Object.keys(hastes);
    var maxRes = resPorHaste ? Math.max.apply(null, resPorHaste) : 1;
    if (maxRes === 0) maxRes = 1;
    hasteKeys.forEach(function(nome, idx) {
      var h = hastes[nome];
      var pt = toC(h.X, h.Y);
      var ccx = pt[0], ccy = pt[1];
      var res = resPorHaste ? resPorHaste[idx] : null;
      if (res !== null && isFinite(res)) {
        var g = ctx.createRadialGradient(ccx, ccy, 4, ccx, ccy, 22);
        g.addColorStop(0, 'rgba(61,139,255,' + (0.3 * res / maxRes) + ')');
        g.addColorStop(1, 'rgba(61,139,255,0)');
        ctx.fillStyle = g; ctx.beginPath(); ctx.arc(ccx, ccy, 22, 0, Math.PI * 2); ctx.fill();
      }
      ctx.fillStyle = '#3d8bff'; ctx.strokeStyle = '#0a0e1a'; ctx.lineWidth = 1.5;
      ctx.beginPath(); ctx.arc(ccx, ccy, 7, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
      ctx.fillStyle = '#93c5fd'; ctx.font = '600 10px "JetBrains Mono",monospace';
      ctx.textAlign = 'center';
      ctx.fillText(nome.replace('haste_', '#'), ccx, ccy - 12);
      if (res !== null && isFinite(res)) {
        ctx.fillStyle = '#fbbf24'; ctx.font = '9px "JetBrains Mono",monospace';
        ctx.fillText(res.toFixed(1) + 'Ω', ccx, ccy + 20);
      }
    });
  });

  return React.createElement('canvas', {
    ref: canvasRef,
    width: 580,
    height: 360,
    style: { width: '100%', borderRadius: 8, background: 'var(--bg-0)', border: '1px solid var(--border)', display: 'block' }
  });
}

// ─── Helpers UI (FORA do componente) ─────────────────────────────────────────

function AtField(props) {
  return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 6 } },
    React.createElement('label', { style: { fontFamily: 'var(--ff-mono)', fontSize: 10, letterSpacing: '0.12em', color: 'var(--fg-mute)', textTransform: 'uppercase' } }, props.label),
    props.children
  );
}

function AtInput(props) {
  var inputStyle = { width: '100%', padding: '8px 12px', background: 'var(--bg-0)', border: '1px solid var(--border)', borderRadius: 6, color: 'var(--fg)', fontFamily: 'var(--ff-mono)', fontSize: 13, outline: 'none' };
  return React.createElement('input', Object.assign({}, props, {
    style: inputStyle,
    onFocus: function(e) { e.target.style.borderColor = 'var(--accent)'; },
    onBlur:  function(e) { e.target.style.borderColor = 'var(--border)'; },
  }));
}

// ModeBtn FORA do componente — recebe modoManual e setModoManual como props
function ModeBtn(props) {
  var active = (props.mode === 'manual') === props.modoManual;
  return React.createElement('button', {
    onClick: function() { props.setModoManual(props.mode === 'manual'); },
    style: {
      padding: '6px 14px', borderRadius: 6, fontFamily: 'var(--ff-mono)', fontSize: 11,
      letterSpacing: '0.06em', cursor: 'pointer', transition: 'all .15s',
      border: active ? '1px solid rgba(61,139,255,0.3)' : '1px solid transparent',
      background: active ? 'var(--accent-soft)' : 'transparent',
      color: active ? 'var(--accent)' : 'var(--fg-mute)',
    }
  }, props.children);
}

// ─── Componente principal ─────────────────────────────────────────────────────

function ModuloAterramento() {
  var rhoState       = useState(100);
  var rho = rhoState[0], setRho = rhoState[1];
  var LState         = useState(2.4);
  var L = LState[0], setL = LState[1];
  var DState         = useState(0.016);
  var D = DState[0], setD = DState[1];
  var csvState       = useState(null);
  var csvData = csvState[0], setCsvData = csvState[1];
  var resultState    = useState(null);
  var resultado = resultState[0], setResultado = resultState[1];
  var erroState      = useState('');
  var erro = erroState[0], setErro = erroState[1];
  var arqState       = useState('');
  var nomeArq = arqState[0], setNomeArq = arqState[1];
  var modoState      = useState(false);
  var modoManual = modoState[0], setModoManual = modoState[1];
  var hastesState    = useState([
    { X: 0, Y: 0 }, { X: 2, Y: 0 }, { X: 0, Y: 2 }, { X: 2, Y: 2 }
  ]);
  var hastesManual = hastesState[0], setHastesManual = hastesState[1];
  var fileRef = useRef(null);

  var onCSV = useCallback(function(e) {
    var file = e.target.files[0]; if (!file) return;
    setNomeArq(file.name);
    var reader = new FileReader();
    reader.onload = function(ev) {
      try {
        var p = parseCSV(ev.target.result);
        if (!Object.keys(p.hastes).length) { setErro('Nenhuma haste (Circle) no CSV.'); setCsvData(null); }
        else { setErro(''); setCsvData(p); }
      } catch (ex) { setErro('Erro CSV: ' + ex.message); setCsvData(null); }
    };
    reader.readAsText(file, 'utf-8');
  }, []);

  var calcular = useCallback(function() {
    setErro('');
    try {
      var hastes = {}, linhas = {};
      if (modoManual) {
        hastesManual.forEach(function(h, i) {
          hastes['haste_' + (i + 1)] = { X: +h.X || 0, Y: +h.Y || 0, L: +L || 2.4, D: +D || 0.016 };
        });
      } else {
        if (!csvData) { setErro('Importe um CSV primeiro.'); return; }
        Object.entries(csvData.hastes).forEach(function(entry) {
          hastes[entry[0]] = Object.assign({}, entry[1], { L: +L || 2.4, D: +D || 0.016 });
        });
        linhas = csvData.linhas;
      }
      if (Object.keys(hastes).length < 2) { setErro('Mínimo 2 hastes para o cálculo.'); return; }
      var res = calcularSistema(hastes, +rho || 100);
      if (!res) { setErro('Erro interno no cálculo.'); return; }
      setResultado(Object.assign({}, res, { hastes: hastes, linhas: linhas }));
    } catch (err) {
      setErro('Erro no cálculo: ' + err.message);
    }
  }, [modoManual, csvData, hastesManual, rho, L, D]);

  var addHaste    = function() { setHastesManual(function(h) { return h.concat([{ X: 0, Y: 0 }]); }); };
  var removeHaste = function(i) { setHastesManual(function(h) { return h.filter(function(_, idx) { return idx !== i; }); }); };
  var updateHaste = function(i, f, v) {
    setHastesManual(function(h) { return h.map(function(it, idx) { return idx === i ? Object.assign({}, it, { [f]: v }) : it; }); });
  };

  var cls = resultado ? classify(resultado.resTotal) : null;

  // ── Seção de resultado (segura) ──────────────────────────────────────────

  var resultSection = null;
  if (resultado && cls) {
    var n = resultado.keys ? resultado.keys.length : 0;
    resultSection = (
      <React.Fragment>
        <div className="vl-result-big" style={{ borderColor: cls.col }}>
          <div className="vl-result-corner vl-result-corner-tl" style={{ borderColor: cls.col }}/>
          <div className="vl-result-corner vl-result-corner-tr" style={{ borderColor: cls.col }}/>
          <div className="vl-result-corner vl-result-corner-bl" style={{ borderColor: cls.col }}/>
          <div className="vl-result-corner vl-result-corner-br" style={{ borderColor: cls.col }}/>
          <div className="vl-result-label" style={{ color: cls.col }}>RESISTÊNCIA TOTAL DO SISTEMA</div>
          <div className="vl-result-row">
            <span className="vl-result-val">{isFinite(resultado.resTotal) ? resultado.resTotal.toFixed(3) : '—'}</span>
            <em style={{ color: cls.col }}>Ω</em>
          </div>
        </div>

        <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 18 }}>
          <span className={'pill pill-' + cls.pill}>{cls.label}</span>
        </div>

        <div className="vl-mini-grid" style={{ gridTemplateColumns: 'repeat(3,1fr)', marginBottom: 18 }}>
          <div className="vl-metric">
            <span className="vl-metric-label">Hastes</span>
            <div className="vl-metric-value"><span className="readout">{n}</span></div>
          </div>
          <div className="vl-metric">
            <span className="vl-metric-label">ρ Solo</span>
            <div className="vl-metric-value"><span className="readout">{rho}</span><em>Ω·m</em></div>
          </div>
          <div className="vl-metric">
            <span className="vl-metric-label">L haste</span>
            <div className="vl-metric-value"><span className="readout">{L}</span><em>m</em></div>
          </div>
        </div>

        <div style={{ background: 'var(--bg-0)', borderRadius: 8, padding: '12px 14px', border: '1px solid var(--border)', fontSize: 11, color: 'var(--fg-mute)', lineHeight: 1.7 }}>
          <b style={{ color: 'var(--fg-dim)', display: 'block', marginBottom: 4, fontFamily: 'var(--ff-mono)', fontSize: 10, letterSpacing: '0.1em', textTransform: 'uppercase' }}>NBR 5419-3 — Referência</b>
          R ≤ 1 Ω — SPDA / Proteção contra descargas<br/>
          R ≤ 10 Ω — Sistemas de distribuição BT<br/>
          R ≤ 100 Ω — Edificações residenciais
        </div>
      </React.Fragment>
    );
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--gap-grid,20px)' }}>

      {/* ── Parâmetros ──────────────────────────────────────── */}
      <div className="panel">
        <div className="panel-head">
          <div>
            <div className="panel-eyebrow">CONFIGURAÇÃO · MÉTODO DAS RESISTÊNCIAS MÚTUAS</div>
            <h3>Parâmetros das Hastes</h3>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 16 }}>
          <AtField label="Resistividade do Solo ρ (Ω·m)">
            <AtInput type="number" value={rho} min={1} onChange={function(e) { setRho(e.target.value); }}/>
          </AtField>
          <AtField label="Comprimento L (m)">
            <AtInput type="number" value={L} step={0.1} min={0.1} onChange={function(e) { setL(e.target.value); }}/>
          </AtField>
          <AtField label="Diâmetro D (m)">
            <AtInput type="number" value={D} step={0.001} min={0.001} onChange={function(e) { setD(e.target.value); }}/>
          </AtField>
        </div>
      </div>

      {/* ── Grid entrada + resultado ────────────────────────── */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 380px', gap: 'var(--gap-grid,20px)', alignItems: 'start' }}>

        {/* Entrada */}
        <div className="panel">
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">ENTRADA DE DADOS</div>
              <h3>Posicionamento das Hastes</h3>
            </div>
            <div style={{ display: 'flex', gap: 6, background: 'var(--bg-0)', padding: 4, borderRadius: 8, border: '1px solid var(--border)' }}>
              <ModeBtn mode="csv" modoManual={modoManual} setModoManual={setModoManual}>📂 CSV AutoCAD</ModeBtn>
              <ModeBtn mode="manual" modoManual={modoManual} setModoManual={setModoManual}>✏️ Manual</ModeBtn>
            </div>
          </div>

          {!modoManual && (
            <div style={{ background: 'var(--bg-0)', border: '1px solid var(--border)', borderRadius: 8, padding: '18px 20px', marginBottom: 16 }}>
              <div className="panel-eyebrow" style={{ marginBottom: 12 }}>ARQUIVO CSV — AUTOCAD DATA EXTRACTION</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
                <button className="btn" onClick={function() { if (fileRef.current) fileRef.current.click(); }}>📂 Selecionar CSV</button>
                <input ref={fileRef} type="file" accept=".csv" onChange={onCSV} style={{ display: 'none' }}/>
                {nomeArq && <span className="mono dim" style={{ fontSize: 12 }}>{nomeArq}</span>}
                {csvData  && (
                  <span style={{ fontSize: 12, color: 'var(--ok)' }}>
                    ✓ {Object.keys(csvData.hastes).length} hastes · {Object.keys(csvData.linhas).length} cabos
                  </span>
                )}
              </div>
              <p style={{ fontSize: 11, color: 'var(--fg-mute)', marginTop: 10, marginBottom: 0, lineHeight: 1.6 }}>
                AutoCAD: <em>Express Tools → Data Extraction</em> · selecionar Circle e Line, campos Center X/Y e Start/End X/Y.
              </p>
            </div>
          )}

          {modoManual && (
            <div style={{ marginBottom: 16 }}>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr auto', gap: 8, alignItems: 'center', marginBottom: 10 }}>
                <span style={{ fontFamily: 'var(--ff-mono)', fontSize: 10, letterSpacing: '0.1em', color: 'var(--fg-mute)', textTransform: 'uppercase' }}>X (m)</span>
                <span style={{ fontFamily: 'var(--ff-mono)', fontSize: 10, letterSpacing: '0.1em', color: 'var(--fg-mute)', textTransform: 'uppercase' }}>Y (m)</span>
                <span style={{ width: 32 }}/>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8, maxHeight: 260, overflowY: 'auto' }}>
                {hastesManual.map(function(h, i) {
                  return (
                    <div key={i} style={{ display: 'grid', gridTemplateColumns: '1fr 1fr auto', gap: 8, alignItems: 'center' }}>
                      <AtInput type="number" value={h.X} step={0.5} onChange={function(e) { updateHaste(i, 'X', e.target.value); }}/>
                      <AtInput type="number" value={h.Y} step={0.5} onChange={function(e) { updateHaste(i, 'Y', e.target.value); }}/>
                      <button onClick={function() { removeHaste(i); }}
                        style={{ width: 32, height: 36, display: 'grid', placeItems: 'center', borderRadius: 6, border: '1px solid rgba(220,38,38,0.3)', color: 'var(--danger)', background: 'transparent', cursor: 'pointer' }}>✕</button>
                    </div>
                  );
                })}
              </div>
              <button className="btn" style={{ marginTop: 10 }} onClick={addHaste}>+ Adicionar haste</button>
            </div>
          )}

          {erro && (
            <div className="vl-banner vl-banner-danger" style={{ marginBottom: 14 }}>⚠ {erro}</div>
          )}

          <button className="btn btn-primary btn-block" onClick={calcular}>
            Calcular Sistema ⏚
          </button>
        </div>

        {/* Resultado */}
        <div className="panel" style={{ position: 'sticky', top: 0 }}>
          <div className="panel-head">
            <div>
              <div className="panel-eyebrow">RESULTADO DO SISTEMA</div>
              <h3>Resistência total</h3>
            </div>
          </div>
          {resultSection || (
            <div style={{ padding: '48px 20px', textAlign: 'center' }}>
              <div style={{ fontSize: 36, marginBottom: 12, opacity: 0.4 }}>⏚</div>
              <h4 style={{ fontFamily: 'var(--ff-display)', fontSize: 15, margin: '0 0 6px', color: 'var(--fg)' }}>Aguardando cálculo</h4>
              <p style={{ fontSize: 12, color: 'var(--fg-mute)', margin: 0 }}>Configure os parâmetros e clique em <b>Calcular Sistema</b>.</p>
            </div>
          )}
        </div>
      </div>

      {/* ── Canvas topologia ─────────────────────────────────── */}
      {resultado && (
        <div className="panel">
          <div className="panel-head">
            <div><div className="panel-eyebrow">VISUALIZAÇÃO · TOPOLOGIA</div><h3>Disposição das hastes e cabos</h3></div>
            <div style={{ display: 'flex', gap: 16, fontFamily: 'var(--ff-mono)', fontSize: 10, color: 'var(--fg-mute)', alignItems: 'center' }}>
              <span>⬤ <span style={{ color: 'var(--accent)' }}>Hastes</span></span>
              <span>— <span style={{ color: 'var(--warn)' }}>Cabos</span></span>
            </div>
          </div>
          <GradeCanvas
            hastes={resultado.hastes}
            linhas={resultado.linhas}
            resPorHaste={resultado.resPorHaste}
            keys={resultado.keys}
          />
        </div>
      )}

      {/* ── Tabela por haste ─────────────────────────────────── */}
      {resultado && resultado.keys && resultado.keys.length > 0 && (
        <div className="panel">
          <div className="panel-head"><div><div className="panel-eyebrow">ANÁLISE DETALHADA</div><h3>Resistências por haste</h3></div></div>
          <div style={{ overflowX: 'auto', border: '1px solid var(--border)', borderRadius: 8 }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
              <thead>
                <tr style={{ background: 'var(--bg-0)' }}>
                  {['HASTE','X (m)','Y (m)','R PRÓPRIA (Ω)','SOMA MÚTUA (Ω)','Σ (Ω)'].map(function(h) {
                    return (
                      <th key={h} style={{ padding: '9px 14px', textAlign: 'left', fontFamily: 'var(--ff-mono)', fontSize: 10, letterSpacing: '0.1em', color: 'var(--fg-mute)', textTransform: 'uppercase', borderBottom: '1px solid var(--border)' }}>{h}</th>
                    );
                  })}
                </tr>
              </thead>
              <tbody>
                {resultado.keys.map(function(k, i) {
                  var h = resultado.hastes ? resultado.hastes[k] : null;
                  if (!h) return null;
                  var rP  = resultado.matriz && resultado.matriz[i] ? resultado.matriz[i][i] : 0;
                  var tot = resultado.resPorHaste ? resultado.resPorHaste[i] : 0;
                  var isMax = tot === Math.max.apply(null, resultado.resPorHaste);
                  return (
                    <tr key={k} style={{ background: isMax ? 'var(--accent-soft)' : undefined, borderBottom: '1px solid var(--border)' }}>
                      <td className="mono" style={{ padding: '8px 14px', color: 'var(--accent)', fontWeight: 600 }}>{k}</td>
                      <td className="mono" style={{ padding: '8px 14px', color: 'var(--fg-dim)' }}>{(h.X || 0).toFixed(4)}</td>
                      <td className="mono" style={{ padding: '8px 14px', color: 'var(--fg-dim)' }}>{(h.Y || 0).toFixed(4)}</td>
                      <td className="mono" style={{ padding: '8px 14px' }}>{isFinite(rP) ? rP.toFixed(4) : '—'}</td>
                      <td className="mono" style={{ padding: '8px 14px' }}>{isFinite(tot - rP) ? (tot - rP).toFixed(4) : '—'}</td>
                      <td className="mono" style={{ padding: '8px 14px', color: 'var(--warn)', fontWeight: 600 }}>{isFinite(tot) ? tot.toFixed(4) : '—'}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* ── Matriz ───────────────────────────────────────────── */}
      {resultado && resultado.matriz && resultado.keys && (
        <div className="panel">
          <div className="panel-head"><div><div className="panel-eyebrow">MATRIZ DE ACOPLAMENTO</div><h3>Resistências mútuas (Ω)</h3></div></div>
          <div style={{ overflowX: 'auto', border: '1px solid var(--border)', borderRadius: 8 }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
              <thead>
                <tr style={{ background: 'var(--bg-0)' }}>
                  <th style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', width: 60 }}/>
                  {resultado.keys.map(function(k) {
                    return (
                      <th key={k} style={{ padding: '8px 12px', fontFamily: 'var(--ff-mono)', fontSize: 10, color: 'var(--fg-mute)', letterSpacing: '0.1em', textTransform: 'uppercase', borderBottom: '1px solid var(--border)' }}>
                        {k.replace('haste_', '#')}
                      </th>
                    );
                  })}
                </tr>
              </thead>
              <tbody>
                {resultado.matriz.map(function(row, i) {
                  return (
                    <tr key={i} style={{ borderBottom: '1px solid var(--border)' }}>
                      <td className="mono" style={{ padding: '7px 12px', fontSize: 10, letterSpacing: '0.1em', color: 'var(--fg-mute)', background: 'var(--bg-0)', textTransform: 'uppercase' }}>
                        {resultado.keys[i] ? resultado.keys[i].replace('haste_', '#') : i}
                      </td>
                      {row.map(function(val, j) {
                        return (
                          <td key={j} className="mono" style={{ padding: '7px 12px', color: i === j ? 'var(--accent)' : 'var(--fg-dim)', background: i === j ? 'var(--accent-soft)' : undefined, fontWeight: i === j ? 600 : 400 }}>
                            {isFinite(val) ? val.toFixed(3) : '—'}
                          </td>
                        );
                      })}
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
}

window.ModuloAterramento = ModuloAterramento;
