<?php
require_once(dirname(__DIR__) . '/config/db.php');
$cdempresaLogada = (int)($_SESSION['cdempresa'] ?? 1);
$empresasInd = $pdo->query("SELECT cdempresa, dsempresa, dsapelido FROM back.empresa WHERE flativo = 0 ORDER BY dsempresa")->fetchAll(PDO::FETCH_ASSOC);
$exerciciosDisp = $pdo->prepare("SELECT DISTINCT anoref FROM back.exercicio WHERE flativo = 0 AND cdempresa = :emp ORDER BY anoref DESC");
$exerciciosDisp->execute([':emp' => $cdempresaLogada]);
$exerciciosDisp = $exerciciosDisp->fetchAll(PDO::FETCH_COLUMN);
$nomeEmpLogada = '';
foreach ($empresasInd as $e) {
    if ((int)$e['cdempresa'] === $cdempresaLogada) { $nomeEmpLogada = $e['dsapelido'] ?: $e['dsempresa']; break; }
}
// Moeda da empresa logada
$stMoeda = $pdo->prepare("SELECT m.simbolo, m.formato FROM back.empresa e LEFT JOIN back.moeda m ON m.cdmoeda = e.cdmoeda WHERE e.cdempresa = :emp");
$stMoeda->execute([':emp' => $cdempresaLogada]);
$moedaEmp = $stMoeda->fetch(PDO::FETCH_ASSOC) ?: ['simbolo' => 'R$', 'formato' => 'decimal'];
?>
<h4 class="mb-3"><i class="bi bi-clipboard-data"></i> Indicadores</h4>
<hr>

<!-- ============================================== -->
<!-- LISTA DE INDICADORES                           -->
<!-- ============================================== -->
<div id="secaoLista">
  <div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
    <div class="input-group input-group-sm" style="max-width:320px;">
      <span class="input-group-text"><i class="bi bi-search"></i></span>
      <input type="text" class="form-control" id="pesquisaInd" placeholder="Pesquisar indicador...">
    </div>
    <button class="btn btn-outline-light btn-sm border-secondary text-dark bg-light" onclick="novoIndicador()">
      <i class="bi bi-plus-circle"></i> Novo Indicador
    </button>
  </div>

  <div class="table-responsive">
    <table class="table table-striped table-hover table-sm align-middle">
      <thead class="table-dark">
        <tr>
          <th>#</th>
          <th>Nome</th>
          <th>Grupo</th>
          <th>Tipo</th>
          <th>Máscara</th>
          <th>Status</th>
          <th class="text-center">Ações</th>
        </tr>
      </thead>
      <tbody id="tbodyIndicadores">
        <tr><td colspan="7" class="text-center text-muted">Carregando...</td></tr>
      </tbody>
    </table>
  </div>
</div>

<!-- ============================================== -->
<!-- MODAL: FORMULÁRIO DE CADASTRO / EDIÇÃO         -->
<!-- ============================================== -->
<div class="modal fade" id="modalFormIndicador" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
  <div class="modal-dialog modal-fullscreen modal-dialog-scrollable">
    <div class="modal-content">
      <div class="modal-header bg-primary text-white py-2">
        <strong class="modal-title" id="formTitulo"><i class="bi bi-plus-circle"></i> Novo Indicador</strong>
        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
      <input type="hidden" id="indCdindicador" value="">

      <!-- Linha 1: Nome, Máscara, Tipo, Descrição -->
      <input type="hidden" id="indOrdem" value="">
      <!-- Linha 0: Grupo -->
      <div class="row g-2 mb-2">
        <div class="col-md-3">
          <label class="form-label mb-1 small fw-semibold">Grupo</label>
          <div class="input-group input-group-sm">
            <select id="indGrupo" class="form-select form-select-sm">
              <option value="">(Sem grupo)</option>
            </select>
            <button class="btn btn-outline-success" type="button" onclick="adicionarGrupoInline()" title="Novo grupo"><i class="bi bi-plus"></i></button>
          </div>
        </div>
      </div>
      <!-- Linha 1: Nome, Máscara, Tipo, Máscara Calc, Descrição -->
      <div class="row g-2 mb-2">
        <div class="col-md-4">
          <label class="form-label mb-1 small fw-semibold">Nome *</label>
          <input type="text" id="indNome" class="form-control form-control-sm" maxlength="200">
        </div>
        <div class="col-md-2">
          <label class="form-label mb-1 small fw-semibold">Máscara *</label>
          <select id="indMascara" class="form-select form-select-sm">
            <option value="inteiro">Inteiro</option>
            <option value="moeda">Moeda</option>
            <option value="percentual">Percentual (%)</option>
          </select>
        </div>
        <div class="col-md-2">
          <label class="form-label mb-1 small fw-semibold">Tipo *</label>
          <select id="indTipo" class="form-select form-select-sm">
            <option value="estatico">Estático</option>
            <option value="calculado">Calculado</option>
          </select>
        </div>
        <div class="col-md-2" id="divMascaraCalc" style="display:none;">
          <label class="form-label mb-1 small fw-semibold">Máscara Calculado</label>
          <select id="indMascaraCalc" class="form-select form-select-sm">
            <option value="inteiro">Inteiro</option>
            <option value="moeda">Moeda</option>
            <option value="percentual">Percentual (%)</option>
          </select>
        </div>
        <div class="col" id="divDescricao">
          <label class="form-label mb-1 small fw-semibold">Descrição</label>
          <input type="text" id="indDescricao" class="form-control form-control-sm" maxlength="500" placeholder="Opcional">
        </div>
      </div>

      <!-- Empresas vinculadas -->
      <div class="mb-2">
        <div class="d-flex justify-content-between align-items-center mb-1">
          <label class="fw-semibold mb-0" style="font-size:0.9rem;">Empresas vinculadas</label>
          <div class="d-flex gap-1">
            <button type="button" class="btn btn-outline-secondary btn-sm py-0 px-2" style="font-size:0.78rem;" onclick="$('.chk-empresa-ind').prop('checked',true)">Todas</button>
            <button type="button" class="btn btn-outline-secondary btn-sm py-0 px-2" style="font-size:0.78rem;" onclick="$('.chk-empresa-ind').prop('checked',false)">Limpar</button>
          </div>
        </div>
        <div id="listaEmpresasInd" style="max-height:100px; overflow-y:auto; border:1px solid #dee2e6; border-radius:6px; padding:6px; column-count:3; column-gap:12px;">
          <?php foreach ($empresasInd as $emp): ?>
          <div class="form-check" style="break-inside:avoid;">
            <input class="form-check-input chk-empresa-ind" type="checkbox" value="<?= (int)$emp['cdempresa'] ?>" id="empInd_<?= (int)$emp['cdempresa'] ?>">
            <label class="form-check-label" for="empInd_<?= (int)$emp['cdempresa'] ?>" style="font-size:0.8rem;">
              <?= htmlspecialchars($emp['dsapelido'] ?: $emp['dsempresa']) ?>
            </label>
          </div>
          <?php endforeach; ?>
        </div>
      </div>

      <hr class="my-2">

      <!-- ====== GRID DE VALORES (empresa logada) ====== -->
      <div>
        <div class="d-flex gap-2 align-items-center mb-2 flex-wrap">
          <span class="badge bg-secondary"><i class="bi bi-building"></i> <?= htmlspecialchars($nomeEmpLogada) ?></span>

          <div class="d-flex align-items-center gap-2 ms-3">
            <label class="small fw-semibold mb-0">Adicionar Exercício:</label>
            <select id="gridExercicioNovo" class="form-select form-select-sm" style="width:90px;">
              <?php foreach ($exerciciosDisp as $ano): ?>
              <option value="<?= (int)$ano ?>"><?= (int)$ano ?></option>
              <?php endforeach; ?>
            </select>
            <button class="btn btn-outline-success btn-sm" onclick="adicionarExercicio()">
              <i class="bi bi-plus"></i> Adicionar
            </button>
          </div>
        </div>

        <div class="table-responsive">
          <table class="table table-bordered table-sm align-middle mb-0" id="tabelaGrid">
            <thead>
              <tr style="background:#2c3e50; color:#fff;">
                <th style="min-width:60px;">Ano</th>
                <th>Jan</th><th>Fev</th><th>Mar</th><th>Abr</th><th>Mai</th><th>Jun</th>
                <th>Jul</th><th>Ago</th><th>Set</th><th>Out</th><th>Nov</th><th>Dez</th>
                <th>Total</th>
                <th id="thConfig" style="width:80px;display:none;" title="Configuração">⚙️ Config</th>
                <th id="thAcoes" style="width:70px;display:none;"></th>
                <th style="width:40px;"></th>
              </tr>
            </thead>
            <tbody id="tbodyGrid">
              <tr><td colspan="20" class="text-center text-muted small">Nenhum exercício adicionado.</td></tr>
            </tbody>
          </table>
        </div>
      </div>

      </div>
      <div class="modal-footer py-2">
        <button class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">
          <i class="bi bi-x-circle"></i> Cancelar
        </button>
        <button class="btn btn-success btn-sm" onclick="salvarIndicador()">
          <i class="bi bi-save"></i> Salvar Indicador
        </button>
      </div>
    </div>
  </div>
