<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8" />
  <title>Incerteza LAGAS (GUM e Monte Carlo) - Versão Final</title>

  <!-- Bibliotecas JS locais (todos no mesmo diretório) -->
  <script src="./math.min.js"></script>
  <script src="./xlsx.full.min.js"></script>
  <script src="./jstat.min.js"></script>
  <script src="./plotly-2.20.0.min.js"></script>
  <!-- html2pdf.bundle.min.js não é mais usado, mas pode ficar se quiser -->

  <style>
    body {
      font-family: "Segoe UI", Tahoma, sans-serif;
      margin: 20px;
      background: #fafafa;
    }

    header, .toolbar {
      display: flex;
      align-items: center;
      margin-bottom: 10px;
    }
    h1 {
      flex: 1;
      color: #444;
      margin: 0;
    }
    button.help-btn {
      background-color: #ffcc00;
      border: none;
      border-radius: 50%;
      font-size: 16px;
      width: 32px;
      height: 32px;
      cursor: pointer;
      margin-left: 10px;
    }
    label {
      font-weight: bold;
      color: #555;
      display: block;
      margin-top: 10px;
    }
    input[type="text"], input[type="file"] {
      width: 100%;
      box-sizing: border-box;
      margin: 4px 0 10px 0;
      padding: 6px;
    }
    table {
      border-collapse: collapse;
      margin-top: 10px;
      width: 100%;
      background: #fff;
    }
    th, td {
      border: 1px solid #ccc;
      padding: 8px;
      text-align: center;
      vertical-align: middle;
    }
    th {
      background-color: #e9e9ff;
      font-weight: 600;
      color: #333;
    }
    tr:nth-child(even) {
      background-color: #fcfcfc;
    }
    .section-title {
      margin-top: 20px;
      color: #333;
      border-bottom: 2px solid #ccc;
      padding-bottom: 4px;
      font-size: 1.2rem;
    }

    /* Área de resultados GUM e MC, cada um com layout side-by-side (texto + gráfico) */
    .results-area {
      display: none;         /* por padrão, escondido */
      margin-top: 20px;
      background-color: #f0f9ff;
      padding: 10px;
      border: 1px solid #cce6ff;
      border-radius: 4px;
      min-height: 400px;

      /* layout side by side */
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
    }
    .results-content {
      width: 48%;
    }
    .chart-container {
      width: 48%;
      min-width: 320px;
      height: 400px;
      border: 1px solid #ccc;
      margin-top: 10px;
      background: #fff;
    }

    hr {
      margin: 20px 0;
    }
    button {
      margin-right: 5px;
      padding: 6px 12px;
      border: none;
      cursor: pointer;
      border-radius: 4px;
      font-size: 14px;
    }
    button:hover {
      opacity: 0.9;
    }
    .primary-btn {
      background-color: #2864dc;
      color: #fff;
    }
    .secondary-btn {
      background-color: #aaa;
      color: #fff;
    }
    .accent-btn {
      background-color: #28c;
      color: #fff;
    }
    [contenteditable="true"] {
      outline: 1px dotted #999;
      min-width: 2em;
    }
    .bottom-space {
      margin-bottom: 15px;
    }

    /* Barra de progresso */
    #progressContainer {
      width: 100%;
      background: #ccc;
      height: 20px;
      margin: 10px 0;
      display: none; /* padrão: escondido */
      border-radius: 4px;
      overflow: hidden;
    }
    #progressBar {
      width: 0%;
      background: #28c;
      height: 100%;
      text-align: center;
      color: #fff;
      line-height: 20px;
      border-radius: 4px 0 0 4px;
    }
  </style>
