{"id":458,"date":"2025-12-12T15:16:53","date_gmt":"2025-12-12T18:16:53","guid":{"rendered":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/?page_id=458"},"modified":"2026-01-01T12:10:31","modified_gmt":"2026-01-01T15:10:31","slug":"adm","status":"publish","type":"page","link":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/adm\/","title":{"rendered":"ADM"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"458\" class=\"elementor elementor-458\">\n\t\t\t\t<div class=\"elementor-element elementor-element-812ffa5 e-flex e-con-boxed e-con e-parent\" data-id=\"812ffa5\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7cd9063 elementor-widget elementor-widget-html\" data-id=\"7cd9063\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<script src=\"https:\/\/unpkg.com\/html5-qrcode\"><\/script>\r\n\r\n<div id=\"reader\" style=\"width:100%;max-width:360px;margin:auto\"><\/div>\r\n<div id=\"status\" style=\"text-align:center;font-weight:bold;margin-top:15px\"><\/div>\r\n\r\n<script>\r\nconst statusEl = document.getElementById(\"status\");\r\n\r\nfunction show(msg, color){\r\n  statusEl.innerText = msg;\r\n  statusEl.style.color = color;\r\n}\r\n\r\nconst qr = new Html5Qrcode(\"reader\");\r\n\r\nqr.start(\r\n  { facingMode: \"environment\" },\r\n  { fps: 10, qrbox: 250 },\r\n  (text) => {\r\n    show(\"QR lido com sucesso\", \"green\");\r\n\r\n    \/\/ Aqui depois conecta no Firebase\r\n    console.log(text);\r\n  }\r\n);\r\n<\/script>\r\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-4f3337c e-flex e-con-boxed e-con e-parent\" data-id=\"4f3337c\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c27c893 elementor-widget elementor-widget-html\" data-id=\"c27c893\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"pt-BR\">\r\n<head>\r\n  <meta charset=\"UTF-8\" \/>\r\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/>\r\n  <title>AGISA | Admin Cashback<\/title>\r\n\r\n  <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\r\n\r\n  <!-- Firebase v8 -->\r\n  <script src=\"https:\/\/www.gstatic.com\/firebasejs\/8.10.0\/firebase-app.js\"><\/script>\r\n  <script src=\"https:\/\/www.gstatic.com\/firebasejs\/8.10.0\/firebase-auth.js\"><\/script>\r\n  <script src=\"https:\/\/www.gstatic.com\/firebasejs\/8.10.0\/firebase-firestore.js\"><\/script>\r\n\r\n  <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/emailjs-com@3\/dist\/email.min.js\"><\/script>\r\n\r\n  <!-- Chart.js correto -->\r\n  <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js@3.7.1\/dist\/chart.min.js\"><\/script>\r\n\r\n  <script>\r\n    \/\/ \u2705 EmailJS (SEUS DADOS)\r\n    const EMAILJS_PUBLIC_KEY = \"Vp5pjJ2jKRxEtQzyY\";\r\n    const EMAILJS_SERVICE_ID = \"service_jmgx8tt\";\r\n\r\n    \/\/ \u2705 TEMPLATE DO \u2714 (B\u00d4NUS LIBERADO)\r\n    const EMAILJS_TEMPLATE_BONUS_LIBERADO = \"template_28kpa55\";\r\n\r\n    \/\/ \u2705 TEMPLATE DO \u274c (ATRASO \/ PERDEU B\u00d4NUS)\r\n    const EMAILJS_TEMPLATE_ATRASO = \"template_qqzmezl\";\r\n\r\n    \/\/ Se voc\u00ea ainda n\u00e3o tem template para \"token de uso\", deixe vazio para n\u00e3o tentar enviar:\r\n    const EMAILJS_TEMPLATE_TOKEN_USO = \"template_y98oy89\";\r\n\r\n    (function () {\r\n      emailjs.init(EMAILJS_PUBLIC_KEY);\r\n    })();\r\n\r\n    \/\/ \u2705 FUN\u00c7\u00c3O SEGURA DE ENVIO DE EMAIL\r\n    function safeSendEmail(templateId, params) {\r\n      if (!templateId) return Promise.resolve();\r\n      return emailjs.send(EMAILJS_SERVICE_ID, templateId, params)\r\n        .then((res) => {\r\n          console.log(\"\u2705 EmailJS OK:\", templateId, res);\r\n          return { success: true, response: res };\r\n        })\r\n        .catch((err) => {\r\n          console.error(\"\u274c EmailJS ERRO:\", templateId, err);\r\n          return { success: false, error: err };\r\n        });\r\n    }\r\n\r\n    \/\/ \u2705 UID(s) autorizados no Admin\r\n    const ADMIN_UIDS = [\r\n      \"ym4JCoATKFXBCHzstdNrJnJFbjm2\"\r\n    ];\r\n  <\/script>\r\n\r\n  <style>\r\n    :root{--ag-yellow:#FFD400;--ag-black:#050505;--ag-gray:#1A1A1A}\r\n    *{box-sizing:border-box}\r\n    body{\r\n      background:var(--ag-black);\r\n      color:#f5f5f5;\r\n      font-family:Inter,Arial,sans-serif;\r\n      -webkit-font-smoothing:antialiased;\r\n      -moz-osx-font-smoothing:grayscale;\r\n      min-height:100vh;\r\n    }\r\n\r\n    \/* \u2705 visual \"redondinho\" *\/\r\n    .ag-card{\r\n      background: linear-gradient(180deg, rgba(26,26,26,1), rgba(18,18,18,1));\r\n      border:1px solid rgba(255,212,0,.22);\r\n      border-radius:18px;\r\n      box-shadow: 0 10px 30px rgba(0,0,0,.35);\r\n    }\r\n\r\n    .ag-input{\r\n      background: rgba(0,0,0,.55);\r\n      border:1px solid rgba(255,255,255,.12);\r\n      padding:11px 12px;\r\n      border-radius:14px;\r\n      color:#fff;\r\n      width:100%;\r\n      outline:none;\r\n      transition: .15s ease;\r\n    }\r\n    .ag-input:focus{\r\n      border-color: rgba(255,212,0,.55);\r\n      box-shadow: 0 0 0 4px rgba(255,212,0,.12);\r\n    }\r\n\r\n    .ag-btn{\r\n      background:var(--ag-yellow);\r\n      color:#000;\r\n      font-weight:900;\r\n      padding:12px 14px;\r\n      border-radius:14px;\r\n      transition:.15s ease;\r\n      box-shadow: 0 10px 20px rgba(0,0,0,.25);\r\n      width:100%;\r\n    }\r\n    .ag-btn:hover{ transform: translateY(-1px); filter: brightness(1.02); }\r\n    .ag-btn:active{ transform: translateY(0px); }\r\n\r\n    .tab-btn{\r\n      padding:10px 10px;\r\n      color:#aaa;\r\n      cursor:pointer;\r\n      border-radius:12px;\r\n      transition:.15s ease;\r\n      border:1px solid transparent;\r\n    }\r\n    .tab-btn:hover{ background: rgba(255,255,255,.06); color:#f0f0f0; }\r\n    .tab-btn.active{\r\n      color:var(--ag-yellow);\r\n      background: rgba(255,212,0,.08);\r\n      border:1px solid rgba(255,212,0,.25);\r\n    }\r\n\r\n    .hidden{display:none}\r\n    table{ border-collapse:separate; border-spacing:0; width:100%; }\r\n    table th, table td{ padding:10px 10px; white-space:nowrap; }\r\n    tbody tr:hover{ background: rgba(255,255,255,.04); }\r\n\r\n    \/* lista clic\u00e1vel da pesquisa *\/\r\n    .opt-row{\r\n      display:flex; justify-content:space-between; align-items:center;\r\n      border:1px solid rgba(255,255,255,.10);\r\n      background:rgba(0,0,0,.35);\r\n      padding:9px 11px;\r\n      border-radius:14px;\r\n      cursor:pointer;\r\n      transition:.15s;\r\n    }\r\n    .opt-row:hover{\r\n      border-color: rgba(255,212,0,.35);\r\n      transform: translateY(-1px);\r\n      background: rgba(255,212,0,.05);\r\n    }\r\n    .opt-l{ font-size:13px; color:#f2f2f2; }\r\n    .opt-r{ font-size:12px; color:#cfcfcf; }\r\n    .subtle{ color:#9ca3af; font-size:11px; }\r\n\r\n    \/* \u2705 modais com borda mais suave *\/\r\n    .modal-shell{\r\n      border-radius: 20px;\r\n      box-shadow: 0 18px 50px rgba(0,0,0,.55);\r\n    }\r\n\r\n    \/* \u2705 LOGIN *\/\r\n    .login-shell{\r\n      min-height:100vh;\r\n      width:100%;\r\n      display:flex;\r\n      align-items:center;\r\n      justify-content:center;\r\n      padding:24px;\r\n      background: radial-gradient(1200px 600px at 50% 10%, rgba(255,212,0,.10), transparent 60%),\r\n                  radial-gradient(900px 500px at 10% 90%, rgba(34,197,94,.08), transparent 55%),\r\n                  var(--ag-black);\r\n    }\r\n    .login-card{\r\n      width:100%;\r\n      max-width:420px;\r\n      padding:18px;\r\n      border-radius:16px;\r\n      background: rgba(8,8,8,.8);\r\n      border:1px solid rgba(255,212,0,.22);\r\n      box-shadow: 0 20px 60px rgba(0,0,0,.55);\r\n      backdrop-filter: blur(10px);\r\n    }\r\n    .login-title{\r\n      display:flex;\r\n      align-items:center;\r\n      justify-content:space-between;\r\n      gap:12px;\r\n      margin-bottom:12px;\r\n    }\r\n    .login-badge{\r\n      font-size:12px;\r\n      padding:4px 10px;\r\n      border-radius:999px;\r\n      border:1px solid rgba(34,197,94,.35);\r\n      color:#34d399;\r\n      background: rgba(34,197,94,.08);\r\n      font-weight:800;\r\n    }\r\n\r\n    \/* \u2705 Multi-vendedor *\/\r\n    .vend-item{\r\n      display:flex; align-items:center; gap:10px;\r\n      padding:8px 10px; border-radius:12px;\r\n      border:1px solid rgba(255,255,255,.10);\r\n      background:rgba(0,0,0,.35);\r\n      cursor:pointer;\r\n      transition:.15s;\r\n    }\r\n    .vend-item:hover{\r\n      border-color: rgba(255,212,0,.35);\r\n      background: rgba(255,212,0,.06);\r\n      transform: translateY(-1px);\r\n    }\r\n    .vend-item input{ transform: scale(1.05); }\r\n\r\n    \/* \u2705 Ajustes responsivos extra *\/\r\n    @media (max-width: 768px){\r\n      header h1{ font-size:18px !important; }\r\n      .login-card{ max-width: 100%; }\r\n      .ag-card{ border-radius:16px; }\r\n      .ag-input, .ag-btn{ border-radius:14px; }\r\n      canvas{ max-height: 260px; }\r\n    }\r\n    @media (min-width: 769px) and (max-width: 1024px){\r\n      canvas{ max-height: 300px; }\r\n    }\r\n  <\/style>\r\n<\/head>\r\n\r\n<body>\r\n\r\n  <!-- \u2705 LOGIN VIEW -->\r\n  <section id=\"loginView\" class=\"login-shell\" style=\"display:flex;\">\r\n    <div class=\"login-card\">\r\n      <div class=\"login-title\">\r\n        <div>\r\n          <div class=\"text-sm text-yellow-300 font-extrabold\">AGISA Admin Cashback<\/div>\r\n          <div class=\"text-xs text-gray-400\">Acesso restrito \u2022 Firebase Auth<\/div>\r\n        <\/div>\r\n        <div class=\"login-badge\">ONLINE<\/div>\r\n      <\/div>\r\n\r\n      <div class=\"space-y-3\">\r\n        <div>\r\n          <label class=\"text-xs text-gray-400\">Login (email)<\/label>\r\n          <input id=\"loginEmail\" class=\"ag-input\" placeholder=\"seuemail@agisa.com.br\" autocomplete=\"username\" \/>\r\n        <\/div>\r\n        <div>\r\n          <label class=\"text-xs text-gray-400\">Senha<\/label>\r\n          <input id=\"loginSenha\" type=\"password\" class=\"ag-input\" placeholder=\"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\" autocomplete=\"current-password\" \/>\r\n        <\/div>\r\n\r\n        <div id=\"loginMsg\" class=\"hidden text-sm text-red-300 bg-red-500\/10 border border-red-400\/20 p-3 rounded-xl\"><\/div>\r\n\r\n        <button id=\"loginBtn\" class=\"ag-btn\">ENTRAR<\/button>\r\n\r\n        <div class=\"text-[11px] text-gray-500 mt-2\">\r\n          Somente usu\u00e1rios autorizados (UID liberado no Firebase).\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- \u2705 APP VIEW -->\r\n  <div id=\"appView\" style=\"display:none;\">\r\n\r\n    <header class=\"px-4 md:px-6 py-4 border-b border-yellow-400\/30 sticky top-0 z-40 bg-black\/70 backdrop-blur\">\r\n      <div class=\"flex items-center justify-between gap-3\">\r\n        <h1 class=\"text-2xl font-extrabold\">\r\n          <span class=\"text-yellow-400\">AGISA<\/span> Admin Cashback\r\n          <span class=\"text-green-400 text-sm ml-3\">\u25cf ONLINE<\/span>\r\n        <\/h1>\r\n\r\n        <div class=\"flex items-center gap-3 text-sm\">\r\n          <span class=\"text-gray-300 hidden sm:inline\">Logado:<\/span>\r\n          <span id=\"whoami\" class=\"text-yellow-200 font-bold truncate max-w-[160px] sm:max-w-[280px]\">\u2014<\/span>\r\n          <button id=\"logoutBtn\" class=\"px-3 py-2 rounded-xl border border-yellow-400\/30 hover:border-yellow-400\/60 hover:bg-yellow-400\/10 transition\">\r\n            Sair\r\n          <\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/header>\r\n\r\n    <main class=\"p-4 md:p-6 max-w-7xl mx-auto space-y-10\">\r\n\r\n      <!-- Cadastro -->\r\n      <section class=\"ag-card p-4 md:p-6\">\r\n        <h2 class=\"text-xl font-bold text-yellow-400 mb-6\">Registrar Nova Transa\u00e7\u00e3o<\/h2>\r\n\r\n        <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n          <input id=\"clientName\" class=\"ag-input\" placeholder=\"Cliente\" \/>\r\n          <input id=\"cnpj\" class=\"ag-input\" placeholder=\"CNPJ\" \/>\r\n          <input id=\"phone\" class=\"ag-input\" placeholder=\"Telefone\" \/>\r\n          <input id=\"email\" class=\"ag-input\" placeholder=\"Email\" \/>\r\n          <input id=\"commercial\" class=\"ag-input\" placeholder=\"Vendedor\" \/>\r\n          <input id=\"contract\" class=\"ag-input\" placeholder=\"Contrato\" \/>\r\n\r\n          <input id=\"months\" type=\"number\" class=\"ag-input\" placeholder=\"Meses de loca\u00e7\u00e3o\" \/>\r\n          <input id=\"dataMobilizacao\" type=\"date\" class=\"ag-input\" \/>\r\n          <input id=\"dataDesmobilizacao\" type=\"date\" class=\"ag-input\" \/>\r\n\r\n          <!-- \u2705 TOTAL do contrato -->\r\n          <input id=\"negotiation\" type=\"number\" class=\"ag-input\" placeholder=\"Valor da negocia\u00e7\u00e3o (TOTAL do contrato)\" \/>\r\n          <input id=\"percent\" type=\"number\" class=\"ag-input\" placeholder=\"% Cashback\" \/>\r\n\r\n          <!-- \u2705 cashback TOTAL -->\r\n          <input id=\"cashback\" class=\"ag-input md:col-span-3 text-yellow-300 font-extrabold\" readonly placeholder=\"Cashback total (do contrato)\" \/>\r\n          <input id=\"token\" class=\"ag-input md:col-span-3 font-mono\" readonly placeholder=\"Chave de resgate\" \/>\r\n        <\/div>\r\n\r\n        <button id=\"saveBtn\" class=\"ag-btn mt-6\">REGISTRAR CLIENTE + HIST\u00d3RICO<\/button>\r\n      <\/section>\r\n\r\n      <!-- Abas -->\r\n      <section>\r\n        <div class=\"flex flex-wrap gap-2 md:gap-3 border-b border-gray-800\/70 mb-4 text-sm pb-3\">\r\n          <button class=\"tab-btn active\" onclick=\"switchTab(event,'cadastros')\">Cadastros<\/button>\r\n          <button class=\"tab-btn\" onclick=\"switchTab(event,'historico')\">Hist\u00f3rico de Emiss\u00f5es<\/button>\r\n          <button class=\"tab-btn\" onclick=\"switchTab(event,'indicadores')\">Indicadores<\/button>\r\n          <button class=\"tab-btn\" onclick=\"abrirModalAuthFinanceiro(event)\">Financeiro ADM<\/button>\r\n        <\/div>\r\n\r\n        <!-- Cadastros -->\r\n        <div id=\"cadastros\" class=\"ag-card p-4 md:p-6 overflow-x-auto\">\r\n          <h3 class=\"text-yellow-400 font-bold mb-4\">Cadastros realizados<\/h3>\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th>Cliente<\/th><th>CNPJ<\/th><th>Contrato<\/th><th>Telefone<\/th><th>Email<\/th><th>Chave<\/th><th>Emiss\u00e3o<\/th><th>Vendedor<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"listaCadastros\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n\r\n        <!-- Hist\u00f3rico -->\r\n        <div id=\"historico\" class=\"ag-card p-4 md:p-6 hidden\">\r\n          <h3 class=\"text-yellow-400 font-bold mb-6\">Libera\u00e7\u00e3o de acesso \u00e0 carteira do cliente<\/h3>\r\n\r\n          <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-4\">\r\n            <input id=\"usoCnpj\" class=\"ag-input\" placeholder=\"CNPJ do cliente\" \/>\r\n            <input id=\"usoContrato\" class=\"ag-input\" placeholder=\"N\u00famero do contrato\" \/>\r\n            <button class=\"ag-btn\" onclick=\"gerarTokenUso()\">GERAR TOKEN<\/button>\r\n          <\/div>\r\n\r\n          <div class=\"mt-4\">\r\n            <label class=\"text-sm text-gray-400\">Token de acesso do cliente<\/label>\r\n            <input id=\"usoToken\" class=\"ag-input font-mono text-yellow-300 font-extrabold\" readonly \/>\r\n          <\/div>\r\n          <p class=\"text-xs text-gray-400 mt-4\">Este token libera o acesso do cliente \u00e0 carteira de b\u00f4nus.<\/p>\r\n\r\n          <hr class=\"my-6 border-gray-800\" \/>\r\n\r\n          <h3 class=\"text-xl font-bold text-yellow-400 mb-4\">Hist\u00f3rico de Emiss\u00f5es de Uso<\/h3>\r\n\r\n          <div class=\"overflow-x-auto\">\r\n            <table class=\"min-w-full text-sm\">\r\n              <thead class=\"border-b border-gray-800 text-gray-400\">\r\n                <tr><th>Data<\/th><th>Cliente<\/th><th>CNPJ<\/th><th>Contrato<\/th><th>Token<\/th><\/tr>\r\n              <\/thead>\r\n              <tbody id=\"listaHistoricoEmissoes\">\r\n                <tr><td colspan=\"5\" class=\"text-center py-4 text-gray-500\">Nenhuma emiss\u00e3o de uso registrada.<\/td><\/tr>\r\n              <\/tbody>\r\n            <\/table>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <!-- Indicadores -->\r\n        <div id=\"indicadores\" class=\"ag-card p-4 md:p-6 hidden\">\r\n          <h3 class=\"text-yellow-400 font-bold mb-4\">Indicadores<\/h3>\r\n\r\n          <!-- \u2705 FILTROS (agora com vendedor multi) -->\r\n          <div class=\"grid grid-cols-1 md:grid-cols-6 gap-4 mb-6\">\r\n\r\n            <select id=\"indMes\" class=\"ag-input\">\r\n              <option value=\"\">Todos os Meses<\/option>\r\n              <option value=\"01\">Janeiro<\/option><option value=\"02\">Fevereiro<\/option><option value=\"03\">Mar\u00e7o<\/option>\r\n              <option value=\"04\">Abril<\/option><option value=\"05\">Maio<\/option><option value=\"06\">Junho<\/option>\r\n              <option value=\"07\">Julho<\/option><option value=\"08\">Agosto<\/option><option value=\"09\">Setembro<\/option>\r\n              <option value=\"10\">Outubro<\/option><option value=\"11\">Novembro<\/option><option value=\"12\">Dezembro<\/option>\r\n            <\/select>\r\n\r\n            <select id=\"indAno\" class=\"ag-input\">\r\n              <option value=\"\">Todos os Anos<\/option>\r\n            <\/select>\r\n\r\n            <input id=\"indClienteFiltro\" class=\"ag-input\" placeholder=\"Cliente ou CNPJ (opcional)\" \/>\r\n\r\n            <!-- \u2705 NOVO: filtro multi vendedor -->\r\n            <div class=\"relative\">\r\n              <button id=\"btnVendedores\" type=\"button\"\r\n                class=\"ag-input text-left flex items-center justify-between gap-2\"\r\n                onclick=\"toggleVendDropdown()\">\r\n                <span id=\"vendLabel\" class=\"truncate\">Todos os vendedores<\/span>\r\n                <span class=\"text-gray-300\">\u25be<\/span>\r\n              <\/button>\r\n\r\n              <div id=\"vendDropdown\"\r\n                class=\"hidden absolute z-50 mt-2 w-full ag-card p-3 rounded-xl\"\r\n                style=\"max-height:260px; overflow:auto;\">\r\n                <div class=\"flex items-center justify-between mb-2\">\r\n                  <span class=\"text-xs text-gray-300 font-bold\">Selecione vendedores<\/span>\r\n                  <button type=\"button\"\r\n                    class=\"text-xs px-2 py-1 rounded-lg border border-yellow-400\/30 hover:border-yellow-400\/60 hover:bg-yellow-400\/10\"\r\n                    onclick=\"limparVendedores()\">Limpar<\/button>\r\n                <\/div>\r\n                <div id=\"vendOptions\" class=\"space-y-2\"><\/div>\r\n              <\/div>\r\n            <\/div>\r\n\r\n            <button class=\"ag-btn md:col-span-2\" onclick=\"carregarIndicadores()\">APLICAR FILTROS<\/button>\r\n          <\/div>\r\n\r\n          <!-- \u2705 CARDS (\u2705 atualizado p\/ 6 colunas e adiciona \"B\u00f4nus vencidos (carteira expirada)\") -->\r\n          <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6 gap-4 mb-8\">\r\n            <div class=\"ag-card p-3 rounded-[18px] cursor-pointer hover:border-yellow-400\/50 transition\" onclick=\"abrirDetalheAPagar()\">\r\n              <div class=\"text-[11px] text-gray-400\">Valor total a pagar (per\u00edodo)<\/div>\r\n              <div id=\"indTotalAPagar\" class=\"text-lg font-extrabold text-yellow-300\">R$ 0,00<\/div>\r\n              <div class=\"text-[10px] text-gray-500 mt-1\">Clique para ver o detalhamento.<\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-3 rounded-[18px] cursor-pointer hover:border-yellow-400\/50 transition\" onclick=\"abrirDetalheUso()\">\r\n              <div class=\"text-[11px] text-gray-400\">Valor total utilizado pelo cliente<\/div>\r\n              <div id=\"indTotalUsoCliente\" class=\"text-lg font-extrabold text-green-400\">R$ 0,00<\/div>\r\n              <div class=\"text-[10px] text-gray-500 mt-1\">Clique para ver o hist\u00f3rico de uso.<\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-3 rounded-[18px] cursor-pointer hover:border-yellow-400\/50 transition\" onclick=\"abrirDetalhePago()\">\r\n              <div class=\"text-[11px] text-gray-400\">Valor total pago pelo financeiro<\/div>\r\n              <div id=\"indTotalPagoFinanceiro\" class=\"text-lg font-extrabold text-blue-300\">R$ 0,00<\/div>\r\n              <div class=\"text-[10px] text-gray-500 mt-1\">Clique para ver o hist\u00f3rico de pagamentos.<\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-3 rounded-[18px]\">\r\n              <div class=\"text-[11px] text-gray-400\">Contratos na pen\u00faltima parcela paga<\/div>\r\n              <div id=\"indPenultimaPaga\" class=\"text-lg font-extrabold\">0<\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-3 rounded-[18px] cursor-pointer hover:border-yellow-400\/50 transition\" onclick=\"abrirDetalheAtrasos()\">\r\n              <div class=\"text-[11px] text-gray-400\">Contratos com parcelas atrasadas<\/div>\r\n              <div id=\"indAtrasados\" class=\"text-lg font-extrabold text-red-400\">0<\/div>\r\n              <div class=\"text-[10px] text-gray-500 mt-1\">Clique para listar atrasos.<\/div>\r\n            <\/div>\r\n\r\n            <!-- \u2705 NOVO: B\u00d4NUS VENCIDOS (saldo expirado na carteira ap\u00f3s 365 dias) -->\r\n            <div class=\"ag-card p-3 rounded-[18px] cursor-pointer hover:border-yellow-400\/50 transition\" onclick=\"abrirDetalheBonusVencidosCarteira()\">\r\n              <div class=\"text-[11px] text-gray-400\">B\u00f4nus vencidos (carteira expirada)<\/div>\r\n              <div id=\"indBonusVencidosQtd\" class=\"text-lg font-extrabold text-orange-300\">0<\/div>\r\n              <div id=\"indBonusVencidosValor\" class=\"text-xs font-bold text-orange-200 mt-1\">R$ 0,00<\/div>\r\n              <div class=\"text-[10px] text-gray-500 mt-1\">Clique para ver detalhes.<\/div>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <!-- \u2705 LINHAS CLIC\u00c1VEIS -->\r\n          <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <h4 class=\"text-lg font-bold mb-2\">R$ a pagar (por m\u00eas)<\/h4>\r\n              <p class=\"subtle mb-2\">Clique no ponto do m\u00eas para abrir o detalhamento.<\/p>\r\n              <canvas id=\"chartIndPagar\"><\/canvas>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <h4 class=\"text-lg font-bold mb-2\">B\u00f4nus pago (por m\u00eas)<\/h4>\r\n              <p class=\"subtle mb-2\">Clique no ponto do m\u00eas para ver pagamentos.<\/p>\r\n              <canvas id=\"chartIndBonus\"><\/canvas>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <h4 class=\"text-lg font-bold mb-2\">Atrasos (por m\u00eas)<\/h4>\r\n              <p class=\"subtle mb-2\">Clique no ponto do m\u00eas para listar atrasos.<\/p>\r\n              <canvas id=\"chartIndAtraso\"><\/canvas>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <!-- \u2705 Pesquisas de Satisfa\u00e7\u00e3o -->\r\n          <div class=\"mt-6 grid grid-cols-1 lg:grid-cols-3 gap-6\">\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <div class=\"text-xs text-gray-400\">Respostas de satisfa\u00e7\u00e3o (per\u00edodo)<\/div>\r\n              <div id=\"indSatisfRespostas\" class=\"text-2xl font-extrabold text-purple-300\">0<\/div>\r\n              <div class=\"text-[11px] text-gray-500 mt-1\">Total de respostas na cole\u00e7\u00e3o.<\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <div class=\"text-xs text-gray-400\">M\u00e9dia de satisfa\u00e7\u00e3o (0\u201310)<\/div>\r\n              <div id=\"indSatisfMedia\" class=\"text-2xl font-extrabold text-purple-300\">\u2014<\/div>\r\n              <div class=\"text-[11px] text-gray-500 mt-1\">Se vier 1\u20135, converte para 0\u201310.<\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <div class=\"text-xs text-gray-400\">NPS (se houver nota 0\u201310)<\/div>\r\n              <div id=\"indSatisfNps\" class=\"text-2xl font-extrabold text-purple-300\">\u2014<\/div>\r\n              <div class=\"text-[11px] text-gray-500 mt-1\">Promotores (9\u201310) \u2212 Detratores (0\u20136).<\/div>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"mt-6 ag-card p-4 rounded-[18px]\">\r\n            <h4 class=\"text-lg font-bold mb-2\">Satisfa\u00e7\u00e3o por m\u00eas<\/h4>\r\n            <canvas id=\"chartIndSatisfacao\"><\/canvas>\r\n            <p class=\"text-[11px] text-gray-500 mt-2\">\r\n              Mostra <b>quantidade<\/b> e <b>m\u00e9dia<\/b> por m\u00eas (se houver nota).\r\n            <\/p>\r\n          <\/div>\r\n\r\n          <!-- \u2705 Google Forms (Pizzas por pergunta + lista clic\u00e1vel) -->\r\n          <div class=\"mt-6 grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <h4 class=\"text-lg font-bold mb-1\">1. Condi\u00e7\u00e3o f\u00edsica do container<\/h4>\r\n              <p class=\"subtle mb-3\">Clique em uma op\u00e7\u00e3o para ver os clientes.<\/p>\r\n              <canvas id=\"chartSatQ1\"><\/canvas>\r\n              <div id=\"listSatQ1\" class=\"mt-3 space-y-2\"><\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <h4 class=\"text-lg font-bold mb-1\">2. Prazo e log\u00edstica de entrega<\/h4>\r\n              <p class=\"subtle mb-3\">Clique em uma op\u00e7\u00e3o para ver os clientes.<\/p>\r\n              <canvas id=\"chartSatQ2\"><\/canvas>\r\n              <div id=\"listSatQ2\" class=\"mt-3 space-y-2\"><\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <h4 class=\"text-lg font-bold mb-1\">3. Fator determinante do neg\u00f3cio<\/h4>\r\n              <p class=\"subtle mb-3\">Clique em uma op\u00e7\u00e3o para ver os clientes.<\/p>\r\n              <canvas id=\"chartSatQ3\"><\/canvas>\r\n              <div id=\"listSatQ3\" class=\"mt-3 space-y-2\"><\/div>\r\n            <\/div>\r\n\r\n            <div class=\"ag-card p-4 rounded-[18px]\">\r\n              <h4 class=\"text-lg font-bold mb-1\">4. Canal que conheceu a AGISA<\/h4>\r\n              <p class=\"subtle mb-3\">Clique em uma op\u00e7\u00e3o para ver os clientes.<\/p>\r\n              <canvas id=\"chartSatQ4\"><\/canvas>\r\n              <div id=\"listSatQ4\" class=\"mt-3 space-y-2\"><\/div>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <!-- Financeiro -->\r\n        <div id=\"financeiro\" class=\"ag-card p-4 md:p-6 hidden\">\r\n          <h3 class=\"text-yellow-400 font-bold mb-4\">Financeiro ADM<\/h3>\r\n          <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-6\">\r\n            <input id=\"finCnpj\" class=\"ag-input\" placeholder=\"CNPJ\" \/>\r\n            <input id=\"finContrato\" class=\"ag-input\" placeholder=\"Contrato\" \/>\r\n            <button class=\"ag-btn\" onclick=\"buscarFinanceiroADM()\">BUSCAR<\/button>\r\n          <\/div>\r\n          <div id=\"resultadoFinanceiro\" class=\"text-sm overflow-x-auto\"><\/div>\r\n        <\/div>\r\n\r\n      <\/section>\r\n\r\n      <!-- Dashboard emiss\u00f5es (aba hist\u00f3rico) -->\r\n      <section id=\"dashboardEmissoes\" class=\"ag-card p-4 md:p-6 hidden\">\r\n        <h2 class=\"text-xl font-bold text-yellow-400 mb-6\">Dashboard de Emiss\u00f5es de Uso<\/h2>\r\n\r\n        <div class=\"grid grid-cols-1 md:grid-cols-4 gap-4 mb-6\">\r\n          <select id=\"filtroMes\" class=\"ag-input\">\r\n            <option value=\"\">Todos os Meses<\/option>\r\n            <option value=\"01\">Janeiro<\/option><option value=\"02\">Fevereiro<\/option><option value=\"03\">Mar\u00e7o<\/option>\r\n            <option value=\"04\">Abril<\/option><option value=\"05\">Maio<\/option><option value=\"06\">Junho<\/option>\r\n            <option value=\"07\">Julho<\/option><option value=\"08\">Agosto<\/option><option value=\"09\">Setembro<\/option>\r\n            <option value=\"10\">Outubro<\/option><option value=\"11\">Novembro<\/option><option value=\"12\">Dezembro<\/option>\r\n          <\/select>\r\n\r\n          <select id=\"filtroAno\" class=\"ag-input\">\r\n            <option value=\"\">Todos os Anos<\/option>\r\n          <\/select>\r\n\r\n          <button class=\"ag-btn md:col-span-2\" onclick=\"carregarDashboard()\">APLICAR FILTROS<\/button>\r\n        <\/div>\r\n\r\n        <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n          <div class=\"ag-card p-4 rounded-[18px]\">\r\n            <h4 class=\"text-lg font-bold mb-2\">Emiss\u00f5es por M\u00eas\/Ano<\/h4>\r\n            <p class=\"subtle mb-2\">Clique no gr\u00e1fico para ver detalhes por m\u00eas.<\/p>\r\n            <canvas id=\"chartEmissaoMensal\"><\/canvas>\r\n\r\n            <div class=\"mt-5\">\r\n              <canvas id=\"chartEmissaoMensalLinha\"><\/canvas>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"ag-card p-4 rounded-[18px]\">\r\n            <h4 class=\"text-lg font-bold mb-2\">Top 5 Clientes por Emiss\u00e3o (pizza)<\/h4>\r\n            <canvas id=\"chartEmissaoCliente\"><\/canvas>\r\n          <\/div>\r\n        <\/div>\r\n      <\/section>\r\n\r\n    <\/main>\r\n\r\n    <!-- \u2705 Modal Autentica\u00e7\u00e3o Financeiro -->\r\n    <div id=\"modalAuthFinanceiro\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-md p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharModalAuthFinanceiro()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n        <h2 class=\"text-lg font-extrabold text-yellow-300 mb-4\">Acesso Restrito<\/h2>\r\n        <p class=\"text-sm text-gray-400 mb-4\">A aba Financeiro requer autentica\u00e7\u00e3o adicional.<\/p>\r\n        \r\n        <div class=\"space-y-3\">\r\n          <div>\r\n            <label class=\"text-xs text-gray-400\">Senha<\/label>\r\n            <input id=\"senhaFinanceiro\" type=\"password\" class=\"ag-input\" placeholder=\"Digite a senha\" autocomplete=\"off\" \/>\r\n          <\/div>\r\n          <div id=\"msgErroSenha\" class=\"hidden text-sm text-red-300 bg-red-500\/10 border border-red-400\/20 p-3 rounded-xl\"><\/div>\r\n          <button class=\"ag-btn\" onclick=\"verificarSenhaFinanceiro()\">ACESSAR<\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Modal Recibo -->\r\n    <div id=\"modalRecibo\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-white text-black w-full max-w-md p-6 relative modal-shell\">\r\n        <button onclick=\"fecharRecibo()\" class=\"absolute top-3 right-4 text-xl\">\u2715<\/button>\r\n        <h2 class=\"text-lg font-bold mb-4\">Comprovante de envio de b\u00f4nus<\/h2>\r\n\r\n        <p><b>Benefici\u00e1rio:<\/b> Cliente<\/p>\r\n        <p><b>Cliente:<\/b> <span id=\"rCliente\"><\/span><\/p>\r\n        <p><b>CNPJ:<\/b> <span id=\"rCnpj\"><\/span><\/p>\r\n        <p><b>Contrato:<\/b> <span id=\"rContrato\"><\/span><\/p>\r\n        <p><b>Parcela:<\/b> <span id=\"rParcela\"><\/span><\/p>\r\n\r\n        <p><b>Valor:<\/b> R$ <span id=\"rTotal\"><\/span><\/p>\r\n        <p><b>%:<\/b> <span id=\"rPercent\"><\/span><\/p>\r\n        <p class=\"font-bold text-green-700\">Valor enviado: R$ <span id=\"rCashback\"><\/span><\/p>\r\n\r\n        <p><b>Data:<\/b> <span id=\"rData\"><\/span><\/p>\r\n        <p><b>Validade:<\/b> <span id=\"rValidade\"><\/span><\/p>\r\n\r\n        <p class=\"text-xs\">Autentica\u00e7\u00e3o: <span id=\"rAuth\"><\/span><\/p>\r\n\r\n        <button onclick=\"window.print()\" class=\"ag-btn mt-4\">IMPRIMIR<\/button>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- \u2705 Modal Detalhe A Pagar -->\r\n    <div id=\"modalAPagar\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-5xl p-4 md:p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharDetalheAPagar()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n\r\n        <h2 class=\"text-lg font-extrabold text-yellow-300 mb-1\">Detalhamento do valor a pagar<\/h2>\r\n        <p id=\"apagarSub\" class=\"text-xs text-gray-400 mb-4\">\u2014<\/p>\r\n\r\n        <div class=\"overflow-x-auto max-h-[60vh] overflow-y-auto\">\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th class=\"text-left\">M\u00eas\/Ano<\/th>\r\n                <th class=\"text-left\">Cliente<\/th>\r\n                <th class=\"text-left\">CNPJ<\/th>\r\n                <th class=\"text-left\">Contrato<\/th>\r\n                <th class=\"text-right\">Valor<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"listaAPagarDetalhe\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- \u2705 Modal Detalhe USO -->\r\n    <div id=\"modalUso\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-5xl p-4 md:p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharDetalheUso()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n\r\n        <h2 class=\"text-lg font-extrabold text-green-300 mb-1\">Hist\u00f3rico de uso (cliente)<\/h2>\r\n        <p id=\"usoSub\" class=\"text-xs text-gray-400 mb-4\">\u2014<\/p>\r\n\r\n        <div class=\"overflow-x-auto max-h-[60vh] overflow-y-auto\">\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th class=\"text-left\">Data<\/th>\r\n                <th class=\"text-left\">Cliente<\/th>\r\n                <th class=\"text-left\">CNPJ<\/th>\r\n                <th class=\"text-left\">Contrato<\/th>\r\n                <th class=\"text-left\">Origem<\/th>\r\n                <th class=\"text-right\">Valor<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"listaUsoDetalhe\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- \u2705 Modal Detalhe PAGO -->\r\n    <div id=\"modalPago\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-6xl p-4 md:p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharDetalhePago()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n\r\n        <h2 class=\"text-lg font-extrabold text-blue-300 mb-1\">Hist\u00f3rico de pagamentos (financeiro)<\/h2>\r\n        <p id=\"pagoSub\" class=\"text-xs text-gray-400 mb-4\">\u2014<\/p>\r\n\r\n        <div class=\"overflow-x-auto max-h-[60vh] overflow-y-auto\">\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th class=\"text-left\">Data<\/th>\r\n                <th class=\"text-left\">Cliente<\/th>\r\n                <th class=\"text-left\">CNPJ<\/th>\r\n                <th class=\"text-left\">Contrato<\/th>\r\n                <th class=\"text-right\">Parcela<\/th>\r\n                <th class=\"text-right\">Valor parcela<\/th>\r\n                <th class=\"text-right\">B\u00f4nus pago<\/th>\r\n                <th class=\"text-left\">Auth<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"listaPagoDetalhe\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- \u2705 Modal Detalhe ATRASOS -->\r\n    <div id=\"modalAtrasos\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-6xl p-4 md:p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharDetalheAtrasos()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n\r\n        <h2 class=\"text-lg font-extrabold text-red-300 mb-1\">Contratos com atraso<\/h2>\r\n        <p id=\"atrasosSub\" class=\"text-xs text-gray-400 mb-4\">\u2014<\/p>\r\n\r\n        <div class=\"overflow-x-auto max-h-[60vh] overflow-y-auto\">\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th class=\"text-left\">M\u00eas\/Ano<\/th>\r\n                <th class=\"text-left\">Cliente<\/th>\r\n                <th class=\"text-left\">CNPJ<\/th>\r\n                <th class=\"text-left\">Contrato<\/th>\r\n                <th class=\"text-right\">Parcela<\/th>\r\n                <th class=\"text-right\">Dias em atraso<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"listaAtrasosDetalhe\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- \u2705 Modal: Clientes por op\u00e7\u00e3o (Pesquisa Satisfa\u00e7\u00e3o) -->\r\n    <div id=\"modalSatClientes\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-6xl p-4 md:p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharModalSatClientes()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n        <h2 id=\"satCliTitle\" class=\"text-lg font-extrabold text-yellow-300 mb-1\">\u2014<\/h2>\r\n        <p id=\"satCliSub\" class=\"text-xs text-gray-400 mb-4\">\u2014<\/p>\r\n\r\n        <div class=\"overflow-x-auto max-h-[60vh] overflow-y-auto\">\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th class=\"text-left\">Data<\/th>\r\n                <th class=\"text-left\">Cliente<\/th>\r\n                <th class=\"text-left\">CNPJ<\/th>\r\n                <th class=\"text-left\">Contrato Novo<\/th>\r\n                <th class=\"text-left\">Token<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"satCliTbody\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- \u2705 Modal Detalhe Emiss\u00f5es por M\u00eas\/Ano (clique no gr\u00e1fico) -->\r\n    <div id=\"modalEmissoesMes\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-6xl p-4 md:p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharEmissoesMes()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n        <h2 id=\"emissoesMesTitle\" class=\"text-lg font-extrabold text-yellow-300 mb-1\">Emiss\u00f5es \u2014 \u2014<\/h2>\r\n        <p id=\"emissoesMesSub\" class=\"text-xs text-gray-400 mb-4\">\u2014<\/p>\r\n\r\n        <div class=\"overflow-x-auto max-h-[60vh] overflow-y-auto\">\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th class=\"text-left\">Data<\/th>\r\n                <th class=\"text-left\">Cliente<\/th>\r\n                <th class=\"text-left\">CNPJ<\/th>\r\n                <th class=\"text-left\">Contrato<\/th>\r\n                <th class=\"text-left\">Token<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"listaEmissoesMes\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- \u2705 NOVO MODAL: B\u00d4NUS VENCIDOS (CARTEIRA EXPIRADA) -->\r\n    <div id=\"modalBonusVencidosCarteira\" class=\"fixed inset-0 bg-black\/70 hidden items-center justify-center z-50 p-3\">\r\n      <div class=\"bg-[#0b0b0b] text-white w-full max-w-6xl p-4 md:p-6 relative border border-yellow-400\/30 modal-shell\">\r\n        <button onclick=\"fecharDetalheBonusVencidosCarteira()\" class=\"absolute top-3 right-4 text-xl text-gray-200\">\u2715<\/button>\r\n\r\n        <h2 class=\"text-lg font-extrabold text-orange-300 mb-1\">B\u00f4nus vencidos (carteira expirada)<\/h2>\r\n        <p id=\"bonusVencidosSub\" class=\"text-xs text-gray-400 mb-4\">\u2014<\/p>\r\n\r\n        <div class=\"overflow-x-auto max-h-[60vh] overflow-y-auto\">\r\n          <table class=\"min-w-full text-sm\">\r\n            <thead class=\"border-b border-gray-800 text-gray-400\">\r\n              <tr>\r\n                <th class=\"text-left\">Data do cr\u00e9dito<\/th>\r\n                <th class=\"text-left\">Validade<\/th>\r\n                <th class=\"text-left\">Cliente<\/th>\r\n                <th class=\"text-left\">CNPJ<\/th>\r\n                <th class=\"text-left\">Contrato<\/th>\r\n                <th class=\"text-right\">Saldo vencido (R$)<\/th>\r\n                <th class=\"text-right\">Dias expirado<\/th>\r\n                <th class=\"text-left\">Origem<\/th>\r\n              <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"listaBonusVencidosCarteira\"><\/tbody>\r\n          <\/table>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n  <\/div><!-- \/appView -->\r\n\r\n<script>\r\ndocument.addEventListener(\"DOMContentLoaded\", function () {\r\n\r\n  \/\/ =========================\r\n  \/\/ \u2705 FIREBASE INIT (1x)\r\n  \/\/ =========================\r\n  firebase.initializeApp({\r\n    apiKey: \"AIzaSyDlk2mb_k97TmVxjMjIScx6JW2R3R9h0hA\",\r\n    authDomain: \"agisa-containners-ltda.firebaseapp.com\",\r\n    projectId: \"agisa-containners-ltda\",\r\n  });\r\n\r\n  const auth = firebase.auth();\r\n  const db = firebase.firestore();\r\n  window.db = db;\r\n\r\n  try { auth.setPersistence(firebase.auth.Auth.Persistence.LOCAL); } catch(e){}\r\n\r\n  const el = (id)=>document.getElementById(id);\r\n\r\n  \/\/ =========================\r\n  \/\/ \u2705 VIEW CONTROL (SEM FLASH)\r\n  \/\/ =========================\r\n  const loginView  = el(\"loginView\");\r\n  const appView    = el(\"appView\");\r\n  const loginEmail = el(\"loginEmail\");\r\n  const loginSenha = el(\"loginSenha\");\r\n  const loginBtn   = el(\"loginBtn\");\r\n  const loginMsg   = el(\"loginMsg\");\r\n  const logoutBtn  = el(\"logoutBtn\");\r\n  const whoami     = el(\"whoami\");\r\n\r\n  function setView(view, message){\r\n    if(view === \"app\"){\r\n      loginView.style.display = \"none\";\r\n      appView.style.display   = \"block\";\r\n      loginMsg.classList.add(\"hidden\");\r\n    }else{\r\n      appView.style.display   = \"none\";\r\n      loginView.style.display = \"flex\";\r\n      if(message){\r\n        loginMsg.textContent = message;\r\n        loginMsg.classList.remove(\"hidden\");\r\n      }else{\r\n        loginMsg.classList.add(\"hidden\");\r\n      }\r\n    }\r\n  }\r\n\r\n  \/\/ come\u00e7a SEMPRE no login\r\n  setView(\"login\");\r\n\r\n  async function ensureAdmin(user){\r\n    if(!user) return false;\r\n    return ADMIN_UIDS.includes(user.uid);\r\n  }\r\n\r\n  let appInited = false;\r\n\r\n  loginBtn.addEventListener(\"click\", async ()=>{\r\n    const email = (loginEmail.value || \"\").trim();\r\n    const senha = (loginSenha.value || \"\").trim();\r\n\r\n    if(!email || !senha){\r\n      setView(\"login\", \"Preencha login (email) e senha.\");\r\n      return;\r\n    }\r\n\r\n    loginBtn.disabled = true;\r\n    loginBtn.textContent = \"ENTRANDO...\";\r\n\r\n    try{\r\n      const cred = await auth.signInWithEmailAndPassword(email, senha);\r\n      const user = cred.user;\r\n\r\n      const ok = await ensureAdmin(user);\r\n      if(!ok){\r\n        await auth.signOut();\r\n        setView(\"login\", \"Acesso negado. UID n\u00e3o autorizado.\");\r\n        return;\r\n      }\r\n\r\n      whoami.textContent = user.email || user.uid || \"\u2014\";\r\n      setView(\"app\");\r\n      if(!appInited){\r\n        appInited = true;\r\n        initAppAfterLogin();\r\n      }\r\n\r\n    }catch(err){\r\n      console.error(\"Login erro:\", err);\r\n      setView(\"login\", \"Erro ao entrar. Verifique email\/senha.\");\r\n    }finally{\r\n      loginBtn.disabled = false;\r\n      loginBtn.textContent = \"ENTRAR\";\r\n    }\r\n  });\r\n\r\n  logoutBtn?.addEventListener(\"click\", async ()=>{\r\n    await auth.signOut();\r\n    appInited = false;\r\n    location.reload();\r\n  });\r\n\r\n  auth.onAuthStateChanged(async (user)=>{\r\n    if(!user){\r\n      setView(\"login\");\r\n      return;\r\n    }\r\n    const ok = await ensureAdmin(user);\r\n    if(!ok){\r\n      await auth.signOut();\r\n      setView(\"login\", \"Acesso negado. UID n\u00e3o autorizado.\");\r\n      return;\r\n    }\r\n    whoami.textContent = user.email || user.uid || \"\u2014\";\r\n    setView(\"app\");\r\n    if(!appInited){\r\n      appInited = true;\r\n      initAppAfterLogin();\r\n    }\r\n  });\r\n\r\n  \/\/ =========================\r\n  \/\/ \u2705 APP (S\u00d3 DEPOIS DO LOGIN)\r\n  \/\/ =========================\r\n  function initAppAfterLogin(){\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 VALIDADE 12 MESES (helpers)\r\n    \/\/ =========================\r\n    function addMonthsSafe(date, months){\r\n      const d = new Date(date);\r\n      const day = d.getDate();\r\n      d.setMonth(d.getMonth() + months);\r\n      if (d.getDate() < day) d.setDate(0);\r\n      return d;\r\n    }\r\n    function toDateSafe(v){\r\n      if(!v) return null;\r\n      if(v.toDate) {\r\n        const d = v.toDate();\r\n        return isNaN(d.getTime()) ? null : d;\r\n      }\r\n      const d2 = new Date(v);\r\n      return isNaN(d2.getTime()) ? null : d2;\r\n    }\r\n    function fmtDateBR(v){\r\n      const d = toDateSafe(v);\r\n      return d ? d.toLocaleDateString(\"pt-BR\") : \"\u2014\";\r\n    }\r\n\r\n    \/\/ \u2705 NOVO (para saldo vencido)\r\n    function daysDiff(a,b){\r\n      return Math.ceil((a.getTime() - b.getTime()) \/ (1000*60*60*24));\r\n    }\r\n\r\n    function safeSendEmail(templateId, params){\r\n      if(!templateId) return Promise.resolve();\r\n      return emailjs.send(EMAILJS_SERVICE_ID, templateId, params)\r\n        .then((res)=>{ console.log(\"EmailJS OK:\", templateId, res); })\r\n        .catch((err)=>{ console.error(\"EmailJS ERRO:\", templateId, err); });\r\n    }\r\n\r\n    \/\/ refs\r\n    const clientName = el(\"clientName\");\r\n    const cnpj = el(\"cnpj\");\r\n    const phone = el(\"phone\");\r\n    const email = el(\"email\");\r\n    const commercial = el(\"commercial\");\r\n    const contract = el(\"contract\");\r\n    const months = el(\"months\");\r\n    const dataMobilizacao = el(\"dataMobilizacao\");\r\n    const dataDesmobilizacao = el(\"dataDesmobilizacao\");\r\n    const negotiation = el(\"negotiation\");\r\n    const percent = el(\"percent\");\r\n    const cashback = el(\"cashback\");\r\n    const token = el(\"token\");\r\n    const saveBtn = el(\"saveBtn\");\r\n\r\n    const listaCadastros = el(\"listaCadastros\");\r\n\r\n    const usoCnpj = el(\"usoCnpj\");\r\n    const usoContrato = el(\"usoContrato\");\r\n    const usoToken = el(\"usoToken\");\r\n    const filtroMes = el(\"filtroMes\");\r\n    const filtroAno = el(\"filtroAno\");\r\n\r\n    const indMes = el(\"indMes\");\r\n    const indAno = el(\"indAno\");\r\n    const indClienteFiltro = el(\"indClienteFiltro\");\r\n\r\n    const finCnpj = el(\"finCnpj\");\r\n    const finContrato = el(\"finContrato\");\r\n    const resultadoFinanceiro = el(\"resultadoFinanceiro\");\r\n\r\n    window.__apagarDetalhe = [];\r\n    window.__usoDetalhe = [];\r\n    window.__pagoDetalhe = [];\r\n    window.__atrasosDetalhe = [];\r\n    window.__indicadoresFiltroTexto = \"\u2014\";\r\n    window.__satRaw = [];\r\n    window.__emissoesDados = [];\r\n\r\n    \/\/ \u2705 NOVO: detalhes do saldo vencido na carteira (365 dias)\r\n    window.__bonusVencidosCarteira = [];\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 FILTRO MULTI-VENDEDOR (Indicadores)\r\n    \/\/ =========================\r\n    const vendDropdown = el(\"vendDropdown\");\r\n    const vendOptions  = el(\"vendOptions\");\r\n    const vendLabel    = el(\"vendLabel\");\r\n\r\n    window.__vendSel = new Set();\r\n\r\n    window.toggleVendDropdown = function(){\r\n      vendDropdown.classList.toggle(\"hidden\");\r\n    };\r\n\r\n    \/\/ fecha dropdown clicando fora\r\n    document.addEventListener(\"click\", (ev)=>{\r\n      const btn = el(\"btnVendedores\");\r\n      if(!btn || !vendDropdown) return;\r\n      const clickedInside = btn.contains(ev.target) || vendDropdown.contains(ev.target);\r\n      if(!clickedInside) vendDropdown.classList.add(\"hidden\");\r\n    });\r\n\r\n    window.limparVendedores = function(){\r\n      window.__vendSel.clear();\r\n      vendOptions?.querySelectorAll(\"input[type='checkbox']\").forEach(ch=> ch.checked = false);\r\n      atualizarLabelVendedores();\r\n    };\r\n\r\n    function normalizaVend(v){ return String(v||\"\").trim(); }\r\n\r\n    function atualizarLabelVendedores(){\r\n      const arr = Array.from(window.__vendSel);\r\n      if(!arr.length){\r\n        vendLabel.textContent = \"Todos os vendedores\";\r\n        return;\r\n      }\r\n      if(arr.length === 1){\r\n        vendLabel.textContent = arr[0];\r\n        return;\r\n      }\r\n      vendLabel.textContent = `${arr.length} vendedores selecionados`;\r\n    }\r\n\r\n    async function carregarListaVendedores(){\r\n      if(!vendOptions) return;\r\n      vendOptions.innerHTML = `<div class=\"text-xs text-gray-400\">Carregando vendedores...<\/div>`;\r\n\r\n      try{\r\n        const snap = await db.collection(\"cashback_contracts\").get();\r\n        const setV = new Set();\r\n\r\n        snap.forEach(doc=>{\r\n          const d = doc.data() || {};\r\n          const v = normalizaVend(d[\"Comercial Nome\"] || d.comercial || d.vendedor || \"\");\r\n          if(v) setV.add(v);\r\n        });\r\n\r\n        const vendedores = Array.from(setV).sort((a,b)=> a.localeCompare(b));\r\n\r\n        if(!vendedores.length){\r\n          vendOptions.innerHTML = `<div class=\"text-xs text-gray-400\">Nenhum vendedor encontrado.<\/div>`;\r\n          return;\r\n        }\r\n\r\n        vendOptions.innerHTML = vendedores.map(v=>{\r\n          const id = \"vend_\" + v.replace(\/\\W+\/g,\"_\").slice(0,40);\r\n          return `\r\n            <label class=\"vend-item\" for=\"${id}\">\r\n              <input id=\"${id}\" type=\"checkbox\" data-v=\"${v}\" \/>\r\n              <span class=\"text-sm\">${v}<\/span>\r\n            <\/label>\r\n          `;\r\n        }).join(\"\");\r\n\r\n        vendOptions.querySelectorAll(\"input[type='checkbox']\").forEach(ch=>{\r\n          ch.addEventListener(\"change\", ()=>{\r\n            const v = ch.getAttribute(\"data-v\");\r\n            if(ch.checked) window.__vendSel.add(v);\r\n            else window.__vendSel.delete(v);\r\n            atualizarLabelVendedores();\r\n          });\r\n        });\r\n\r\n        atualizarLabelVendedores();\r\n      }catch(err){\r\n        console.error(\"Erro carregar vendedores:\", err);\r\n        vendOptions.innerHTML = `<div class=\"text-xs text-red-300\">Erro ao carregar vendedores.<\/div>`;\r\n      }\r\n    }\r\n\r\n    \/\/ carrega lista 1x ao iniciar\r\n    carregarListaVendedores();\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 Helpers gerais\r\n    \/\/ =========================\r\n    function gerarToken() {\r\n      return \"AGISA-\" + Math.random().toString(36).substr(2, 8).toUpperCase();\r\n    }\r\n    function gerarAutenticacao() {\r\n      return \"RCB-\" + Date.now();\r\n    }\r\n    function fmtBRL(n){\r\n      return Number(n||0).toLocaleString(\"pt-BR\",{style:\"currency\",currency:\"BRL\"});\r\n    }\r\n    function mesAnoFromDate(dt){\r\n      const y = dt.getFullYear();\r\n      const m = String(dt.getMonth()+1).padStart(2,\"0\");\r\n      return `${y}-${m}`;\r\n    }\r\n    function matchesFilter(mesAno, mes, ano){\r\n      if(mes && ano) return mesAno === `${ano}-${mes}`;\r\n      if(ano) return mesAno.startsWith(`${ano}-`);\r\n      return true;\r\n    }\r\n    function onlyDigits(s){ return String(s||\"\").replace(\/\\D\/g,\"\"); }\r\n    function normText(s){ return String(s||\"\").toLowerCase().trim(); }\r\n\r\n    function filtroClienteOK(nome, cnpjStr){\r\n      const f = normText(indClienteFiltro?.value || \"\");\r\n      if(!f) return true;\r\n\r\n      const cnpjDigits = onlyDigits(cnpjStr);\r\n      const fDigits = onlyDigits(f);\r\n\r\n      if(fDigits){\r\n        return cnpjDigits.includes(fDigits);\r\n      }\r\n      return normText(nome).includes(f);\r\n    }\r\n\r\n    function normalizeContract(d){\r\n      const meses = Number(d.contratoMeses || 0);\r\n\r\n      const isNovo = d.negociacaoTotal !== undefined && d.negociacaoTotal !== null;\r\n      const totalNovo = Number(d.negociacaoTotal ?? 0);\r\n      const totalAntigo = Number(d.valorMensal ?? d[\"negocia\u00e7\u00e3o Total\"] ?? 0);\r\n\r\n      const totalContrato = isNovo ? totalNovo : totalAntigo;\r\n\r\n      \/\/ \u2705 CORRE\u00c7\u00c3O: Mant\u00e9m o valor TOTAL do contrato em cada parcela\r\n      const parcela = Number(totalContrato);\r\n\r\n      const pct = Number(d.CashbackPercentual ?? 0);\r\n\r\n      const cashbackTotal = Number(\r\n        d.cashbackTotal ??\r\n        ((totalContrato * pct)\/100)\r\n      );\r\n\r\n      \/\/ \u2705 CORRE\u00c7\u00c3O: Cashback tamb\u00e9m \u00e9 mantido por m\u00eas (n\u00e3o dividido)\r\n      const cashbackParcela = Number(\r\n        d.cashbackMensal ??\r\n        ((totalContrato * pct)\/100)\r\n      );\r\n\r\n      return { meses, totalContrato, parcela, pct, cashbackTotal, cashbackParcela };\r\n    }\r\n\r\n    function preencherAnos(selectEl){\r\n      while(selectEl.options.length>1) selectEl.remove(1);\r\n      for(let y=2040;y>=2020;y--){\r\n        const opt=document.createElement(\"option\");\r\n        opt.value=String(y);\r\n        opt.textContent=String(y);\r\n        selectEl.appendChild(opt);\r\n      }\r\n    }\r\n    preencherAnos(filtroAno);\r\n    preencherAnos(indAno);\r\n\r\n    token.value = gerarToken();\r\n\r\n    function recalcularCashbackTotal(){\r\n      const total = Number(negotiation.value || 0);\r\n      const pct = Number(percent.value || 0);\r\n      cashback.value = (total && pct) ? ((total*pct)\/100).toFixed(2) : \"\";\r\n    }\r\n    negotiation.oninput = percent.oninput = months.oninput = recalcularCashbackTotal;\r\n\r\n    saveBtn.onclick = async () => {\r\n      const totalNegociacao = Number(negotiation.value || 0);\r\n      const meses = Number(months.value || 0);\r\n      const pct = Number(percent.value || 0);\r\n\r\n      if(!clientName.value || !cnpj.value || !contract.value || !meses || !dataMobilizacao.value || !totalNegociacao || !pct){\r\n        alert(\"Preencha Cliente, CNPJ, Contrato, Meses, Data Mobiliza\u00e7\u00e3o, Valor Total e %.\");\r\n        return;\r\n      }\r\n\r\n      \/\/ \u2705 CORRE\u00c7\u00c3O: Valor da parcela = valor total do contrato (n\u00e3o dividido)\r\n      const valorParcela = totalNegociacao;\r\n      const cashbackTotal = (totalNegociacao*pct)\/100;\r\n      \/\/ \u2705 CORRE\u00c7\u00c3O: Cashback por m\u00eas = percentual total (n\u00e3o dividido pelos meses)\r\n      const cashbackParcela = (totalNegociacao*pct)\/100;\r\n\r\n      await db.collection(\"cashback_contracts\").add({\r\n        \"Nome do cliente\": clientName.value,\r\n        \"CNPJ\": cnpj.value.replace(\/\\D\/g,\"\"),\r\n        \"Telefone\": phone.value,\r\n        \"Email\": email.value,\r\n        \"Comercial Nome\": commercial.value,\r\n        \"N\u00famero do contrato\": contract.value,\r\n\r\n        contratoMeses: meses,\r\n        dataMobilizacao: dataMobilizacao.value,\r\n        dataDesmobilizacao: dataDesmobilizacao.value,\r\n\r\n        negociacaoTotal: totalNegociacao,\r\n        valorMensal: valorParcela,\r\n        CashbackPercentual: pct,\r\n        cashbackTotal: cashbackTotal,\r\n        cashbackMensal: cashbackParcela,\r\n\r\n        redeemCode: token.value,\r\n        \"Carimbo de tempo\": firebase.firestore.FieldValue.serverTimestamp(),\r\n        Status: \"ATIVO\"\r\n      });\r\n\r\n      await carregarCadastros();\r\n      await carregarListaVendedores(); \/\/ \u2705 atualiza lista de vendedores\r\n\r\n      token.value = gerarToken();\r\n      negotiation.value = \"\";\r\n      percent.value = \"\";\r\n      cashback.value = \"\";\r\n    };\r\n\r\n    async function carregarCadastros(){\r\n      listaCadastros.innerHTML = \"\";\r\n      const snap = await db.collection(\"cashback_contracts\").orderBy(\"Carimbo de tempo\",\"desc\").get();\r\n      snap.forEach(d=>{\r\n        const x=d.data();\r\n        listaCadastros.innerHTML += `<tr class=\"border-b border-gray-800\">\r\n          <td>${x[\"Nome do cliente\"]||\"\"}<\/td>\r\n          <td>${x[\"CNPJ\"]||\"\"}<\/td>\r\n          <td>${x[\"N\u00famero do contrato\"]||\"\"}<\/td>\r\n          <td>${x[\"Telefone\"]||\"\"}<\/td>\r\n          <td>${x[\"Email\"]||\"\"}<\/td>\r\n          <td class=\"font-mono text-yellow-300\">${x.redeemCode||\"\"}<\/td>\r\n          <td>${x[\"Carimbo de tempo\"]?.toDate?.().toLocaleDateString(\"pt-BR\")||\"-\"}<\/td>\r\n          <td>${x[\"Comercial Nome\"]||\"\"}<\/td>\r\n        <\/tr>`;\r\n      });\r\n    }\r\n    carregarCadastros();\r\n\r\n    window.carregarHistoricoEmissoes = async function(){\r\n      const lista = el(\"listaHistoricoEmissoes\");\r\n      lista.innerHTML = '<tr><td colspan=\"5\" class=\"text-center py-4 text-gray-500\">Carregando hist\u00f3rico...<\/td><\/tr>';\r\n\r\n      const mes = filtroMes.value;\r\n      const ano = filtroAno.value;\r\n\r\n      try{\r\n        const snap = await db.collection(\"emissao_de_uso\").orderBy(\"data_emissao\",\"desc\").get();\r\n        const rows = [];\r\n        snap.forEach(doc=>{\r\n          const x=doc.data();\r\n          const mesAno = x.mes_ano || \"\";\r\n          if(!matchesFilter(mesAno, mes, ano)) return;\r\n          rows.push(x);\r\n        });\r\n\r\n        if(!rows.length){\r\n          lista.innerHTML = '<tr><td colspan=\"5\" class=\"text-center py-4 text-gray-500\">Nenhuma emiss\u00e3o de uso registrada.<\/td><\/tr>';\r\n          return;\r\n        }\r\n\r\n        lista.innerHTML = rows.map(x=>{\r\n          const dataFormatada = x.data_emissao?.toDate?.().toLocaleDateString(\"pt-BR\") || \"N\/A\";\r\n          return `<tr class=\"border-b border-gray-800\">\r\n            <td>${dataFormatada}<\/td>\r\n            <td>${x.cliente||\"\"}<\/td>\r\n            <td>${x.cnpj||\"\"}<\/td>\r\n            <td>${x.contrato||\"\"}<\/td>\r\n            <td class=\"font-mono text-yellow-300\">${x.token||\"\"}<\/td>\r\n          <\/tr>`;\r\n        }).join(\"\");\r\n\r\n      }catch(err){\r\n        console.error(\"Erro hist\u00f3rico:\", err);\r\n        lista.innerHTML = '<tr><td colspan=\"5\" class=\"text-center py-4 text-red-400\">Erro ao carregar hist\u00f3rico.<\/td><\/tr>';\r\n      }\r\n    };\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 \"GOOGLE FORMS\" PIZZA\r\n    \/\/ =========================\r\n    function buildFormsColors(n){\r\n      const colors = [];\r\n      for(let i=0;i<n;i++){\r\n        const hue = Math.round((360\/n)*i);\r\n        colors.push(`hsl(${hue}, 75%, 55%)`);\r\n      }\r\n      return colors;\r\n    }\r\n\r\n    const piePercentLabelsPlugin = {\r\n      id: \"piePercentLabels\",\r\n      afterDatasetsDraw(chart, args, pluginOptions) {\r\n        const { ctx } = chart;\r\n        const opts = pluginOptions || {};\r\n        const minPercent = typeof opts.minPercent === \"number\" ? opts.minPercent : 4;\r\n        const fontSize = opts.fontSize || 12;\r\n\r\n        chart.data.datasets.forEach((dataset, datasetIndex) => {\r\n          const meta = chart.getDatasetMeta(datasetIndex);\r\n          if (!meta || meta.type !== \"doughnut\") return;\r\n\r\n          const total = dataset.data.reduce((a,b)=>a+Number(b||0), 0);\r\n          if(!total) return;\r\n\r\n          meta.data.forEach((arc, i) => {\r\n            const val = Number(dataset.data[i] || 0);\r\n            if(!val) return;\r\n\r\n            const pct = (val\/total)*100;\r\n            if(pct < minPercent) return;\r\n\r\n            const pos = arc.tooltipPosition();\r\n            ctx.save();\r\n            ctx.fillStyle = \"#ffffff\";\r\n            ctx.font = `700 ${fontSize}px Inter, Arial`;\r\n            ctx.textAlign = \"center\";\r\n            ctx.textBaseline = \"middle\";\r\n            ctx.shadowColor = \"rgba(0,0,0,0.35)\";\r\n            ctx.shadowBlur = 6;\r\n            ctx.fillText(`${pct.toFixed(0)}%`, pos.x, pos.y);\r\n            ctx.restore();\r\n          });\r\n        });\r\n      }\r\n    };\r\n\r\n    function makeFormsDonutConfig({labels, data, title, valueFormatter}){\r\n      const colors = buildFormsColors(labels.length);\r\n      return {\r\n        type: \"doughnut\",\r\n        data: {\r\n          labels,\r\n          datasets: [{\r\n            label: title || \"\",\r\n            data,\r\n            backgroundColor: colors,\r\n            borderColor: \"rgba(0,0,0,0.25)\",\r\n            borderWidth: 1,\r\n            hoverOffset: 6\r\n          }]\r\n        },\r\n        options: {\r\n          responsive: true,\r\n          cutout: \"55%\",\r\n          plugins: {\r\n            legend: {\r\n              position: \"right\",\r\n              labels: {\r\n                color: \"#f5f5f5\",\r\n                boxWidth: 12,\r\n                padding: 14,\r\n                generateLabels(chart){\r\n                  const ds = chart.data.datasets[0];\r\n                  const total = ds.data.reduce((a,b)=>a+Number(b||0),0);\r\n                  return chart.data.labels.map((lbl, i) => {\r\n                    const val = Number(ds.data[i] || 0);\r\n                    const pct = total ? Math.round((val\/total)*100) : 0;\r\n                    const c = ds.backgroundColor[i];\r\n                    return { text: `${lbl} \u2014 ${pct}%`, fillStyle: c, strokeStyle: c, lineWidth: 0, index: i };\r\n                  });\r\n                }\r\n              }\r\n            },\r\n            tooltip: {\r\n              callbacks: {\r\n                label(context){\r\n                  const ds = context.dataset;\r\n                  const label = (context.chart.data.labels || [])[context.dataIndex] || \"\";\r\n                  const val = Number(ds.data[context.dataIndex] || 0);\r\n                  const total = ds.data.reduce((a,b)=>a+Number(b||0),0);\r\n                  const pct = total ? ((val\/total)*100) : 0;\r\n                  const vtxt = valueFormatter ? valueFormatter(val) : String(val);\r\n                  return `${label}: ${vtxt} (${pct.toFixed(1)}%)`;\r\n                }\r\n              }\r\n            },\r\n            piePercentLabels: { minPercent: 4, fontSize: 12 }\r\n          }\r\n        },\r\n        plugins: [piePercentLabelsPlugin]\r\n      };\r\n    }\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 LINHA CLIC\u00c1VEL\r\n    \/\/ =========================\r\n    function makeLineConfig({ labels, data, title, valueFormatter, onPointClick, color }){\r\n      return {\r\n        type: \"line\",\r\n        data: {\r\n          labels,\r\n          datasets: [{\r\n            label: title || \"\",\r\n            data,\r\n            tension: 0.25,\r\n            fill: false,\r\n            borderWidth: 3,\r\n            borderColor: color || \"rgba(255,212,0,0.95)\",\r\n            pointBackgroundColor: color || \"rgba(255,212,0,0.95)\",\r\n            pointBorderColor: \"rgba(0,0,0,0.35)\",\r\n            pointRadius: 4,\r\n            pointHoverRadius: 7\r\n          }]\r\n        },\r\n        options: {\r\n          responsive: true,\r\n          interaction: { mode: \"nearest\", intersect: true },\r\n          plugins: {\r\n            legend: { display: false },\r\n            tooltip: {\r\n              callbacks: {\r\n                label(ctx){\r\n                  const v = Number(ctx.parsed.y || 0);\r\n                  return valueFormatter ? valueFormatter(v) : String(v);\r\n                }\r\n              }\r\n            }\r\n          },\r\n          scales: {\r\n            y: {\r\n              beginAtZero: true,\r\n              ticks: { color:\"#f5f5f5\" },\r\n              grid: { color:\"rgba(255,255,255,0.10)\" }\r\n            },\r\n            x: {\r\n              ticks: { color:\"#f5f5f5\" },\r\n              grid: { color:\"rgba(255,255,255,0.05)\" }\r\n            }\r\n          },\r\n          onClick: (event, elements, chart) => {\r\n            const pts = chart.getElementsAtEventForMode(event, \"nearest\", {intersect:true}, true);\r\n            if(!pts.length) return;\r\n            const idx = pts[0].index;\r\n            const mesAno = chart.data.labels[idx];\r\n            if(onPointClick) onPointClick(mesAno);\r\n          }\r\n        }\r\n      };\r\n    }\r\n\r\n    \/\/ Dashboard emiss\u00f5es\r\n    let chartEmissaoMensalInstance=null;\r\n    let chartEmissaoClienteInstance=null;\r\n    let chartEmissaoMensalLinhaInstance=null;\r\n\r\n    window.abrirEmissoesMes = function(mesAno){\r\n      el(\"emissoesMesTitle\").textContent = `Emiss\u00f5es \u2014 ${mesAno}`;\r\n      el(\"emissoesMesSub\").textContent = \"Clique no X para fechar \u2022 Lista baseada em emissao_de_uso\";\r\n\r\n      const tbody = el(\"listaEmissoesMes\");\r\n      const rows = (window.__emissoesDados || []).filter(r => (r.mes_ano || \"\") === mesAno);\r\n\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"5\" class=\"text-center py-4 text-gray-500\">Sem emiss\u00f5es para ${mesAno}.<\/td><\/tr>`;\r\n      }else{\r\n        tbody.innerHTML = rows\r\n          .sort((a,b)=>{\r\n            const da = a.data_emissao?.toDate ? a.data_emissao.toDate() : (a.data_emissao ? new Date(a.data_emissao) : new Date(0));\r\n            const dbb = b.data_emissao?.toDate ? b.data_emissao.toDate() : (b.data_emissao ? new Date(b.data_emissao) : new Date(0));\r\n            return dbb - da;\r\n          })\r\n          .map(x=>{\r\n            const d = x.data_emissao?.toDate ? x.data_emissao.toDate() : (x.data_emissao ? new Date(x.data_emissao) : null);\r\n            const dataTxt = d && !isNaN(d.getTime()) ? d.toLocaleString(\"pt-BR\") : \"\u2014\";\r\n            return `\r\n              <tr class=\"border-b border-gray-800\">\r\n                <td>${dataTxt}<\/td>\r\n                <td>${x.cliente || \"\u2014\"}<\/td>\r\n                <td>${x.cnpj || \"\u2014\"}<\/td>\r\n                <td>${x.contrato || \"\u2014\"}<\/td>\r\n                <td class=\"font-mono text-yellow-300\">${x.token || \"\u2014\"}<\/td>\r\n              <\/tr>\r\n            `;\r\n          }).join(\"\");\r\n      }\r\n\r\n      const modal = el(\"modalEmissoesMes\");\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n\r\n    window.fecharEmissoesMes = function(){\r\n      const modal = el(\"modalEmissoesMes\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n\r\n    window.carregarDashboard = async function(){\r\n      const mes = filtroMes.value;\r\n      const ano = filtroAno.value;\r\n\r\n      try{\r\n        const snap = await db.collection(\"emissao_de_uso\").orderBy(\"data_emissao\",\"desc\").get();\r\n        const dados = [];\r\n        snap.forEach(doc=>{\r\n          const x=doc.data();\r\n          const mesAno = x.mes_ano || \"\";\r\n          if(!matchesFilter(mesAno, mes, ano)) return;\r\n          dados.push(x);\r\n        });\r\n\r\n        window.__emissoesDados = dados;\r\n\r\n        const emissaoMensal = dados.reduce((acc, item)=>{\r\n          const key = item.mes_ano || \"SEM_MES_ANO\";\r\n          acc[key]=(acc[key]||0)+1;\r\n          return acc;\r\n        },{});\r\n\r\n        const labelsMensal = Object.keys(emissaoMensal).sort();\r\n        const dataMensal = labelsMensal.map(k=>emissaoMensal[k]);\r\n\r\n        if(chartEmissaoMensalInstance) chartEmissaoMensalInstance.destroy();\r\n        chartEmissaoMensalInstance = new Chart(el(\"chartEmissaoMensal\").getContext(\"2d\"),{\r\n          type:\"bar\",\r\n          data:{ labels: labelsMensal, datasets:[{ label:\"N\u00ba de Emiss\u00f5es\", data:dataMensal, backgroundColor:\"rgba(255,212,0,0.7)\", borderColor:\"rgba(255,212,0,1)\", borderWidth:1 }] },\r\n          options:{\r\n            responsive:true,\r\n            scales:{\r\n              y:{beginAtZero:true,ticks:{color:\"#f5f5f5\"},grid:{color:\"rgba(255,255,255,0.1)\"}},\r\n              x:{ticks:{color:\"#f5f5f5\"},grid:{color:\"rgba(255,255,255,0.1)\"}}\r\n            },\r\n            plugins:{legend:{display:false}},\r\n            onClick: (event, elements, chart)=>{\r\n              const pts = chart.getElementsAtEventForMode(event, \"nearest\", {intersect:true}, true);\r\n              if(!pts.length) return;\r\n              const idx = pts[0].index;\r\n              const mesAno = chart.data.labels[idx];\r\n              if(mesAno) abrirEmissoesMes(mesAno);\r\n            }\r\n          }\r\n        });\r\n\r\n        if(chartEmissaoMensalLinhaInstance) chartEmissaoMensalLinhaInstance.destroy();\r\n        chartEmissaoMensalLinhaInstance = new Chart(\r\n          el(\"chartEmissaoMensalLinha\").getContext(\"2d\"),\r\n          makeLineConfig({\r\n            labels: labelsMensal,\r\n            data: dataMensal,\r\n            title: \"Emiss\u00f5es (linha)\",\r\n            valueFormatter: (v)=> `${v} emiss\u00e3o(\u00f5es)`,\r\n            onPointClick: (mesAno)=> abrirEmissoesMes(mesAno),\r\n            color: \"rgba(255,212,0,0.95)\"\r\n          })\r\n        );\r\n\r\n        const emissaoCliente = dados.reduce((acc, item)=>{\r\n          const key = item.cliente || item.cnpj || \"Cliente\";\r\n          acc[key]=(acc[key]||0)+1;\r\n          return acc;\r\n        },{});\r\n\r\n        const top = Object.entries(emissaoCliente).sort((a,b)=>b[1]-a[1]).slice(0,5);\r\n        const labelsCliente = top.map(x=>x[0]);\r\n        const dataCliente = top.map(x=>x[1]);\r\n\r\n        if(chartEmissaoClienteInstance) chartEmissaoClienteInstance.destroy();\r\n\r\n        chartEmissaoClienteInstance = new Chart(\r\n          el(\"chartEmissaoCliente\").getContext(\"2d\"),\r\n          makeFormsDonutConfig({\r\n            labels: labelsCliente,\r\n            data: dataCliente,\r\n            title: \"Top 5 Emiss\u00f5es\",\r\n            valueFormatter: (v)=> `${v} emiss\u00e3o(\u00f5es)`\r\n          })\r\n        );\r\n\r\n      }catch(err){\r\n        console.error(\"Erro dashboard emiss\u00f5es:\", err);\r\n        alert(\"Erro ao carregar dashboard. Verifique o console.\");\r\n      }\r\n    };\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 SATISFA\u00c7\u00c3O (coleta + gr\u00e1ficos)\r\n    \/\/ =========================\r\n    const SATISFACAO_COLLECTIONS = [\r\n      \"satisfacao\",\r\n      \"pesquisas_satisfacao\",\r\n      \"pesquisa_satisfacao\",\r\n      \"pesquisasDeSatisfacao\",\r\n      \"pesquisas_satisfacao_agisa\"\r\n    ];\r\n\r\n    function pickDate(o){\r\n      const candidates = [\r\n        o.data_resposta, o.data, o.createdAt, o.criadoEm, o.criado_em, o.timestamp, o.carimbo,\r\n        o[\"Carimbo de tempo\"], o[\"carimbo de tempo\"]\r\n      ];\r\n      for (const c of candidates){\r\n        if(!c) continue;\r\n        if (c.toDate) {\r\n          const d = c.toDate();\r\n          if(!isNaN(d.getTime())) return d;\r\n        }\r\n        const d2 = new Date(c);\r\n        if(!isNaN(d2.getTime())) return d2;\r\n      }\r\n      return null;\r\n    }\r\n\r\n    function pickNota(o){\r\n      const candidates = [o.nota, o.avaliacao, o.avalia\u00e7\u00e3o, o.rating, o.score, o.nps];\r\n      for (const v of candidates){\r\n        const n = Number(v);\r\n        if(Number.isFinite(n)) return n;\r\n      }\r\n      return null;\r\n    }\r\n\r\n    function normalizeNotaTo10(n){\r\n      if(n <= 5) return n * 2;\r\n      return n;\r\n    }\r\n\r\n    async function carregarSatisfacaoRaw({ mes, ano, mapCnpjNome }){\r\n      let snap = null;\r\n      for (const col of SATISFACAO_COLLECTIONS) {\r\n        try{ snap = await db.collection(col).get(); break; }catch(e){ snap = null; }\r\n      }\r\n      if(!snap) return [];\r\n\r\n      const rows = [];\r\n      snap.forEach(doc=>{\r\n        const o = doc.data() || {};\r\n        const d = pickDate(o);\r\n        const key = d ? mesAnoFromDate(d) : \"SEM_DATA\";\r\n\r\n        if(d){\r\n          if(!matchesFilter(key, mes, ano)) return;\r\n        }else{\r\n          if(mes || ano) return;\r\n        }\r\n\r\n        const cnpjO = onlyDigits(o.cnpj || o[\"CNPJ\"] || \"\");\r\n        const nomeO = o.cliente || o.nome || mapCnpjNome.get(cnpjO) || \"\u2014\";\r\n        if(!filtroClienteOK(nomeO, cnpjO)) return;\r\n\r\n        const resp = o.respostas || {};\r\n        rows.push({\r\n          id: doc.id,\r\n          data: d,\r\n          mes_ano: key,\r\n          cnpj: cnpjO,\r\n          cliente: nomeO,\r\n          token: o.token || \"\",\r\n          contratoNovo: o.contratoNovo || o.contrato_novo || o.contrato || \"\",\r\n          respostas: {\r\n            q1: resp.q1 || o.q1 || \"\",\r\n            q2: resp.q2 || o.q2 || \"\",\r\n            q3: resp.q3 || o.q3 || \"\",\r\n            q4: resp.q4 || o.q4 || \"\"\r\n          },\r\n          raw: o\r\n        });\r\n      });\r\n      return rows;\r\n    }\r\n\r\n    function renderQuestion({qid, options, rows, chartId, listId, chartRefSetter}){\r\n      const counts = {};\r\n      options.forEach(o=>counts[o]=0);\r\n\r\n      rows.forEach(r=>{\r\n        const v = (r.respostas?.[qid] || \"\").trim();\r\n        if(v && counts[v] !== undefined) counts[v]++;\r\n      });\r\n\r\n      const total = Object.values(counts).reduce((a,b)=>a+b,0);\r\n      const labels = options.filter(o=>counts[o]>0);\r\n      const data = labels.map(o=>counts[o]);\r\n\r\n      const ctx = document.getElementById(chartId).getContext(\"2d\");\r\n      const prev = chartRefSetter.get();\r\n      if(prev) prev.destroy();\r\n\r\n      const chart = new Chart(ctx, makeFormsDonutConfig({\r\n        labels: labels.length ? labels : [\"Sem respostas\"],\r\n        data: labels.length ? data : [1],\r\n        title: \"Q\",\r\n        valueFormatter: (v)=> `${v} resp.`\r\n      }));\r\n      chartRefSetter.set(chart);\r\n\r\n      const box = document.getElementById(listId);\r\n      if(!total){\r\n        box.innerHTML = `<div class=\"text-sm text-gray-400\">Sem respostas no per\u00edodo.<\/div>`;\r\n        return;\r\n      }\r\n\r\n      box.innerHTML = options.map(opt=>{\r\n        const n = counts[opt] || 0;\r\n        const pct = total ? Math.round((n\/total)*100) : 0;\r\n        const disabled = n===0 ? \"opacity:.5; pointer-events:none;\" : \"\";\r\n        return `\r\n          <div class=\"opt-row\" style=\"${disabled}\" onclick=\"abrirModalSatClientes('${qid}','${opt}')\">\r\n            <div class=\"opt-l\">${opt}<\/div>\r\n            <div class=\"opt-r\">${pct}% (${n})<\/div>\r\n          <\/div>\r\n        `;\r\n      }).join(\"\");\r\n    }\r\n\r\n    let chartSatQ1=null, chartSatQ2=null, chartSatQ3=null, chartSatQ4=null;\r\n\r\n    window.abrirModalSatClientes = function(qid, opt){\r\n      const rows = (window.__satRaw || []).filter(r => (r.respostas?.[qid] || \"\").trim() === opt);\r\n      const titleMap = {\r\n        q1: \"1. Condi\u00e7\u00e3o f\u00edsica do container\",\r\n        q2: \"2. Prazo e log\u00edstica de entrega\",\r\n        q3: \"3. Fator determinante do neg\u00f3cio\",\r\n        q4: \"4. Canal que conheceu a AGISA\"\r\n      };\r\n\r\n      el(\"satCliTitle\").textContent = `${titleMap[qid] || qid} \u2014 ${opt}`;\r\n      el(\"satCliSub\").textContent = window.__indicadoresFiltroTexto || \"\u2014\";\r\n\r\n      const tbody = el(\"satCliTbody\");\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"5\" class=\"text-center py-4 text-gray-500\">Sem clientes nessa op\u00e7\u00e3o.<\/td><\/tr>`;\r\n      }else{\r\n        tbody.innerHTML = rows\r\n          .sort((a,b)=> (b.data||0) - (a.data||0))\r\n          .map(r=>{\r\n            const dt = r.data && !isNaN(r.data.getTime()) ? r.data.toLocaleString(\"pt-BR\") : \"\u2014\";\r\n            return `\r\n              <tr class=\"border-b border-gray-800\">\r\n                <td>${dt}<\/td>\r\n                <td>${r.cliente || \"\u2014\"}<\/td>\r\n                <td>${r.cnpj || \"\u2014\"}<\/td>\r\n                <td>${r.contratoNovo || \"\u2014\"}<\/td>\r\n                <td class=\"font-mono text-yellow-300\">${r.token || \"\u2014\"}<\/td>\r\n              <\/tr>\r\n            `;\r\n          }).join(\"\");\r\n      }\r\n\r\n      const modal = el(\"modalSatClientes\");\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n\r\n    window.fecharModalSatClientes = function(){\r\n      const modal = el(\"modalSatClientes\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 Indicadores (linhas + clique)\r\n    \/\/ =========================\r\n    let chartIndSatisfacao = null;\r\n    let chartIndPagar=null, chartIndBonus=null, chartIndAtraso=null;\r\n\r\n    async function carregarSatisfacaoIndicadores({ mes, ano, mapCnpjNome }) {\r\n      if(el(\"indSatisfRespostas\")) el(\"indSatisfRespostas\").textContent = \"0\";\r\n      if(el(\"indSatisfMedia\")) el(\"indSatisfMedia\").textContent = \"\u2014\";\r\n      if(el(\"indSatisfNps\")) el(\"indSatisfNps\").textContent = \"\u2014\";\r\n\r\n      const porMes = {};\r\n      const rows = await carregarSatisfacaoRaw({ mes, ano, mapCnpjNome });\r\n      window.__satRaw = rows;\r\n\r\n      let totalRespostas = 0;\r\n      let somaNotas = 0, countNotas = 0;\r\n      let promotores = 0, detratores = 0, totalNpsBase = 0;\r\n\r\n      rows.forEach(r=>{\r\n        totalRespostas++;\r\n        const key = r.mes_ano || \"SEM_DATA\";\r\n        if(!porMes[key]) porMes[key] = { count:0, soma:0, countNota:0, prom:0, det:0, totNps:0 };\r\n        porMes[key].count++;\r\n\r\n        const notaRaw = pickNota(r.raw||{});\r\n        if(notaRaw !== null){\r\n          const nota10 = normalizeNotaTo10(notaRaw);\r\n          if(Number.isFinite(nota10)){\r\n            somaNotas += nota10;\r\n            countNotas++;\r\n\r\n            porMes[key].soma += nota10;\r\n            porMes[key].countNota++;\r\n\r\n            totalNpsBase++;\r\n            porMes[key].totNps++;\r\n\r\n            if(nota10 >= 9) { promotores++; porMes[key].prom++; }\r\n            else if(nota10 <= 6) { detratores++; porMes[key].det++; }\r\n          }\r\n        }\r\n      });\r\n\r\n      if(el(\"indSatisfRespostas\")) el(\"indSatisfRespostas\").textContent = String(totalRespostas);\r\n\r\n      if(countNotas > 0 && el(\"indSatisfMedia\")){\r\n        el(\"indSatisfMedia\").textContent = (somaNotas \/ countNotas).toFixed(1);\r\n      }\r\n\r\n      if(totalNpsBase > 0 && el(\"indSatisfNps\")){\r\n        const nps = ((promotores\/totalNpsBase)*100) - ((detratores\/totalNpsBase)*100);\r\n        el(\"indSatisfNps\").textContent = String(Math.round(nps));\r\n      }\r\n\r\n      const labels = Object.keys(porMes).filter(k => k !== \"SEM_DATA\").sort();\r\n      const dataQtd = labels.map(k => porMes[k]?.count || 0);\r\n      const dataMedia = labels.map(k => porMes[k]?.countNota ? (porMes[k].soma \/ porMes[k].countNota) : null);\r\n\r\n      if(!el(\"chartIndSatisfacao\")) return;\r\n      if(chartIndSatisfacao) chartIndSatisfacao.destroy();\r\n\r\n      chartIndSatisfacao = new Chart(el(\"chartIndSatisfacao\").getContext(\"2d\"),{\r\n        data:{\r\n          labels,\r\n          datasets:[\r\n            {\r\n              type:\"bar\",\r\n              label:\"Respostas\",\r\n              data:dataQtd,\r\n              backgroundColor:\"rgba(155, 89, 182, 0.55)\",\r\n              borderColor:\"rgba(155, 89, 182, 1)\",\r\n              borderWidth:1,\r\n              yAxisID:\"y\"\r\n            },\r\n            {\r\n              type:\"line\",\r\n              label:\"M\u00e9dia (0\u201310)\",\r\n              data:dataMedia,\r\n              borderColor:\"rgba(155, 89, 182, 1)\",\r\n              backgroundColor:\"rgba(155, 89, 182, 0.15)\",\r\n              tension:0.25,\r\n              spanGaps:true,\r\n              yAxisID:\"y1\"\r\n            }\r\n          ]\r\n        },\r\n        options:{\r\n          responsive:true,\r\n          scales:{\r\n            y:{ beginAtZero:true, ticks:{color:\"#f5f5f5\"}, grid:{color:\"rgba(255,255,255,0.1)\"} },\r\n            y1:{ beginAtZero:true, suggestedMax:10, position:\"right\", ticks:{color:\"#f5f5f5\"}, grid:{drawOnChartArea:false} },\r\n            x:{ ticks:{color:\"#f5f5f5\"}, grid:{color:\"rgba(255,255,255,0.1)\"} }\r\n          },\r\n          plugins:{ legend:{ labels:{color:\"#f5f5f5\"} } }\r\n        }\r\n      });\r\n\r\n      const q1opts = [\"Excelente\",\"Bom\",\"Regular\",\"Ruim\"];\r\n      const q2opts = [\"Muito \u00e1gil\",\"Satisfeito\",\"Regular\",\"Insatisfeito\"];\r\n      const q3opts = [\"Confian\u00e7a\/Credibilidade\",\"Custo-benef\u00edcio\",\"Atendimento\",\"Disponibilidade\"];\r\n      const q4opts = [\"Google\",\"Redes Sociais\",\"Indica\u00e7\u00e3o\",\"J\u00e1 sou cliente\"];\r\n\r\n      renderQuestion({ qid:\"q1\", options:q1opts, rows, chartId:\"chartSatQ1\", listId:\"listSatQ1\", chartRefSetter:{ get:()=>chartSatQ1, set:(c)=>chartSatQ1=c } });\r\n      renderQuestion({ qid:\"q2\", options:q2opts, rows, chartId:\"chartSatQ2\", listId:\"listSatQ2\", chartRefSetter:{ get:()=>chartSatQ2, set:(c)=>chartSatQ2=c } });\r\n      renderQuestion({ qid:\"q3\", options:q3opts, rows, chartId:\"chartSatQ3\", listId:\"listSatQ3\", chartRefSetter:{ get:()=>chartSatQ3, set:(c)=>chartSatQ3=c } });\r\n      renderQuestion({ qid:\"q4\", options:q4opts, rows, chartId:\"chartSatQ4\", listId:\"listSatQ4\", chartRefSetter:{ get:()=>chartSatQ4, set:(c)=>chartSatQ4=c } });\r\n    }\r\n\r\n    \/\/ \u2705 abrir por m\u00eas\r\n    window.abrirDetalheAPagarMes = function(mesAno){\r\n      el(\"apagarSub\").textContent = (window.__indicadoresFiltroTexto || \"\u2014\") + \" | M\u00eas\/Ano: \" + mesAno;\r\n      const tbody = el(\"listaAPagarDetalhe\");\r\n      const rows = (window.__apagarDetalhe || []).filter(r => r.mes_ano === mesAno);\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"5\" class=\"text-center py-4 text-gray-500\">Sem registros para ${mesAno}.<\/td><\/tr>`;\r\n      } else {\r\n        tbody.innerHTML = rows.map(r=>`\r\n          <tr class=\"border-b border-gray-800\">\r\n            <td>${r.mes_ano || \"\u2014\"}<\/td>\r\n            <td>${r.cliente || \"\u2014\"}<\/td>\r\n            <td>${r.cnpj || \"\u2014\"}<\/td>\r\n            <td>${r.contrato || \"\u2014\"}<\/td>\r\n            <td class=\"text-right\">${fmtBRL(r.valor)}<\/td>\r\n          <\/tr>\r\n        `).join(\"\");\r\n      }\r\n      el(\"modalAPagar\").classList.remove(\"hidden\"); el(\"modalAPagar\").classList.add(\"flex\");\r\n    };\r\n\r\n    window.abrirDetalhePagoMes = function(mesAno){\r\n      el(\"pagoSub\").textContent = (window.__indicadoresFiltroTexto || \"\u2014\") + \" | M\u00eas\/Ano: \" + mesAno;\r\n      const tbody = el(\"listaPagoDetalhe\");\r\n      const rows = (window.__pagoDetalhe || []).filter(r => r.mes_ano === mesAno);\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"8\" class=\"text-center py-4 text-gray-500\">Sem pagamentos para ${mesAno}.<\/td><\/tr>`;\r\n      } else {\r\n        tbody.innerHTML = rows.map(r=>{\r\n          const d = r.data?.toDate ? r.data.toDate() : (r.data ? new Date(r.data) : null);\r\n          const dataTxt = d && !isNaN(d.getTime()) ? d.toLocaleString(\"pt-BR\") : \"\u2014\";\r\n          return `\r\n            <tr class=\"border-b border-gray-800\">\r\n              <td>${dataTxt}<\/td>\r\n              <td>${r.cliente || \"\u2014\"}<\/td>\r\n              <td>${r.cnpj || \"\u2014\"}<\/td>\r\n              <td>${r.contrato || \"\u2014\"}<\/td>\r\n              <td class=\"text-right\">${r.parcela ?? \"\u2014\"}<\/td>\r\n              <td class=\"text-right\">${fmtBRL(r.valor_parcela)}<\/td>\r\n              <td class=\"text-right text-green-300\">${fmtBRL(r.cashback)}<\/td>\r\n              <td>${r.auth || \"\u2014\"}<\/td>\r\n            <\/tr>\r\n          `;\r\n        }).join(\"\");\r\n      }\r\n      el(\"modalPago\").classList.remove(\"hidden\"); el(\"modalPago\").classList.add(\"flex\");\r\n    };\r\n\r\n    window.abrirDetalheAtrasosMes = function(mesAno){\r\n      el(\"atrasosSub\").textContent = (window.__indicadoresFiltroTexto || \"\u2014\") + \" | M\u00eas\/Ano: \" + mesAno;\r\n      const tbody = el(\"listaAtrasosDetalhe\");\r\n      const rows = (window.__atrasosDetalhe || []).filter(r => r.mes_ano === mesAno);\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"6\" class=\"text-center py-4 text-gray-500\">Sem atrasos para ${mesAno}.<\/td><\/tr>`;\r\n      } else {\r\n        tbody.innerHTML = rows.map(r=>`\r\n          <tr class=\"border-b border-gray-800\">\r\n            <td>${r.mes_ano || \"\u2014\"}<\/td>\r\n            <td>${r.cliente || \"\u2014\"}<\/td>\r\n            <td>${r.cnpj || \"\u2014\"}<\/td>\r\n            <td>${r.contrato || \"\u2014\"}<\/td>\r\n            <td class=\"text-right\">${r.parcela ?? \"\u2014\"}<\/td>\r\n            <td class=\"text-right\">${r.dias_atraso ?? \"\u2014\"}<\/td>\r\n          <\/tr>\r\n        `).join(\"\");\r\n      }\r\n      el(\"modalAtrasos\").classList.remove(\"hidden\"); el(\"modalAtrasos\").classList.add(\"flex\");\r\n    };\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 NOVO: modal \u201cB\u00f4nus vencidos (carteira expirada)\u201d\r\n    \/\/ =========================\r\n    window.abrirDetalheBonusVencidosCarteira = function(){\r\n      const modal = el(\"modalBonusVencidosCarteira\");\r\n      el(\"bonusVencidosSub\").textContent = window.__indicadoresFiltroTexto;\r\n\r\n      const tbody = el(\"listaBonusVencidosCarteira\");\r\n      const rows = window.__bonusVencidosCarteira || [];\r\n\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"8\" class=\"text-center py-4 text-gray-500\">Sem saldo vencido na carteira para o filtro aplicado.<\/td><\/tr>`;\r\n      }else{\r\n        tbody.innerHTML = rows\r\n          .sort((a,b)=>{\r\n            const va = a.validade ? new Date(a.validade) : new Date(0);\r\n            const vb = b.validade ? new Date(b.validade) : new Date(0);\r\n            return vb - va;\r\n          })\r\n          .map(r=>{\r\n            const dCred = r.dataCredito && !isNaN(new Date(r.dataCredito).getTime())\r\n              ? new Date(r.dataCredito).toLocaleString(\"pt-BR\")\r\n              : \"\u2014\";\r\n            const dVal = r.validade && !isNaN(new Date(r.validade).getTime())\r\n              ? new Date(r.validade).toLocaleDateString(\"pt-BR\")\r\n              : \"\u2014\";\r\n\r\n            return `\r\n              <tr class=\"border-b border-gray-800\">\r\n                <td>${dCred}<\/td>\r\n                <td class=\"text-orange-200 font-bold\">${dVal}<\/td>\r\n                <td>${r.cliente || \"\u2014\"}<\/td>\r\n                <td>${r.cnpj || \"\u2014\"}<\/td>\r\n                <td>${r.contrato || \"\u2014\"}<\/td>\r\n                <td class=\"text-right text-orange-200 font-bold\">${fmtBRL(r.saldoVencido)}<\/td>\r\n                <td class=\"text-right\">${r.diasExpirado ?? \"\u2014\"}<\/td>\r\n                <td>${r.origem || \"\u2014\"}<\/td>\r\n              <\/tr>\r\n            `;\r\n          }).join(\"\");\r\n      }\r\n\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n\r\n    window.fecharDetalheBonusVencidosCarteira = function(){\r\n      const modal = el(\"modalBonusVencidosCarteira\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n\r\n    \/\/ =========================\r\n    \/\/ \u2705 CARREGAR INDICADORES\r\n    \/\/ =========================\r\n    window.carregarIndicadores = async function(){\r\n      const mes = indMes.value;\r\n      const ano = indAno.value;\r\n\r\n      window.__apagarDetalhe = [];\r\n      window.__usoDetalhe = [];\r\n      window.__pagoDetalhe = [];\r\n      window.__atrasosDetalhe = [];\r\n      window.__bonusVencidosCarteira = []; \/\/ \u2705 novo\r\n\r\n      const fTxtParts = [];\r\n      if(mes && ano) fTxtParts.push(`M\u00eas\/Ano: ${mes}\/${ano}`);\r\n      else if(ano) fTxtParts.push(`Ano: ${ano}`);\r\n      else if(mes) fTxtParts.push(`M\u00eas: ${mes}`);\r\n\r\n      const fCli = (indClienteFiltro.value||\"\").trim();\r\n      if(fCli) fTxtParts.push(`Cliente\/CNPJ: ${fCli}`);\r\n\r\n      \/\/ \u2705 adiciona vendedores no resumo do filtro\r\n      if(window.__vendSel && window.__vendSel.size){\r\n        const arr = Array.from(window.__vendSel);\r\n        fTxtParts.push(`Vendedores: ${arr.join(\", \")}`);\r\n      }\r\n\r\n      window.__indicadoresFiltroTexto = fTxtParts.length ? fTxtParts.join(\" | \") : \"Sem filtros\";\r\n\r\n      let totalAPagar=0;\r\n      let totalPagoFinanceiro=0;\r\n      let totalUsoCliente=0;\r\n      let penultimaPaga=0;\r\n      const atrasadosSet=new Set();\r\n\r\n      const pagarPorMes={};\r\n      const bonusPorMes={};\r\n      const atrasosPorMes={};\r\n\r\n      const hoje=new Date();\r\n      const mapCnpjNome = new Map();\r\n\r\n      \/\/ \u2705 Ledger para calcular SALDO vencido (cr\u00e9ditos x d\u00e9bitos)\r\n      const credits = []; \/\/ cr\u00e9ditos de b\u00f4nus pagos (recibo)\r\n      const debits  = []; \/\/ usos (uso_saldo \/ wallet_usos)\r\n\r\n      const snap = await db.collection(\"cashback_contracts\").get();\r\n\r\n      snap.forEach(doc=>{\r\n        const d=doc.data();\r\n        const id=doc.id;\r\n\r\n        const nome = d[\"Nome do cliente\"] || \"\u2014\";\r\n        const cnpjStr = d[\"CNPJ\"] || \"\";\r\n        const cnpjDig = onlyDigits(cnpjStr);\r\n        mapCnpjNome.set(cnpjDig, nome);\r\n\r\n        if(!filtroClienteOK(nome, cnpjStr)) return;\r\n\r\n        \/\/ \u2705 FILTRO POR VENDEDOR (multi)\r\n        const vend = (d[\"Comercial Nome\"] || d.comercial || d.vendedor || \"\").toString().trim();\r\n        if(window.__vendSel && window.__vendSel.size){\r\n          if(!window.__vendSel.has(vend)) return;\r\n        }\r\n\r\n        const n = normalizeContract(d);\r\n        const pagamentos = d.pagamentos || {};\r\n\r\n        const start = d.dataMobilizacao ? new Date(d.dataMobilizacao) : null;\r\n        if(!start || isNaN(start.getTime()) || n.meses<=0) return;\r\n\r\n        const pen = n.meses - 1;\r\n        if(pen>=1){\r\n          const penPago = pagamentos[pen]?.status===\"PAGO\";\r\n          const ultPago = pagamentos[n.meses]?.status===\"PAGO\";\r\n          const penIni = new Date(start); penIni.setMonth(start.getMonth()+(pen-1));\r\n          const penKey = mesAnoFromDate(penIni);\r\n          if(penPago && !ultPago && matchesFilter(penKey, mes, ano)) penultimaPaga++;\r\n        }\r\n\r\n        for(let p=1;p<=n.meses;p++){\r\n          const ini = new Date(start); ini.setMonth(start.getMonth()+(p-1));\r\n          const fim = new Date(ini); fim.setMonth(ini.getMonth()+1); fim.setDate(0);\r\n          const key = mesAnoFromDate(ini);\r\n\r\n          if(!matchesFilter(key, mes, ano)) continue;\r\n\r\n          totalAPagar += n.parcela;\r\n          pagarPorMes[key] = (pagarPorMes[key]||0) + n.parcela;\r\n\r\n          window.__apagarDetalhe.push({\r\n            mes_ano: key, cliente: nome, cnpj: cnpjStr || \"\u2014\",\r\n            contrato: d[\"N\u00famero do contrato\"] || \"\u2014\",\r\n            valor: n.parcela\r\n          });\r\n\r\n          const pago = pagamentos[p]?.status===\"PAGO\";\r\n          if(pago){\r\n            const rec = pagamentos[p]?.recibo || {};\r\n            const recCash = Number(rec.cashback ?? n.cashbackParcela);\r\n            const recValorParcela = Number(rec.valor ?? n.parcela);\r\n\r\n            totalPagoFinanceiro += recCash;\r\n            bonusPorMes[key] = (bonusPorMes[key]||0) + recCash;\r\n\r\n            window.__pagoDetalhe.push({\r\n              mes_ano: key,\r\n              data: rec.data || null,\r\n              cliente: nome,\r\n              cnpj: cnpjStr || \"\u2014\",\r\n              contrato: d[\"N\u00famero do contrato\"] || \"\u2014\",\r\n              parcela: p,\r\n              valor_parcela: recValorParcela,\r\n              cashback: recCash,\r\n              auth: rec.auth || \"\u2014\"\r\n            });\r\n\r\n            \/\/ \u2705 CR\u00c9DITO para ledger de carteira (para calcular saldo vencido)\r\n            \/\/ Guarda mesmo que fora do filtro m\u00eas\/ano? -> Aqui est\u00e1 dentro do filtro (key),\r\n            \/\/ ent\u00e3o vai obedecer ao filtro do Indicadores.\r\n            const dataCred = toDateSafe(rec.data) || null;\r\n            const validade = toDateSafe(rec.validadeSaldoEm || rec.validade) || (dataCred ? addMonthsSafe(dataCred, 12) : null);\r\n\r\n            credits.push({\r\n              cnpj: cnpjDig || \"\",\r\n              cliente: nome,\r\n              contrato: d[\"N\u00famero do contrato\"] || \"\u2014\",\r\n              origem: \"recibo_pagamento\",\r\n              dataCredito: dataCred,\r\n              validade: validade,\r\n              valor: recCash,\r\n              remaining: recCash\r\n            });\r\n          }else{\r\n            if(fim < hoje){\r\n              atrasadosSet.add(id);\r\n              atrasosPorMes[key] = (atrasosPorMes[key]||0) + 1;\r\n\r\n              const dias = Math.max(0, Math.ceil((hoje - fim) \/ (1000 * 60 * 60 * 24)));\r\n              window.__atrasosDetalhe.push({\r\n                mes_ano: key,\r\n                cliente: nome,\r\n                cnpj: cnpjStr || \"\u2014\",\r\n                contrato: d[\"N\u00famero do contrato\"] || \"\u2014\",\r\n                parcela: p,\r\n                dias_atraso: dias\r\n              });\r\n            }\r\n          }\r\n        }\r\n      });\r\n\r\n      \/\/ usos (d\u00e9bitos para ledger)\r\n      try{\r\n        const usoSaldoSnap = await db.collection(\"uso_saldo\").get();\r\n        usoSaldoSnap.forEach(doc=>{\r\n          const u = doc.data();\r\n          const cnpjU = onlyDigits(u.cnpj || \"\");\r\n          const nomeU = mapCnpjNome.get(cnpjU) || u.cliente || u.nome || \"\u2014\";\r\n          const dataU = u.data?.toDate ? u.data.toDate() : (u.data ? new Date(u.data) : null);\r\n\r\n          if(!filtroClienteOK(nomeU, cnpjU)) return;\r\n\r\n          \/\/ \ud83d\udd35 Aqui mantemos o total de USO com filtro (igual j\u00e1 era)\r\n          if(dataU && !isNaN(dataU.getTime())){\r\n            const key = mesAnoFromDate(dataU);\r\n            if(!matchesFilter(key, mes, ano)) return;\r\n          }else{\r\n            if(mes || ano) return;\r\n          }\r\n\r\n          const valor = Number(u.valor || 0);\r\n          totalUsoCliente += valor;\r\n\r\n          window.__usoDetalhe.push({\r\n            data: u.data || null, cliente: nomeU, cnpj: cnpjU || \"\u2014\",\r\n            contrato: u.novoContrato || u.contrato || \"\u2014\",\r\n            origem: \"uso_saldo\", valor\r\n          });\r\n\r\n          \/\/ \u2705 d\u00e9bito para ledger (para saldo vencido) \u2014 usa a data real do uso (sem filtro para abater corretamente)\r\n          const dataUsoReal = u.data?.toDate ? u.data.toDate() : (u.data ? new Date(u.data) : null);\r\n          if(dataUsoReal && !isNaN(dataUsoReal.getTime()) && valor>0){\r\n            debits.push({\r\n              cnpj: cnpjU,\r\n              cliente: nomeU,\r\n              contrato: u.novoContrato || u.contrato || \"\u2014\",\r\n              origem: \"uso_saldo\",\r\n              data: dataUsoReal,\r\n              valor: valor\r\n            });\r\n          }\r\n        });\r\n      }catch(e){}\r\n\r\n      \/\/ (opcional) wallet_usos (d\u00e9bitos para ledger)\r\n      try{\r\n        const walletUsosSnap = await db.collection(\"wallet_usos\").get();\r\n        walletUsosSnap.forEach(doc=>{\r\n          const u = doc.data();\r\n          const cnpjU = onlyDigits(u.cnpj || \"\");\r\n          const nomeU = u.cliente || u.nome || mapCnpjNome.get(cnpjU) || \"\u2014\";\r\n          const dataU = u.data?.toDate ? u.data.toDate() : (u.data ? new Date(u.data) : null);\r\n\r\n          if(!filtroClienteOK(nomeU, cnpjU)) return;\r\n\r\n          \/\/ \ud83d\udd35 total de uso (com filtro) \u2014 igual j\u00e1 era\r\n          if(dataU && !isNaN(dataU.getTime())){\r\n            const key = mesAnoFromDate(dataU);\r\n            if(!matchesFilter(key, mes, ano)) return;\r\n          }else{\r\n            if(mes || ano) return;\r\n          }\r\n\r\n          const valor = Number(u.valor ?? u.valorUtilizado ?? 0);\r\n          totalUsoCliente += valor;\r\n\r\n          window.__usoDetalhe.push({\r\n            data: u.data || null, cliente: nomeU, cnpj: cnpjU || \"\u2014\",\r\n            contrato: u.contrato || \"\u2014\",\r\n            origem: \"wallet_usos\", valor\r\n          });\r\n\r\n          \/\/ \u2705 d\u00e9bito para ledger (sem filtro p\/ abater correto)\r\n          const dataUsoReal = u.data?.toDate ? u.data.toDate() : (u.data ? new Date(u.data) : null);\r\n          if(dataUsoReal && !isNaN(dataUsoReal.getTime()) && valor>0){\r\n            debits.push({\r\n              cnpj: cnpjU,\r\n              cliente: nomeU,\r\n              contrato: u.contrato || \"\u2014\",\r\n              origem: \"wallet_usos\",\r\n              data: dataUsoReal,\r\n              valor: valor\r\n            });\r\n          }\r\n        });\r\n      }catch(e){}\r\n\r\n      \/\/ =========================\r\n      \/\/ \u2705 NOVO: calcula SALDO vencido (cr\u00e9ditos - d\u00e9bitos) e conta apenas o que expirou\r\n      \/\/ Regra: cr\u00e9dito expira na data de validade do recibo (validadeSaldoEm\/validade) ou dataCredito+12 meses.\r\n      \/\/ \"B\u00f4nus vencidos\" = saldo (remaining) > 0 cujo validade < hoje.\r\n      \/\/ =========================\r\n      \/\/ Agrupa por CNPJ e abate d\u00e9bitos do mais antigo (FIFO)\r\n      const creditsBy = new Map();\r\n      credits.forEach(c=>{\r\n        const k = c.cnpj || \"\";\r\n        if(!creditsBy.has(k)) creditsBy.set(k, []);\r\n        creditsBy.get(k).push(c);\r\n      });\r\n\r\n      const debitsBy = new Map();\r\n      debits.forEach(d=>{\r\n        const k = d.cnpj || \"\";\r\n        if(!debitsBy.has(k)) debitsBy.set(k, []);\r\n        debitsBy.get(k).push(d);\r\n      });\r\n\r\n      \/\/ Ordena e abate\r\n      creditsBy.forEach((arr, cnpjKey)=>{\r\n        arr.sort((a,b)=>{\r\n          const da = a.dataCredito ? new Date(a.dataCredito) : new Date(0);\r\n          const dbb = b.dataCredito ? new Date(b.dataCredito) : new Date(0);\r\n          return da - dbb;\r\n        });\r\n\r\n        const dArr = (debitsBy.get(cnpjKey) || []).slice().sort((a,b)=> a.data - b.data);\r\n\r\n        let i=0;\r\n        for(const deb of dArr){\r\n          let restanteDeb = Number(deb.valor || 0);\r\n          while(restanteDeb > 0 && i < arr.length){\r\n            const cr = arr[i];\r\n            const rem = Number(cr.remaining || 0);\r\n            if(rem <= 0){\r\n              i++;\r\n              continue;\r\n            }\r\n            const abat = Math.min(rem, restanteDeb);\r\n            cr.remaining = rem - abat;\r\n            restanteDeb -= abat;\r\n            if(cr.remaining <= 0) i++;\r\n          }\r\n        }\r\n      });\r\n\r\n      \/\/ Soma vencidos\r\n      let vencQtd = 0;\r\n      let vencValor = 0;\r\n\r\n      credits.forEach(c=>{\r\n        const validade = c.validade ? new Date(c.validade) : null;\r\n        const rem = Number(c.remaining || 0);\r\n        if(!(rem > 0)) return;\r\n        if(!validade || isNaN(validade.getTime())) return;\r\n\r\n        if(validade < hoje){\r\n          vencQtd += 1;\r\n          vencValor += rem;\r\n\r\n          const diasExp = Math.max(0, daysDiff(hoje, validade));\r\n          window.__bonusVencidosCarteira.push({\r\n            dataCredito: c.dataCredito,\r\n            validade: validade,\r\n            cliente: c.cliente || \"\u2014\",\r\n            cnpj: c.cnpj || \"\u2014\",\r\n            contrato: c.contrato || \"\u2014\",\r\n            saldoVencido: rem,\r\n            diasExpirado: diasExp,\r\n            origem: c.origem || \"carteira\"\r\n          });\r\n        }\r\n      });\r\n\r\n      \/\/ atualiza cards\r\n      el(\"indTotalAPagar\").textContent = fmtBRL(totalAPagar);\r\n      el(\"indTotalUsoCliente\").textContent = fmtBRL(totalUsoCliente);\r\n      el(\"indTotalPagoFinanceiro\").textContent = fmtBRL(totalPagoFinanceiro);\r\n      el(\"indPenultimaPaga\").textContent = String(penultimaPaga);\r\n      el(\"indAtrasados\").textContent = String(atrasadosSet.size);\r\n\r\n      \/\/ \u2705 NOVO card \u201cB\u00f4nus vencidos (carteira expirada)\u201d\r\n      if(el(\"indBonusVencidosQtd\")) el(\"indBonusVencidosQtd\").textContent = String(vencQtd);\r\n      if(el(\"indBonusVencidosValor\")) el(\"indBonusVencidosValor\").textContent = fmtBRL(vencValor);\r\n\r\n      const labels = Array.from(new Set([\r\n        ...Object.keys(pagarPorMes),\r\n        ...Object.keys(bonusPorMes),\r\n        ...Object.keys(atrasosPorMes)\r\n      ])).sort();\r\n\r\n      const dataPagar = labels.map(k=>pagarPorMes[k]||0);\r\n      const dataBonus = labels.map(k=>bonusPorMes[k]||0);\r\n      const dataAtrasos = labels.map(k=>atrasosPorMes[k]||0);\r\n\r\n      if(chartIndPagar) chartIndPagar.destroy();\r\n      chartIndPagar = new Chart(\r\n        el(\"chartIndPagar\").getContext(\"2d\"),\r\n        makeLineConfig({\r\n          labels,\r\n          data: dataPagar,\r\n          title: \"R$ a pagar\",\r\n          valueFormatter: (v)=> fmtBRL(v),\r\n          onPointClick: (mesAno)=> abrirDetalheAPagarMes(mesAno),\r\n          color: \"rgba(255,212,0,0.95)\"\r\n        })\r\n      );\r\n\r\n      if(chartIndBonus) chartIndBonus.destroy();\r\n      chartIndBonus = new Chart(\r\n        el(\"chartIndBonus\").getContext(\"2d\"),\r\n        makeLineConfig({\r\n          labels,\r\n          data: dataBonus,\r\n          title: \"B\u00f4nus pago\",\r\n          valueFormatter: (v)=> fmtBRL(v),\r\n          onPointClick: (mesAno)=> abrirDetalhePagoMes(mesAno),\r\n          color: \"rgba(34,197,94,0.95)\"\r\n        })\r\n      );\r\n\r\n      if(chartIndAtraso) chartIndAtraso.destroy();\r\n      chartIndAtraso = new Chart(\r\n        el(\"chartIndAtraso\").getContext(\"2d\"),\r\n        makeLineConfig({\r\n          labels,\r\n          data: dataAtrasos,\r\n          title: \"Atrasos\",\r\n          valueFormatter: (v)=> `${v} atraso(s)`,\r\n          onPointClick: (mesAno)=> abrirDetalheAtrasosMes(mesAno),\r\n          color: \"rgba(248,113,113,0.95)\"\r\n        })\r\n      );\r\n\r\n      try{\r\n        await carregarSatisfacaoIndicadores({ mes, ano, mapCnpjNome });\r\n      }catch(e){\r\n        console.error(\"Erro satisfa\u00e7\u00e3o:\", e);\r\n      }\r\n    };\r\n\r\n    \/\/ \u2705 Modais (Indicadores)\r\n    window.abrirDetalheAPagar = function(){\r\n      const modal = el(\"modalAPagar\");\r\n      el(\"apagarSub\").textContent = window.__indicadoresFiltroTexto;\r\n\r\n      const tbody = el(\"listaAPagarDetalhe\");\r\n      const rows = window.__apagarDetalhe || [];\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"5\" class=\"text-center py-4 text-gray-500\">Sem registros para o filtro aplicado.<\/td><\/tr>`;\r\n      }else{\r\n        tbody.innerHTML = rows\r\n          .sort((a,b)=> String(a.mes_ano).localeCompare(String(b.mes_ano)))\r\n          .map(r=>`\r\n            <tr class=\"border-b border-gray-800\">\r\n              <td>${r.mes_ano || \"\u2014\"}<\/td>\r\n              <td>${r.cliente || \"\u2014\"}<\/td>\r\n              <td>${r.cnpj || \"\u2014\"}<\/td>\r\n              <td>${r.contrato || \"\u2014\"}<\/td>\r\n              <td class=\"text-right\">${fmtBRL(r.valor)}<\/td>\r\n            <\/tr>\r\n          `).join(\"\");\r\n      }\r\n\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n    window.fecharDetalheAPagar = function(){\r\n      const modal = el(\"modalAPagar\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n\r\n    window.abrirDetalheUso = function(){\r\n      const modal = el(\"modalUso\");\r\n      el(\"usoSub\").textContent = window.__indicadoresFiltroTexto;\r\n\r\n      const tbody = el(\"listaUsoDetalhe\");\r\n      const rows = window.__usoDetalhe || [];\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"6\" class=\"text-center py-4 text-gray-500\">Sem registros de uso para o filtro aplicado.<\/td><\/tr>`;\r\n      }else{\r\n        tbody.innerHTML = rows\r\n          .sort((a,b)=>{\r\n            const da = a.data?.toDate ? a.data.toDate() : (a.data ? new Date(a.data) : new Date(0));\r\n            const dbb = b.data?.toDate ? b.data.toDate() : (b.data ? new Date(b.data) : new Date(0));\r\n            return dbb - da;\r\n          })\r\n          .map(r=>{\r\n            const d = r.data?.toDate ? r.data.toDate() : (r.data ? new Date(r.data) : null);\r\n            const dataTxt = d && !isNaN(d.getTime()) ? d.toLocaleString(\"pt-BR\") : \"\u2014\";\r\n            return `\r\n              <tr class=\"border-b border-gray-800\">\r\n                <td>${dataTxt}<\/td>\r\n                <td>${r.cliente || \"\u2014\"}<\/td>\r\n                <td>${r.cnpj || \"\u2014\"}<\/td>\r\n                <td>${r.contrato || \"\u2014\"}<\/td>\r\n                <td>${r.origem || \"\u2014\"}<\/td>\r\n                <td class=\"text-right\">${fmtBRL(r.valor)}<\/td>\r\n              <\/tr>\r\n            `;\r\n          }).join(\"\");\r\n      }\r\n\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n    window.fecharDetalheUso = function(){\r\n      const modal = el(\"modalUso\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n\r\n    window.abrirDetalhePago = function(){\r\n      const modal = el(\"modalPago\");\r\n      el(\"pagoSub\").textContent = window.__indicadoresFiltroTexto;\r\n\r\n      const tbody = el(\"listaPagoDetalhe\");\r\n      const rows = window.__pagoDetalhe || [];\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"8\" class=\"text-center py-4 text-gray-500\">Sem pagamentos (PAGO) para o filtro aplicado.<\/td><\/tr>`;\r\n      }else{\r\n        tbody.innerHTML = rows\r\n          .sort((a,b)=>{\r\n            const da = a.data?.toDate ? a.data.toDate() : (a.data ? new Date(a.data) : new Date(0));\r\n            const dbb = b.data?.toDate ? b.data.toDate() : (b.data ? new Date(b.data) : new Date(0));\r\n            return dbb - da;\r\n          })\r\n          .map(r=>{\r\n            const d = r.data?.toDate ? r.data.toDate() : (r.data ? new Date(r.data) : null);\r\n            const dataTxt = d && !isNaN(d.getTime()) ? d.toLocaleString(\"pt-BR\") : \"\u2014\";\r\n            return `\r\n              <tr class=\"border-b border-gray-800\">\r\n                <td>${dataTxt}<\/td>\r\n                <td>${r.cliente || \"\u2014\"}<\/td>\r\n                <td>${r.cnpj || \"\u2014\"}<\/td>\r\n                <td>${r.contrato || \"\u2014\"}<\/td>\r\n                <td class=\"text-right\">${r.parcela ?? \"\u2014\"}<\/td>\r\n                <td class=\"text-right\">${fmtBRL(r.valor_parcela)}<\/td>\r\n                <td class=\"text-right text-green-300\">${fmtBRL(r.cashback)}<\/td>\r\n                <td>${r.auth || \"\u2014\"}<\/td>\r\n              <\/tr>\r\n            `;\r\n          }).join(\"\");\r\n      }\r\n\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n    window.fecharDetalhePago = function(){\r\n      const modal = el(\"modalPago\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n\r\n    window.abrirDetalheAtrasos = function(){\r\n      const modal = el(\"modalAtrasos\");\r\n      el(\"atrasosSub\").textContent = window.__indicadoresFiltroTexto;\r\n\r\n      const tbody = el(\"listaAtrasosDetalhe\");\r\n      const rows = window.__atrasosDetalhe || [];\r\n      if(!rows.length){\r\n        tbody.innerHTML = `<tr><td colspan=\"6\" class=\"text-center py-4 text-gray-500\">Sem atrasos para o filtro aplicado.<\/td><\/tr>`;\r\n      }else{\r\n        tbody.innerHTML = rows\r\n          .sort((a,b)=> String(a.mes_ano).localeCompare(String(b.mes_ano)))\r\n          .map(r=>`\r\n            <tr class=\"border-b border-gray-800\">\r\n              <td>${r.mes_ano || \"\u2014\"}<\/td>\r\n              <td>${r.cliente || \"\u2014\"}<\/td>\r\n              <td>${r.cnpj || \"\u2014\"}<\/td>\r\n              <td>${r.contrato || \"\u2014\"}<\/td>\r\n              <td class=\"text-right\">${r.parcela ?? \"\u2014\"}<\/td>\r\n              <td class=\"text-right\">${r.dias_atraso ?? \"\u2014\"}<\/td>\r\n            <\/tr>\r\n          `).join(\"\");\r\n      }\r\n\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n    window.fecharDetalheAtrasos = function(){\r\n      const modal = el(\"modalAtrasos\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n\r\n    \/\/ Tabs\r\n    window.switchTab = function(e, id){\r\n      [\"cadastros\",\"historico\",\"indicadores\",\"financeiro\"].forEach(t=>el(t).classList.add(\"hidden\"));\r\n      el(id).classList.remove(\"hidden\");\r\n\r\n      document.querySelectorAll(\".tab-btn\").forEach(b=>b.classList.remove(\"active\"));\r\n      e.target.classList.add(\"active\");\r\n\r\n      if(id===\"historico\"){\r\n        el(\"dashboardEmissoes\").classList.remove(\"hidden\");\r\n        carregarHistoricoEmissoes();\r\n        carregarDashboard();\r\n      }else{\r\n        el(\"dashboardEmissoes\").classList.add(\"hidden\");\r\n      }\r\n\r\n      if(id===\"indicadores\"){\r\n        carregarIndicadores();\r\n      }\r\n    };\r\n\r\n    \/\/ Modal recibo\r\n    window.abrirRecibo = function(r){\r\n      el(\"rCliente\").innerText = r.cliente || \"\";\r\n      el(\"rCnpj\").innerText = r.cnpj || \"\";\r\n      el(\"rContrato\").innerText = r.contrato || \"\";\r\n      el(\"rParcela\").innerText = r.parcela || \"\";\r\n      el(\"rTotal\").innerText = Number(r.valor||0).toFixed(2);\r\n      el(\"rPercent\").innerText = r.percent ?? \"\";\r\n      el(\"rCashback\").innerText = Number(r.cashback||0).toFixed(2);\r\n\r\n      const dEmissao = toDateSafe(r.data) || new Date();\r\n      el(\"rData\").innerText = dEmissao.toLocaleString(\"pt-BR\");\r\n\r\n      el(\"rValidade\").innerText = fmtDateBR(r.validadeSaldoEm || r.validade);\r\n      el(\"rAuth\").innerText = r.auth || \"\";\r\n\r\n      const modal = el(\"modalRecibo\");\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n    };\r\n    window.fecharRecibo = function(){\r\n      const modal = el(\"modalRecibo\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n    };\r\n    window.reabrirRecibo = function(id, p){\r\n      db.collection(\"cashback_contracts\").doc(id).get().then(d=>{\r\n        const rec = d.data()?.pagamentos?.[p]?.recibo;\r\n        if(!rec){ alert(\"Recibo n\u00e3o encontrado.\"); return; }\r\n        abrirRecibo(rec);\r\n      });\r\n    };\r\n\r\n    \/\/ Financeiro ADM\r\n    window.buscarFinanceiroADM = async function(){\r\n      const cnpjV = finCnpj.value.replace(\/\\D\/g,\"\");\r\n      const contratoV = finContrato.value;\r\n      if(!cnpjV || !contratoV){ resultadoFinanceiro.innerText=\"Informe CNPJ e Contrato\"; return; }\r\n\r\n      const s = await db.collection(\"cashback_contracts\")\r\n        .where(\"CNPJ\",\"==\",cnpjV)\r\n        .where(\"N\u00famero do contrato\",\"==\",contratoV)\r\n        .limit(1).get();\r\n\r\n      if(s.empty){ resultadoFinanceiro.innerText=\"Contrato n\u00e3o encontrado\"; return; }\r\n\r\n      const doc = s.docs[0];\r\n      const d = doc.data();\r\n      const n = normalizeContract(d);\r\n      const pgt = d.pagamentos || {};\r\n      const m = n.meses;\r\n      const v = n.parcela;\r\n      const p = n.pct;\r\n      const c = n.cashbackParcela;\r\n\r\n      const i = new Date(d.dataMobilizacao);\r\n      let h = `<table class=\"min-w-full text-xs\">\r\n        <thead><tr class=\"text-gray-300\">\r\n          <th>Parcela<\/th><th>M\u00eas<\/th><th>In\u00edcio<\/th><th>Fim<\/th><th>Valor<\/th><th>%<\/th><th>Cashback<\/th><th>Status<\/th><th>A\u00e7\u00f5es<\/th>\r\n        <\/tr><\/thead><tbody>`;\r\n\r\n      for(let x=0;x<m;x++){\r\n        const ini = new Date(i); ini.setMonth(i.getMonth()+x);\r\n        const fim = new Date(ini); fim.setMonth(ini.getMonth()+1); fim.setDate(0);\r\n\r\n        const pago = pgt[x+1]?.status===\"PAGO\";\r\n        h += `<tr class=\"border-b border-gray-800\">\r\n          <td>${x+1}<\/td>\r\n          <td>${ini.toLocaleDateString(\"pt-BR\",{month:\"long\",year:\"numeric\"})}<\/td>\r\n          <td>${ini.toLocaleDateString(\"pt-BR\")}<\/td>\r\n          <td>${fim.toLocaleDateString(\"pt-BR\")}<\/td>\r\n          <td>${fmtBRL(v)}<\/td>\r\n          <td>${p}%<\/td>\r\n          <td class=\"text-green-400\">${fmtBRL(c)}<\/td>\r\n          <td class=\"${pago ? \"text-green-400 font-bold\" : \"\"}\">${pago ? \"PAGO\" : \"PENDENTE\"}<\/td>\r\n          <td class=\"flex gap-3 justify-center text-lg\">\r\n            <button class=\"hover:scale-105 transition\" onclick=\"confirmarPagamento('${doc.id}',${x+1})\">\u2714<\/button>\r\n            <button class=\"${pago ? \"\" : \"hidden\"} hover:scale-105 transition\" onclick=\"reabrirRecibo('${doc.id}',${x+1})\">\ud83d\udcc4<\/button>\r\n            <button class=\"text-red-400 hover:scale-105 transition\" onclick=\"enviarAvisoAtraso('${doc.id}',${x+1})\">\u274c<\/button>\r\n          <\/td>\r\n        <\/tr>`;\r\n      }\r\n\r\n      resultadoFinanceiro.innerHTML = h + \"<\/tbody><\/table>\";\r\n    };\r\n\r\n    \/\/ \u2714 ENVIA B\u00d4NUS\r\n    window.confirmarPagamento = function(id, parcela){\r\n      if(!confirm(\"Voc\u00ea deseja fazer esse envio do b\u00f4nus?\")) return;\r\n\r\n      db.collection(\"cashback_contracts\").doc(id).get().then(d=>{\r\n        const c = d.data();\r\n        const n = normalizeContract(c);\r\n\r\n        const dataEmissao = new Date();\r\n        const validade = addMonthsSafe(dataEmissao, 12);\r\n\r\n        const r = {\r\n          cliente: c[\"Nome do cliente\"],\r\n          cnpj: c[\"CNPJ\"],\r\n          contrato: c[\"N\u00famero do contrato\"],\r\n          parcela: parcela,\r\n          valor: n.parcela,\r\n          percent: n.pct,\r\n          cashback: n.cashbackParcela,\r\n          data: dataEmissao,\r\n          validade: validade,\r\n          validadeSaldoEm: validade,\r\n          auth: gerarAutenticacao()\r\n        };\r\n\r\n        const clienteEmail = c[\"Email\"] || \"\";\r\n\r\n        db.collection(\"cashback_contracts\").doc(id).set({\r\n          pagamentos: { [parcela]: { status:\"PAGO\", recibo:r } }\r\n        },{merge:true}).then(()=>{\r\n\r\n          safeSendEmail(EMAILJS_TEMPLATE_BONUS_LIBERADO, {\r\n            contrato: String(r.contrato ?? \"\"),\r\n            parcela: String(r.parcela ?? \"\"),\r\n            Cliente: String(r.cliente ?? \"\"),\r\n            cliente: String(r.cliente ?? \"\"),\r\n            valor_parcela: Number(r.valor || 0),\r\n            cashback_valor: Number(r.cashback || 0),\r\n            Cashback: Number(r.cashback || 0),\r\n            cashback: Number(r.cashback || 0),\r\n            Auth: String(r.auth ?? \"\"),\r\n            auth: String(r.auth ?? \"\"),\r\n            dados: \"B\u00f4nus liberado \u2714\",\r\n            data: new Date().toLocaleString(\"pt-BR\"),\r\n            ano: String(new Date().getFullYear()),\r\n            validade: fmtDateBR(r.validadeSaldoEm),\r\n            Validade: fmtDateBR(r.validadeSaldoEm),\r\n            email: String(clienteEmail || \"\"),\r\n            \"E-mail\": String(clienteEmail || \"\")\r\n          });\r\n\r\n          abrirRecibo(r);\r\n          buscarFinanceiroADM();\r\n          try{ carregarIndicadores(); }catch(e){}\r\n        });\r\n      });\r\n    };\r\n\r\n    \/\/ \u274c ENVIA ATRASO\r\n    window.enviarAvisoAtraso = function(id, parcela){\r\n      if(!confirm(\"Enviar e-mail de aviso de atraso ao cliente?\")) return;\r\n\r\n      db.collection(\"cashback_contracts\").doc(id).get().then(d=>{\r\n        const c = d.data();\r\n        const n = normalizeContract(c);\r\n\r\n        const clienteEmail = c[\"Email\"] || \"\";\r\n        const contratoNum  = c[\"N\u00famero do contrato\"] || \"\";\r\n        const clienteNome  = c[\"Nome do cliente\"] || \"\";\r\n\r\n        const valorParcela = Number(n.parcela || c.valorMensal || 0);\r\n        const cashbackMes  = Number(n.cashbackParcela || c.cashbackMensal || 0);\r\n\r\n        emailjs.send(EMAILJS_SERVICE_ID, EMAILJS_TEMPLATE_ATRASO, {\r\n          contrato: String(contratoNum),\r\n          parcela: String(parcela),\r\n          Cliente: String(clienteNome),\r\n          cliente: String(clienteNome),\r\n          valor_parcela: valorParcela,\r\n          Cashback: cashbackMes,\r\n          cashback: cashbackMes,\r\n          cashback_valor: cashbackMes,\r\n          dados: \"Parcela em atraso (b\u00f4nus n\u00e3o liberado)\",\r\n          Auth: \"AVISO-ATRASO\",\r\n          auth: \"AVISO-ATRASO\",\r\n          email: String(clienteEmail || \"\"),\r\n          \"E-mail\": String(clienteEmail || \"\"),\r\n          data: new Date().toLocaleString(\"pt-BR\"),\r\n          ano: String(new Date().getFullYear())\r\n        })\r\n        .then((res)=> console.log(\"Email atraso OK:\", res))\r\n        .catch((err)=> console.error(\"Email atraso ERRO:\", err));\r\n      });\r\n    };\r\n\r\n    \/\/ =============================\r\n    \/\/ \u2705 AUTENTICA\u00c7\u00c3O FINANCEIRO (com hash SHA-256)\r\n    \/\/ =============================\r\n    \r\n    \/\/ Fun\u00e7\u00e3o para gerar hash SHA-256 da senha\r\n    async function hashSenha(senha) {\r\n      const encoder = new TextEncoder();\r\n      const data = encoder.encode(senha);\r\n      const hashBuffer = await crypto.subtle.digest('SHA-256', data);\r\n      const hashArray = Array.from(new Uint8Array(hashBuffer));\r\n      const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\r\n      return hashHex;\r\n    }\r\n    \r\n    \/\/ Hash pr\u00e9-calculado da senha: %2026%agisaclound\r\n    const SENHA_FINANCEIRO_HASH = \"071a7523a8358aed1b4583a80807755956c08f75dc1a0efb4bdc47935ecccc47\";\r\n    \r\n    window.abrirModalAuthFinanceiro = async function(event){\r\n      event.preventDefault();\r\n      event.stopPropagation();\r\n      \r\n      \/\/ Limpar campo de senha\r\n      el(\"senhaFinanceiro\").value = \"\";\r\n      el(\"msgErroSenha\").classList.add(\"hidden\");\r\n      \r\n      \/\/ Abrir modal\r\n      const modal = el(\"modalAuthFinanceiro\");\r\n      modal.classList.remove(\"hidden\");\r\n      modal.classList.add(\"flex\");\r\n      \r\n      \/\/ Focar no campo de senha\r\n      setTimeout(()=>{ el(\"senhaFinanceiro\").focus(); }, 100);\r\n    };\r\n    \r\n    window.fecharModalAuthFinanceiro = function(){\r\n      const modal = el(\"modalAuthFinanceiro\");\r\n      modal.classList.add(\"hidden\");\r\n      modal.classList.remove(\"flex\");\r\n      el(\"senhaFinanceiro\").value = \"\";\r\n    };\r\n    \r\n    window.verificarSenhaFinanceiro = async function(){\r\n      const senhaDigitada = el(\"senhaFinanceiro\").value;\r\n      \r\n      if(!senhaDigitada){\r\n        el(\"msgErroSenha\").textContent = \"Digite a senha.\";\r\n        el(\"msgErroSenha\").classList.remove(\"hidden\");\r\n        return;\r\n      }\r\n      \r\n      try{\r\n        const hashDigitado = await hashSenha(senhaDigitada);\r\n        \r\n        if(hashDigitado === SENHA_FINANCEIRO_HASH){\r\n          \/\/ Senha correta!\r\n          window.__financeiro_autenticado = true;\r\n          fecharModalAuthFinanceiro();\r\n          switchTab(null, 'financeiro');\r\n        }else{\r\n          \/\/ Senha incorreta\r\n          el(\"msgErroSenha\").textContent = \"Senha incorreta. Tente novamente.\";\r\n          el(\"msgErroSenha\").classList.remove(\"hidden\");\r\n          el(\"senhaFinanceiro\").value = \"\";\r\n          el(\"senhaFinanceiro\").focus();\r\n        }\r\n      }catch(err){\r\n        console.error(\"Erro ao verificar senha:\", err);\r\n        el(\"msgErroSenha\").textContent = \"Erro ao verificar senha. Tente novamente.\";\r\n        el(\"msgErroSenha\").classList.remove(\"hidden\");\r\n      }\r\n    };\r\n    \r\n    \/\/ Permitir Enter para enviar a senha\r\n    document.addEventListener(\"keydown\", function(event){\r\n      if(event.key === \"Enter\"){\r\n        const modal = el(\"modalAuthFinanceiro\");\r\n        if(modal && !modal.classList.contains(\"hidden\")){\r\n          event.preventDefault();\r\n          verificarSenhaFinanceiro();\r\n        }\r\n      }\r\n    });\r\n\r\n    \/\/ Token uso + hist\u00f3rico\r\n    window.gerarTokenUso = function(){\r\n      const cnpjV = usoCnpj.value.replace(\/\\D\/g,\"\");\r\n      const contratoV = usoContrato.value;\r\n\r\n      if(!cnpjV || !contratoV){ alert(\"Preencha CNPJ e contrato\"); return; }\r\n\r\n      db.collection(\"cashback_contracts\").where(\"CNPJ\",\"==\",cnpjV).limit(1).get().then(s=>{\r\n        let clienteNome=\"Cliente Desconhecido\";\r\n        let clienteEmail=\"\";\r\n\r\n        if(!s.empty){\r\n          const cd=s.docs[0].data();\r\n          clienteNome=cd[\"Nome do cliente\"];\r\n          clienteEmail=cd[\"Email\"];\r\n        }else{\r\n          alert(\"Aten\u00e7\u00e3o: Cliente n\u00e3o encontrado na base (cashback_contracts). Usando placeholder.\");\r\n        }\r\n\r\n        if(!confirm(`Voc\u00ea deseja emitir a ordem de uso para o cliente ${clienteNome} (CNPJ: ${cnpjV}, Contrato: ${contratoV})?`)) return;\r\n\r\n        const tokenGerado = \"AGISA-WLT-\" + Math.random().toString(36).substr(2,6).toUpperCase();\r\n\r\n        db.collection(\"wallet_tokens\")\r\n          .where(\"cnpj\",\"==\",cnpjV)\r\n          .where(\"contrato\",\"==\",contratoV)\r\n          .where(\"status\",\"==\",\"ATIVO\")\r\n          .get()\r\n          .then(s2=>{\r\n            const batch=db.batch();\r\n\r\n            s2.forEach(doc=>batch.update(doc.ref,{status:\"REVOGADO\"}));\r\n\r\n            \/\/ \u2705 expira\u00e7\u00e3o 7 dias\r\n            const exp = new Date();\r\n            exp.setDate(exp.getDate() + 7);\r\n\r\n            const ref = db.collection(\"wallet_tokens\").doc();\r\n            batch.set(ref,{\r\n              cnpj: cnpjV,\r\n              contrato: contratoV,\r\n              token: tokenGerado,\r\n              status: \"ATIVO\",\r\n              usado: false,\r\n              criadoEm: firebase.firestore.FieldValue.serverTimestamp(),\r\n              expiraEm: exp\r\n            });\r\n\r\n            const agora = new Date();\r\n            const mesAno = `${agora.getFullYear()}-${String(agora.getMonth()+1).padStart(2,'0')}`;\r\n\r\n            batch.set(db.collection(\"emissao_de_uso\").doc(),{\r\n              cliente: clienteNome,\r\n              cnpj: cnpjV,\r\n              contrato: contratoV,\r\n              token: tokenGerado,\r\n              data_emissao: firebase.firestore.FieldValue.serverTimestamp(),\r\n              mes_ano: mesAno\r\n            });\r\n\r\n            batch.commit().then(()=>{\r\n              usoToken.value = tokenGerado;\r\n              alert(\"Token gerado e hist\u00f3rico registrado com sucesso!\");\r\n\r\n              safeSendEmail(EMAILJS_TEMPLATE_TOKEN_USO, {\r\n                contrato: String(contratoV || \"\"),\r\n                Cliente: String(clienteNome || \"\"),\r\n                cliente: String(clienteNome || \"\"),\r\n                dados: \"Token de uso gerado\",\r\n                token: String(tokenGerado || \"\"),\r\n                email: String(clienteEmail || \"\"),\r\n                \"E-mail\": String(clienteEmail || \"\")\r\n              });\r\n\r\n              carregarHistoricoEmissoes();\r\n              carregarDashboard();\r\n            });\r\n          });\r\n      });\r\n    };\r\n\r\n    filtroMes.onchange = ()=>{ carregarHistoricoEmissoes(); carregarDashboard(); };\r\n    filtroAno.onchange = ()=>{ carregarHistoricoEmissoes(); carregarDashboard(); };\r\n  }\r\n\r\n});\r\n<\/script>\r\n\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>AGISA | Admin Cashback AGISA Admin Cashback Acesso restrito \u2022 Firebase Auth ONLINE Login (email) Senha ENTRAR Somente usu\u00e1rios autorizados (UID liberado no Firebase). AGISA Admin Cashback \u25cf ONLINE Logado: \u2014 Sair Registrar Nova Transa\u00e7\u00e3o REGISTRAR CLIENTE + HIST\u00d3RICO Cadastros Hist\u00f3rico de Emiss\u00f5es Indicadores Financeiro ADM Cadastros realizados Cliente CNPJ Contrato Telefone Email Chave Emiss\u00e3o [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-458","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/pages\/458","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/comments?post=458"}],"version-history":[{"count":866,"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/pages\/458\/revisions"}],"predecessor-version":[{"id":1649,"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/pages\/458\/revisions\/1649"}],"wp:attachment":[{"href":"https:\/\/agisa.com.br\/bonus.agisa.com.br\/wp-json\/wp\/v2\/media?parent=458"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}