</div>

<!-- ============================================== -->
<!-- MODAL: Configurar Linha (operador + contas)    -->
<!-- ============================================== -->
<div class="modal fade" id="modalConfigLinha" tabindex="-1">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header bg-info text-dark py-2">
        <strong class="modal-title"><i class="bi bi-gear"></i> Configurar Linha — <span id="cfgLinhaAno"></span></strong>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <input type="hidden" id="cfgCdindvalor" value="">

        <!-- Operador -->
        <div class="mb-3">
          <label class="form-label fw-semibold small">Operador entre valor digitado</label>
          <div class="btn-group btn-group-sm" id="cfgGrupoOperador">
            <button type="button" class="btn btn-outline-dark active" data-op="+" onclick="cfgSelecionarOp(this)">+ Soma</button>
            <button type="button" class="btn btn-outline-dark" data-op="-" onclick="cfgSelecionarOp(this)">− Subtração</button>
            <button type="button" class="btn btn-outline-dark" data-op="*" onclick="cfgSelecionarOp(this)">× Multiplicação</button>
            <button type="button" class="btn btn-outline-dark" data-op="/" onclick="cfgSelecionarOp(this)">÷ Divisão</button>
          </div>
        </div>

        <!-- Contas -->
        <div>
          <label class="form-label fw-semibold small">Contas Contábeis</label>
          <div class="d-flex align-items-center gap-2 mb-1">
            <div class="input-group input-group-sm">
              <span class="input-group-text"><i class="bi bi-search"></i></span>
              <input type="text" class="form-control" id="cfgBuscaConta" placeholder="Pesquisar conta...">
              <button class="btn btn-outline-secondary" type="button" id="btnLimparCfgBusca">&times;</button>
            </div>
            <small class="text-muted" id="cfgBuscaInfo" style="white-space:nowrap;"></small>
          </div>
          <div id="cfgContasBadges" class="mb-1" style="min-height:22px;"></div>
          <div id="cfgArvoreContas" class="border rounded p-2 overflow-auto" style="height:250px;"></div>
        </div>
      </div>
      <div class="modal-footer py-1">
        <button class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
        <button class="btn btn-success btn-sm" onclick="salvarConfigLinha()"><i class="bi bi-save"></i> Salvar Configuração</button>
      </div>
    </div>
  </div>
</div>

<!-- ============================================== -->
<!-- MODAL: Copiar Valores de Outro Indicador       -->
<!-- ============================================== -->
<div class="modal fade" id="modalCopiarValores" tabindex="-1">
  <div class="modal-dialog modal-sm">
    <div class="modal-content">
      <div class="modal-header bg-primary text-white py-2">
        <strong class="modal-title"><i class="bi bi-clipboard-data"></i> Copiar Valores — <span id="copiarAnoLabel"></span></strong>
        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <input type="hidden" id="copiarAnoref" value="">
        <p class="small text-muted mb-2">Apenas valores preenchidos (≠ 0) na origem serão copiados para meses zerados no destino. Somente indicadores com a mesma máscara são listados.</p>
        <label class="form-label fw-semibold small">Indicador de origem</label>
        <select id="copiarOrigemSelect" class="form-select form-select-sm">
          <option value="">Carregando...</option>
        </select>
      </div>
      <div class="modal-footer py-1">
        <button class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
        <button class="btn btn-primary btn-sm" onclick="executarCopiarValores()"><i class="bi bi-clipboard-check"></i> Copiar</button>
      </div>
    </div>
  </div>
</div>