</head>
<body>

  <header>
    <h1>Incerteza LAGAS (GUM e Monte Carlo)</h1>
    <button class="help-btn" onclick="exibirAjuda()">?</button>
  </header>

  <!-- Toolbar superior -->
  <div class="toolbar">
    <div style="flex:1;">
      <label for="arquivoExcel">Carregar arquivo Excel (.xlsx):</label>
      <input type="file" id="arquivoExcel" accept=".xlsx" />
    </div>
    <button class="accent-btn" onclick="carregarExcel()">Carregar</button>
    <!-- Botão para abrir documentacao.pdf localmente -->
    <button onclick="abrirDocumentacao()">Documentação</button>
  </div>

  <hr />

  <!-- Entradas -->
  <label>Modelo matemático (ex.: Y = sin(X1) + log(X2)):</label>
  <input type="text" id="modelo" placeholder="Y = sin(X1) + log(X2)" onblur="gerarTabelas()" />

  <label>Nível de confiança (ex.: 95):</label>
  <input type="text" id="confianca" value="95" />

  <label>Nº de Amostras (Monte Carlo):</label>
  <input type="text" id="numAmostrasMC" value="10000" />

  <!-- Tabelas -->
  <div id="tabelas-container" class="bottom-space"></div>

  <!-- Botões para calcular -->
  <div>
    <button class="primary-btn" onclick="calcularGUM()">Calcular GUM</button>
    <button class="secondary-btn" onclick="calcularMonteCarlo()">Calcular Monte Carlo</button>
    <button onclick="salvarExcel()">Salvar em Excel</button>
  </div>

  <!-- Barra de progresso (apenas Monte Carlo) -->
  <div id="progressContainer">
    <div id="progressBar">0%</div>
  </div>

  <!-- Resultados GUM (texto + gráfico), inicialmente escondido -->
  <div id="gumArea" class="results-area">
    <div class="results-content" id="gumText"></div>
    <div class="chart-container" id="gumGraph"></div>
  </div>

  <!-- Resultados Monte Carlo (texto + gráfico), inicialmente escondido -->
  <div id="mcArea" class="results-area">
    <div class="results-content" id="mcText"></div>
    <div class="chart-container" id="mcGraph"></div>
  </div>

  <script>
    // ============ Variáveis Globais ============
    let dadosVariaveisAntigos = {};
    let dadosCorrelacoesAntigas = {};
    let listaVariaveis = [];

    // ============ Funções Básicas ==============
    function exibirAjuda() {
      alert(
        "Cálculo de incertezas pelos métodos GUM e Monte Carlo\n\n" +
        "1) Digite o modelo (ex: Y = sin(X1) + log(X2)) e clique fora.\n" +
        "2) Edite valores, incertezas, correlações.\n" +
        "3) Ajuste nivel de confiança e nº de amostras.\n" +
        "4) Clique em Calcular GUM ou Calcular Monte Carlo.\n" +
        "5) Observe o resultado e o gráfico ao lado.\n"+
	"6) Para mais informações, consulte a documentação.\n\n"+
	"Contato: focosta@inmetro.gov.br"
      );
    }

    function abrirDocumentacao() {
      // Abre documentacao.pdf no mesmo diretório
      window.open("./documentacao.pdf", "_blank");
    }

    function armazenarDadosAtuais() {
      listaVariaveis.forEach(vi => {
        if (!dadosVariaveisAntigos[vi]) {
          dadosVariaveisAntigos[vi] = { valor: "1.0", U: "0.2", k: "2.0", v: "10" };
        }
        const tdV = document.getElementById(`valor_${vi}`);
        const tdU = document.getElementById(`U_${vi}`);
        const tdK = document.getElementById(`k_${vi}`);
        const tdDf= document.getElementById(`v_${vi}`);
        if (tdV && tdU && tdK && tdDf) {
          dadosVariaveisAntigos[vi].valor = tdV.textContent.trim();
          dadosVariaveisAntigos[vi].U     = tdU.textContent.trim();
          dadosVariaveisAntigos[vi].k     = tdK.textContent.trim();
          dadosVariaveisAntigos[vi].v     = tdDf.textContent.trim();
        }
      });

      listaVariaveis.forEach(vi => {
        if(!dadosCorrelacoesAntigas[vi]){
          dadosCorrelacoesAntigas[vi]={};
        }
        listaVariaveis.forEach(vj=>{
          const td= document.getElementById(`corr_${vi}_${vj}`);
          if(td){
            dadosCorrelacoesAntigas[vi][vj]= td.textContent.trim();
          }
        });
      });
    }

    function gerarTabelas(){
      armazenarDadosAtuais();
      const inputModelo= document.getElementById("modelo").value.trim();
      if(!inputModelo) return;

      const partes= inputModelo.split("=");
      if(partes.length<2) return;
      const expr= partes[1].trim();

      let raiz;
      try{
        raiz= math.parse(expr);
      }catch(e){
        alert("Expressão inválida: " + e);
        return;
      }

      const varsDetectadas=[];
      raiz.traverse((node, path, parent)=>{
        if(node.type==="SymbolNode"){
          const nome= node.name;
          const isFunc=(typeof math[nome]==='function');
          const isConst=(nome==='pi'||nome==='e'||nome==='Infinity');
          if(!isFunc && !isConst){
            varsDetectadas.push(nome);
          }
        }
      });
      listaVariaveis= [...new Set(varsDetectadas)];

      const divTabelas= document.getElementById("tabelas-container");
      divTabelas.innerHTML="";
      if(listaVariaveis.length===0){
        divTabelas.innerHTML="<p>Nenhuma variável identificada no modelo.</p>";
        return;
      }

      // Tabela de variáveis
      let htmlVars= `<h3 class="section-title">Tabela de Variáveis</h3>
      <table><thead><tr>
        <th>Variável</th>
        <th>Valor</th>
        <th>U</th>
        <th>k</th>
        <th>ν</th>
      </tr></thead><tbody>`;
      listaVariaveis.forEach(vi=>{
        let info= dadosVariaveisAntigos[vi]||{valor:"1.0",U:"0.2",k:"2.0",v:"10"};
        htmlVars+=`
          <tr>
            <td><strong>${vi}</strong></td>
            <td contenteditable="true" id="valor_${vi}">${info.valor}</td>
            <td contenteditable="true" id="U_${vi}">${info.U}</td>
            <td contenteditable="true" id="k_${vi}">${info.k}</td>
            <td contenteditable="true" id="v_${vi}">${info.v}</td>
          </tr>
        `;
      });
      htmlVars+="</tbody></table>";

      // Tabela de correlações
      let htmlCorr=`<h3 class="section-title">Tabela de Correlações</h3>
      <table><thead><tr><th></th>`;
      listaVariaveis.forEach(vv=>{ htmlCorr+=`<th>${vv}</th>`; });
      htmlCorr+=`</tr></thead><tbody>`;
      listaVariaveis.forEach((vi,i)=>{
        htmlCorr+=`<tr><th>${vi}</th>`;
        listaVariaveis.forEach((vj,j)=>{
          let val="0.0";
          if(dadosCorrelacoesAntigas[vi] && dadosCorrelacoesAntigas[vi][vj]!==undefined){
            val= dadosCorrelacoesAntigas[vi][vj];
          }else if(i===j){
            val="1.0";
          }
          htmlCorr+=`
            <td contenteditable="true" id="corr_${vi}_${vj}">
              ${val}
            </td>
          `;
        });
        htmlCorr+="</tr>";
      });
      htmlCorr+="</tbody></table>";

      divTabelas.innerHTML= htmlVars + htmlCorr;
    }

    // Funções auxiliares
    function lerDados(){
      const valores={}, incertPadrao={}, dof={}, correlation={};
      listaVariaveis.forEach(vi=>{
        const vStr= document.getElementById(`valor_${vi}`).textContent.trim();
        const uStr= document.getElementById(`U_${vi}`).textContent.trim();
        const kStr= document.getElementById(`k_${vi}`).textContent.trim();
        const dfStr=document.getElementById(`v_${vi}`).textContent.trim();
        const vNum= parseFloat(vStr)||0;
        const uNum= parseFloat(uStr)||0;
        const kNum= parseFloat(kStr)||1;
        const dfNum=parseFloat(dfStr)||1;
        valores[vi]= vNum;
        incertPadrao[vi]= uNum/kNum;
        dof[vi]= dfNum;
      });
      listaVariaveis.forEach(vi=>{
        correlation[vi]={};
        listaVariaveis.forEach(vj=>{
          let cStr= document.getElementById(`corr_${vi}_${vj}`).textContent.trim();
          correlation[vi][vj]= parseFloat(cStr)||0;
        });
      });
      return {valores, incertPadrao, dof, correlation};
    }

    function calcularFatorCobertura(conf, df){
      if(df<=0) return 1.0;
      const alpha= 1-(conf/100);
      const p=1-alpha/2;
      return jStat.studentt.inv(p, df);
    }

    function quantil(arr, p){
      if(!arr.length) return NaN;
      if(p<=0) return arr[0];
      if(p>=1) return arr[arr.length-1];
      const idx=(arr.length-1)*p;
      const floor= Math.floor(idx);
      const frac= idx-floor;
      if(floor+1< arr.length){
        return arr[floor]*(1-frac) + arr[floor+1]*frac;
      } else {
        return arr[floor];
      }
    }

    // ====== Calcular GUM ======
    function calcularGUM(){
      // Esconde MC
      document.getElementById("mcArea").style.display="none";
      // Monta GUM
      const gumArea= document.getElementById("gumArea");
      gumArea.style.display="flex"; // exibe
      const gumText= document.getElementById("gumText");
      const gumGraph= document.getElementById("gumGraph");

      // Limpa grafico e texto
      gumText.innerHTML="";
      Plotly.purge(gumGraph);

      const {valores, incertPadrao, dof, correlation}= lerDados();
      const modelo= document.getElementById("modelo").value.trim();
      const partes= modelo.split("=");
      if(partes.length<2){
        alert("Modelo inválido (GUM).");
        gumArea.style.display="none";
        return;
      }
      const expr= partes[1].trim();

      // avalia
      let valModelo=0;
      try{
        const f= math.parse(expr);
        valModelo= f.evaluate(valores);
      }catch(e){
        alert("Erro ao avaliar GUM: "+ e);
        gumArea.style.display="none";
        return;
      }

      // deriv
      let deriv={};
      try{
        listaVariaveis.forEach(vi=>{
          const df_dxi= math.derivative(expr, vi);
          deriv[vi]= df_dxi.evaluate(valores);
        });
      }catch(er){
        alert("Erro nas derivadas: "+er);
        gumArea.style.display="none";
        return;
      }

      // soma quadr c/ correlação => uc^2
      let uc2=0;
      listaVariaveis.forEach(vi=>{
        uc2+= (deriv[vi]*incertPadrao[vi])**2;
      });
      for(let i=0; i<listaVariaveis.length;i++){
        for(let j=i+1;j<listaVariaveis.length;j++){
          let vi= listaVariaveis[i];
          let vj= listaVariaveis[j];
          let r= correlation[vi][vj];
          uc2+= 2*(deriv[vi]*incertPadrao[vi])*(deriv[vj]*incertPadrao[vj])*r;
        }
      }
      const uc= Math.sqrt(uc2);

      // Welch-Satterthwaite sem corr no denominador
      let ucNoCorr2=0;
      listaVariaveis.forEach(vi=>{
        ucNoCorr2+= (deriv[vi]*incertPadrao[vi])**2;
      });
      const ucNoCorr= Math.sqrt(ucNoCorr2);

      let somaWS=0;
      listaVariaveis.forEach(vi=>{
        const val4= (deriv[vi]*incertPadrao[vi])**4;
        somaWS+= val4/dof[vi];
      });
      let veff= Infinity;
      if(somaWS>0){
        veff= (ucNoCorr**4)/somaWS;
      }

      const conf= parseFloat(document.getElementById("confianca").value)||95;
      const k= calcularFatorCobertura(conf, veff);
      const Uexp= k*uc;

      // Texto
      gumText.innerHTML= `
        <h2>GUM</h2>
        <p><strong>Modelo:</strong> ${modelo}</p>
        <p><strong>Nível de confiança:</strong> ${conf}%</p>
        <p><strong>Valor do modelo:</strong> ${valModelo.toFixed(6)}</p>
        <p><strong>u<sub>c</sub>:</strong> ${uc.toFixed(6)}</p>
        <p><strong>ν<sub>eff</sub>:</strong> ${veff.toFixed(2)}</p>
        <p><strong>k:</strong> ${k.toFixed(3)}</p>
        <p><strong>U expandida (k·u<sub>c</sub>):</strong> ${Uexp.toFixed(6)}</p>
      `;

      // Plot da PDF Normal
      let sigma= uc;
      let mean= valModelo;
      let minX= mean-4*sigma, maxX= mean+4*sigma;
      let step= (maxX-minX)/100;
      let xVals=[], yVals=[];
      for(let x=minX; x<=maxX; x+=step){
        let pdf= (1/(sigma*Math.sqrt(2*Math.PI)))*
                 Math.exp(-0.5*((x-mean)/sigma)**2);
        xVals.push(x);
        yVals.push(pdf);
      }
      // limites
      let lowConf= mean- Uexp;
      let highConf= mean+ Uexp;
      let tracePDF= {
        x: xVals,
        y: yVals,
        mode: 'lines',
        name: 'Distribuição Normal GUM',
        fill: 'tozeroy'
      };
      let shapes= [
        {
          type: 'line',
          x0: lowConf,
          x1: lowConf,
          y0: 0,
          y1: 1,
          line: { color:'red', dash:'dot', width:2 },
          yref: 'paper'
        },
        {
          type: 'line',
          x0: highConf,
          x1: highConf,
          y0: 0,
          y1: 1,
          line: { color:'red', dash:'dot', width:2 },
          yref: 'paper'
        }
      ];
      let layout= {
        title: "Curva Normal (GUM)",
        xaxis: { title: "Y" },
        yaxis: { title: "PDF" },
        shapes: shapes
      };
      Plotly.newPlot(gumGraph, [tracePDF], layout);
    }

    // ====== Calcular Monte Carlo com barra de progresso ======
    function calcularMonteCarlo(){
      // Esconde GUM
      document.getElementById("gumArea").style.display="none";
      // Mostra MC
      const mcArea= document.getElementById("mcArea");
      mcArea.style.display="flex";
      const mcText= document.getElementById("mcText");
      const mcGraph= document.getElementById("mcGraph");

      // Limpa
      mcText.innerHTML="";
      Plotly.purge(mcGraph);

      // Inicia barra de progresso
      const progCont= document.getElementById("progressContainer");
      const progBar= document.getElementById("progressBar");
      progCont.style.display="block"; // exibe a barra
      progBar.style.width= "0%";
      progBar.textContent= "0%";

      const {valores, incertPadrao, dof, correlation}= lerDados();
      const modelo= document.getElementById("modelo").value.trim();
      const partes= modelo.split("=");
      if(partes.length<2){
        alert("Modelo inválido (MC).");
        mcArea.style.display="none";
        progCont.style.display="none";
        return;
      }
      const expr= partes[1].trim();

      let f;
      try{
        f= math.parse(expr);
      }catch(e){
        alert("Erro parse MC: "+ e);
        mcArea.style.display="none";
        progCont.style.display="none";
        return;
      }

      const n= listaVariaveis.length;
      if(n===0){
        alert("Nenhuma variável p/ MC.");
        mcArea.style.display="none";
        progCont.style.display="none";
        return;
      }

      // mean e cov
      let meanVec= new Array(n);
      for(let i=0; i<n; i++){
        let vi= listaVariaveis[i];
        meanVec[i]= valores[vi];
      }
      let covMat= new Array(n).fill(null).map(()=> new Array(n).fill(0));
      for(let i=0;i<n;i++){
        let vi= listaVariaveis[i];
        for(let j=0;j<n;j++){
          let vj= listaVariaveis[j];
          let r= correlation[vi][vj];
          let ui= incertPadrao[vi];
          let uj= incertPadrao[vj];
          covMat[i][j]= r*ui*uj;
        }
      }

      let L;
      try{
        L= jStat.cholesky(covMat); // uso de cholesky
      }catch(er){
        alert("Erro cholesky: "+er);
        mcArea.style.display="none";
        progCont.style.display="none";
        return;
      }

      const N= parseInt(document.getElementById("numAmostrasMC").value)||10000;
      let ySamples= new Array(N);

      // Vamos fazer chunk approach p/ não travar UI e atualizar a barra
      let chunkSize= 500; // ajusta conforme necessário
      let currentIndex= 0;

      function processChunk(){
        let end= Math.min(currentIndex+chunkSize, N);
        for(let k=currentIndex; k< end; k++){
          // z normal(0,1)
          let z= new Array(n);
          for(let i=0;i<n;i++){ z[i]= jStat.randn(); }
          let xSim= new Array(n);
          for(let i=0;i<n;i++){
            let s=0;
            for(let j=0;j<n;j++){
              s+= L[i][j]*z[j];
            }
            xSim[i]= meanVec[i]+ s;
          }
          let valsObj={};
          for(let i=0;i<n;i++){
            valsObj[ listaVariaveis[i] ]= xSim[i];
          }
          let yVal=0;
          try{
            yVal= f.evaluate(valsObj);
          }catch(ei){ yVal= NaN; }
          ySamples[k]= yVal;
        }
        currentIndex= end;

        // atualiza barra
        let percent= ((currentIndex/N)*100).toFixed(1);
        progBar.style.width= percent+"%";
        progBar.textContent= percent+"%";

        if(currentIndex< N){
          // continua
          setTimeout(processChunk, 0);
        }else{
          // acabou
          progCont.style.display="none";
          finalizeMC();
        }
      }

      function finalizeMC(){
        ySamples.sort((a,b)=> a-b);
        const conf= parseFloat(document.getElementById("confianca").value)||95;
        const alpha= 1-(conf/100);
        const pLow= alpha/2, pHigh=1- alpha/2;
        let meanY= jStat.mean(ySamples);
        let yLow= quantil(ySamples, pLow);
        let yHigh= quantil(ySamples, pHigh);

        mcText.innerHTML= `
          <h2>Monte Carlo</h2>
          <p><strong>Modelo:</strong> ${modelo}</p>
          <p><strong>Nível de confiança:</strong> ${conf}%</p>
          <p><strong>Nº de amostras:</strong> ${N}</p>
          <p><strong>Média (amostral):</strong> ${meanY.toFixed(6)}</p>
          <p><strong>Intervalo [${(pLow*100).toFixed(1)}%, ${(pHigh*100).toFixed(1)}%]:</strong><br/>
          [${yLow.toFixed(6)}, ${yHigh.toFixed(6)}]</p>
        `;

        let traceHist= {
          x: ySamples,
          type: 'histogram',
          name: 'Hist Y'
        };
        let layoutMC= {
          title: `Histograma Monte Carlo (N=${N})`,
          xaxis: { title: "Y" },
          yaxis: { title: "Frequência" }
        };
        Plotly.newPlot("mcGraph", [traceHist], layoutMC);
      }

      // inicia a simulação em chunks
      currentIndex= 0;
      processChunk();
    }

    // ====== Salvar Excel ======
    function salvarExcel(){
      const inputModelo= document.getElementById("modelo").value.trim();
      const inputConf= document.getElementById("confianca").value.trim();

      const sheetMC=[];
      sheetMC.push(["Modelo e Nível de Confiança"]);
      sheetMC.push([]);
      sheetMC.push(["Modelo matemático:", inputModelo]);
      sheetMC.push(["Nível de confiança:", inputConf]);
      const wsMC= XLSX.utils.aoa_to_sheet(sheetMC);

      const sheetVars=[];
      sheetVars.push(["Variável","Valor","U","k","ν"]);
      listaVariaveis.forEach(vi=>{
        const tdV= document.getElementById(`valor_${vi}`);
        const tdU= document.getElementById(`U_${vi}`);
        const tdK= document.getElementById(`k_${vi}`);
        const tdDf=document.getElementById(`v_${vi}`);
        sheetVars.push([
          vi,
          tdV? tdV.textContent:"1.0",
          tdU? tdU.textContent:"0.2",
          tdK? tdK.textContent:"2.0",
          tdDf?tdDf.textContent:"10"
        ]);
      });
      const wsVars= XLSX.utils.aoa_to_sheet(sheetVars);

      const sheetCorr=[];
      const header=[""].concat(listaVariaveis);
      sheetCorr.push(header);
      listaVariaveis.forEach(vi=>{
        const row=[vi];
        listaVariaveis.forEach(vj=>{
          const td= document.getElementById(`corr_${vi}_${vj}`);
          row.push(td? td.textContent:"0.0");
        });
        sheetCorr.push(row);
      });
      const wsCorr= XLSX.utils.aoa_to_sheet(sheetCorr);

      const wb= XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, wsMC,"Modelo_e_Confianca");
      XLSX.utils.book_append_sheet(wb, wsVars,"Variaveis");
      XLSX.utils.book_append_sheet(wb, wsCorr,"Correlacoes");

      XLSX.writeFile(wb, "resultado_incertezas.xlsx");
    }

    // ====== Carregar Excel ======
    function carregarExcel(){
      const fileInput= document.getElementById("arquivoExcel");
      if(!fileInput.files.length){
        alert("Selecione um arquivo .xlsx");
        return;
      }
      const file= fileInput.files[0];
      const reader= new FileReader();
      reader.onload= function(e){
        const data= new Uint8Array(e.target.result);
        let wb;
        try{
          wb= XLSX.read(data,{type:"array"});
        }catch(er){
          alert("Erro lendo xlsx: "+er);
          return;
        }
        if(!wb.Sheets["Modelo_e_Confianca"]||
           !wb.Sheets["Variaveis"]||
           !wb.Sheets["Correlacoes"]){
          alert("Faltam abas: Modelo_e_Confianca, Variaveis, Correlacoes.");
          return;
        }
        // Planilha 1
        const wsMC= wb.Sheets["Modelo_e_Confianca"];
        const dataMC= XLSX.utils.sheet_to_json(wsMC,{header:1});
        let modeloLido="", confLida="";
        dataMC.forEach(row=>{
          if(!row|| row.length<2) return;
          if(row[0]==="Modelo matemático:") modeloLido=row[1];
          if(row[0]==="Nível de confiança:") confLida=row[1];
        });
        document.getElementById("modelo").value= modeloLido;
        document.getElementById("confianca").value= confLida;

        gerarTabelas();

        // Planilha 2
        const wsVars= wb.Sheets["Variaveis"];
        const dataVars= XLSX.utils.sheet_to_json(wsVars,{header:1});
        for(let i=1;i<dataVars.length;i++){
          const row= dataVars[i];
          if(!row||row.length<5) continue;
          let nomeVar= row[0];
          if(!listaVariaveis.includes(nomeVar)) continue;
          document.getElementById(`valor_${nomeVar}`).textContent= row[1];
          document.getElementById(`U_${nomeVar}`).textContent= row[2];
          document.getElementById(`k_${nomeVar}`).textContent= row[3];
          document.getElementById(`v_${nomeVar}`).textContent= row[4];
        }

        // Planilha 3
        const wsCorr= wb.Sheets["Correlacoes"];
        const dataCorr= XLSX.utils.sheet_to_json(wsCorr,{header:1});
        if(dataCorr.length>1){
          const header= dataCorr[0];
          const colVars= header.slice(1);
          for(let i=1;i<dataCorr.length;i++){
            const row= dataCorr[i];
            if(!row||row.length<2) continue;
            let vi= row[0];
            if(!listaVariaveis.includes(vi))continue;
            for(let j=1;j<row.length;j++){
              let vj= colVars[j-1];
              if(!listaVariaveis.includes(vj))continue;
              document.getElementById(`corr_${vi}_${vj}`).textContent= row[j];
            }
          }
        }
        alert("Arquivo carregado!");
      };
      reader.readAsArrayBuffer(file);
    }
  </script>
<footer style="margin-top: 20px; text-align: center; color: #777;">
  Incerteza LAGAS :: v. 1.0 :: Este programa pode gerar cálculos incorretos, confira sempre os resultados.
</footer>
</body>
</html>
