{"id":7334,"date":"2026-04-09T18:46:41","date_gmt":"2026-04-09T21:46:41","guid":{"rendered":"https:\/\/saudecajati.com.br\/?page_id=7334"},"modified":"2026-04-29T09:48:52","modified_gmt":"2026-04-29T12:48:52","slug":"leitor-de-afd","status":"publish","type":"page","link":"https:\/\/saudecajati.com.br\/index.php\/leitor-de-afd\/","title":{"rendered":"Leitor de AFD"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"7334\" class=\"elementor elementor-7334\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c5a85fc e-flex e-con-boxed e-con e-parent\" data-id=\"c5a85fc\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-fe9b81a elementor-align-center elementor-icon-list--layout-traditional elementor-list-item-link-full_width elementor-invisible elementor-widget elementor-widget-icon-list\" data-id=\"fe9b81a\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_animation&quot;:&quot;slideInDown&quot;}\" data-widget_type=\"icon-list.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul class=\"elementor-icon-list-items\">\n\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Leitor de AFD<\/span>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\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-7bffa37 e-flex e-con-boxed e-con e-parent\" data-id=\"7bffa37\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f3d0bc4 elementor-widget elementor-widget-html\" data-id=\"f3d0bc4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\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    <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;600;700;800&display=swap\" rel=\"stylesheet\">\r\n    <style>\r\n        \/* CONFIGURA\u00c7\u00c3O GLOBAL - PADR\u00c3O CAJATI *\/\r\n        #leitor-afd-app {\r\n            font-family: 'Inter', sans-serif !important;\r\n            background-color: #f4f6f8 !important;\r\n            padding: 20px !important;\r\n            color: #2c3e50 !important;\r\n            max-width: 900px !important;\r\n            margin: 20px auto !important;\r\n            border-radius: 12px !important;\r\n            box-shadow: 0 4px 10px rgba(0,0,0,0.05) !important;\r\n            border: 1px solid #e2e8f0 !important;\r\n        }\r\n\r\n        .card-config {\r\n            background: #ffffff !important;\r\n            padding: 20px !important;\r\n            border-radius: 12px !important;\r\n            border: 1px solid #edf2f7 !important;\r\n            margin-bottom: 15px !important;\r\n        }\r\n\r\n        .label-instrucao {\r\n            display: block !important;\r\n            font-weight: 700 !important;\r\n            margin-bottom: 8px !important;\r\n            color: #00A09A !important;\r\n            font-size: 13px !important;\r\n            text-transform: uppercase !important;\r\n        }\r\n\r\n        .afd-input {\r\n            width: 100% !important;\r\n            padding: 12px !important;\r\n            border: 2px solid #edf2f7 !important;\r\n            border-radius: 8px !important;\r\n            font-size: 15px !important;\r\n            box-sizing: border-box !important;\r\n            font-family: 'Inter', sans-serif !important;\r\n            outline: none !important;\r\n        }\r\n\r\n        .afd-input:focus { border-color: #00A09A !important; }\r\n        .afd-input:disabled { background-color: #f4f6f8 !important; cursor: not-allowed; }\r\n\r\n        \/* BOT\u00c3O *\/\r\n        .btn-cajati {\r\n            width: 100% !important;\r\n            background-color: #00A09A !important;\r\n            color: #ffffff !important;\r\n            border: none !important;\r\n            padding: 15px !important;\r\n            border-radius: 8px !important;\r\n            font-weight: 700 !important;\r\n            font-size: 16px !important;\r\n            cursor: pointer !important;\r\n            display: flex !important;\r\n            align-items: center !important;\r\n            justify-content: center !important;\r\n            transition: background-color 0.2s !important;\r\n            margin-top: 15px !important;\r\n        }\r\n\r\n        .btn-cajati:hover:not(:disabled) { background-color: #00827d !important; }\r\n        .btn-cajati:disabled { background-color: #cbd5e1 !important; cursor: not-allowed; }\r\n        \r\n        .afd-status { text-align: center !important; margin-top: 15px !important; font-size: 13px !important; font-weight: 600 !important; }\r\n\r\n        \/* ESTILOS DA PR\u00c9VIA NA TELA *\/\r\n        .preview-container {\r\n            margin-top: 25px;\r\n            background: #ffffff;\r\n            border-radius: 12px;\r\n            border: 1px solid #edf2f7;\r\n            overflow: hidden;\r\n            display: none; \r\n        }\r\n        \r\n        .cabecalho-preview {\r\n            padding: 15px 20px;\r\n            background: #f8fafc;\r\n            border-bottom: 2px solid #00A09A;\r\n            font-size: 14px;\r\n            color: #1e293b;\r\n            display: flex;\r\n            justify-content: space-between;\r\n            align-items: center;\r\n        }\r\n\r\n        .tabela-preview { width: 100%; border-collapse: collapse; font-size: 13px; }\r\n        .tabela-preview th { background-color: #00A09A; color: white; padding: 10px 8px; text-align: center; }\r\n        .tabela-preview td { padding: 8px; text-align: center; border-bottom: 1px solid #edf2f7; vertical-align: middle; }\r\n        .tabela-preview tr:last-child td { border-bottom: none; }\r\n        \r\n        .uni-tag { font-size: 9px; color: #64748b; display: block; margin-top: 2px; line-height: 1; font-weight: 600; text-transform: uppercase; }\r\n    <\/style>\r\n<\/head>\r\n<body>\r\n\r\n<div id=\"leitor-afd-app\">\r\n    \r\n    <div class=\"card-config\">\r\n        <label class=\"label-instrucao\">1. Arquivos AFD (.txt) - Pode selecionar v\u00e1rios de unidades diferentes<\/label>\r\n        <input type=\"file\" id=\"arquivo-ponto\" class=\"afd-input\" accept=\".txt, .afd\" multiple onchange=\"lerArquivosAFD(event)\">\r\n    <\/div>\r\n\r\n    <div style=\"display: grid; grid-template-columns: 1.5fr 1fr; gap: 15px;\">\r\n        <div class=\"card-config\">\r\n            <label class=\"label-instrucao\">2. Selecionar Servidor<\/label>\r\n            <select id=\"seletor-servidor\" class=\"afd-input\" disabled onchange=\"validarSelecao(); atualizarPrevia();\">\r\n                <option value=\"\">Aguardando arquivo...<\/option>\r\n            <\/select>\r\n        <\/div>\r\n\r\n        <div class=\"card-config\">\r\n            <label class=\"label-instrucao\">3. M\u00eas de Refer\u00eancia<\/label>\r\n            <input type=\"month\" id=\"mes-ref\" class=\"afd-input\" onchange=\"atualizarListaServidores(); atualizarPrevia();\">\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <button onclick=\"imprimirFolha()\" class=\"btn-cajati\" id=\"btn-imprimir\" disabled>\r\n        Imprimir PDF\r\n    <\/button>\r\n    \r\n    <div id=\"afd-status\" class=\"afd-status\" style=\"color: #64748b;\">Insira os arquivos gerados pelos rel\u00f3gios para come\u00e7ar.<\/div>\r\n\r\n    <div id=\"area-previa\"><\/div>\r\n<\/div>\r\n\r\n<script>\r\n    let bancoDadosAFD = {}; \r\n\r\n    \/\/ INTELIG\u00caNCIA MATEM\u00c1TICA PARA CPF E PIS\r\n    function isCPF(cpf) {\r\n        cpf = cpf.replace(\/[^\\d]+\/g,'');\r\n        if(cpf === '' || cpf.length !== 11 || \/^(.)\\1+$\/.test(cpf)) return false;\r\n        let add = 0;\r\n        for (let i=0; i < 9; i ++) add += parseInt(cpf.charAt(i)) * (10 - i);\r\n        let rev = 11 - (add % 11);\r\n        if (rev === 10 || rev === 11) rev = 0;\r\n        if (rev !== parseInt(cpf.charAt(9))) return false;\r\n        add = 0;\r\n        for (let i = 0; i < 10; i ++) add += parseInt(cpf.charAt(i)) * (11 - i);\r\n        rev = 11 - (add % 11);\r\n        if (rev === 10 || rev === 11) rev = 0;\r\n        return rev === parseInt(cpf.charAt(10));\r\n    }\r\n\r\n    function isPIS(pis) {\r\n        pis = pis.replace(\/[^\\d]+\/g,'');\r\n        if (pis === '' || pis.length !== 11 || \/^(.)\\1+$\/.test(pis)) return false;\r\n        let multiplicador = [3,2,9,8,7,6,5,4,3,2];\r\n        let soma = 0;\r\n        for (let i = 0; i < 10; i++) soma += parseInt(pis.charAt(i)) * multiplicador[i];\r\n        let resto = soma % 11;\r\n        let digito = 11 - resto;\r\n        if (digito === 10 || digito === 11) digito = 0;\r\n        return digito === parseInt(pis.charAt(10));\r\n    }\r\n\r\n    function formatarIdentificacao(docRaw) {\r\n        if (!docRaw) return \"\";\r\n        let numeros = docRaw.replace(\/^0+\/, ''); \r\n        if (numeros.length < 11) numeros = numeros.padStart(11, '0'); \r\n\r\n        if (isCPF(numeros)) {\r\n            return `CPF: ${numeros.replace(\/(\\d{3})(\\d{3})(\\d{3})(\\d{2})\/, \"$1.$2.$3-$4\")}`;\r\n        } else if (isPIS(numeros)) {\r\n            return `PIS: ${numeros.replace(\/(\\d{3})(\\d{5})(\\d{2})(\\d{1})\/, \"$1.$2.$3-$4\")}`;\r\n        } else {\r\n            return `DOC: ${numeros}`; \r\n        }\r\n    }\r\n\r\n    function atualizarListaServidores() {\r\n        const select = document.getElementById('seletor-servidor');\r\n        const mesRef = document.getElementById('mes-ref').value;\r\n        const valorAtual = select.value; \r\n\r\n        select.innerHTML = '<option value=\"\">-- Selecione o Servidor --<\/option>';\r\n\r\n        if (!mesRef || Object.keys(bancoDadosAFD).length === 0) return;\r\n\r\n        const listaIdsFiltrada = Object.keys(bancoDadosAFD).filter(idKey => {\r\n            const marcacoesDoMes = bancoDadosAFD[idKey].marcacoes[mesRef];\r\n            return marcacoesDoMes && Object.keys(marcacoesDoMes).length > 0;\r\n        });\r\n\r\n        listaIdsFiltrada.sort((a, b) => {\r\n            let textoA = bancoDadosAFD[a].nome ? bancoDadosAFD[a].nome : formatarIdentificacao(bancoDadosAFD[a].docBruto);\r\n            let textoB = bancoDadosAFD[b].nome ? bancoDadosAFD[b].nome : formatarIdentificacao(bancoDadosAFD[b].docBruto);\r\n            return textoA.localeCompare(textoB);\r\n        }).forEach(idKey => {\r\n            const opt = document.createElement('option');\r\n            opt.value = idKey;\r\n            \r\n            let textoParaExibir = bancoDadosAFD[idKey].nome;\r\n            if (!textoParaExibir) {\r\n                textoParaExibir = formatarIdentificacao(bancoDadosAFD[idKey].docBruto);\r\n            }\r\n            \r\n            opt.textContent = textoParaExibir;\r\n            select.appendChild(opt);\r\n        });\r\n\r\n        if (listaIdsFiltrada.includes(valorAtual)) {\r\n            select.value = valorAtual;\r\n        } else {\r\n            select.value = \"\"; \r\n            document.getElementById('area-previa').innerHTML = \"\"; \r\n        }\r\n\r\n        select.disabled = listaIdsFiltrada.length === 0;\r\n        validarSelecao();\r\n    }\r\n\r\n    const readFileAsText = (file) => {\r\n        return new Promise((resolve, reject) => {\r\n            const reader = new FileReader();\r\n            reader.onload = (e) => resolve(e.target.result);\r\n            reader.onerror = (e) => reject(e);\r\n            reader.readAsText(file, 'ISO-8859-1');\r\n        });\r\n    };\r\n\r\n    async function lerArquivosAFD(event) {\r\n        const files = event.target.files;\r\n        if (!files || files.length === 0) return;\r\n\r\n        document.getElementById('afd-status').textContent = \"Processando arquivos e cruzando dados...\";\r\n        document.getElementById('afd-status').style.color = \"#64748b\";\r\n\r\n        bancoDadosAFD = {};\r\n        const mapNomes = {}; \r\n        let mesesEncontrados = new Set(); \r\n\r\n        try {\r\n            for (let i = 0; i < files.length; i++) {\r\n                const text = await readFileAsText(files[i]);\r\n                const linhas = text.split(\/\\r?\\n\/);\r\n                \r\n                let unidadeDoArquivo = \"UNIDADE N\u00c3O INFORMADA\";\r\n\r\n                linhas.forEach(linha => {\r\n                    const linhaTrim = linha.trim();\r\n                    if (linhaTrim.length === 0) return;\r\n                    \r\n                    if (linhaTrim.length > 50 && linhaTrim.substring(9, 10) === '2') {\r\n                        const blocos = linhaTrim.split(\/\\s{2,}\/);\r\n                        const textos = blocos.filter(b => \/[A-Za-z]{3,}\/.test(b));\r\n                        if (textos.length >= 2) {\r\n                            unidadeDoArquivo = textos[1].replace(\/[0-9a-fA-F]{4,}$\/i, '').trim();\r\n                        }\r\n                    }\r\n\r\n                    if (linhaTrim.substring(9, 10) === '5') {\r\n                        const match = linhaTrim.match(\/([IAE])(\\d{11,12})(.*)\/);\r\n                        if (match) {\r\n                            const idRaw = match[2];\r\n                            const idKey = idRaw.replace(\/^0+\/, '') || idRaw;\r\n                            const rawName = match[3];\r\n                            let nomeLimpo = rawName.split(\/\\s{2,}\/)[0].replace(\/[0-9a-fA-F]{8,}$\/i, '').trim();\r\n\r\n                            if (idKey && nomeLimpo) mapNomes[idKey] = { nome: nomeLimpo };\r\n                        }\r\n                    }\r\n                });\r\n\r\n                linhas.forEach(linha => {\r\n                    const linhaTrim = linha.trim();\r\n                    \r\n                    if (linhaTrim.substring(9, 10) === '3') {\r\n                        const dia = linhaTrim.substring(10, 12);\r\n                        const mes = linhaTrim.substring(12, 14);\r\n                        const ano = linhaTrim.substring(14, 18);\r\n                        const horaFormatada = linhaTrim.substring(18, 20) + ':' + linhaTrim.substring(20, 22);\r\n                        \r\n                        const resto = linhaTrim.substring(22);\r\n                        let idRaw = resto.length > 4 ? resto.substring(0, resto.length - 4) : resto;\r\n                        let idKey = idRaw.replace(\/^0+\/, '') || idRaw; \r\n\r\n                        if (!bancoDadosAFD[idKey]) {\r\n                            bancoDadosAFD[idKey] = {\r\n                                nome: \"\", \r\n                                marcacoes: {},\r\n                                docBruto: idKey\r\n                            };\r\n                        }\r\n\r\n                        const chaveMes = `${ano}-${mes}`;\r\n                        mesesEncontrados.add(chaveMes); \r\n\r\n                        if (!bancoDadosAFD[idKey].marcacoes[chaveMes]) bancoDadosAFD[idKey].marcacoes[chaveMes] = {};\r\n                        if (!bancoDadosAFD[idKey].marcacoes[chaveMes][dia]) bancoDadosAFD[idKey].marcacoes[chaveMes][dia] = {}; \r\n                        \r\n                        bancoDadosAFD[idKey].marcacoes[chaveMes][dia][horaFormatada] = unidadeDoArquivo;\r\n                    }\r\n                });\r\n            }\r\n\r\n            Object.keys(bancoDadosAFD).forEach(idKey => {\r\n                bancoDadosAFD[idKey].nome = mapNomes[idKey]?.nome || \"\";\r\n            });\r\n\r\n            if (mesesEncontrados.size > 0) {\r\n                let sortedMeses = Array.from(mesesEncontrados).sort();\r\n                document.getElementById('mes-ref').value = sortedMeses[sortedMeses.length - 1]; \r\n            } else {\r\n                document.getElementById('mes-ref').value = new Date().toISOString().slice(0, 7);\r\n            }\r\n            \r\n            atualizarListaServidores();\r\n\r\n            document.getElementById('area-previa').innerHTML = \"\";\r\n            document.getElementById('btn-imprimir').disabled = true;\r\n            \r\n            if (Object.keys(bancoDadosAFD).length > 0) {\r\n                document.getElementById('afd-status').textContent = `Pronto! Lidos ${files.length} arquivo(s) consolidados com sucesso.`;\r\n                document.getElementById('afd-status').style.color = \"#00A09A\";\r\n            } else {\r\n                document.getElementById('afd-status').textContent = \"Nenhum dado encontrado nos arquivos.\";\r\n                document.getElementById('afd-status').style.color = \"red\";\r\n            }\r\n\r\n        } catch (error) {\r\n            console.error(error);\r\n            document.getElementById('afd-status').textContent = \"Erro ao processar os arquivos.\";\r\n            document.getElementById('afd-status').style.color = \"red\";\r\n        }\r\n    }\r\n\r\n    function validarSelecao() {\r\n        document.getElementById('btn-imprimir').disabled = (document.getElementById('seletor-servidor').value === \"\");\r\n    }\r\n\r\n    function calcularTotalHorasDia(horasArray) {\r\n        if (!horasArray || horasArray.length === 0) return \"\";\r\n        let totalMinutos = 0;\r\n        function converterParaMinutos(horaString) {\r\n            if (!horaString) return 0;\r\n            const [h, m] = horaString.split(':').map(Number);\r\n            return (h * 60) + m;\r\n        }\r\n        if (horasArray[0] && horasArray[1]) totalMinutos += (converterParaMinutos(horasArray[1]) - converterParaMinutos(horasArray[0]));\r\n        if (horasArray[2] && horasArray[3]) totalMinutos += (converterParaMinutos(horasArray[3]) - converterParaMinutos(horasArray[2]));\r\n        if (horasArray[4] && horasArray[5]) totalMinutos += (converterParaMinutos(horasArray[5]) - converterParaMinutos(horasArray[4]));\r\n        \r\n        if (totalMinutos <= 0) return \"\";\r\n        const horasTotais = Math.floor(totalMinutos \/ 60);\r\n        const minutosRestantes = totalMinutos % 60;\r\n        return `${String(horasTotais).padStart(2, '0')}:${String(minutosRestantes).padStart(2, '0')}`;\r\n    }\r\n\r\n    function abreviarNomeUnidade(nomeLong) {\r\n        if (!nomeLong) return \"\";\r\n        return nomeLong.replace(\/^USF \/i, '').replace(\/^UBS \/i, '').replace(\/^PREFEITURA \/i, '').substring(0, 15).trim() + (nomeLong.length > 15 ? '.' : '');\r\n    }\r\n\r\n    function formatarCelula(hora, unidade, multiplasUnidades) {\r\n        if (!hora) return '';\r\n        if (!multiplasUnidades) return hora; \r\n        return `${hora}<br><span class=\"uni-tag\">${abreviarNomeUnidade(unidade)}<\/span>`;\r\n    }\r\n\r\n    function atualizarPrevia() {\r\n        const idKey = document.getElementById('seletor-servidor').value;\r\n        const mesRef = document.getElementById('mes-ref').value;\r\n        const divPrevia = document.getElementById('area-previa');\r\n\r\n        if (!idKey || !mesRef) { divPrevia.innerHTML = \"\"; return; }\r\n\r\n        const [ano, mes] = mesRef.split('-');\r\n        const servidor = bancoDadosAFD[idKey];\r\n        const marcacoesDoMes = servidor.marcacoes[mesRef] || {};\r\n        \r\n        let unidadesDoMes = new Set();\r\n        Object.values(marcacoesDoMes).forEach(diaObj => {\r\n            Object.values(diaObj).forEach(uni => unidadesDoMes.add(uni));\r\n        });\r\n        const multiplasUnidades = unidadesDoMes.size > 1;\r\n        let cabecalhoUnidade = unidadesDoMes.size === 0 ? \"SEM REGISTROS NESTE M\u00caS\" : \r\n                               (multiplasUnidades ? \"M\u00daLTIPLAS UNIDADES\" : Array.from(unidadesDoMes)[0]);\r\n\r\n        const diasNoMes = new Date(ano, mes, 0).getDate();\r\n        let linhasTabelaHTML = '';\r\n\r\n        const feriadosFixos = {\r\n            \"01-01\": \"FERIADO: CONFRATERNIZA\u00c7\u00c3O UNIVERSAL\",\r\n            \"02-16\": \"P. FACULTATIVO: CARNAVAL\",\r\n            \"02-17\": \"P. FACULTATIVO: CARNAVAL\",\r\n            \"02-18\": \"P. FACULTATIVO: CINZAS\",\r\n            \"04-03\": \"FERIADO: PAIX\u00c3O DE CRISTO\",\r\n            \"04-20\": \"PONTO FACULTATIVO\",\r\n            \"04-21\": \"FERIADO: TIRADENTES\",\r\n            \"05-01\": \"FERIADO: DIA DO TRABALHADOR\",\r\n            \"05-18\": \"PONTO FACULTATIVO\",\r\n            \"05-19\": \"FERIADO: ANIVERS\u00c1RIO CAJATI\",\r\n            \"06-04\": \"FERIADO: CORPUS CHRISTI\",\r\n            \"06-05\": \"PONTO FACULTATIVO\",\r\n            \"06-13\": \"FERIADO: SANTO ANT\u00d4NIO\",\r\n            \"07-09\": \"FERIADO: REV. CONST. 1932\",\r\n            \"07-10\": \"PONTO FACULTATIVO\",\r\n            \"09-07\": \"FERIADO: INDEPEND\u00caNCIA DO BRASIL\",\r\n            \"10-12\": \"FERIADO: N. SR\u00aa APARECIDA\",\r\n            \"10-28\": \"P. FACULTATIVO: DIA DO FUNC. P\u00daBLICO\",\r\n            \"11-02\": \"FERIADO: FINADOS\",\r\n            \"11-15\": \"FERIADO: PROC. DA REP\u00daBLICA\",\r\n            \"11-20\": \"FERIADO: CONSCI\u00caNCIA NEGRA\",\r\n            \"12-25\": \"FERIADO: NATAL\"\r\n        };\r\n\r\n        for (let i = 1; i <= diasNoMes; i++) {\r\n            const diaStr = String(i).padStart(2, '0');\r\n            const marcacoesDia = marcacoesDoMes[diaStr] || {};\r\n            const horas = Object.keys(marcacoesDia).sort();\r\n            \r\n            const dataAtual = new Date(ano, parseInt(mes) - 1, i);\r\n            const diaSemana = dataAtual.getDay(); \r\n            const mesDiaStr = `${mes}-${diaStr}`;\r\n            const nomeFeriado = feriadosFixos[mesDiaStr];\r\n\r\n            let estiloLinha = \"\";\r\n            let textoObservacao = \"\";\r\n\r\n            if (nomeFeriado) { estiloLinha = \"background-color: #f8fafc;\"; textoObservacao = `<strong>${nomeFeriado}<\/strong>`; } \r\n            else if (diaSemana === 0) { estiloLinha = \"background-color: #f8fafc;\"; textoObservacao = \"<strong>DOMINGO<\/strong>\"; } \r\n            else if (diaSemana === 6) { estiloLinha = \"background-color: #f8fafc;\"; textoObservacao = \"<strong>S\u00c1BADO<\/strong>\"; }\r\n\r\n            const totalHorasCalculadas = calcularTotalHorasDia(horas);\r\n            let conteudoUltimaColuna = totalHorasCalculadas !== \"\" ? `<strong>${totalHorasCalculadas}<\/strong>` : textoObservacao;\r\n            let corDestaque = totalHorasCalculadas !== \"\" ? \"#00A09A\" : \"#64748b\";\r\n\r\n            let c1 = formatarCelula(horas[0], marcacoesDia[horas[0]], multiplasUnidades);\r\n            let c2 = formatarCelula(horas[1], marcacoesDia[horas[1]], multiplasUnidades);\r\n            let c3 = formatarCelula(horas[2], marcacoesDia[horas[2]], multiplasUnidades);\r\n            let c4 = formatarCelula(horas[3], marcacoesDia[horas[3]], multiplasUnidades);\r\n            let c5 = formatarCelula(horas[4], marcacoesDia[horas[4]], multiplasUnidades);\r\n            let c6 = formatarCelula(horas[5], marcacoesDia[horas[5]], multiplasUnidades);\r\n\r\n            linhasTabelaHTML += `\r\n                <tr style=\"${estiloLinha}\">\r\n                    <td><strong>${diaStr}<\/strong><\/td>\r\n                    <td>${c1 || '-'}<\/td>\r\n                    <td>${c2 || '-'}<\/td>\r\n                    <td>${c3 || '-'}<\/td>\r\n                    <td>${c4 || '-'}<\/td>\r\n                    <td>${c5 || '-'}<\/td>\r\n                    <td>${c6 || '-'}<\/td>\r\n                    <td style=\"color: ${corDestaque};\">${conteudoUltimaColuna}<\/td>\r\n                <\/tr>\r\n            `;\r\n        }\r\n\r\n        let nomeCabecalho = servidor.nome ? servidor.nome.toUpperCase() : formatarIdentificacao(servidor.docBruto);\r\n\r\n        divPrevia.innerHTML = `\r\n            <div class=\"preview-container\" style=\"display: block;\">\r\n                <div class=\"cabecalho-preview\">\r\n                    <div style=\"text-align: left; max-width: 60%;\">\r\n                        <div style=\"font-size: 11px; color: #64748b; text-transform: uppercase;\">Servidor<\/div>\r\n                        <strong>${nomeCabecalho}<\/strong>\r\n                    <\/div>\r\n                    <div style=\"text-align: right; max-width: 40%;\">\r\n                        <div style=\"font-size: 11px; color: #64748b; text-transform: uppercase;\">Unidade(s) de Trabalho<\/div>\r\n                        <strong>${cabecalhoUnidade}<\/strong>\r\n                    <\/div>\r\n                <\/div>\r\n                <table class=\"tabela-preview\">\r\n                    <thead>\r\n                        <tr>\r\n                            <th width=\"8%\">DIA<\/th>\r\n                            <th width=\"12%\">ENTRADA 1<\/th>\r\n                            <th width=\"12%\">SA\u00cdDA 1<\/th>\r\n                            <th width=\"12%\">ENTRADA 2<\/th>\r\n                            <th width=\"12%\">SA\u00cdDA 2<\/th>\r\n                            <th width=\"12%\">ENTRADA 3<\/th>\r\n                            <th width=\"12%\">SA\u00cdDA 3<\/th>\r\n                            <th width=\"20%\">TOTAL HORAS<\/th>\r\n                        <\/tr>\r\n                    <\/thead>\r\n                    <tbody>\r\n                        ${linhasTabelaHTML}\r\n                    <\/tbody>\r\n                <\/table>\r\n            <\/div>\r\n        `;\r\n    }\r\n\r\n    function imprimirFolha() {\r\n        const idKey = document.getElementById('seletor-servidor').value;\r\n        const mesRef = document.getElementById('mes-ref').value;\r\n\r\n        if (!idKey || !mesRef) { alert(\"Selecione um servidor e o m\u00eas.\"); return; }\r\n\r\n        const [ano, mes] = mesRef.split('-');\r\n        const servidor = bancoDadosAFD[idKey];\r\n        const marcacoesDoMes = servidor.marcacoes[mesRef] || {};\r\n        \r\n        let unidadesDoMes = new Set();\r\n        Object.values(marcacoesDoMes).forEach(diaObj => { Object.values(diaObj).forEach(uni => unidadesDoMes.add(uni)); });\r\n        const multiplasUnidades = unidadesDoMes.size > 1;\r\n        let cabecalhoUnidade = unidadesDoMes.size === 0 ? \"SEM REGISTROS\" : (multiplasUnidades ? \"M\u00daLTIPLAS UNIDADES\" : Array.from(unidadesDoMes)[0]);\r\n\r\n        const diasNoMes = new Date(ano, mes, 0).getDate();\r\n        let linhasTabelaHTML = '';\r\n\r\n        const feriadosFixos = {\r\n            \"01-01\": \"FERIADO: CONFRATERNIZA\u00c7\u00c3O UNIVERSAL\",\r\n            \"02-16\": \"P. FACULTATIVO: CARNAVAL\",\r\n            \"02-17\": \"P. FACULTATIVO: CARNAVAL\",\r\n            \"02-18\": \"P. FACULTATIVO: CINZAS\",\r\n            \"04-03\": \"FERIADO: PAIX\u00c3O DE CRISTO\",\r\n            \"04-20\": \"PONTO FACULTATIVO\",\r\n            \"04-21\": \"FERIADO: TIRADENTES\",\r\n            \"05-01\": \"FERIADO: DIA DO TRABALHADOR\",\r\n            \"05-18\": \"PONTO FACULTATIVO\",\r\n            \"05-19\": \"FERIADO: ANIVERS\u00c1RIO CAJATI\",\r\n            \"06-04\": \"FERIADO: CORPUS CHRISTI\",\r\n            \"06-05\": \"PONTO FACULTATIVO\",\r\n            \"06-13\": \"FERIADO: SANTO ANT\u00d4NIO\",\r\n            \"07-09\": \"FERIADO: REV. CONST. 1932\",\r\n            \"07-10\": \"PONTO FACULTATIVO\",\r\n            \"09-07\": \"FERIADO: INDEPEND\u00caNCIA DO BRASIL\",\r\n            \"10-12\": \"FERIADO: N. SR\u00aa APARECIDA\",\r\n            \"10-28\": \"P. FACULTATIVO: DIA DO FUNC. P\u00daBLICO\",\r\n            \"11-02\": \"FERIADO: FINADOS\",\r\n            \"11-15\": \"FERIADO: PROC. DA REP\u00daBLICA\",\r\n            \"11-20\": \"FERIADO: CONSCI\u00caNCIA NEGRA\",\r\n            \"12-25\": \"FERIADO: NATAL\"\r\n        };\r\n\r\n        for (let i = 1; i <= diasNoMes; i++) {\r\n            const diaStr = String(i).padStart(2, '0');\r\n            const marcacoesDia = marcacoesDoMes[diaStr] || {};\r\n            const horas = Object.keys(marcacoesDia).sort();\r\n            \r\n            const dataAtual = new Date(ano, parseInt(mes) - 1, i);\r\n            const diaSemana = dataAtual.getDay(); \r\n            const mesDiaStr = `${mes}-${diaStr}`;\r\n            const nomeFeriado = feriadosFixos[mesDiaStr];\r\n\r\n            let estiloLinha = \"\";\r\n            let textoObservacao = \"\";\r\n\r\n            if (nomeFeriado) { estiloLinha = \"background-color: #f1f5f9; -webkit-print-color-adjust: exact; print-color-adjust: exact;\"; textoObservacao = `<strong>${nomeFeriado}<\/strong>`; } \r\n            else if (diaSemana === 0) { estiloLinha = \"background-color: #f1f5f9; -webkit-print-color-adjust: exact; print-color-adjust: exact;\"; textoObservacao = \"<strong>DOMINGO<\/strong>\"; } \r\n            else if (diaSemana === 6) { estiloLinha = \"background-color: #f1f5f9; -webkit-print-color-adjust: exact; print-color-adjust: exact;\"; textoObservacao = \"<strong>S\u00c1BADO<\/strong>\"; }\r\n\r\n            const totalHorasCalculadas = calcularTotalHorasDia(horas);\r\n            let conteudoUltimaColuna = totalHorasCalculadas !== \"\" ? `<strong>${totalHorasCalculadas}<\/strong>` : textoObservacao;\r\n\r\n            let c1 = formatarCelula(horas[0], marcacoesDia[horas[0]], multiplasUnidades);\r\n            let c2 = formatarCelula(horas[1], marcacoesDia[horas[1]], multiplasUnidades);\r\n            let c3 = formatarCelula(horas[2], marcacoesDia[horas[2]], multiplasUnidades);\r\n            let c4 = formatarCelula(horas[3], marcacoesDia[horas[3]], multiplasUnidades);\r\n            let c5 = formatarCelula(horas[4], marcacoesDia[horas[4]], multiplasUnidades);\r\n            let c6 = formatarCelula(horas[5], marcacoesDia[horas[5]], multiplasUnidades);\r\n\r\n            linhasTabelaHTML += `\r\n                <tr style=\"${estiloLinha}\">\r\n                    <td><strong>${diaStr}<\/strong><\/td>\r\n                    <td>${c1 || ''}<\/td>\r\n                    <td>${c2 || ''}<\/td>\r\n                    <td>${c3 || ''}<\/td>\r\n                    <td>${c4 || ''}<\/td>\r\n                    <td>${c5 || ''}<\/td>\r\n                    <td>${c6 || ''}<\/td>\r\n                    <td style=\"color: #64748b;\">${conteudoUltimaColuna}<\/td>\r\n                <\/tr>\r\n            `;\r\n        }\r\n\r\n        let nomeCabecalho = servidor.nome ? servidor.nome.toUpperCase() : formatarIdentificacao(servidor.docBruto);\r\n        let nomeArquivoDesejado = `${nomeCabecalho} - ${cabecalhoUnidade}`;\r\n\r\n        const htmlImpressao = `\r\n            <!DOCTYPE html>\r\n            <html>\r\n            <head>\r\n                <title>${nomeArquivoDesejado}<\/title>\r\n                <style>\r\n                    body { font-family: Arial, sans-serif; margin: 0; padding: 10px 20px; color: #000; background: #fff; }\r\n                    .header-print { display: flex; align-items: center; border-bottom: 2px solid #00A09A; padding-bottom: 5px; margin-bottom: 10px; }\r\n                    .header-logo { height: 55px; } \r\n                    .header-center { margin-left: 20px; font-size: 11px; font-weight: 600; line-height: 1.2; }\r\n                    .titulo-documento-print { background-color: #00A09A; color: white; padding: 6px; border-radius: 6px; font-size: 16px; text-align: center; font-weight: 800; margin-bottom: 10px; text-transform: uppercase; -webkit-print-color-adjust: exact; print-color-adjust: exact; }\r\n                    .print-info { display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 10px; font-size: 12px; font-weight: 700; }\r\n                    \r\n                    .print-table { width: 100%; border-collapse: collapse; font-size: 11px; margin-bottom: 15px; }\r\n                    .print-table th { background-color: #00A09A; color: white; padding: 4px; border: 1px solid #008580; -webkit-print-color-adjust: exact; print-color-adjust: exact; }\r\n                    .print-table td { border: 1px solid #00A09A; padding: 3px; text-align: center; vertical-align: middle; } \r\n                    .print-table tbody tr { border-bottom: 1px solid #00A09A; }\r\n                    \r\n                    .uni-tag { font-size: 8px; color: #555; display: block; margin-top: 1px; font-weight: bold; text-transform: uppercase; line-height: 1; }\r\n                    .footer-print-text { text-align: center; font-size: 10px; margin-bottom: 25px; margin-top: 10px; }\r\n                    .signature-box { border-top: 1px solid #000; width: 60%; margin: 0 auto; text-align: center; padding-top: 5px; font-weight: bold; font-size: 12px; }\r\n                    .site-link { text-align: center; color: #00A09A; font-weight: bold; margin-top: 10px; font-size: 11px; }\r\n                    \r\n                    @page { size: A4 portrait; margin: 0.8cm; }\r\n                <\/style>\r\n            <\/head>\r\n            <body>\r\n                <div class=\"header-print\">\r\n                    <img decoding=\"async\" src=\"https:\/\/saudecajati.com.br\/wp-content\/uploads\/2026\/04\/LOGO-SAUDE-UPSCALER-1-300x109.png\" class=\"header-logo\">\r\n                    <div class=\"header-center\">\r\n                        SECRETARIA MUNICIPAL DE SA\u00daDE<br>\r\n                        (13) 3854 8500 - ramal 2140<br>\r\n                        Rua Teodoro Ferreira Machado, s\/n \u2013 Centro \u2013 CEP 11.950-000<br>\r\n                        Cajati, SP\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <div class=\"titulo-documento-print\">\r\n                    CONTROLE DE FREQU\u00caNCIA INDIVIDUAL\r\n                <\/div>\r\n                \r\n                <div class=\"print-info\">\r\n                    <div style=\"flex: 1; text-align: left;\">\r\n                        <div style=\"font-size: 10px; color: #333; font-weight: normal;\">SERVIDOR(A)<\/div>\r\n                        <div>${nomeCabecalho}<\/div>\r\n                    <\/div>\r\n                    <div style=\"flex: 1; text-align: center;\">\r\n                        <div style=\"font-size: 10px; color: #333; font-weight: normal;\">UNIDADE(S)<\/div>\r\n                        <div>${cabecalhoUnidade}<\/div>\r\n                    <\/div>\r\n                    <div style=\"flex: 1; text-align: right;\">\r\n                        <div style=\"font-size: 10px; color: #333; font-weight: normal;\">M\u00caS REFER\u00caNCIA<\/div>\r\n                        <div>${mes}\/${ano}<\/div>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <table class=\"print-table\">\r\n                    <thead>\r\n                        <tr>\r\n                            <th width=\"8%\">DIA<\/th>\r\n                            <th width=\"12%\">ENTRADA 1<\/th>\r\n                            <th width=\"12%\">SA\u00cdDA 1<\/th>\r\n                            <th width=\"12%\">ENTRADA 2<\/th>\r\n                            <th width=\"12%\">SA\u00cdDA 2<\/th>\r\n                            <th width=\"12%\">ENTRADA 3<\/th>\r\n                            <th width=\"12%\">SA\u00cdDA 3<\/th>\r\n                            <th width=\"20%\">TOTAL HORAS<\/th>\r\n                        <\/tr>\r\n                    <\/thead>\r\n                    <tbody>\r\n                        ${linhasTabelaHTML}\r\n                    <\/tbody>\r\n                <\/table>\r\n                \r\n                <div class=\"footer-print-text\">\r\n                    Declaro que as informa\u00e7\u00f5es acima s\u00e3o verdadeiras e refletem minha jornada de trabalho.\r\n                <\/div>\r\n                <div class=\"signature-box\">\r\n                    Assinatura do Servidor\r\n                <\/div>\r\n                <div class=\"site-link\">\r\n                    www.saudecajati.com.br\r\n                <\/div>\r\n            <\/body>\r\n            <\/html>\r\n        `;\r\n\r\n        let iframe = document.getElementById('iframe-impressao');\r\n        if (!iframe) {\r\n            iframe = document.createElement('iframe');\r\n            iframe.id = 'iframe-impressao';\r\n            iframe.style.position = 'absolute';\r\n            iframe.style.width = '1px';\r\n            iframe.style.height = '1px';\r\n            iframe.style.left = '-9999px';\r\n            iframe.style.border = 'none';\r\n            document.body.appendChild(iframe);\r\n        }\r\n\r\n        iframe.contentWindow.document.open();\r\n        iframe.contentWindow.document.write(htmlImpressao);\r\n        iframe.contentWindow.document.close();\r\n\r\n        \/\/ NOVO TRUQUE: Guarda o t\u00edtulo original do WordPress e muda temporariamente para o desejado\r\n        const tituloOriginalWordPress = document.title;\r\n        document.title = nomeArquivoDesejado;\r\n\r\n        setTimeout(function() {\r\n            try {\r\n                iframe.contentWindow.focus();\r\n                iframe.contentWindow.print();\r\n            } catch (error) {\r\n                console.warn(\"Bloqueio de iframe detectado. Abrindo em nova aba para impress\u00e3o.\");\r\n                let printWindow = window.open('', '_blank');\r\n                if (printWindow) {\r\n                    printWindow.document.write(htmlImpressao);\r\n                    printWindow.document.close();\r\n                    printWindow.focus();\r\n                    setTimeout(() => { printWindow.print(); }, 500);\r\n                } else {\r\n                    alert(\"A impress\u00e3o foi bloqueada pelo navegador. Permita a abertura de pop-ups para imprimir.\");\r\n                }\r\n            }\r\n\r\n            \/\/ NOVO TRUQUE: Devolve o t\u00edtulo original do WordPress 2 segundos ap\u00f3s chamar o popup de impress\u00e3o\r\n            setTimeout(() => {\r\n                document.title = tituloOriginalWordPress;\r\n            }, 2000);\r\n\r\n        }, 500);\r\n    }\r\n<\/script>\r\n\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4508c19 elementor-align-center elementor-icon-list--layout-traditional elementor-list-item-link-full_width elementor-invisible elementor-widget elementor-widget-icon-list\" data-id=\"4508c19\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_animation&quot;:&quot;slideInDown&quot;}\" data-widget_type=\"icon-list.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul class=\"elementor-icon-list-items\">\n\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Calculadora de Ponto<\/span>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2ee84c4 elementor-widget elementor-widget-html\" data-id=\"2ee84c4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"ponto-app-container\" class=\"ponto-wrapper\">\r\n    \r\n    <div class=\"ponto-header\">\r\n        <div class=\"ponto-status-card\">\r\n            <div id=\"ponto-relogio\" class=\"ponto-clock\">00:00:00<\/div>\r\n        <\/div>\r\n        <div class=\"ponto-date-container\">\r\n            <label for=\"data-seletor\">Data da Exporta\u00e7\u00e3o:<\/label>\r\n            <input type=\"date\" id=\"data-seletor\" class=\"ponto-date-input\">\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"ponto-colagem-area\">\r\n        <label for=\"input-colagem\">Importa\u00e7\u00e3o R\u00e1pida (Cole aqui):<\/label>\r\n        <input type=\"text\" id=\"input-colagem\" placeholder=\"Ex: 08:3311:5513:05\" oninput=\"processarColagem(this)\">\r\n    <\/div>\r\n\r\n    <div class=\"ponto-grid\">\r\n        <div class=\"ponto-box\" id=\"box-entrada\">\r\n            <span class=\"ponto-box-title\">Entrada<\/span>\r\n            <div class=\"ponto-box-controls\">\r\n                <input type=\"time\" id=\"time-entrada\" class=\"ponto-time-input\" onchange=\"entradaManual('entrada')\">\r\n                <button onclick=\"registrarAgora('entrada')\" class=\"ponto-btn-toque\">\u23f1\ufe0f Toque<\/button>\r\n            <\/div>\r\n        <\/div>\r\n        \r\n        <div class=\"ponto-box\" id=\"box-saida-almoco\">\r\n            <span class=\"ponto-box-title\">Sa\u00edda Almo\u00e7o<\/span>\r\n            <div class=\"ponto-box-controls\">\r\n                <input type=\"time\" id=\"time-saida-almoco\" class=\"ponto-time-input\" onchange=\"entradaManual('saida-almoco')\">\r\n                <button onclick=\"registrarAgora('saida-almoco')\" class=\"ponto-btn-toque\">\u23f1\ufe0f Toque<\/button>\r\n            <\/div>\r\n        <\/div>\r\n        \r\n        <div class=\"ponto-box\" id=\"box-retorno-almoco\">\r\n            <span class=\"ponto-box-title\">Retorno Almo\u00e7o<\/span>\r\n            <div class=\"ponto-box-controls\">\r\n                <input type=\"time\" id=\"time-retorno-almoco\" class=\"ponto-time-input\" onchange=\"entradaManual('retorno-almoco')\">\r\n                <button onclick=\"registrarAgora('retorno-almoco')\" class=\"ponto-btn-toque\">\u23f1\ufe0f Toque<\/button>\r\n            <\/div>\r\n        <\/div>\r\n        \r\n        <div class=\"ponto-box\" id=\"box-saida-trabalho\">\r\n            <span class=\"ponto-box-title\">Sa\u00edda<\/span>\r\n            <div class=\"ponto-box-controls\">\r\n                <input type=\"time\" id=\"time-saida-trabalho\" class=\"ponto-time-input\" onchange=\"entradaManual('saida-trabalho')\">\r\n                <button onclick=\"registrarAgora('saida-trabalho')\" class=\"ponto-btn-toque\">\u23f1\ufe0f Toque<\/button>\r\n            <\/div>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"previsao-container\" class=\"ponto-previsao\" style=\"display: none;\">\r\n        <div id=\"texto-previsao\" class=\"previsao-hora\"><\/div>\r\n        <div id=\"texto-falta\" class=\"previsao-falta\"><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"ponto-actions\">\r\n        <button onclick=\"exportarRelatorio()\" class=\"ponto-btn-export\">\r\n            <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"margin-right: 5px;\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"><\/path><polyline points=\"7 10 12 15 17 10\"><\/polyline><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"><\/line><\/svg>\r\n            Exportar Relat\u00f3rio\r\n        <\/button>\r\n    <\/div>\r\n\r\n    <div id=\"ponto-log\" class=\"ponto-msg\">Esta calculadora n\u00e3o salva dados. Atualizar a p\u00e1gina limpar\u00e1 os hor\u00e1rios.<\/div>\r\n<\/div>\r\n\r\n<style>\r\n    .ponto-wrapper {\r\n        font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif !important;\r\n        max-width: 800px !important;\r\n        margin: 20px auto !important;\r\n        padding: 25px !important;\r\n        background: #ffffff !important;\r\n        border: 1px solid #e0e0e0 !important;\r\n        border-radius: 16px !important;\r\n        box-sizing: border-box !important;\r\n        color: #4a4a4a !important;\r\n        box-shadow: 0 4px 12px rgba(0,0,0,0.05) !important;\r\n    }\r\n\r\n    .ponto-header {\r\n        display: flex !important;\r\n        justify-content: space-between !important;\r\n        align-items: center !important;\r\n        margin-bottom: 20px !important;\r\n        gap: 15px !important;\r\n    }\r\n\r\n    .ponto-status-card {\r\n        background: #f8fdfd !important;\r\n        border: 2px solid #00A09A !important;\r\n        border-radius: 12px !important;\r\n        padding: 10px 20px !important;\r\n        text-align: center !important;\r\n        flex-grow: 1 !important;\r\n    }\r\n\r\n    .ponto-clock {\r\n        font-size: 32px !important;\r\n        font-weight: 800 !important;\r\n        color: #00A09A !important;\r\n        letter-spacing: 2px !important;\r\n    }\r\n\r\n    .ponto-colagem-area {\r\n        margin-bottom: 20px !important;\r\n        background: #f9f9f9 !important;\r\n        padding: 12px !important;\r\n        border-radius: 8px !important;\r\n        border: 1px dashed #00A09A !important;\r\n    }\r\n\r\n    .ponto-colagem-area label {\r\n        display: block !important;\r\n        font-size: 12px !important;\r\n        font-weight: 700 !important;\r\n        color: #00A09A !important;\r\n        margin-bottom: 5px !important;\r\n    }\r\n\r\n    .ponto-colagem-area input {\r\n        width: 100% !important;\r\n        padding: 8px !important;\r\n        border: 1px solid #ddd !important;\r\n        border-radius: 4px !important;\r\n        box-sizing: border-box !important;\r\n    }\r\n\r\n    .ponto-grid {\r\n        display: grid !important;\r\n        grid-template-columns: repeat(4, 1fr) !important;\r\n        gap: 15px !important;\r\n        margin-bottom: 20px !important;\r\n    }\r\n\r\n    .ponto-box {\r\n        background: #fafafa !important;\r\n        border: 2px solid #eeeeee !important;\r\n        border-radius: 10px !important;\r\n        padding: 12px !important;\r\n        display: flex !important;\r\n        flex-direction: column !important;\r\n        align-items: center !important;\r\n        gap: 10px !important;\r\n        transition: all 0.2s ease !important;\r\n    }\r\n\r\n    .ponto-box.active {\r\n        border-color: #00A09A !important;\r\n        background: #f0fafa !important;\r\n    }\r\n\r\n    .ponto-time-input {\r\n        width: 100% !important;\r\n        padding: 8px !important;\r\n        border: 1px solid #ddd !important;\r\n        border-radius: 6px !important;\r\n        font-size: 16px !important;\r\n        font-weight: 600 !important;\r\n        text-align: center !important;\r\n    }\r\n\r\n    \/* ESTILO CORRIGIDO PARA O BOT\u00c3O DO WORDPRESS *\/\r\n    .ponto-btn-toque {\r\n        width: 100% !important;\r\n        background: #00A09A !important;\r\n        color: white !important;\r\n        border: none !important;\r\n        padding: 6px 4px !important;\r\n        border-radius: 6px !important;\r\n        cursor: pointer !important;\r\n        font-weight: 600 !important;\r\n        font-size: 13px !important;\r\n        line-height: 1.2 !important;\r\n        margin: 0 !important;\r\n        box-sizing: border-box !important;\r\n        min-height: unset !important;\r\n        display: block !important;\r\n        white-space: nowrap !important;\r\n    }\r\n\r\n    .ponto-previsao {\r\n        background: #f0fafa !important;\r\n        border-left: 4px solid #00A09A !important;\r\n        padding: 15px !important;\r\n        border-radius: 6px !important;\r\n        margin-bottom: 20px !important;\r\n        text-align: center !important;\r\n    }\r\n\r\n    .previsao-hora strong { color: #00A09A; font-size: 18px; }\r\n\r\n    .ponto-btn-export {\r\n        width: 100% !important;\r\n        background: #ffffff !important;\r\n        color: #00A09A !important;\r\n        border: 2px solid #00A09A !important;\r\n        padding: 12px !important;\r\n        border-radius: 8px !important;\r\n        font-weight: 700 !important;\r\n        cursor: pointer !important;\r\n        display: flex !important;\r\n        justify-content: center !important;\r\n        align-items: center !important;\r\n    }\r\n\r\n    .ponto-btn-export:hover { background: #00A09A !important; color: white !important; }\r\n\r\n    @media (max-width: 650px) {\r\n        .ponto-grid { grid-template-columns: 1fr 1fr !important; }\r\n    }\r\n<\/style>\r\n\r\n<script>\r\n    function getHojeFormatado() {\r\n        const tzoffset = (new Date()).getTimezoneOffset() * 60000;\r\n        return (new Date(Date.now() - tzoffset)).toISOString().slice(0, 10);\r\n    }\r\n\r\n    function inicializarApp() {\r\n        document.getElementById('data-seletor').value = getHojeFormatado();\r\n        setInterval(atualizarRelogio, 1000);\r\n        atualizarRelogio();\r\n    }\r\n\r\n    function atualizarRelogio() {\r\n        const agora = new Date();\r\n        const h = String(agora.getHours()).padStart(2, '0');\r\n        const m = String(agora.getMinutes()).padStart(2, '0');\r\n        const s = String(agora.getSeconds()).padStart(2, '0');\r\n        document.getElementById('ponto-relogio').textContent = `${h}:${m}:${s}`;\r\n        calcularPrevisao();\r\n    }\r\n\r\n    function processarColagem(el) {\r\n        const valor = el.value;\r\n        \/\/ Regex que identifica o formato 00:00 ou 0000\r\n        const horarios = valor.match(\/\\d{2}:?\\d{2}\/g);\r\n\r\n        if (horarios && horarios.length >= 1) {\r\n            const ids = ['entrada', 'saida-almoco', 'retorno-almoco', 'saida-trabalho'];\r\n            \r\n            horarios.forEach((hora, index) => {\r\n                if (index < ids.length) {\r\n                    let hf = hora.includes(':') ? hora : hora.slice(0, 2) + ':' + hora.slice(2);\r\n                    document.getElementById(`time-${ids[index]}`).value = hf;\r\n                    verificarAtivo(ids[index]);\r\n                }\r\n            });\r\n\r\n            el.value = ''; \/\/ Limpa o campo de colagem\r\n            calcularPrevisao();\r\n            \r\n            \/\/ Foca no campo de sa\u00edda final se colou 3 hor\u00e1rios\r\n            if (horarios.length === 3) {\r\n                document.getElementById('time-saida-trabalho').focus();\r\n            }\r\n        }\r\n    }\r\n\r\n    function registrarAgora(tipo) {\r\n        const agora = new Date();\r\n        const horaFormatada = String(agora.getHours()).padStart(2, '0') + \":\" + String(agora.getMinutes()).padStart(2, '0');\r\n        document.getElementById(`time-${tipo}`).value = horaFormatada;\r\n        verificarAtivo(tipo);\r\n        calcularPrevisao();\r\n    }\r\n\r\n    function entradaManual(tipo) {\r\n        verificarAtivo(tipo);\r\n        calcularPrevisao();\r\n    }\r\n\r\n    function verificarAtivo(tipo) {\r\n        const input = document.getElementById(`time-${tipo}`);\r\n        const box = document.getElementById(`box-${tipo}`);\r\n        input.value ? box.classList.add('active') : box.classList.remove('active');\r\n    }\r\n\r\n    function converterParaMinutos(horaString) {\r\n        const [h, m] = horaString.split(':').map(Number);\r\n        return (h * 60) + m;\r\n    }\r\n\r\n    function formatarMinutosParaHora(totalMinutos) {\r\n        let minFechados = totalMinutos % 1440;\r\n        const h = Math.floor(minFechados \/ 60);\r\n        const m = minFechados % 60;\r\n        return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\r\n    }\r\n\r\n    function calcularPrevisao() {\r\n        const v1 = document.getElementById('time-entrada').value;\r\n        const v2 = document.getElementById('time-saida-almoco').value;\r\n        const v3 = document.getElementById('time-retorno-almoco').value;\r\n        const v4 = document.getElementById('time-saida-trabalho').value;\r\n\r\n        const container = document.getElementById('previsao-container');\r\n        const tPrev = document.getElementById('texto-previsao');\r\n        const tFalta = document.getElementById('texto-falta');\r\n\r\n        if (v1 && v2 && v3) {\r\n            const m1 = converterParaMinutos(v1);\r\n            const m2 = converterParaMinutos(v2);\r\n            const m3 = converterParaMinutos(v3);\r\n\r\n            const trabManha = m2 - m1;\r\n            const saidaIdealMin = m3 + (480 - trabManha);\r\n            const horaSaidaIdeal = formatarMinutosParaHora(saidaIdealMin);\r\n\r\n            if (v4) {\r\n                tPrev.innerHTML = `Expediente conclu\u00eddo.`;\r\n                tFalta.textContent = `A sa\u00edda ideal era \u00e0s ${horaSaidaIdeal}`;\r\n            } else {\r\n                const agora = new Date();\r\n                const mAgora = (agora.getHours() * 60) + agora.getMinutes();\r\n                const resta = saidaIdealMin - mAgora;\r\n\r\n                tPrev.innerHTML = `Para fechar 8h, saia \u00e0s: <strong>${horaSaidaIdeal}<\/strong>`;\r\n                if (resta > 0) {\r\n                    tFalta.textContent = `Faltam ${Math.floor(resta\/60)}h ${resta%60}m`;\r\n                    tFalta.style.color = '#00A09A';\r\n                } else {\r\n                    tFalta.textContent = `Jornada conclu\u00edda!`;\r\n                    tFalta.style.color = '#e67e22';\r\n                }\r\n            }\r\n            container.style.display = 'block';\r\n        } else {\r\n            container.style.display = 'none';\r\n        }\r\n    }\r\n\r\n    function exportarRelatorio() {\r\n        const data = document.getElementById('data-seletor').value.split('-').reverse().join('\/');\r\n        const v = id => document.getElementById(`time-${id}`).value || '--:--';\r\n        \r\n        let c = `RELAT\u00d3RIO DE PONTO\\nData: ${data}\\n--------------------------\\n`;\r\n        c += `Entrada: ${v('entrada')}\\nSa\u00edda Almo\u00e7o: ${v('saida-almoco')}\\nRetorno Almo\u00e7o: ${v('retorno-almoco')}\\nSa\u00edda: ${v('saida-trabalho')}`;\r\n\r\n        const blob = new Blob([c], { type: 'text\/plain' });\r\n        const a = document.createElement('a');\r\n        a.href = URL.createObjectURL(blob);\r\n        a.download = `ponto_${data.replace(\/\\\/\/g, '-')}.txt`;\r\n        a.click();\r\n    }\r\n\r\n    document.addEventListener(\"DOMContentLoaded\", inicializarApp);\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2a663fa e-con-full e-flex e-con e-child\" data-id=\"2a663fa\" data-element_type=\"container\" data-e-type=\"container\">\n\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>Leitor de AFD 1. Arquivos AFD (.txt) &#8211; Pode selecionar v\u00e1rios de unidades diferentes 2. Selecionar Servidor Aguardando arquivo&#8230; 3. M\u00eas de Refer\u00eancia Imprimir PDF Insira os arquivos gerados pelos rel\u00f3gios para come\u00e7ar. Calculadora de Ponto 00:00:00 Data da Exporta\u00e7\u00e3o: Importa\u00e7\u00e3o R\u00e1pida (Cole aqui): Entrada \u23f1\ufe0f Toque Sa\u00edda Almo\u00e7o \u23f1\ufe0f Toque Retorno Almo\u00e7o \u23f1\ufe0f Toque [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"inline_featured_image":false,"footnotes":""},"class_list":["post-7334","page","type-page","status-publish","hentry"],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/pages\/7334","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/comments?post=7334"}],"version-history":[{"count":256,"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/pages\/7334\/revisions"}],"predecessor-version":[{"id":7753,"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/pages\/7334\/revisions\/7753"}],"wp:attachment":[{"href":"https:\/\/saudecajati.com.br\/index.php\/wp-json\/wp\/v2\/media?parent=7334"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}