<!-- ============================================== -->
<!-- MODAL: Clonar Exercício (config operador+contas)-->
<!-- ============================================== -->
<div class="modal fade" id="modalClonarExercicio" tabindex="-1">
  <div class="modal-dialog modal-sm">
    <div class="modal-content">
      <div class="modal-header bg-secondary text-white py-2">
        <strong class="modal-title"><i class="bi bi-copy"></i> Clonar Configuração — <span id="clonarAnoLabel"></span></strong>
        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <input type="hidden" id="clonarCdindvalor" value="">
        <input type="hidden" id="clonarAnoOrigem" value="">
        <p class="small text-muted mb-2">A configuração de operador e contas será copiada para o exercício selecionado.</p>
        <div class="mb-2">
          <span class="small fw-semibold">Operador:</span> <span id="clonarOpLabel" class="badge bg-dark"></span>
          <span class="small fw-semibold ms-2">Contas:</span> <span id="clonarContasLabel" class="badge bg-success"></span>
        </div>
        <label class="form-label fw-semibold small">Exercício de destino</label>
        <select id="clonarDestinoSelect" class="form-select form-select-sm">
          <option value="">-- Selecione --</option>
        </select>
      </div>
      <div class="modal-footer py-1">
        <button class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
        <button class="btn btn-secondary btn-sm" onclick="executarClonarExercicio()"><i class="bi bi-copy"></i> Clonar</button>
      </div>
    </div>
  </div>
</div>

<style>
#cfgArvoreContas ul, #arvoreContasCache ul { list-style:none; padding-left:15px; }
#cfgArvoreContas li, #arvoreContasCache li { margin:2px 0; }
.toggle-icon { cursor:pointer; width:14px; display:inline-block; }
.conta-label { cursor:pointer; font-size:0.82rem; }
.sintetico { font-weight:bold; color:#000; }
.analitico { font-weight:normal; color:#333; }
.conta-match { background:#fff3cd; border-radius:3px; padding:0 3px; }
.campo-mes { text-align:right; font-size:0.82rem; min-width:80px; }
.campo-mes:focus { background:#fffbe6; }
.calc-display { font-size:0.68rem; color:#0d6efd; text-align:right; margin-top:1px; white-space:nowrap; }
.badge-conta { font-size:0.72rem; }
.btn-config-linha { font-size:0.7rem; padding:1px 5px; }
#modalConfigLinha { z-index: 1060 !important; }
#modalCopiarValores { z-index: 1060 !important; }
#modalClonarExercicio { z-index: 1060 !important; }
</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script>
// =========================================
// ESTADO
// =========================================
let contasMap = {};       // cdcontacontabil => dsconta
let modoEdicao = false;
let gridExercicios = [];  // [2025, 2026, ...]
let gridValores = {};     // 'anoref' => {jan:0, ..., cdindvalor: N, operador: '+', contas: []}
const mesesCols = ['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez'];
let cfgContasSel = new Set(); // contas selecionadas no modal
let cfgOperador = '+';
let arvoreCarregada = false;
let arvoreHtml = '';

// =========================================
// LISTA
// =========================================
async function carregarIndicadores() {
  const tbody = document.getElementById('tbodyIndicadores');
  tbody.innerHTML = '<tr><td colspan="8" class="text-center text-muted">Carregando...</td></tr>';
  try {
    const resp = await fetch('?m=indicadores_actions&ajax=listar_indicadores');
    const data = await resp.json();
    if (!data.ok) throw new Error(data.msg);
    const lista = data.data || [];
    if (!lista.length) {
      tbody.innerHTML = '<tr><td colspan="8" class="text-center text-muted">Nenhum indicador cadastrado.</td></tr>';
      return;
    }
    tbody.innerHTML = lista.map(ind => {
      const status = ind.flativo == 0
        ? '<span class="badge bg-success">Ativo</span>'
        : '<span class="badge bg-secondary">Inativo</span>';
      const tipoLabel = ind.tipo === 'calculado'
        ? '<span class="badge bg-info text-dark">Calculado</span>'
        : '<span class="badge bg-warning text-dark">Estático</span>';
      const grupoLabel = ind.dsgrupo ? esc(ind.dsgrupo) : '<span class="text-muted">—</span>';
      return `<tr data-nome="${esc(ind.nome).toLowerCase()}">
        <td>${ind.cdindicador}</td>
        <td><strong>${esc(ind.nome)}</strong>${ind.descricao ? '<br><small class="text-muted">'+esc(ind.descricao)+'</small>' : ''}</td>
        <td>${grupoLabel}</td>
        <td>${tipoLabel}</td>
        <td>${ind.mascara}</td>
        <td>${status}</td>
        <td class="text-center">
          <div class="btn-group btn-group-sm">
            <button class="btn btn-outline-primary" onclick="editarIndicador(${ind.cdindicador})" title="Editar"><i class="bi bi-pencil"></i></button>
            <button class="btn btn-outline-warning" onclick="toggleIndicador(${ind.cdindicador})" title="Ativar/Desativar"><i class="bi bi-arrow-repeat"></i></button>
            <button class="btn btn-outline-danger" onclick="excluirIndicador(${ind.cdindicador})" title="Excluir"><i class="bi bi-trash"></i></button>
          </div>
        </td>
      </tr>`;
    }).join('');
  } catch (e) {
    tbody.innerHTML = `<tr><td colspan="8" class="text-center text-danger">${esc(e.message)}</td></tr>`;
  }
}

$('#pesquisaInd').on('input', function() {
  const q = this.value.toLowerCase().trim();
  $('#tbodyIndicadores tr').each(function() {
    const nome = $(this).attr('data-nome') || '';
    $(this).toggle(!q || nome.includes(q));
  });
});

function esc(s) {
  if (!s) return '';
  const d = document.createElement('div');
  d.textContent = s;
  return d.innerHTML;
}

// =========================================
// GRUPOS DE INDICADORES
// =========================================
async function carregarGrupos(selValue) {
  try {
    const resp = await fetch('?m=indicadores_actions&ajax=listar_grupos');
    const data = await resp.json();
    if (!data.ok) return;
    const sel = document.getElementById('indGrupo');
    sel.innerHTML = '<option value="">(Sem grupo)</option>';
    (data.data || []).forEach(g => {
      const opt = document.createElement('option');
      opt.value = g.cdgrupo;
      opt.textContent = g.dsgrupo;
      sel.appendChild(opt);
    });
    if (selValue) sel.value = selValue;
  } catch (e) { /* silencioso */ }
}

async function adicionarGrupoInline() {
  const nome = prompt('Nome do novo grupo de indicadores:');
  if (!nome || !nome.trim()) return;
  if (!confirm(`Tem certeza que deseja incluir o grupo "${nome.trim()}"?`)) return;
  try {
    const resp = await fetch('?m=indicadores_actions&ajax=criar_grupo', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({ dsgrupo: nome.trim() })
    });
    const data = await resp.json();
    if (!data.ok) return alert(data.msg);
    alert(data.msg);
    await carregarGrupos(data.cdgrupo);
  } catch (e) {
    alert('Erro ao criar grupo: ' + e.message);
  }
}

// =========================================
// CRUD LISTA
// =========================================
async function toggleIndicador(id) {
  const fd = new FormData(); fd.append('cdindicador', id);
  const resp = await fetch('?m=indicadores_actions&ajax=toggle_indicador', { method:'POST', body:fd });
  const data = await resp.json();
  alert(data.msg);
  if (data.ok) carregarIndicadores();
}

async function excluirIndicador(id) {
  if (!confirm('Excluir este indicador e todos os dados vinculados?')) return;
  const fd = new FormData(); fd.append('cdindicador', id);
  const resp = await fetch('?m=indicadores_actions&ajax=excluir_indicador', { method:'POST', body:fd });
  const data = await resp.json();
  alert(data.msg);
  if (data.ok) { carregarIndicadores(); fecharFormulario(); }
}

// =========================================
// FORMULÁRIO: Novo / Editar
// =========================================
function novoIndicador() {
  modoEdicao = false;
  gridExercicios = [];
  gridValores = {};

  document.getElementById('indCdindicador').value = '';
  document.getElementById('indNome').value = '';
  document.getElementById('indDescricao').value = '';
  document.getElementById('indMascara').value = 'inteiro';
  document.getElementById('indMascaraCalc').value = 'inteiro';
  document.getElementById('indTipo').value = 'estatico';
  document.getElementById('indOrdem').value = '';
  document.getElementById('indGrupo').value = '';
  $('.chk-empresa-ind').prop('checked', false);

  document.getElementById('formTitulo').innerHTML = '<i class="bi bi-plus-circle"></i> Novo Indicador';
  atualizarColunaConfig();
  renderizarGrid();
  carregarGrupos();
  bootstrap.Modal.getOrCreateInstance(document.getElementById('modalFormIndicador')).show();
}

async function editarIndicador(id) {
  try {
    const resp = await fetch(`?m=indicadores_actions&ajax=obter_indicador&cdindicador=${id}`);
    const data = await resp.json();
    if (!data.ok) return alert(data.msg);

    const ind = data.data;
    modoEdicao = true;
    gridExercicios = [...ind.exercicios];
    gridValores = {};

    document.getElementById('indCdindicador').value = ind.cdindicador;
    document.getElementById('indNome').value = ind.nome || '';
    document.getElementById('indDescricao').value = ind.descricao || '';
    document.getElementById('indMascara').value = ind.mascara || 'inteiro';
    document.getElementById('indMascaraCalc').value = ind.mascara_calc || 'inteiro';
    document.getElementById('indTipo').value = ind.tipo || 'estatico';
    document.getElementById('indOrdem').value = ind.ordem || '';

    // Grupo
    await carregarGrupos(ind.cdgrupo || '');

    // Empresas
    $('.chk-empresa-ind').prop('checked', false);
    ind.empresas.forEach(empId => $(`#empInd_${empId}`).prop('checked', true));

    document.getElementById('formTitulo').innerHTML = '<i class="bi bi-pencil"></i> Editar Indicador #' + ind.cdindicador;
    atualizarColunaConfig();
    await carregarGrid();
    bootstrap.Modal.getOrCreateInstance(document.getElementById('modalFormIndicador')).show();
  } catch (e) {
    alert('Erro: ' + e.message);
  }
}

function fecharFormulario() {
  const modalEl = document.getElementById('modalFormIndicador');
  const modal = bootstrap.Modal.getInstance(modalEl);
  if (modal) modal.hide();
}

// =========================================
// COLUNA CONFIG (visível só para calculado)
// =========================================
function atualizarColunaConfig() {
  const tipo = document.getElementById('indTipo').value;
  const show = tipo === 'calculado';
  document.getElementById('thConfig').style.display = show ? '' : 'none';
  document.getElementById('thAcoes').style.display = show ? '' : 'none';
  document.getElementById('divMascaraCalc').style.display = show ? '' : 'none';
}
$('#indTipo').on('change', function() {
  atualizarColunaConfig();
  renderizarGrid();
});

// =========================================
// GRID: Renderização
// =========================================
function renderizarGrid() {
  const tbody = document.getElementById('tbodyGrid');
  const isCalc = document.getElementById('indTipo').value === 'calculado';
  const colSpan = isCalc ? 17 : 15;

  if (!gridExercicios.length) {
    tbody.innerHTML = `<tr><td colspan="${colSpan}" class="text-center text-muted small">Nenhum exercício adicionado.</td></tr>`;
    return;
  }

  tbody.innerHTML = gridExercicios.map(ano => {
    const vals = gridValores[ano] || {};
    const cdindvalor = vals.cdindvalor || 0;

    let html = `<tr data-anoref="${ano}"><td class="fw-bold">${ano}</td>`;
    let total = 0;
    let totalCalc = 0;
    let countCalc = 0;

    mesesCols.forEach(mes => {
      const v = parseFloat(vals[mes]) || 0;
      total += v;
      const vc = parseFloat(vals[mes + '_calc']) || 0;
      totalCalc += vc;
      if (vc !== 0) countCalc++;
      const calcLine = (isCalc && vc !== 0) ? `<div class="calc-display" data-calc-mes="${mes}">→ ${formatarValorCalc(vc)}</div>` : (isCalc ? `<div class="calc-display" data-calc-mes="${mes}"></div>` : '');
      html += `<td><input type="text" class="form-control form-control-sm campo-mes"
                 data-anoref="${ano}" data-mes="${mes}" data-cdindvalor="${cdindvalor}"
                 value="${formatarValor(v)}">${calcLine}</td>`;
    });

    html += `<td class="fw-bold text-end">${formatarValor(total)}`;
    if (isCalc && countCalc > 0) {
      const mediaCalc = totalCalc / countCalc;
      html += `<div class="calc-display">→ Méd: ${formatarValorCalc(mediaCalc)}</div>`;
    }
    html += `</td>`;

    // Coluna config (calculado)
    if (isCalc) {
      const nContas = (vals.contas || []).length;
      const opLabel = vals.operador || '';
      const hasConfig = nContas > 0;
      const btnClass = hasConfig ? 'btn-outline-success' : 'btn-outline-danger';
      const iconExtra = hasConfig ? ` ${opLabel} (${nContas})` : ' <small>Pendente</small>';
      if (cdindvalor > 0) {
        html += `<td class="text-center">
          <button class="btn ${btnClass} btn-sm btn-config-linha" onclick="abrirConfigLinha(${cdindvalor}, ${ano})" title="Configurar operador e contas">
            <i class="bi bi-gear"></i>${iconExtra}
          </button></td>`;
        // Coluna ações (clonar + prévia)
        html += `<td class="text-center text-nowrap">
          <button class="btn btn-outline-secondary btn-sm py-0 px-1" onclick="clonarExercicio(${cdindvalor}, ${ano})" title="Clonar configuração">
            <i class="bi bi-copy"></i>
          </button>
          ${hasConfig ? `<button class="btn btn-outline-info btn-sm py-0 px-1 ms-1" onclick="calcularPrevia(${cdindvalor}, ${ano})" title="Calcular prévia">
            <i class="bi bi-calculator"></i>
          </button>` : ''}
        </td>`;
      } else {
        html += `<td class="text-center">
          <button class="btn btn-outline-warning btn-sm btn-config-linha" disabled title="Salve o indicador primeiro">
            <i class="bi bi-gear"></i> <small>Salvar antes</small>
          </button></td>`;
        html += `<td></td>`;
      }
    }

    html += `<td class="text-center text-nowrap">`;
    if (cdindvalor > 0 && modoEdicao) {
      html += `<button class="btn btn-outline-primary btn-sm py-0 px-1 me-1" onclick="abrirCopiarValores(${ano})" title="Copiar valores de outro indicador"><i class="bi bi-clipboard-data"></i></button>`;
    }
    html += `<button class="btn btn-outline-danger btn-sm py-0 px-1" onclick="removerExercicio(${ano})" title="Remover"><i class="bi bi-x"></i></button></td>`;
    html += '</tr>';
    return html;
  }).join('');

  aplicarEventosCampos();
}

async function carregarGrid() {
  const cdindicador = document.getElementById('indCdindicador').value;

  if (!gridExercicios.length) {
    renderizarGrid();
    return;
  }

  if (modoEdicao && cdindicador) {
    for (const ano of gridExercicios) {
      try {
        const resp = await fetch(`?m=indicadores_actions&ajax=obter_valores&cdindicador=${cdindicador}&anoref=${ano}`);
        const data = await resp.json();
        if (data.ok && data.data) {
          gridValores[ano] = data.data;
        }
      } catch (e) { console.error(e); }
    }
  }

  renderizarGrid();
}

// =========================================
// GRID: Adicionar / Remover exercício
// =========================================
function adicionarExercicio() {
  const ano = parseInt(document.getElementById('gridExercicioNovo').value);
  if (!ano) return;
  if (gridExercicios.includes(ano)) return alert('Exercício já adicionado.');
  gridExercicios.push(ano);
  gridExercicios.sort((a, b) => a - b);

  const cdindicador = document.getElementById('indCdindicador').value;
  if (modoEdicao && cdindicador) {
    const empresas = [...document.querySelectorAll('.chk-empresa-ind:checked')].map(c => parseInt(c.value));
    fetch('?m=indicadores_actions&ajax=atualizar_indicador', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        cdindicador: parseInt(cdindicador),
        nome: document.getElementById('indNome').value,
        descricao: document.getElementById('indDescricao').value,
        tipo: document.getElementById('indTipo').value,
        mascara: document.getElementById('indMascara').value,
        ordem: document.getElementById('indOrdem').value,
        empresas,
        exercicios: gridExercicios
      })
    }).then(r => r.json()).then(d => {
      if (!d.ok) alert(d.msg);
      else carregarGrid(); // reload to get cdindvalor
    });
  } else {
    renderizarGrid();
  }
}

function removerExercicio(ano) {
  if (!confirm(`Remover exercício ${ano} e seus valores?`)) return;
  gridExercicios = gridExercicios.filter(a => a !== ano);

  const cdindicador = document.getElementById('indCdindicador').value;
  if (modoEdicao && cdindicador) {
    fetch('?m=indicadores_actions&ajax=desvincular_exercicio', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({ cdindicador: parseInt(cdindicador), anoref: ano })
    });
  }

  delete gridValores[ano];
  renderizarGrid();
}

// =========================================
// GRID: Eventos dos campos
// =========================================
function aplicarEventosCampos() {
  document.querySelectorAll('.campo-mes').forEach(input => {
    input.addEventListener('focus', function() { this.select(); });

    input.addEventListener('blur', async function() {
      const anoref = parseInt(this.dataset.anoref);
      const mes = this.dataset.mes;
      const cdindvalor = parseInt(this.dataset.cdindvalor) || 0;
      const valor = converterParaNumero(this.value);
      this.value = formatarValor(valor);

      if (!gridValores[anoref]) gridValores[anoref] = {};
      gridValores[anoref][mes] = valor;
      if (cdindvalor) gridValores[anoref].cdindvalor = cdindvalor;

      // Recalcular total visual
      let total = 0;
      const tr = this.closest('tr');
      tr.querySelectorAll('.campo-mes').forEach(c => { total += converterParaNumero(c.value); });
      // Encontrar coluna total (td.fw-bold.text-end)
      const tdTotal = tr.querySelector('td.fw-bold.text-end');
      if (tdTotal) tdTotal.textContent = formatarValor(total);

      // Salvar no banco se editando
      if (modoEdicao && cdindvalor > 0) {
        try {
          await fetch('?m=indicadores_actions&ajax=salvar_valor', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({ cdindvalor, mes, valor })
          });
        } catch (e) { console.error('Erro ao salvar:', e); }
      }
    });

    input.addEventListener('keydown', function(e) {
      if (e.key === 'Enter' || (e.key === 'Tab' && !e.shiftKey)) {
        e.preventDefault();
        const campos = [...document.querySelectorAll('.campo-mes')];
        const idx = campos.indexOf(this);
        if (campos[idx + 1]) campos[idx + 1].focus();
      }
    });
  });
}

// =========================================
// SALVAR INDICADOR
// =========================================
async function salvarIndicador() {
  const cdindicador = document.getElementById('indCdindicador').value;
  const nome = document.getElementById('indNome').value.trim();
  const descricao = document.getElementById('indDescricao').value.trim();
  const tipo = document.getElementById('indTipo').value;
  const mascara = document.getElementById('indMascara').value;
  const mascaraCalc = document.getElementById('indMascaraCalc')?.value || 'inteiro';
  const ordem = document.getElementById('indOrdem').value;
  const cdgrupo = document.getElementById('indGrupo').value || null;

  if (!nome) return alert('❌ Informe o nome do indicador.');

  // Validar configuração obrigatória para calculado
  if (tipo === 'calculado' && modoEdicao && gridExercicios.length > 0) {
    for (const ano of gridExercicios) {
      const vals = gridValores[ano] || {};
      if (vals.cdindvalor && (!vals.contas || vals.contas.length === 0)) {
        return alert(`❌ O exercício ${ano} precisa ter a configuração de operador e contas definida (clique em ⚙️).`);
      }
    }
  }

  const empresas = [...document.querySelectorAll('.chk-empresa-ind:checked')].map(c => parseInt(c.value));

  // Coletar valores da grid
  const valores = {};
  Object.keys(gridValores).forEach(anoKey => {
    const v = gridValores[anoKey];
    const obj = {};
    mesesCols.forEach(m => { obj[m] = v[m] || 0; });
    valores[anoKey] = obj;
  });

  const payload = {
    nome, descricao, tipo, mascara, mascara_calc: mascaraCalc, ordem, cdgrupo, empresas,
    exercicios: gridExercicios,
    valores
  };

  const isEdit = cdindicador && cdindicador !== '';
  if (isEdit) payload.cdindicador = parseInt(cdindicador);

  const acao = isEdit ? 'atualizar_indicador' : 'salvar_indicador';

  try {
    const resp = await fetch(`?m=indicadores_actions&ajax=${acao}`, {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(payload)
    });
    const data = await resp.json();
    alert(data.msg);
    if (data.ok) {
      fecharFormulario();
      carregarIndicadores();
    }
  } catch (e) {
    alert('Erro: ' + e.message);
  }
}

// =========================================
// FORMATAÇÃO
// =========================================
function converterParaNumero(v) {
  if (!v) return 0;
  v = String(v).replace(/\./g, '').replace(',', '.').replace(/[^\d.\-]/g, '');
  return parseFloat(v) || 0;
}

const moedaEmpresa = { simbolo: <?= json_encode($moedaEmp['simbolo'] ?? 'R$') ?>, formato: <?= json_encode($moedaEmp['formato'] ?? 'decimal') ?> };

function formatarValor(v) {
  const n = Number(v) || 0;
  const mascara = document.getElementById('indMascara')?.value || 'inteiro';
  return formatarComMascara(n, mascara);
}

function formatarValorCalc(v) {
  const n = Number(v) || 0;
  const mascara = document.getElementById('indMascaraCalc')?.value || 'inteiro';
  return formatarComMascara(n, mascara);
}

function formatarComMascara(n, mascara) {
  if (mascara === 'inteiro') {
    return Math.round(n).toLocaleString('pt-BR');
  }
  if (mascara === 'percentual') {
    return n.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '%';
  }
  // moeda: usar símbolo e formato da empresa
  const decimals = moedaEmpresa.formato === 'inteiro' ? 0 : 2;
  const formatted = n.toLocaleString('pt-BR', { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
  return moedaEmpresa.simbolo + ' ' + formatted;
}

// =========================================
// MODAL: Configurar Linha (operador + contas)
// =========================================
async function abrirConfigLinha(cdindvalor, anoref) {
  document.getElementById('cfgCdindvalor').value = cdindvalor;
  document.getElementById('cfgLinhaAno').textContent = anoref;

  // Carregar árvore no modal (só uma vez)
  if (!arvoreCarregada) {
    await carregarArvoreContas();
  }

  // Carregar config existente da linha
  try {
    const resp = await fetch(`?m=indicadores_actions&ajax=obter_config_linha&cdindvalor=${cdindvalor}`);
    const data = await resp.json();
    cfgOperador = data.operador || '+';
    cfgContasSel = new Set(data.contas || []);
  } catch (e) {
    cfgOperador = '+';
    cfgContasSel.clear();
  }

  // Aplicar no modal
  $('#cfgGrupoOperador button').removeClass('active');
  $(`#cfgGrupoOperador button[data-op="${cfgOperador}"]`).addClass('active');
  marcarContasModal();
  renderizarCfgBadges();

  bootstrap.Modal.getOrCreateInstance(document.getElementById('modalConfigLinha')).show();
}

function cfgSelecionarOp(btn) {
  $('#cfgGrupoOperador button').removeClass('active');
  $(btn).addClass('active');
  cfgOperador = btn.dataset.op;
}

async function salvarConfigLinha() {
  const cdindvalor = parseInt(document.getElementById('cfgCdindvalor').value);
  if (!cdindvalor) return;

  try {
    const resp = await fetch('?m=indicadores_actions&ajax=salvar_config_linha', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        cdindvalor,
        operador: cfgOperador,
        contas: [...cfgContasSel]
      })
    });
    const data = await resp.json();
    if (!data.ok) return alert(data.msg);

    alert(data.msg);
    bootstrap.Modal.getInstance(document.getElementById('modalConfigLinha')).hide();

    // Recarregar grid com valores calculados pelo backend
    await carregarGrid();
  } catch (e) {
    alert('Erro: ' + e.message);
  }
}

// =========================================
// ÁRVORE DE CONTAS (cache + modal)
// =========================================
async function carregarArvoreContas() {
  try {
    const resp = await fetch('?m=planocontabil_actions&ajax=tree');
    const data = await resp.json();
    const $container = $('#cfgArvoreContas');
    $container.empty();
    montarArvore($container, data);
    arvoreCarregada = true;
  } catch (e) {
    console.error('Erro árvore:', e);
  }
}

function montarArvore($container, itens) {
  const $ul = $('<ul></ul>');
  itens.forEach(item => {
    const temFilhos = item.children && item.children.length > 0;
    contasMap[item.cdcontacontabil] = item.dsconta;
    const $li = $('<li></li>');
    $li.attr('data-cd', String(item.cdcontacontabil || ''));
    $li.attr('data-search', String((item.dsconta || '') + ' ' + (item.fltipo === 'S' ? 'sintetico' : (item.flnatureza || ''))));

    const $toggle = $('<span class="toggle-icon text-secondary me-1">' +
      (temFilhos ? '<i class="bi bi-plus-square"></i>' : '') + '</span>');
    const estilo = item.fltipo === 'S' ? 'sintetico' : 'analitico';
    const $chk = $(`<input type="checkbox" class="form-check-input me-1 cfg-conta-check" value="${item.cdcontacontabil}">`);
    const descricao = item.fltipo === 'S' ? item.dsconta : `${item.dsconta} (${item.flnatureza})`;
    const $label = $(`<span class="conta-label ${estilo}">${descricao}</span>`);
    const $sub = $('<ul style="display:none;"></ul>');
    if (temFilhos) montarArvore($sub, item.children);

    $toggle.on('click', function() {
      $sub.toggle();
      $(this).find('i').toggleClass('bi-plus-square bi-dash-square');
    });

    $chk.on('change', function() {
      const cd = parseInt($(this).val());
      if (this.checked) cfgContasSel.add(cd);
      else cfgContasSel.delete(cd);
      renderizarCfgBadges();
    });

    $li.append($toggle).append($chk).append($label).append($sub);
    $ul.append($li);
  });
  $container.append($ul);
}

function marcarContasModal() {
  $('#cfgArvoreContas .cfg-conta-check').each(function() {
    const cd = parseInt($(this).val());
    $(this).prop('checked', cfgContasSel.has(cd));
    if (cfgContasSel.has(cd)) {
      $(this).parentsUntil('#cfgArvoreContas', 'ul').show();
      $(this).parentsUntil('#cfgArvoreContas', 'li').each(function() {
        $(this).children('.toggle-icon').find('i').removeClass('bi-plus-square').addClass('bi-dash-square');
      });
    }
  });
}

function renderizarCfgBadges() {
  const container = document.getElementById('cfgContasBadges');
  if (!cfgContasSel.size) {
    container.innerHTML = '<small class="text-muted">Nenhuma conta selecionada</small>';
    return;
  }
  container.innerHTML = [...cfgContasSel].map(cd => {
    const nome = contasMap[cd] || cd;
    return `<span class="badge bg-success badge-conta me-1 mb-1">${cd} - ${esc(nome)}
      <i class="bi bi-x ms-1" style="cursor:pointer;" onclick="cfgRemoverConta(${cd})"></i></span>`;
  }).join('');
}

function cfgRemoverConta(cd) {
  cfgContasSel.delete(cd);
  $(`#cfgArvoreContas .cfg-conta-check[value="${cd}"]`).prop('checked', false);
  renderizarCfgBadges();
}

// Busca contas no modal
function normTxt(s) {
  return String(s || '').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}

function aplicarBuscaContasCfg() {
  const q = normTxt($('#cfgBuscaConta').val().trim());
  const $root = $('#cfgArvoreContas > ul').first();
  const $info = $('#cfgBuscaInfo');
  $('#cfgArvoreContas .conta-label').removeClass('conta-match');
  if (!$root.length) { $info.text(''); return; }
  if (!q) { $root.find('li').show(); $info.text(''); return; }

  let matchesDiretos = 0;
  function walk($li) {
    const cd = normTxt($li.attr('data-cd'));
    const txt = normTxt($li.attr('data-search'));
    const selfMatch = cd.includes(q) || txt.includes(q);
    let childMatch = false;
    const $sub = $li.children('ul');
    if ($sub.length) {
      $sub.children('li').each(function() { if (walk($(this))) childMatch = true; });
    }
    const match = selfMatch || childMatch;
    $li.toggle(match);
    if (selfMatch) {
      $li.children('.conta-label').addClass('conta-match');
      matchesDiretos++;
      $li.parentsUntil('#cfgArvoreContas', 'ul').show();
      $li.parentsUntil('#cfgArvoreContas', 'li').each(function() {
        $(this).children('.toggle-icon').find('i').removeClass('bi-plus-square').addClass('bi-dash-square');
      });
    }
    if (childMatch) {
      $sub.show();
      $li.children('.toggle-icon').find('i').removeClass('bi-plus-square').addClass('bi-dash-square');
    }
    return match;
  }
  $root.children('li').each(function() { walk($(this)); });
  $info.text(matchesDiretos ? `${matchesDiretos} conta(s)` : 'Nenhuma');
}

let cfgBuscaTimer = null;
$('#cfgBuscaConta').on('input', function() {
  clearTimeout(cfgBuscaTimer);
  cfgBuscaTimer = setTimeout(aplicarBuscaContasCfg, 120);
});
$('#btnLimparCfgBusca').on('click', function() {
  $('#cfgBuscaConta').val('').focus();
  aplicarBuscaContasCfg();
});

// =========================================
// COPIAR VALORES DE OUTRO INDICADOR
// =========================================
async function abrirCopiarValores(anoref) {
  const cdindicador = document.getElementById('indCdindicador').value;
  if (!cdindicador) return alert('❌ Salve o indicador primeiro.');

  document.getElementById('copiarAnoref').value = anoref;
  document.getElementById('copiarAnoLabel').textContent = anoref;
  const sel = document.getElementById('copiarOrigemSelect');
  sel.innerHTML = '<option value="">Carregando...</option>';

  bootstrap.Modal.getOrCreateInstance(document.getElementById('modalCopiarValores')).show();

  try {
    const resp = await fetch(`?m=indicadores_actions&ajax=listar_indicadores_copiaveis&cdindicador=${cdindicador}&anoref=${anoref}`);
    const data = await resp.json();
    if (!data.ok) { sel.innerHTML = `<option value="">❌ ${data.msg}</option>`; return; }
    if (!data.indicadores.length) { sel.innerHTML = '<option value="">Nenhum indicador compatível encontrado</option>'; return; }
    sel.innerHTML = '<option value="">-- Selecione --</option>' +
      data.indicadores.map(i => `<option value="${i.cdindicador}">${esc(i.nome)}</option>`).join('');
  } catch (e) {
    sel.innerHTML = '<option value="">Erro ao carregar</option>';
  }
}

async function executarCopiarValores() {
  const cdindicador = document.getElementById('indCdindicador').value;
  const anoref = parseInt(document.getElementById('copiarAnoref').value);
  const cdindOrigem = parseInt(document.getElementById('copiarOrigemSelect').value);
  if (!cdindOrigem) return alert('❌ Selecione um indicador de origem.');

  try {
    const resp = await fetch('?m=indicadores_actions&ajax=copiar_valores_indicador', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        cdindicador_origem: cdindOrigem,
        cdindicador_destino: parseInt(cdindicador),
        anoref
      })
    });
    const data = await resp.json();
    alert(data.msg);
    if (data.ok && data.copiados > 0) {
      bootstrap.Modal.getInstance(document.getElementById('modalCopiarValores')).hide();
      await carregarGrid();
    }
  } catch (e) {
    alert('Erro: ' + e.message);
  }
}

// =========================================
// CLONAR EXERCÍCIO (calculado)
// =========================================
function clonarExercicio(cdindvalorOrigem, anoOrigem) {
  const valsOrigem = gridValores[anoOrigem] || {};
  if (!valsOrigem.contas || valsOrigem.contas.length === 0) {
    return alert('❌ Esta linha não possui configuração de operador/contas para clonar.');
  }

  const disponiveis = <?= json_encode($exerciciosDisp) ?>.filter(a => !gridExercicios.includes(parseInt(a)));
  if (!disponiveis.length) {
    return alert('❌ Não há exercícios disponíveis para clonar. Todos já estão adicionados.');
  }

  document.getElementById('clonarCdindvalor').value = cdindvalorOrigem;
  document.getElementById('clonarAnoOrigem').value = anoOrigem;
  document.getElementById('clonarAnoLabel').textContent = anoOrigem;
  document.getElementById('clonarOpLabel').textContent = valsOrigem.operador || '+';
  document.getElementById('clonarContasLabel').textContent = valsOrigem.contas.length + ' conta(s)';

  const sel = document.getElementById('clonarDestinoSelect');
  sel.innerHTML = '<option value="">-- Selecione --</option>' +
    disponiveis.map(a => `<option value="${a}">${a}</option>`).join('');

  bootstrap.Modal.getOrCreateInstance(document.getElementById('modalClonarExercicio')).show();
}

async function executarClonarExercicio() {
  const cdindvalorOrigem = parseInt(document.getElementById('clonarCdindvalor').value);
  const anoInt = parseInt(document.getElementById('clonarDestinoSelect').value);
  if (!anoInt) return alert('❌ Selecione um exercício de destino.');

  const cdindicador = document.getElementById('indCdindicador').value;
  if (!cdindicador) return alert('❌ Salve o indicador primeiro.');

  try {
    const resp = await fetch('?m=indicadores_actions&ajax=clonar_exercicio', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        cdindicador: parseInt(cdindicador),
        cdindvalor_origem: cdindvalorOrigem,
        anoref_destino: anoInt
      })
    });
    const data = await resp.json();
    if (!data.ok) return alert(data.msg);

    alert(data.msg);
    bootstrap.Modal.getInstance(document.getElementById('modalClonarExercicio')).hide();
    if (!gridExercicios.includes(anoInt)) {
      gridExercicios.push(anoInt);
      gridExercicios.sort((a, b) => a - b);
    }
    await carregarGrid();
  } catch (e) {
    alert('Erro: ' + e.message);
  }
}

// =========================================
// CALCULAR PRÉVIA (valores calculados da MV)
// =========================================
async function calcularPrevia(cdindvalor, anoref) {
  try {
    const resp = await fetch(`?m=indicadores_actions&ajax=calcular_previa&cdindvalor=${cdindvalor}`);
    const data = await resp.json();
    if (!data.ok) return alert(data.msg);

    const valores = data.valores;
    const tr = document.querySelector(`#tbodyGrid tr[data-anoref="${anoref}"]`);
    if (!tr) return;

    let totalCalc = 0;
    let countCalc = 0;
    mesesCols.forEach(mes => {
      const v = parseFloat(valores[mes]) || 0;
      totalCalc += v;
      if (v !== 0) countCalc++;
      // Atualizar display _calc abaixo do input
      const calcDiv = tr.querySelector(`.calc-display[data-calc-mes="${mes}"]`);
      if (calcDiv) {
        calcDiv.textContent = v !== 0 ? `\u2192 ${formatarValorCalc(v)}` : '';
        calcDiv.style.color = '#198754';
        setTimeout(() => { calcDiv.style.color = '#0d6efd'; }, 2000);
      }
      // Salvar no estado local
      if (!gridValores[anoref]) gridValores[anoref] = {};
      gridValores[anoref][mes + '_calc'] = v;
    });

    // Atualizar total calc
    const tdTotal = tr.querySelector('td.fw-bold.text-end');
    if (tdTotal) {
      let calcTotalDiv = tdTotal.querySelector('.calc-display');
      if (!calcTotalDiv) {
        calcTotalDiv = document.createElement('div');
        calcTotalDiv.className = 'calc-display';
        tdTotal.appendChild(calcTotalDiv);
      }
      calcTotalDiv.textContent = countCalc > 0 ? `\u2192 M\u00e9d: ${formatarValorCalc(totalCalc / countCalc)}` : '';
    }
  } catch (e) {
    alert('Erro ao calcular prévia: ' + e.message);
  }
}

// =========================================
// MODAL STACKING (form + config)
// =========================================
$('#modalConfigLinha').on('shown.bs.modal', function() {
  $('.modal-backdrop').last().css('z-index', 1055);
});
$('#modalConfigLinha').on('hidden.bs.modal', function() {
  if ($('#modalFormIndicador').hasClass('show')) {
    document.body.classList.add('modal-open');
  }
});
$('#modalCopiarValores').on('shown.bs.modal', function() {
  $('.modal-backdrop').last().css('z-index', 1055);
});
$('#modalCopiarValores').on('hidden.bs.modal', function() {
  if ($('#modalFormIndicador').hasClass('show')) {
    document.body.classList.add('modal-open');
  }
});
$('#modalClonarExercicio').on('shown.bs.modal', function() {
  $('.modal-backdrop').last().css('z-index', 1055);
});
$('#modalClonarExercicio').on('hidden.bs.modal', function() {
  if ($('#modalFormIndicador').hasClass('show')) {
    document.body.classList.add('modal-open');
  }
});

// =========================================
// INIT
// =========================================
carregarIndicadores();
</script>
