{"id":1166,"date":"2026-02-27T15:50:27","date_gmt":"2026-02-27T15:50:27","guid":{"rendered":"https:\/\/www.decalcer.com\/?page_id=1166"},"modified":"2026-06-03T07:24:42","modified_gmt":"2026-06-03T07:24:42","slug":"gt-v2-0","status":"publish","type":"page","link":"https:\/\/www.decalcer.com\/en\/gt-v2-0\/","title":{"rendered":"GT V2.0"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"1166\" class=\"elementor elementor-1166\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1f15742 e-flex e-con-boxed e-con e-parent\" data-id=\"1f15742\" 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-b0440eb elementor-widget elementor-widget-html\" data-id=\"b0440eb\" data-element_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>  \n<html lang=\"pt\">  \n<head>  \n    <meta charset=\"UTF-8\">  \n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">  \n    <title>Gest\u00e3o de Trabalhos | Decalcer<\/title>  \n  \n    <!-- 1. Configura\u00e7\u00e3o PWA e \u00cdcones -->  \n    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">  \n    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">  \n    <meta name=\"theme-color\" content=\"#ffffff\">  \n  \n    <link rel=\"apple-touch-icon\" href=\"https:\/\/decalcer.com\/gticon.jpg?v=3\">  \n    <link rel=\"shortcut icon\" href=\"https:\/\/decalcer.com\/gticon.jpg?v=3\">  \n  \n    <!-- 2. Carregamento Seguro e Direto de Depend\u00eancias -->  \n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>  \n    <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">  \n      \n    <script src=\"https:\/\/www.gstatic.com\/firebasejs\/10.12.2\/firebase-app-compat.js\"><\/script>  \n    <script src=\"https:\/\/www.gstatic.com\/firebasejs\/10.12.2\/firebase-auth-compat.js\"><\/script>  \n    <script src=\"https:\/\/www.gstatic.com\/firebasejs\/10.12.2\/firebase-firestore-compat.js\"><\/script>  \n  \n    <style>  \n        body { margin: 0; padding: 0; background-color: #f8fafc; }  \n  \n        #job-manager-app-container {  \n            font-family: 'Inter', sans-serif;  \n            background-color: #f8fafc;  \n            color: #334155;  \n            line-height: 1.6;  \n            font-size: 15px;  \n            -webkit-font-smoothing: antialiased;  \n            touch-action: manipulation;   \n        }  \n          \n        #job-manager-app-container button {  \n            box-shadow: none;  \n            text-shadow: none;  \n            margin: 0;  \n            outline: none !important;  \n            touch-action: manipulation;  \n        }  \n          \n        #job-manager-app-container ::-webkit-scrollbar { width: 6px; height: 6px; }  \n        #job-manager-app-container ::-webkit-scrollbar-track { background: transparent; }  \n        #job-manager-app-container ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; }  \n        #job-manager-app-container ::-webkit-scrollbar-thumb:hover { background: #94a3b8; }  \n  \n        #job-manager-app-container .lightbox-hidden { display: none !important; }   \n        #job-manager-app-container .fixed { z-index: 999999; }  \n          \n        #job-manager-app-container input:focus,   \n        #job-manager-app-container select:focus,   \n        #job-manager-app-container textarea:focus {  \n            outline: none;  \n            box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1);   \n            border-color: #6366f1;  \n        }  \n          \n        #job-manager-app-container input:disabled,   \n        #job-manager-app-container select:disabled,   \n        #job-manager-app-container textarea:disabled {  \n            background-color: #f1f5f9;  \n            cursor: not-allowed;  \n            opacity: 0.8;  \n        }  \n  \n        .css-spinner {  \n            border: 3px solid #e2e8f0;  \n            border-top: 3px solid #6366f1;  \n            border-radius: 50%;  \n            width: 40px;  \n            height: 40px;  \n            animation: spin 0.8s linear infinite;  \n            margin: 0 auto 20px auto;  \n        }  \n          \n        @keyframes spin {  \n            0% { transform: rotate(0deg); }  \n            100% { transform: rotate(360deg); }  \n        }  \n  \n        #app-loading-indicator {  \n            text-align: center;  \n            padding: 60px 20px;  \n            color: #64748b;  \n            font-weight: 500;  \n        }  \n  \n        .stat-card-enter { animation: fadeInScale 0.3s ease-out forwards; }  \n        @keyframes fadeInScale {  \n            from { opacity: 0; transform: scale(0.95); }  \n            to { opacity: 1; transform: scale(1); }  \n        }  \n  \n        #toast-container {  \n            position: fixed;  \n            top: 20px;  \n            right: 20px;  \n            z-index: 9999999;  \n            display: flex;  \n            flex-direction: column;  \n            gap: 10px;  \n            pointer-events: none;  \n        }  \n        .toast {  \n            background: white;  \n            padding: 12px 20px;  \n            border-radius: 12px;  \n            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);  \n            display: flex;  \n            align-items: center;  \n            gap: 12px;  \n            font-size: 14px;  \n            font-weight: 500;  \n            animation: slideIn 0.3s cubic-bezier(0.16, 1, 0.3, 1);  \n            pointer-events: auto;  \n            border: 1px solid #f1f5f9;  \n            max-width: 90vw;  \n        }  \n        .toast.success { border-left: 4px solid #10b981; }  \n        .toast.error { border-left: 4px solid #ef4444; }  \n        .toast.info { border-left: 4px solid #3b82f6; }  \n          \n        @keyframes slideIn {  \n            from { transform: translateY(-20px); opacity: 0; }  \n            to { transform: translateY(0); opacity: 1; }  \n        }  \n        @keyframes slideOut {  \n            to { transform: translateX(100%); opacity: 0; }  \n        }  \n  \n        .zoom-grab { cursor: grab; }  \n        .zoom-grabbing { cursor: grabbing; }  \n  \n        .donut-segment {  \n            transition: stroke-dasharray 1s ease-out, stroke-dashoffset 1s ease-out;  \n        }  \n  \n        .kanban-column {  \n            min-height: 200px;  \n            transition: background-color 0.2s ease, border-color 0.2s ease;  \n        }  \n        .kanban-column.drag-over {  \n            background-color: #f1f5f9;  \n            border-color: #818cf8;  \n            border-style: dashed;  \n        }  \n        .kanban-card.is-dragging {  \n            opacity: 0.5;  \n            transform: scale(0.98);  \n        }  \n          \n        #kanban-board {  \n            scroll-snap-type: x mandatory;  \n        }  \n        .kanban-column-container {  \n            scroll-snap-align: start;  \n        }  \n  \n        \/* INJECTED: Novos estilos para Pedidos de Material *\/  \n        .nav-tab-active { border-bottom: 2px solid #6366f1; color: #4f46e5; background-color: #f8fafc; }  \n        .nav-tab-inactive { border-bottom: 2px solid transparent; color: #64748b; }  \n        .nav-tab-inactive:hover { color: #334155; background-color: #f1f5f9; }  \n        .subtab-active { background-color: #6366f1; color: white; box-shadow: 0 4px 6px -1px rgba(99, 102, 241, 0.2); }  \n        .subtab-inactive { background-color: white; color: #64748b; border: 1px solid #e2e8f0; }  \n        .subtab-inactive:hover { background-color: #f8fafc; }  \n    <\/style>  \n<\/head>  \n<body>  \n  \n<div id=\"job-manager-app-container\" class=\"w-full relative min-h-[600px]\">  \n  \n    <div id=\"toast-container\"><\/div>  \n  \n    <div id=\"app-loading-indicator\">  \n        <div class=\"css-spinner\"><\/div>  \n        <span class=\"text-sm uppercase tracking-wide\">A iniciar sistema...<\/span>  \n    <\/div>  \n  \n    <div id=\"main-interface\" class=\"hidden pb-12\">  \n          \n        <div class=\"sticky top-0 z-30 mb-6 transition-all duration-200\">  \n            <div class=\"bg-white\/90 backdrop-blur-xl shadow-sm border-b border-gray-100\">  \n                <div class=\"max-w-7xl mx-auto px-4 sm:px-6 py-4 flex flex-col md:flex-row items-center justify-between gap-4\">  \n                    <div class=\"flex items-center space-x-4 w-full md:w-auto\">  \n                        <div id=\"logo-container\" class=\"flex-shrink-0 transition-transform hover:scale-105\"><\/div>  \n                        <div class=\"h-6 w-px bg-gray-200 hidden sm:block\"><\/div>  \n                        <h2 class=\"text-lg sm:text-xl font-bold text-slate-800 tracking-tight m-0 p-0\">Gest\u00e3o de Trabalhos<\/h2>  \n                    <\/div>  \n                      \n                    <div class=\"flex items-center space-x-3 w-full md:w-auto justify-end\">  \n                        <div id=\"user-info-display\" class=\"text-xs font-medium text-slate-500 hidden md:block px-2\"><\/div>  \n                          \n                        <button id=\"btn-settings-trigger\" class=\"hidden sm:flex items-center gap-2 px-3 py-2 text-sm bg-white border border-slate-200 text-slate-600 font-medium rounded-xl hover:bg-slate-50 hover:text-indigo-600 transition-colors cursor-pointer shadow-sm\" title=\"Backup e Defini\u00e7\u00f5es\">  \n                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/svg>  \n                            <span class=\"hidden md:inline\">Defini\u00e7\u00f5es<\/span>  \n                        <\/button>  \n  \n                        <button id=\"btn-colors-trigger\" class=\"hidden sm:flex items-center gap-2 px-3 py-2 text-sm bg-white border border-slate-200 text-slate-600 font-medium rounded-xl hover:bg-slate-50 hover:text-indigo-600 transition-colors cursor-pointer shadow-sm\">  \n                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2.5 17a2.5 2.5 0 0 1 5 0V5a2.5 2.5 0 0 1-5 0v12Z\"\/><path d=\"M7.5 12h5\"\/><path d=\"M12.5 17a2.5 2.5 0 0 0 5 0V5a2.5 2.5 0 0 0-5 0v12Z\"\/><path d=\"M17.5 12h3\"\/><\/svg>  \n                            <span class=\"hidden md:inline\">Cores<\/span>  \n                        <\/button>  \n  \n                        <button id=\"btn-login-trigger\" class=\"px-5 py-2 text-sm bg-slate-800 text-white font-medium rounded-xl shadow-md hover:bg-slate-700 hover:shadow-lg active:scale-95 transition-all duration-200 border-none cursor-pointer flex items-center\">  \n                            Login  \n                        <\/button>  \n                          \n                        <div class=\"px-4 py-2 bg-indigo-50 border border-indigo-100 rounded-xl hidden sm:flex items-center space-x-2\">  \n                            <span class=\"text-xs font-bold text-indigo-400 uppercase tracking-wider\">Total<\/span>  \n                            <span id=\"job-count\" class=\"text-base font-bold text-indigo-700\">0<\/span>  \n                        <\/div>  \n                    <\/div>  \n                <\/div>  \n                  \n                <!-- INJECTED: Main Navigation System -->  \n                <div class=\"max-w-7xl mx-auto px-4 sm:px-6 flex gap-2 pt-2\" id=\"main-nav-tabs\">  \n                    <button id=\"tab-trabalhos\" class=\"px-5 py-2.5 text-sm font-bold rounded-t-xl nav-tab-active transition-colors cursor-pointer border-none outline-none\">  \n                        Produ\u00e7\u00e3o  \n                    <\/button>  \n                    <button id=\"tab-materiais\" class=\"px-5 py-2.5 text-sm font-bold rounded-t-xl nav-tab-inactive transition-colors cursor-pointer border-none outline-none flex items-center gap-2\">  \n                        Pedidos de Material  \n                        <span id=\"badge-pedidos-pendentes\" class=\"hidden bg-rose-500 text-white text-[10px] px-1.5 py-0.5 rounded-full leading-none\">0<\/span>  \n                    <\/button>  \n                <\/div>  \n            <\/div>  \n        <\/div>  \n  \n        <div class=\"max-w-7xl mx-auto px-4 sm:px-6 relative\">  \n              \n            <div id=\"login-warning\" class=\"mb-8 p-6 bg-amber-50 border border-amber-100 rounded-2xl text-amber-900 text-sm font-medium flex items-center shadow-sm hidden\">  \n                <svg class=\"w-5 h-5 mr-3 text-amber-500\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\/><\/svg>  \n                Por favor, inicie sess\u00e3o para ter acesso total (edi\u00e7\u00e3o e remo\u00e7\u00e3o).  \n            <\/div>  \n  \n            <!-- CONTE\u00daDO ORIGINAL DE TRABALHOS -->  \n            <div id=\"app-content\" class=\"space-y-6\">  \n                  \n                <div class=\"bg-white p-1 rounded-2xl shadow-sm border border-slate-100\">  \n                    <div class=\"grid grid-cols-1 md:grid-cols-12 gap-2 p-2\">  \n                        <div class=\"md:col-span-3 relative\">  \n                            <input type=\"text\" id=\"search-input\" placeholder=\"Pesquisa...\"   \n                                   class=\"w-full pl-10 pr-4 py-3 bg-slate-50 border-transparent rounded-xl text-slate-700 placeholder-slate-400 focus:bg-white transition-all text-sm font-medium\">  \n                            <svg class=\"w-4 h-4 text-slate-400 absolute left-3.5 top-3.5\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\/><\/svg>  \n                        <\/div>  \n                          \n                        <div class=\"md:col-span-2\">  \n                            <select id=\"filter-type\" class=\"w-full py-3 px-3 bg-slate-50 border-transparent rounded-xl text-slate-700 text-sm font-medium cursor-pointer focus:bg-white transition-all appearance-none\">  \n                                <option value=\"Todos\">Tipo: Todos<\/option>  \n                                <option value=\"Produ\u00e7\u00e3o\">Produ\u00e7\u00e3o<\/option>  \n                                <option value=\"Ensaio\">Ensaios<\/option>  \n                            <\/select>  \n                        <\/div>  \n  \n                        <div class=\"md:col-span-2\">  \n                            <select id=\"filter-status\" class=\"w-full py-3 px-3 bg-slate-50 border-transparent rounded-xl text-slate-700 text-sm font-medium cursor-pointer focus:bg-white transition-all appearance-none\">  \n                                <option value=\"Todos\">Estado: Todos<\/option>  \n                                <option value=\"Aberto\">Aberto<\/option>  \n                                <option value=\"Em Progresso\">Em Progresso<\/option>  \n                                <option value=\"Concluido\">Conclu\u00eddo<\/option>  \n                                <option value=\"Sem Or\u00e7amento\">Sem Or\u00e7amento<\/option>  \n                            <\/select>  \n                        <\/div>  \n  \n                        <div class=\"md:col-span-3 flex space-x-2\">  \n                            <button id=\"search-btn\" class=\"flex-1 py-3 bg-indigo-600 text-white font-semibold rounded-xl shadow-md shadow-indigo-200 hover:bg-indigo-700 transition-all active:scale-95 border-none cursor-pointer text-sm\">  \n                                Filtrar  \n                            <\/button>  \n                            <button id=\"btn-show-all\" type=\"button\" class=\"px-3 py-3 bg-white text-slate-600 font-semibold rounded-xl border border-slate-200 hover:bg-slate-50 transition-all cursor-pointer text-sm\">  \n                                Limpar  \n                            <\/button>  \n                        <\/div>  \n  \n                        <!-- Alternador de Vista (Lista \/ Kanban) -->  \n                        <div class=\"md:col-span-2 flex items-center justify-end bg-slate-50 rounded-xl p-1 border border-slate-100\">  \n                            <button id=\"btn-view-list\" class=\"flex-1 flex justify-center items-center py-2 rounded-lg text-slate-400 hover:text-slate-600 transition-colors border-none cursor-pointer\" title=\"Vista em Lista\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"><\/line><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"><\/line><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"><\/line><line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\"><\/line><line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\"><\/line><line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\"><\/line><\/svg>  \n                            <\/button>  \n                            <button id=\"btn-view-kanban\" class=\"flex-1 flex justify-center items-center py-2 rounded-lg bg-white shadow-sm text-indigo-600 font-bold transition-all border-none cursor-pointer\" title=\"Vista Kanban\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"><\/rect><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"><\/line><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"><\/line><\/svg>  \n                            <\/button>  \n                        <\/div>  \n                    <\/div>  \n                <\/div>  \n  \n                <div id=\"stats-dashboard\" class=\"bg-white rounded-2xl shadow-sm border border-slate-100 p-5 hidden\">  \n                    <div class=\"flex flex-wrap justify-between items-center mb-4 gap-2\">  \n                        <div class=\"flex items-center gap-3\">  \n                            <h4 class=\"text-xs font-bold text-slate-400 uppercase tracking-wide flex items-center m-0\">  \n                                <svg class=\"w-4 h-4 mr-1.5\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\/><\/svg>  \n                                An\u00e1lise de Produ\u00e7\u00e3o  \n                            <\/h4>  \n                            <button id=\"btn-open-stats-modal\" class=\"px-3 py-1 bg-indigo-50 hover:bg-indigo-100 text-indigo-600 text-xs font-bold rounded-lg transition-colors border-none cursor-pointer flex items-center\">  \n                                + Estat\u00edsticas Detalhadas  \n                            <\/button>  \n                        <\/div>  \n                        <span id=\"total-sheets-badge\" class=\"text-xs font-bold text-indigo-600 bg-indigo-50 px-2 py-1 rounded-md\">0 Folhas Total<\/span>  \n                    <\/div>  \n                    <div id=\"stats-container\" class=\"grid grid-cols-2 sm:grid-cols-4 md:grid-cols-7 gap-4\">  \n                    <\/div>  \n                <\/div>  \n  \n                <div class=\"bg-white rounded-2xl shadow-sm border border-slate-100 overflow-hidden\">  \n                    <div class=\"px-6 py-4 bg-slate-50 border-b border-slate-100 flex justify-between items-center cursor-pointer hover:bg-slate-100 transition-colors\" id=\"btn-toggle-form\">  \n                        <h3 class=\"text-base font-bold text-slate-700 m-0 p-0 flex items-center\">  \n                            <span class=\"w-8 h-8 rounded-lg bg-indigo-100 text-indigo-600 flex items-center justify-center mr-3 text-lg font-bold shadow-sm\">+<\/span>  \n                            Novo Registo  \n                        <\/h3>  \n                        <span class=\"text-slate-400 text-sm font-medium\">Clique para expandir<\/span>  \n                    <\/div>  \n                      \n                    <form id=\"job-form\" class=\"hidden p-6 sm:p-8\" action=\"\">  \n                        <div class=\"grid grid-cols-1 md:grid-cols-12 gap-6 mb-8\">  \n                            <div class=\"space-y-1 md:col-span-2 lg:col-span-2\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">ID \u00danico<\/label>  \n                                <input type=\"text\" placeholder=\"Auto\" readonly class=\"w-full p-3 bg-slate-100 border border-slate-200 rounded-xl font-mono text-sm text-slate-400 cursor-not-allowed\" title=\"O ID ser\u00e1 gerado automaticamente ao guardar\">  \n                            <\/div>  \n                            <div class=\"space-y-1 md:col-span-3 lg:col-span-4\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Refer\u00eancia *<\/label>  \n                                <input type=\"text\" id=\"job-reference\" required class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">  \n                            <\/div>  \n                            <div class=\"space-y-1 md:col-span-4 lg:col-span-4\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Cliente *<\/label>  \n                                <input type=\"hidden\" id=\"job-client\" required>   \n                                <div class=\"flex\">  \n                                    <div id=\"job-client-display\" class=\"flex-1 p-3 bg-slate-50 border border-slate-200 border-r-0 rounded-l-xl text-slate-700 truncate font-medium flex items-center\">Nenhum<\/div>  \n                                    <button type=\"button\" id=\"btn-select-client-add\" class=\"px-4 bg-indigo-50 text-indigo-600 border border-indigo-100 border-l-0 rounded-r-xl hover:bg-indigo-100 font-medium text-sm transition-colors cursor-pointer\">Escolher<\/button>  \n                                <\/div>  \n                            <\/div>  \n                            <div class=\"space-y-1 md:col-span-3 lg:col-span-2\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Data *<\/label>  \n                                <input type=\"date\" id=\"job-date\" required class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-slate-600\">  \n                            <\/div>  \n                        <\/div>  \n  \n                        <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6 mb-8\">  \n                            <div class=\"space-y-1\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Tipo de Trabalho<\/label>  \n                                <select id=\"job-type\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors appearance-none cursor-pointer font-medium text-slate-700\">  \n                                    <option value=\"Produ\u00e7\u00e3o\">Produ\u00e7\u00e3o<\/option>  \n                                    <option value=\"Ensaio\">Ensaio<\/option>  \n                                <\/select>  \n                            <\/div>  \n                            <div class=\"space-y-1\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Operador<\/label>  \n                                <input type=\"text\" id=\"job-operator\" placeholder=\"Quem imprimiu?\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">  \n                            <\/div>  \n                            <div class=\"space-y-1\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">M\u00e1quina<\/label>  \n                                <input type=\"text\" id=\"job-machine\" placeholder=\"Ex: Roland\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">  \n                            <\/div>\n                            <div class=\"space-y-1\">\n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Data de Entrega<\/label>\n                                <input type=\"date\" id=\"job-data-entrega\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-slate-600\">\n                            <\/div>\n                            <div class=\"space-y-1\">\n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Desenhador<\/label>\n                                <input type=\"text\" id=\"job-desenhador\" placeholder=\"Ex: Paulo\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">\n                            <\/div>\n                            <div class=\"space-y-1\">\n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Temperatura<\/label>\n                                <input type=\"text\" id=\"job-temperatura\" placeholder=\"Ex: 800\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">\n                            <\/div>  \n                              \n                            <div class=\"space-y-1\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Folhas (Tam \/ Qtd)<\/label>  \n                                <div class=\"flex gap-2\">  \n                                    <select id=\"job-size\" class=\"w-2\/3 p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-sm appearance-none cursor-pointer truncate\">  \n                                    <\/select>  \n                                    <input type=\"number\" id=\"job-sheets\" min=\"0\" value=\"1\" placeholder=\"Qtd\" class=\"w-1\/3 p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-center font-bold\">  \n                                <\/div>  \n                            <\/div>  \n  \n                            <div class=\"space-y-1\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Estado<\/label>  \n                                <select id=\"job-status\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors appearance-none cursor-pointer\">  \n                                    <option value=\"Aberto\">Aberto<\/option>  \n                                    <option value=\"Em Progresso\">Em Progresso<\/option>  \n                                    <option value=\"Concluido\">Conclu\u00eddo<\/option>  \n                                    <option value=\"Sem Or\u00e7amento\">Sem Or\u00e7amento<\/option>  \n                                <\/select>  \n                            <\/div>  \n                        <\/div>  \n  \n                        <div class=\"grid grid-cols-1 gap-6 mb-8\">  \n                            <div class=\"space-y-1\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Imagem URL<\/label>  \n                                <div class=\"flex gap-2\">  \n                                    <input type=\"url\" id=\"job-image-url\" placeholder=\"https:\/\/...\" class=\"flex-1 p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-sm\">  \n                                    <button type=\"button\" id=\"btn-view-image-add\" class=\"px-3 bg-slate-100 text-slate-500 rounded-xl hover:bg-slate-200 border-none cursor-pointer\">  \n                                        <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/svg>  \n                                    <\/button>  \n                                <\/div>  \n                            <\/div>  \n                        <\/div>  \n                          \n                        <div class=\"space-y-1 mb-8\">  \n                            <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Observa\u00e7\u00f5es<\/label>  \n                            <textarea id=\"job-observations\" rows=\"2\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors resize-none\"><\/textarea>  \n                        <\/div>  \n                          \n                        <div class=\"bg-slate-50 rounded-xl p-6 border border-slate-100 mb-8\">  \n                            <div class=\"flex justify-between items-center mb-4\">  \n                                <h4 class=\"text-sm font-bold text-slate-700 uppercase tracking-wide\">Cores do Trabalho<\/h4>  \n                                <button type=\"button\" id=\"btn-add-color-row-create\" class=\"text-xs bg-white border border-slate-200 text-indigo-600 font-bold px-3 py-1.5 rounded-lg hover:bg-indigo-50 transition-colors shadow-sm cursor-pointer\">  \n                                    + Adicionar Cor  \n                                <\/button>  \n                            <\/div>  \n                            <div id=\"colors-container-add\" class=\"flex flex-col gap-3\">  \n                            <\/div>  \n                            <p class=\"text-[10px] text-slate-400 mt-2 text-right italic\">Preencha apenas o necess\u00e1rio.<\/p>  \n                        <\/div>  \n  \n                        <div class=\"bg-pink-50 rounded-xl p-6 border border-pink-100 mb-8 relative overflow-hidden\">  \n                            <div class=\"absolute -right-4 -top-4 text-pink-100 opacity-50\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"100\" height=\"100\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\"><\/path><\/svg>  \n                            <\/div>  \n                            <div class=\"flex flex-col sm:flex-row sm:justify-between sm:items-center relative z-10 gap-4\">  \n                                <div>  \n                                    <h4 class=\"text-sm font-bold text-pink-700 uppercase tracking-wide\">Etiquetas de Expedi\u00e7\u00e3o<\/h4>  \n                                    <p class=\"text-xs text-pink-600\/80 mt-1\">Configure os dados exatos para impress\u00e3o de etiquetas.<\/p>  \n                                <\/div>  \n                                <button type=\"button\" id=\"btn-open-label-config-add\" class=\"px-4 py-2 bg-white text-pink-600 font-bold rounded-lg shadow-sm border border-pink-200 hover:bg-pink-50 transition-colors cursor-pointer text-sm whitespace-nowrap\">  \n                                    Configurar Etiquetas  \n                                <\/button>  \n                            <\/div>  \n                        <\/div>  \n  \n                        <div class=\"flex justify-end pt-4\">  \n                            <button type=\"submit\" class=\"px-8 py-3 bg-indigo-600 text-white font-bold rounded-xl shadow-lg shadow-indigo-200 hover:bg-indigo-700 hover:shadow-xl hover:-translate-y-0.5 transition-all border-none cursor-pointer w-full sm:w-auto\">  \n                                Criar Registo  \n                            <\/button>  \n                        <\/div>  \n                    <input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>  \n                <\/div>  \n  \n                <!-- VISTA EM LISTA (GRID) -->  \n                <div id=\"jobs-list\" class=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 pb-12 hidden\"><\/div>  \n  \n                <!-- VISTA KANBAN (BOARD) -->  \n                <div id=\"kanban-board\" class=\"flex gap-6 overflow-x-auto pb-8 items-start min-h-[500px] hidden\">  \n                    <!-- Colunas geradas via JS -->  \n                <\/div>  \n  \n                <div id=\"no-jobs\" class=\"hidden flex flex-col items-center justify-center py-16 text-slate-400 bg-white rounded-3xl border border-dashed border-slate-200\">  \n                    <svg class=\"w-12 h-12 mb-3 text-slate-200\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\/><\/svg>  \n                    <p class=\"text-lg font-medium\">Nenhum registo encontrado<\/p>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- INJECTED: CONTE\u00daDO NOVO DE PEDIDOS DE MATERIAL -->  \n            <div id=\"material-content\" class=\"hidden space-y-6\">  \n                <!-- Header Control Material -->  \n                <div class=\"flex flex-col sm:flex-row justify-between items-center gap-4 bg-white p-4 rounded-2xl shadow-sm border border-slate-100\">  \n                    <div class=\"flex bg-slate-100 p-1 rounded-xl w-full sm:w-auto\">  \n                        <button id=\"subtab-pendentes\" class=\"flex-1 sm:px-6 py-2 text-sm font-bold rounded-lg subtab-active transition-all cursor-pointer outline-none\">  \n                            Pendentes (<span id=\"count-mat-pendentes\">0<\/span>)  \n                        <\/button>  \n                        <button id=\"subtab-encomendados\" class=\"flex-1 sm:px-6 py-2 text-sm font-bold rounded-lg subtab-inactive transition-all cursor-pointer outline-none\">  \n                            J\u00e1 Encomendados  \n                        <\/button>  \n                    <\/div>  \n                      \n                    <button id=\"btn-open-material-modal\" class=\"w-full sm:w-auto px-5 py-2.5 bg-indigo-600 text-white font-bold rounded-xl shadow-md hover:bg-indigo-700 transition-colors border-none cursor-pointer flex items-center justify-center gap-2\">  \n                        <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4v16m8-8H4\"><\/path><\/svg>  \n                        Novo Pedido  \n                    <\/button>  \n                <\/div>  \n  \n                <!-- Lista de Pendentes -->  \n                <div id=\"material-list-pendentes\" class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">  \n                    <!-- Gerado via JS -->  \n                <\/div>  \n  \n                <!-- Lista de Encomendados -->  \n                <div id=\"material-list-encomendados\" class=\"hidden grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 opacity-75\">  \n                    <!-- Gerado via JS -->  \n                <\/div>  \n  \n                <!-- Empty State Material -->  \n                <div id=\"no-materials\" class=\"hidden flex flex-col items-center justify-center py-16 text-slate-400 bg-white rounded-3xl border border-dashed border-slate-200\">  \n                    <svg class=\"w-12 h-12 mb-3 text-slate-200\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"><\/path><\/svg>  \n                    <p class=\"text-lg font-medium\">Nenhum pedido de material.<\/p>  \n                <\/div>  \n            <\/div>  \n              \n            <datalist id=\"color-suggestions\"><\/datalist>  \n            <datalist id=\"temp-suggestions\">  \n                <option value=\"520\u00ba\">  \n                <option value=\"580\u00ba\">  \n                <option value=\"600\u00ba\">  \n                <option value=\"620\u00ba\">  \n                <option value=\"750\u00ba\">  \n                <option value=\"780\u00ba\">  \n                <option value=\"800\u00ba\">  \n                <option value=\"820\u00ba\">  \n                <option value=\"1050\u00ba\">  \n                <option value=\"1200\u00ba\">  \n            <\/datalist>  \n  \n            <!-- Modal de Estat\u00edsticas UI MELHORADO -->  \n            <div id=\"stats-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/80 backdrop-blur-sm flex items-center justify-center p-2 sm:p-4 z-50\">  \n                <div class=\"bg-white rounded-2xl shadow-2xl w-full max-w-5xl max-h-[95vh] sm:max-h-[90vh] flex flex-col overflow-hidden\">  \n                      \n                    <!-- Cabe\u00e7alho (Fixo) -->  \n                    <div class=\"p-4 sm:p-6 border-b border-slate-100 flex justify-between items-center bg-white shrink-0 z-10\">  \n                        <div class=\"flex items-center gap-3\">  \n                            <div class=\"w-10 h-10 bg-indigo-100 text-indigo-600 rounded-xl flex items-center justify-center shrink-0\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"\/><path d=\"M8 17V7\"\/><path d=\"M12 17v-6\"\/><path d=\"M16 17v-3\"\/><\/svg>  \n                            <\/div>  \n                            <div>  \n                                <h3 class=\"text-base sm:text-lg font-bold text-slate-800 m-0 leading-tight\">Estat\u00edsticas<\/h3>  \n                                <p class=\"text-[10px] sm:text-xs text-slate-400 m-0 hidden sm:block\">An\u00e1lise de produ\u00e7\u00e3o e clientes<\/p>  \n                            <\/div>  \n                        <\/div>  \n                        <button id=\"btn-close-stats\" class=\"p-2 text-slate-400 hover:text-slate-600 rounded-full hover:bg-slate-50 transition-colors border-none cursor-pointer shrink-0\">  \n                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"\/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"\/><\/svg>  \n                        <\/button>  \n                    <\/div>  \n                      \n                    <!-- \u00c1rea de Scroll Principal -->  \n                    <div class=\"flex-1 overflow-y-auto bg-slate-50 custom-scrollbar relative\">  \n                          \n                        <!-- Filtros -->  \n                        <div class=\"p-4 sm:p-6 bg-white border-b border-slate-200\">  \n                            <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-3 mb-3\">  \n                                <div>  \n                                    <label class=\"text-[10px] sm:text-xs font-bold text-slate-400 uppercase tracking-wider block mb-1\">Filtrar por Cliente<\/label>  \n                                    <select id=\"stats-client-filter\" class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm font-medium cursor-pointer focus:bg-white focus:border-indigo-500 transition-colors outline-none\">  \n                                        <option value=\"\">Todos os Clientes (Vis\u00e3o Geral)<\/option>  \n                                    <\/select>  \n                                <\/div>  \n                                <div>  \n                                    <label class=\"text-[10px] sm:text-xs font-bold text-slate-400 uppercase tracking-wider block mb-1\">Tipo de Trabalho<\/label>  \n                                    <select id=\"stats-type-filter\" class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm font-medium cursor-pointer focus:bg-white focus:border-indigo-500 transition-colors outline-none\">  \n                                        <option value=\"Todos\">Ambos (Produ\u00e7\u00e3o e Ensaios)<\/option>  \n                                        <option value=\"Produ\u00e7\u00e3o\">Apenas Produ\u00e7\u00e3o<\/option>  \n                                        <option value=\"Ensaio\">Apenas Ensaios<\/option>  \n                                    <\/select>  \n                                <\/div>  \n                            <\/div>  \n                              \n                            <div class=\"flex flex-wrap gap-3 items-end\">  \n                                <div class=\"w-full sm:flex-1 sm:min-w-[130px]\">  \n                                    <label class=\"text-[10px] sm:text-xs font-bold text-slate-400 uppercase tracking-wider block mb-1\">Data In\u00edcio<\/label>  \n                                    <input type=\"date\" id=\"stats-date-start\" class=\"w-full p-2.5 bg-slate-50 focus:bg-white border border-slate-200 rounded-xl text-sm font-medium transition-colors\">  \n                                <\/div>  \n                                <div class=\"w-full sm:flex-1 sm:min-w-[130px]\">  \n                                    <label class=\"text-[10px] sm:text-xs font-bold text-slate-400 uppercase tracking-wider block mb-1\">Data Fim<\/label>  \n                                    <input type=\"date\" id=\"stats-date-end\" class=\"w-full p-2.5 bg-slate-50 focus:bg-white border border-slate-200 rounded-xl text-sm font-medium transition-colors\">  \n                                <\/div>  \n                                <div class=\"w-full sm:w-auto flex gap-2 pt-1 sm:pt-0\">  \n                                    <button id=\"btn-stats-all-time\" class=\"flex-1 sm:flex-none px-4 py-2.5 bg-white border border-slate-200 text-slate-600 hover:bg-slate-50 font-semibold rounded-xl text-sm cursor-pointer whitespace-nowrap transition-colors\">  \n                                        Limpar  \n                                    <\/button>  \n                                    <button id=\"btn-calc-stats\" class=\"flex-1 sm:flex-none px-6 py-2.5 bg-indigo-600 text-white font-bold rounded-xl shadow-md hover:bg-indigo-700 cursor-pointer whitespace-nowrap transition-colors\">  \n                                        Calcular  \n                                    <\/button>  \n                                <\/div>  \n                            <\/div>  \n                        <\/div>  \n  \n                        <!-- Resultados das Estat\u00edsticas -->  \n                        <div class=\"p-4 sm:p-6\">  \n                            <div class=\"grid grid-cols-2 sm:grid-cols-3 gap-3 sm:gap-4 mb-6 sm:mb-8\">  \n                                <div class=\"bg-white p-3 sm:p-4 rounded-xl border border-slate-100 shadow-sm col-span-2 sm:col-span-1\">  \n                                    <p class=\"text-[10px] sm:text-xs text-slate-400 uppercase font-bold mb-1\">Total Trabalhos<\/p>  \n                                    <p id=\"stats-total-jobs\" class=\"text-xl sm:text-2xl font-bold text-slate-800\">0<\/p>  \n                                <\/div>  \n                                <div class=\"bg-white p-3 sm:p-4 rounded-xl border border-slate-100 shadow-sm\">  \n                                    <p class=\"text-[10px] sm:text-xs text-slate-400 uppercase font-bold mb-1\">Total Folhas<\/p>  \n                                    <p id=\"stats-total-sheets\" class=\"text-xl sm:text-2xl font-bold text-indigo-600\">0<\/p>  \n                                <\/div>  \n                                <div class=\"bg-white p-3 sm:p-4 rounded-xl border border-slate-100 shadow-sm\">  \n                                    <p class=\"text-[10px] sm:text-xs text-slate-400 uppercase font-bold mb-1\">Cores Usadas<\/p>  \n                                    <p id=\"stats-total-colors\" class=\"text-xl sm:text-2xl font-bold text-pink-600\">0<\/p>  \n                                <\/div>  \n                            <\/div>  \n  \n                             <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6 mb-6 sm:mb-8\">  \n                                <!-- Gr\u00e1fico Circular -->  \n                                <div class=\"bg-white p-4 sm:p-5 rounded-xl border border-slate-100 shadow-sm lg:col-span-1 flex flex-col\">  \n                                    <h4 class=\"text-sm font-bold text-slate-700 mb-4 text-center w-full border-b border-slate-50 pb-2\">Distribui\u00e7\u00e3o de Folhas<\/h4>  \n                                    <div id=\"stats-donut-chart-container\" class=\"flex-1 flex items-center justify-center py-2 sm:py-4\">  \n                                    <\/div>  \n                                <\/div>  \n                                  \n                                <!-- Volume por Cliente -->  \n                                <div class=\"bg-white p-4 sm:p-5 rounded-xl border border-slate-100 shadow-sm lg:col-span-1\">  \n                                    <h4 class=\"text-sm font-bold text-slate-700 mb-4\">Volume por Cliente (Top 5)<\/h4>  \n                                    <div id=\"stats-chart-clients\" class=\"space-y-3\"><\/div>  \n                                <\/div>  \n  \n                                <!-- Cores Mais Usadas -->  \n                                <div class=\"bg-white p-4 sm:p-5 rounded-xl border border-slate-100 shadow-sm lg:col-span-1\">  \n                                    <h4 class=\"text-sm font-bold text-slate-700 mb-4\">Cores Mais Usadas (Top 5)<\/h4>  \n                                    <div id=\"stats-chart-colors\" class=\"space-y-3\"><\/div>  \n                                <\/div>  \n                            <\/div>  \n  \n                            <div class=\"bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden overflow-x-auto\">  \n                                <table class=\"w-full text-sm text-left min-w-[400px]\">  \n                                    <thead class=\"bg-slate-50 text-slate-500 font-bold uppercase text-[10px] sm:text-xs\">  \n                                        <tr>  \n                                            <th class=\"px-4 sm:px-6 py-3\">Cliente<\/th>  \n                                            <th class=\"px-2 sm:px-6 py-3 text-center\">Trabalhos<\/th>  \n                                            <th class=\"px-2 sm:px-6 py-3 text-center\">Folhas<\/th>  \n                                            <th class=\"px-2 sm:px-6 py-3 text-center\">Vol. Cores*<\/th>  \n                                        <\/tr>  \n                                    <\/thead>  \n                                    <tbody id=\"stats-table-body\" class=\"divide-y divide-slate-100 text-slate-700 text-xs sm:text-sm\">  \n                                    <\/tbody>  \n                                <\/table>  \n                                <div class=\"p-3 bg-slate-50 text-[10px] sm:text-xs text-slate-400 text-right italic border-t border-slate-200\">  \n                                    *Vol. Cores = N\u00ba de registos de cor associados aos trabalhos.  \n                                <\/div>  \n                            <\/div>  \n                        <\/div>  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- Edit Modal -->  \n            <div id=\"edit-lightbox-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/60 backdrop-blur-sm flex items-center justify-center p-4 transition-opacity z-50\">  \n                <div class=\"bg-white rounded-2xl shadow-2xl w-full max-w-4xl max-h-[90vh] overflow-y-auto relative animate-fade-in-up\">  \n                    <div class=\"sticky top-0 bg-white\/95 backdrop-blur border-b border-slate-100 px-8 py-5 flex justify-between items-center z-10\">  \n                        <div>  \n                            <h3 class=\"text-xl font-bold text-slate-800 m-0\" id=\"edit-modal-title\">Editar<\/h3>  \n                            <p class=\"text-xs text-slate-400 m-0 mt-1\">Edite os detalhes do trabalho abaixo<\/p>  \n                        <\/div>  \n                        <div class=\"flex items-center gap-2\">  \n                            <button id=\"btn-print-labels\" type=\"button\" class=\"p-2 mr-2 bg-pink-50 text-pink-600 rounded-lg hover:bg-pink-100 transition-colors border-none cursor-pointer flex items-center gap-2\" title=\"Imprimir Etiquetas\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\"><\/path><\/svg>  \n                                <span class=\"text-sm font-bold hidden sm:inline\">Etiquetas<\/span>  \n                            <\/button>  \n                            <button id=\"btn-print-fichas\" type=\"button\" class=\"p-2 mr-2 bg-emerald-50 text-emerald-600 rounded-lg hover:bg-emerald-100 transition-colors border-none cursor-pointer flex items-center gap-2\" title=\"Pr\u00e9-visualizar e imprimir as 3 Fichas\">\n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"\/><polyline points=\"14 2 14 8 20 8\"\/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"\/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"\/><\/svg>\n                                <span class=\"text-sm font-bold hidden sm:inline\">Fichas<\/span>\n                            <\/button>\n                            <button id=\"btn-print-job\" class=\"p-2 mr-2 bg-indigo-50 text-indigo-600 rounded-lg hover:bg-indigo-100 transition-colors border-none cursor-pointer flex items-center gap-2\" title=\"Imprimir Ficha\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 9 6 2 18 2 18 9\"\/><path d=\"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\"\/><rect x=\"6\" y=\"14\" width=\"12\" height=\"8\"\/><\/svg>  \n                                <span class=\"text-sm font-bold hidden sm:inline\">Imprimir<\/span>  \n                            <\/button>  \n                            <button id=\"btn-close-edit\" class=\"p-2 bg-slate-100 text-slate-500 rounded-full hover:bg-slate-200 transition-colors border-none cursor-pointer\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"\/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"\/><\/svg>  \n                            <\/button>  \n                        <\/div>  \n                    <\/div>  \n                      \n                    <div class=\"p-8\">  \n                        <form id=\"edit-job-form\" action=\"\">  \n                            <input type=\"hidden\" id=\"edit-job-id\">  \n                            <div class=\"grid grid-cols-1 md:grid-cols-12 gap-6 mb-8\">  \n                                <div class=\"space-y-1 md:col-span-2 lg:col-span-2\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">ID \u00danico<\/label>  \n                                    <input type=\"text\" id=\"edit-job-numero-registo\" readonly class=\"w-full p-3 bg-slate-100 border border-slate-200 rounded-xl font-mono text-sm text-slate-500 cursor-not-allowed outline-none\" title=\"Se estiver S\/N ser\u00e1 gerado um novo ID ao guardar\">  \n                                <\/div>  \n                                <div class=\"space-y-1 md:col-span-3 lg:col-span-4\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Refer\u00eancia<\/label>  \n                                    <input type=\"text\" id=\"edit-job-reference\" required class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors font-semibold text-slate-700\">  \n                                <\/div>  \n                                <div class=\"space-y-1 md:col-span-4 lg:col-span-4\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Cliente<\/label>  \n                                    <input type=\"hidden\" id=\"edit-job-client\" required>   \n                                    <div class=\"flex\">  \n                                        <div id=\"edit-job-client-display\" class=\"flex-1 p-3 bg-slate-50 border border-slate-200 border-r-0 rounded-l-xl text-slate-700 truncate font-medium flex items-center\">Nenhum<\/div>  \n                                        <button type=\"button\" id=\"btn-select-client-edit\" class=\"px-4 bg-indigo-50 text-indigo-600 border border-indigo-100 border-l-0 rounded-r-xl hover:bg-indigo-100 font-medium text-sm transition-colors cursor-pointer\">Mudar<\/button>  \n                                    <\/div>  \n                                <\/div>  \n                                <div class=\"space-y-1 md:col-span-3 lg:col-span-2\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Data<\/label>  \n                                    <input type=\"date\" id=\"edit-job-date\" required class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-slate-600\">  \n                                <\/div>  \n                            <\/div>  \n  \n                            <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6 mb-8\">  \n                                <div class=\"space-y-1\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Tipo de Trabalho<\/label>  \n                                    <select id=\"edit-job-type\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors cursor-pointer font-medium text-slate-700\">  \n                                        <option value=\"Produ\u00e7\u00e3o\">Produ\u00e7\u00e3o<\/option>  \n                                        <option value=\"Ensaio\">Ensaio<\/option>  \n                                    <\/select>  \n                                <\/div>  \n                                <div class=\"space-y-1\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Operador<\/label>  \n                                    <input type=\"text\" id=\"edit-job-operator\" placeholder=\"Quem imprimiu?\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">  \n                                <\/div>  \n                                <div class=\"space-y-1\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">M\u00e1quina<\/label>  \n                                    <input type=\"text\" id=\"edit-job-machine\" placeholder=\"Ex: Roland\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">  \n                                <\/div>\n                                <div class=\"space-y-1\">\n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Data de Entrega<\/label>\n                                    <input type=\"date\" id=\"edit-job-data-entrega\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-slate-600\">\n                                <\/div>\n                                <div class=\"space-y-1\">\n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Desenhador<\/label>\n                                    <input type=\"text\" id=\"edit-job-desenhador\" placeholder=\"Ex: Paulo\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">\n                                <\/div>\n                                <div class=\"space-y-1\">\n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Temperatura<\/label>\n                                    <input type=\"text\" id=\"edit-job-temperatura\" placeholder=\"Ex: 800\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">\n                                <\/div>  \n                                  \n                                <div class=\"space-y-1\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Folhas (Tam \/ Qtd)<\/label>  \n                                    <div class=\"flex gap-2\">  \n                                        <select id=\"edit-job-size\" class=\"w-2\/3 p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-sm appearance-none cursor-pointer truncate\">  \n                                        <\/select>  \n                                        <input type=\"number\" id=\"edit-job-sheets\" min=\"0\" placeholder=\"Qtd\" class=\"w-1\/3 p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-center font-bold\">  \n                                    <\/div>  \n                                <\/div>  \n  \n                                <div class=\"space-y-1\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Estado<\/label>  \n                                    <select id=\"edit-job-status\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors cursor-pointer\">  \n                                        <option value=\"Aberto\">Aberto<\/option>  \n                                        <option value=\"Em Progresso\">Em Progresso<\/option>  \n                                        <option value=\"Concluido\">Conclu\u00eddo<\/option>  \n                                        <option value=\"Sem Or\u00e7amento\">Sem Or\u00e7amento<\/option>  \n                                    <\/select>  \n                                <\/div>  \n                            <\/div>  \n  \n                            <div class=\"grid grid-cols-1 gap-6 mb-8\">  \n                                <div class=\"space-y-1\">  \n                                    <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Imagem URL<\/label>  \n                                    <div class=\"flex gap-2\">  \n                                        <input type=\"url\" id=\"edit-job-image-url\" class=\"flex-1 p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors text-sm\">  \n                                        <button type=\"button\" id=\"btn-view-image-edit\" class=\"px-3 bg-indigo-50 text-indigo-600 rounded-xl hover:bg-indigo-100 border-none cursor-pointer\">  \n                                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/svg>  \n                                        <\/button>  \n                                    <\/div>  \n                                <\/div>  \n                            <\/div>  \n                              \n                            <div class=\"space-y-1 mb-8\">  \n                                <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Observa\u00e7\u00f5es<\/label>  \n                                <textarea id=\"edit-job-observations\" rows=\"3\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors resize-none\"><\/textarea>  \n                            <\/div>  \n                              \n                            <div class=\"bg-slate-50 rounded-xl p-6 border border-slate-100 mb-8\">  \n                                <div class=\"flex justify-between items-center mb-4\">  \n                                    <h4 class=\"text-sm font-bold text-slate-700 uppercase tracking-wide\">Cores<\/h4>  \n                                    <button type=\"button\" id=\"btn-add-color-row-edit\" class=\"text-xs bg-white border border-slate-200 text-indigo-600 font-bold px-3 py-1.5 rounded-lg hover:bg-indigo-50 transition-colors shadow-sm cursor-pointer\">  \n                                        + Adicionar Cor  \n                                    <\/button>  \n                                <\/div>  \n                                <div id=\"colors-container-edit\" class=\"flex flex-col gap-3\"><\/div>  \n                            <\/div>  \n  \n                            <div class=\"bg-pink-50 rounded-xl p-6 border border-pink-100 mb-8 relative overflow-hidden\">  \n                                <div class=\"absolute -right-4 -top-4 text-pink-100 opacity-50\">  \n                                    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"100\" height=\"100\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\"><\/path><\/svg>  \n                                <\/div>  \n                                <div class=\"flex flex-col sm:flex-row sm:justify-between sm:items-center relative z-10 gap-4\">  \n                                    <div>  \n                                        <h4 class=\"text-sm font-bold text-pink-700 uppercase tracking-wide\">Etiquetas de Expedi\u00e7\u00e3o<\/h4>  \n                                        <p class=\"text-xs text-pink-600\/80 mt-1\">Configure os dados exatos para impress\u00e3o de etiquetas.<\/p>  \n                                    <\/div>  \n                                    <button type=\"button\" id=\"btn-open-label-config-edit\" class=\"px-4 py-2 bg-white text-pink-600 font-bold rounded-lg shadow-sm border border-pink-200 hover:bg-pink-50 transition-colors cursor-pointer text-sm whitespace-nowrap\">  \n                                        Configurar Etiquetas  \n                                    <\/button>  \n                                <\/div>  \n                            <\/div>  \n  \n                            <div class=\"flex justify-between items-center pt-6 border-t border-slate-100\">  \n                                <button type=\"button\" id=\"btn-delete-job\" class=\"px-4 py-2 text-rose-600 bg-rose-50 hover:bg-rose-100 font-medium rounded-xl transition-colors border-none cursor-pointer text-sm\">  \n                                    Apagar Registo  \n                                <\/button>  \n                                <div class=\"flex gap-3\">  \n                                    <button type=\"button\" id=\"btn-cancel-edit\" class=\"px-6 py-2.5 bg-white border border-slate-200 text-slate-600 font-semibold rounded-xl hover:bg-slate-50 cursor-pointer\">Cancelar<\/button>  \n                                    <button type=\"submit\" class=\"px-8 py-2.5 bg-indigo-600 text-white font-bold rounded-xl shadow-lg shadow-indigo-200 hover:bg-indigo-700 hover:-translate-y-0.5 transition-all border-none cursor-pointer\">  \n                                        Guardar  \n                                    <\/button>  \n                                <\/div>  \n                            <\/div>  \n                        <input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- Modal de Configura\u00e7\u00e3o de Etiquetas -->  \n            <div id=\"label-config-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/80 backdrop-blur-sm flex items-center justify-center p-4 z-[110]\">  \n                <div class=\"bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden\">  \n                    <div class=\"px-6 py-4 border-b border-slate-100 flex justify-between items-center bg-slate-50\">  \n                        <h3 class=\"text-lg font-bold text-slate-800 m-0 flex items-center gap-2\">  \n                            <svg class=\"w-5 h-5 text-pink-600\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\"><\/path><\/svg>  \n                            Configurar Etiquetas  \n                        <\/h3>  \n                        <button type=\"button\" id=\"btn-close-label-modal\" class=\"text-slate-400 hover:text-slate-600 cursor-pointer border-none bg-transparent\">\u2715<\/button>  \n                    <\/div>  \n                    <form id=\"label-config-form\" class=\"p-6 space-y-4\" action=\"\">  \n                        <div>  \n                            <label class=\"block text-xs font-bold text-slate-500 uppercase mb-1\">Descri\u00e7\u00e3o<\/label>  \n                            <input type=\"text\" id=\"label-desc\" class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm\">  \n                        <\/div>  \n                        <div>  \n                            <label class=\"block text-xs font-bold text-slate-500 uppercase mb-1\">C\u00f3digo do Artigo (EAN 13)<\/label>  \n                            <input type=\"text\" id=\"label-code\" maxlength=\"13\" class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm\" placeholder=\"At\u00e9 13 d\u00edgitos num\u00e9ricos\">  \n                        <\/div>  \n                        <div class=\"grid grid-cols-2 gap-4\">  \n                            <div>  \n                                <label class=\"block text-xs font-bold text-slate-500 uppercase mb-1\">Quantidade<\/label>  \n                                <input type=\"number\" id=\"label-qty\" class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm\">  \n                            <\/div>  \n                            <div>  \n                                <label class=\"block text-xs font-bold text-slate-500 uppercase mb-1\">Data Envio<\/label>  \n                                <input type=\"date\" id=\"label-date\" class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm\">  \n                            <\/div>  \n                        <\/div>  \n                        <div>  \n                            <label class=\"block text-xs font-bold text-slate-500 uppercase mb-1\">Lote<\/label>  \n                            <input type=\"text\" id=\"label-lote\" class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm\">  \n                        <\/div>  \n                        <div class=\"pt-4 mt-2 border-t border-slate-100 flex justify-end gap-3\">  \n                            <button type=\"button\" id=\"btn-clear-labels\" class=\"px-4 py-2 text-rose-600 bg-rose-50 hover:bg-rose-100 rounded-lg text-sm font-semibold cursor-pointer border-none\">Limpar Predefini\u00e7\u00e3o<\/button>  \n                            <button type=\"submit\" class=\"px-6 py-2 bg-pink-600 text-white rounded-lg text-sm font-bold shadow-md hover:bg-pink-700 cursor-pointer border-none\">Guardar Dados<\/button>  \n                        <\/div>  \n                    <input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- INJECTED: Modal de Defini\u00e7\u00f5es \/ Backup -->  \n            <div id=\"settings-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/80 backdrop-blur-sm flex items-center justify-center p-4 z-[105]\">  \n                <div class=\"bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden\">  \n                    <div class=\"px-6 py-4 border-b border-slate-100 flex justify-between items-center bg-slate-50\">  \n                        <h3 class=\"text-lg font-bold text-slate-800 m-0 flex items-center gap-2\">  \n                            <svg class=\"w-5 h-5 text-indigo-600\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/svg>  \n                            Backup e Defini\u00e7\u00f5es  \n                        <\/h3>  \n                        <button type=\"button\" id=\"btn-close-settings\" class=\"text-slate-400 hover:text-slate-600 cursor-pointer border-none bg-transparent\">\u2715<\/button>  \n                    <\/div>  \n                    <div class=\"p-6 space-y-6\">  \n                          \n                        <!-- Sec\u00e7\u00e3o Exportar -->  \n                        <div class=\"bg-indigo-50\/50 p-4 rounded-xl border border-indigo-100\">  \n                            <h4 class=\"text-sm font-bold text-slate-800 mb-2\">Exportar Dados (Backup)<\/h4>  \n                            <p class=\"text-xs text-slate-500 mb-4\">Descarregue uma c\u00f3pia de seguran\u00e7a completa de todas as cole\u00e7\u00f5es (Trabalhos, Clientes, Cores, etc).<\/p>  \n                            <button id=\"btn-export-backup\" class=\"w-full px-4 py-2 bg-indigo-600 text-white font-bold rounded-lg shadow-md hover:bg-indigo-700 cursor-pointer border-none flex items-center justify-center gap-2\">  \n                                <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\/><\/svg>  \n                                Descarregar Ficheiro .JSON  \n                            <\/button>  \n                        <\/div>  \n  \n                        <!-- Sec\u00e7\u00e3o Importar -->  \n                        <div class=\"bg-rose-50\/50 p-4 rounded-xl border border-rose-100\">  \n                            <h4 class=\"text-sm font-bold text-slate-800 mb-2 text-rose-800\">Restaurar Dados<\/h4>  \n                            <p class=\"text-xs text-rose-600\/80 mb-4 font-medium\">Aten\u00e7\u00e3o: A importa\u00e7\u00e3o ir\u00e1 adicionar e substituir os dados existentes com base no ficheiro de backup.<\/p>  \n                              \n                            <input type=\"file\" id=\"backup-file-input\" accept=\".json\" class=\"hidden\">  \n                            <div class=\"flex gap-2\">  \n                                <button id=\"btn-trigger-file\" class=\"flex-1 px-4 py-2 bg-white text-slate-700 border border-slate-200 font-bold rounded-lg hover:bg-slate-50 cursor-pointer\">  \n                                    Escolher Ficheiro  \n                                <\/button>  \n                                <button id=\"btn-import-backup\" class=\"px-4 py-2 bg-rose-600 text-white font-bold rounded-lg shadow-md hover:bg-rose-700 cursor-pointer border-none disabled:opacity-50 disabled:cursor-not-allowed\" disabled>  \n                                    Restaurar  \n                                <\/button>  \n                            <\/div>  \n                            <p id=\"file-name-display\" class=\"text-[10px] text-slate-400 mt-2 truncate text-center\"><\/p>  \n                        <\/div>  \n  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- INJECTED: Modal Pedido de Material (Agora suporta Edi\u00e7\u00e3o) -->  \n            <div id=\"material-request-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/60 backdrop-blur-sm flex items-center justify-center p-4 z-[105]\">  \n                <div class=\"bg-white p-6 rounded-2xl shadow-2xl w-full max-w-2xl flex flex-col max-h-[90vh]\">  \n                    <div class=\"flex justify-between items-center mb-4 border-b border-slate-100 pb-4\">  \n                        <h3 id=\"material-modal-title\" class=\"text-lg font-bold text-slate-800 flex items-center gap-2\">  \n                            <svg class=\"w-5 h-5 text-indigo-600\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"><\/path><\/svg>  \n                            Novo Pedido de Material  \n                        <\/h3>  \n                        <button id=\"btn-close-material-modal\" class=\"text-slate-400 hover:text-slate-600 cursor-pointer border-none bg-transparent\">\u2715<\/button>  \n                    <\/div>  \n                      \n                    <form id=\"material-request-form\" class=\"flex-1 overflow-y-auto custom-scrollbar pr-2 flex flex-col justify-between\" action=\"\">  \n                        <div class=\"space-y-4\">  \n                            <input type=\"hidden\" id=\"mat-req-id\">  \n                            <div>  \n                                <label class=\"block text-xs font-bold text-slate-500 uppercase mb-1\">Data do Pedido<\/label>  \n                                <input type=\"date\" id=\"mat-req-date\" required class=\"w-full p-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm focus:border-indigo-500\">  \n                            <\/div>  \n  \n                            <div class=\"border-t border-slate-100 pt-4 mt-2\">  \n                                <div class=\"flex justify-between items-center mb-2\">  \n                                    <label class=\"block text-xs font-bold text-slate-500 uppercase\">Artigos a Pedir<\/label>  \n                                    <button type=\"button\" id=\"btn-add-mat-field\" class=\"text-xs bg-indigo-50 text-indigo-600 px-3 py-1 rounded-md font-bold hover:bg-indigo-100 border-none cursor-pointer\">  \n                                        + Adicionar Linha  \n                                    <\/button>  \n                                <\/div>  \n                                <div id=\"material-fields-container\" class=\"space-y-3\">  \n                                    <!-- Linhas din\u00e2micas injetadas via JS -->  \n                                <\/div>  \n                            <\/div>  \n                        <\/div>  \n  \n                        <div class=\"pt-4 mt-6 border-t border-slate-100 flex justify-between items-center\">  \n                            <button type=\"button\" id=\"btn-delete-mat\" class=\"hidden px-4 py-2 text-rose-600 bg-rose-50 hover:bg-rose-100 rounded-lg text-sm font-semibold cursor-pointer border-none\">Apagar Pedido<\/button>  \n                            <button type=\"submit\" id=\"btn-submit-mat\" class=\"px-6 py-2 bg-indigo-600 text-white rounded-lg text-sm font-bold shadow-md hover:bg-indigo-700 cursor-pointer border-none ml-auto\">Submeter Pedido<\/button>  \n                        <\/div>  \n                    <input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- Login Modal -->  \n            <div id=\"login-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/80 backdrop-blur-sm flex items-center justify-center p-4 z-50\">  \n                <div class=\"bg-white p-8 rounded-2xl shadow-2xl w-full max-w-sm border border-slate-100\">  \n                    <div class=\"text-center mb-8\">  \n                        <div class=\"w-12 h-12 bg-indigo-100 text-indigo-600 rounded-full flex items-center justify-center mx-auto mb-4\">  \n                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"\/><circle cx=\"12\" cy=\"7\" r=\"4\"\/><\/svg>  \n                        <\/div>  \n                        <h3 class=\"text-2xl font-bold text-slate-800 m-0\">Login<\/h3>  \n                        <p class=\"text-slate-500 mt-2 text-sm\">Aceda \u00e0 \u00e1rea de gest\u00e3o<\/p>  \n                    <\/div>  \n                    <form id=\"login-form\" class=\"space-y-5\" action=\"\">  \n                        <div class=\"space-y-1\">  \n                            <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Email<\/label>  \n                            <input type=\"email\" id=\"login-email\" required class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">  \n                        <\/div>  \n                        <div class=\"space-y-1\">  \n                            <label class=\"text-xs font-bold text-slate-400 uppercase tracking-wider ml-1\">Password<\/label>  \n                            <input type=\"password\" id=\"login-password\" required class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white transition-colors\">  \n                        <\/div>  \n                        <p id=\"login-error\" class=\"text-rose-500 text-xs hidden bg-rose-50 p-2 rounded-lg text-center font-medium\"><\/p>  \n                        <button type=\"submit\" class=\"w-full py-3 rounded-xl shadow-lg shadow-indigo-200 text-sm font-bold text-white bg-indigo-600 hover:bg-indigo-700 transition-all border-none cursor-pointer\">Entrar<\/button>  \n                    <input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>  \n                    <div class=\"mt-6 text-center\">  \n                        <button id=\"btn-cancel-login\" class=\"text-sm text-slate-400 hover:text-slate-600 bg-transparent border-none cursor-pointer font-medium\">Voltar<\/button>  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- Client Modal -->  \n            <div id=\"client-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/60 backdrop-blur-sm flex items-center justify-center p-4 z-50\">  \n                <div class=\"bg-white p-6 rounded-2xl shadow-2xl w-full max-w-md max-h-[80vh] flex flex-col\">  \n                    <h3 class=\"text-lg font-bold text-slate-800 mb-6 flex items-center\">  \n                        <span class=\"w-8 h-8 rounded-lg bg-emerald-100 text-emerald-600 flex items-center justify-center mr-3\">  \n                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\"\/><circle cx=\"9\" cy=\"7\" r=\"4\"\/><line x1=\"23\" y1=\"11\" x2=\"17\" y2=\"11\"\/><line x1=\"20\" y1=\"8\" x2=\"20\" y2=\"14\"\/><\/svg>  \n                        <\/span>  \n                        Clientes  \n                    <\/h3>  \n                    <form id=\"client-form-add\" class=\"mb-4 p-4 border border-slate-100 rounded-xl bg-slate-50\" action=\"\">  \n                        <div class=\"flex gap-2\">  \n                            <input type=\"text\" id=\"new-client-name\" required placeholder=\"Nome do novo cliente...\" class=\"flex-1 p-2 bg-white border border-slate-200 rounded-lg focus:border-emerald-500 text-sm\">  \n                            <button type=\"submit\" class=\"px-4 py-2 bg-emerald-600 text-white font-semibold rounded-lg hover:bg-emerald-700 border-none cursor-pointer text-sm\">Add<\/button>  \n                        <\/div>  \n                    <input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>  \n                    <div class=\"flex-1 overflow-y-auto pr-1 custom-scrollbar\">  \n                        <div id=\"client-list-container\" class=\"space-y-2\"><\/div>  \n                        <p id=\"no-clients-msg\" class=\"text-slate-400 text-sm text-center py-4 italic hidden\">Nenhum cliente registado.<\/p>  \n                    <\/div>  \n                    <div class=\"mt-6 pt-4 border-t border-slate-100 text-right\">  \n                        <button id=\"btn-close-client-modal\" class=\"px-5 py-2 text-slate-600 font-semibold rounded-lg hover:bg-slate-100 border-none cursor-pointer\">Fechar<\/button>  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- Color DB Modal -->  \n            <div id=\"color-db-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/80 backdrop-blur-sm flex items-center justify-center p-4 z-50\">  \n                <div class=\"bg-white p-0 rounded-2xl shadow-2xl w-full max-w-3xl max-h-[90vh] flex flex-col overflow-hidden\">  \n                    <div class=\"px-6 py-5 border-b border-slate-100 flex justify-between items-center bg-white shrink-0\">  \n                        <h3 class=\"text-xl font-bold text-slate-800 m-0 flex items-center\">  \n                            <span class=\"w-10 h-10 rounded-xl bg-pink-100 text-pink-600 flex items-center justify-center mr-3 shadow-sm\">  \n                                <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2.5 17a2.5 2.5 0 0 1 5 0V5a2.5 2.5 0 0 1-5 0v12Z\"\/><path d=\"M7.5 12h5\"\/><path d=\"M12.5 17a2.5 2.5 0 0 0 5 0V5a2.5 2.5 0 0 0-5 0v12Z\"\/><path d=\"M17.5 12h3\"\/><\/svg>  \n                            <\/span>  \n                            Base de Cores  \n                        <\/h3>  \n                        <button id=\"btn-close-color-modal-top\" class=\"p-2 bg-slate-100 text-slate-500 rounded-full hover:bg-slate-200 transition-colors border-none cursor-pointer\">  \n                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"\/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"\/><\/svg>  \n                        <\/button>  \n                    <\/div>  \n                      \n                    <div class=\"flex-1 overflow-y-auto p-6 bg-slate-50 custom-scrollbar\">  \n                          \n                        <div class=\"bg-white p-5 rounded-xl border border-slate-200 shadow-sm mb-6\">  \n                            <form id=\"color-form-add\" class=\"grid grid-cols-1 md:grid-cols-12 gap-4\" action=\"\">  \n                                <div class=\"md:col-span-3\">  \n                                    <label class=\"block text-xs font-bold text-slate-400 uppercase tracking-wider mb-1.5\">Name<\/label>  \n                                    <input type=\"text\" id=\"new-color-name\" required placeholder=\"Ex: Azul\u00e3o\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:border-pink-500 focus:bg-white text-sm font-semibold transition-all\">  \n                                <\/div>  \n                                <div class=\"md:col-span-2\">  \n                                     <label class=\"block text-xs font-bold text-slate-400 uppercase tracking-wider mb-1.5\">Temp<\/label>  \n                                     <input type=\"text\" id=\"new-color-temp\" list=\"temp-suggestions\" placeholder=\"Ex: 820\u00ba\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:border-pink-500 focus:bg-white text-sm text-center transition-all\">  \n                                <\/div>  \n                                <div class=\"md:col-span-7\">   \n                                    <label class=\"block text-xs font-bold text-slate-400 uppercase tracking-wider mb-1.5\">F\u00f3rmula<\/label>  \n                                    <textarea id=\"new-color-comp\" required placeholder=\"Ex: 50% Azul + 50% Base\" rows=\"2\" class=\"w-full p-3 bg-slate-50 border border-slate-200 rounded-xl focus:border-pink-500 focus:bg-white text-sm transition-all resize-none\"><\/textarea>  \n                                <\/div>  \n                                  \n                                <div class=\"md:col-span-12 flex items-center justify-between mt-2 pt-4 border-t border-slate-100\">  \n                                     <label class=\"relative inline-flex items-center cursor-pointer\">  \n                                        <input type=\"checkbox\" id=\"is-contra-tipo\" class=\"sr-only peer\">  \n                                        <div class=\"w-11 h-6 bg-slate-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-indigo-600\"><\/div>  \n                                        <span class=\"ml-3 text-sm font-bold text-slate-600\">Com Variantes?<\/span>  \n                                     <\/label>  \n                                     <div class=\"flex gap-2\">  \n                                        <button type=\"button\" id=\"btn-cancel-color-edit\" class=\"hidden px-4 py-2 bg-slate-100 text-slate-600 font-bold rounded-xl hover:bg-slate-200 border-none cursor-pointer text-sm\">Cancelar<\/button>  \n                                        <button type=\"submit\" id=\"btn-save-color\" class=\"px-6 py-2 bg-pink-600 text-white font-bold rounded-xl hover:bg-pink-700 border-none cursor-pointer text-sm shadow-md transition-transform\">  \n                                            Salvar F\u00f3rmula  \n                                        <\/button>  \n                                     <\/div>  \n                                <\/div>  \n                                  \n                                <div id=\"alternatives-section\" class=\"md:col-span-12 hidden mt-2 bg-indigo-50\/50 rounded-xl p-4 border border-indigo-100\">  \n                                     <h4 class=\"text-xs font-bold text-indigo-400 uppercase tracking-wider mb-3\">Variantes Alternativas<\/h4>  \n                                     <div id=\"alternatives-list\" class=\"space-y-3\"><\/div>  \n                                     <button type=\"button\" id=\"btn-add-alt\" class=\"mt-3 w-full py-2.5 text-sm flex items-center justify-center text-indigo-600 font-bold bg-white border border-indigo-100 rounded-xl shadow-sm cursor-pointer hover:bg-indigo-50\">  \n                                        + Adicionar Variante  \n                                     <\/button>  \n                                <\/div>  \n                            <input type=\"hidden\" name=\"trp-form-language\" value=\"en\"\/><\/form>  \n                        <\/div>  \n  \n                        <div>  \n                            <div class=\"mb-4 flex gap-2\">  \n                                <div class=\"relative flex-1\">  \n                                    <input type=\"text\" id=\"search-color-db\" placeholder=\"Pesquisar f\u00f3rmula...\" class=\"w-full p-3 pl-10 bg-white border border-slate-200 rounded-xl text-sm shadow-sm focus:border-pink-500 focus:outline-none\">  \n                                    <svg class=\"w-4 h-4 text-slate-400 absolute left-3.5 top-3.5\" fill=\"none\" stroke=\"currentColor\" viewbox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\/><\/svg>  \n                                <\/div>  \n                                <button type=\"button\" id=\"btn-export-colors-excel\" class=\"px-4 py-2 bg-pink-50 text-pink-600 hover:bg-pink-100 rounded-xl font-bold text-sm transition-colors border-none cursor-pointer flex items-center justify-center gap-2 shadow-sm whitespace-nowrap\" title=\"Exportar Tintas para Excel\">  \n                                    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"><\/path><polyline points=\"14 2 14 8 20 8\"><\/polyline><line x1=\"8\" y1=\"13\" x2=\"16\" y2=\"13\"><\/line><line x1=\"8\" y1=\"17\" x2=\"16\" y2=\"17\"><\/line><polyline points=\"10 9 9 9 8 9\"><\/polyline><\/svg>  \n                                    <span class=\"hidden sm:inline\">Exportar .CSV<\/span>  \n                                <\/button>  \n                            <\/div>  \n                            <div id=\"color-db-list-container\" class=\"space-y-3\"><\/div>  \n                            <div id=\"no-colors-msg\" class=\"flex flex-col items-center justify-center py-10 text-slate-400 hidden bg-white rounded-xl border border-dashed border-slate-200\">  \n                                <span class=\"text-sm font-medium\">Nenhum registo encontrado<\/span>  \n                            <\/div>  \n                        <\/div>  \n  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n            <!-- Lightbox Imagem -->  \n            <div id=\"lightbox-modal\" class=\"lightbox-hidden fixed inset-0 bg-black\/95 flex items-center justify-center p-0 z-[60] overflow-hidden\">  \n                <div class=\"absolute top-4 left-0 right-0 flex justify-center gap-3 z-50 pointer-events-none\">  \n                    <div class=\"bg-slate-800\/80 backdrop-blur rounded-full p-2 flex items-center gap-3 pointer-events-auto shadow-2xl border border-white\/10\">  \n                        <button id=\"btn-zoom-out\" class=\"w-10 h-10 flex items-center justify-center text-white hover:bg-white\/20 rounded-full transition-colors\">  \n                            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>  \n                        <\/button>  \n                        <span id=\"zoom-level\" class=\"text-white text-xs font-mono font-bold w-12 text-center\">100%<\/span>  \n                        <button id=\"btn-zoom-in\" class=\"w-10 h-10 flex items-center justify-center text-white hover:bg-white\/20 rounded-full transition-colors\">  \n                             <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>  \n                        <\/button>  \n                         <div class=\"w-px h-6 bg-white\/20 mx-1\"><\/div>  \n                        <button id=\"btn-zoom-reset\" class=\"px-3 h-8 text-xs font-bold text-white\/80 hover:text-white hover:bg-white\/10 rounded-lg transition-colors\">  \n                            Reset  \n                        <\/button>  \n                    <\/div>  \n                <\/div>  \n  \n                <div id=\"lightbox-container\" class=\"w-full h-full flex items-center justify-center overflow-hidden cursor-grab active:cursor-grabbing relative\">  \n                    <img decoding=\"async\" id=\"lightbox-image\" src=\"\" class=\"max-h-full max-w-full object-contain transition-transform duration-100 ease-out origin-center\" draggable=\"false\">  \n                <\/div>  \n                  \n                <button id=\"btn-close-lightbox\" class=\"absolute top-4 right-4 w-10 h-10 flex items-center justify-center bg-white\/10 hover:bg-white\/20 text-white rounded-full transition-colors border-none cursor-pointer z-50 backdrop-blur-sm\">  \n                    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"\/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"\/><\/svg>  \n                <\/button>  \n            <\/div>  \n  \n            <!-- Modais Secund\u00e1rios -->  \n            <div id=\"variant-selection-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/60 backdrop-blur-sm flex items-center justify-center p-4 z-[105]\">  \n                <div class=\"bg-white p-6 rounded-2xl shadow-2xl w-full max-w-md flex flex-col\">  \n                    <h3 class=\"text-lg font-bold text-slate-800 mb-2\">Escolher Variante<\/h3>  \n                    <div id=\"variant-options-list\" class=\"space-y-3 flex-1 overflow-y-auto max-h-[60vh] custom-scrollbar p-1\"><\/div>  \n                    <div class=\"mt-6 pt-4 border-t border-slate-100 text-right\">  \n                        <button id=\"btn-close-variant-modal\" class=\"px-5 py-2 text-slate-600 font-semibold rounded-lg hover:bg-slate-100 border-none cursor-pointer\">Cancelar<\/button>  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n            <div id=\"confirmation-modal\" class=\"lightbox-hidden fixed inset-0 bg-slate-900\/60 backdrop-blur-sm flex items-center justify-center p-4 z-[100]\">  \n                <div class=\"bg-white p-6 rounded-2xl shadow-2xl w-full max-w-xs text-center\">  \n                    <h3 id=\"confirm-title\" class=\"text-lg font-bold text-slate-800 mb-2\">Tem a certeza?<\/h3>  \n                    <p id=\"confirm-message\" class=\"text-slate-500 text-sm mb-6 leading-relaxed\">Esta a\u00e7\u00e3o n\u00e3o pode ser revertida.<\/p>  \n                    <div class=\"flex gap-3 justify-center\">  \n                        <button id=\"btn-cancel-confirm\" class=\"px-4 py-2 bg-white border border-slate-200 text-slate-600 font-semibold rounded-lg hover:bg-slate-50 cursor-pointer\">Cancelar<\/button>  \n                        <button id=\"confirm-action-button\" class=\"px-4 py-2 bg-rose-600 text-white font-semibold rounded-lg shadow-md hover:bg-rose-700 border-none cursor-pointer\">Confirmar<\/button>  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n  \n        <\/div>  \n    <\/div>  \n<\/div>  \n  \n<script>  \n\/\/ ============================================================================  \n\/\/ 1. O C\u00d3DIGO ORIGINAL INTOC\u00c1VEL DO GERADOR DE ETIQUETAS  \n\/\/ ============================================================================  \nconst HTML_GERADOR_ETIQUETAS = `  \n<div id=\"gerador-etiqueta\" style=\"max-width:700px; margin:auto;\">  \n  <form id=\"formEtiqueta\" onsubmit=\"return false;\">  \n    <label>Descri\u00e7\u00e3o do Produto:<\/label><br>  \n    <input type=\"text\" id=\"descricao\" required><br><br>  \n  \n    <label>C\u00f3digo do Artigo (at\u00e9 13 d\u00edgitos):<\/label><br>  \n    <input type=\"text\" id=\"codigo\" required><br><br>  \n  \n    <label>Quantidade:<\/label><br>  \n    <input type=\"number\" id=\"quantidade\" required><br><br>  \n  \n    <label>Lote do Produto:<\/label><br>  \n    <input type=\"text\" id=\"lote\" required><br><br>  \n  \n    <label>Data de Envio:<\/label><br>  \n    <input type=\"date\" id=\"dataEnvio\" required><br><br>  \n  \n    <button id=\"btnGerar\" type=\"button\">Gerar Etiquetas<\/button>  \n  <\/form>  \n  \n  <div id=\"mensagemErro\" style=\"color:darkred; margin-top:10px; display:none;\"><\/div>  \n  \n  <div id=\"a4\" style=\"display:none; margin-top:10px;\">  \n    <!-- Etiqueta Original -->  \n    <div class=\"etiqueta-coluna\">  \n      <div class=\"logo\">  \n        <img decoding=\"async\" src=\"https:\/\/decalcer.com\/wp\/wp-content\/uploads\/2023\/06\/logo-decalcer-768x256.png\"  \n             alt=\"Decalcer\" style=\"max-width:150px; height:auto; margin-bottom:5px;\">  \n      <\/div>  \n      <div class=\"titulo\">Etiqueta GS1-128 - Original<\/div>  \n      <div class=\"etiqueta-conteudo\" style=\"text-align:center;\">  \n        <svg class=\"gs1\"><\/svg>  \n        <div class=\"textoHuman\"><\/div>  \n        <p><strong>Produto:<\/strong> <span class=\"txtDescricao\"><\/span><\/p>  \n        <p><strong>Quantidade:<\/strong> <span class=\"txtQuantidade\"><\/span><\/p>  \n        <p><strong>Lote:<\/strong> <span class=\"txtLote\"><\/span><\/p>  \n        <p><strong>Data de Envio:<\/strong> <span class=\"txtDataEnvio\"><\/span><\/p>  \n      <\/div>  \n    <\/div>  \n  \n    <!-- Etiqueta C\u00f3pia -->  \n    <div class=\"etiqueta-coluna\">  \n      <div class=\"logo\">  \n        <img decoding=\"async\" src=\"https:\/\/decalcer.com\/wp\/wp-content\/uploads\/2023\/06\/logo-decalcer-768x256.png\"  \n             alt=\"Decalcer\" style=\"max-width:150px; height:auto; margin-bottom:5px;\">  \n      <\/div>  \n      <div class=\"titulo\">Etiqueta GS1-128 - C\u00f3pia<\/div>  \n      <div class=\"etiqueta-conteudo\" style=\"text-align:center;\">  \n        <svg class=\"gs1\"><\/svg>  \n        <div class=\"textoHuman\"><\/div>  \n        <p><strong>Produto:<\/strong> <span class=\"txtDescricao\"><\/span><\/p>  \n        <p><strong>Quantidade:<\/strong> <span class=\"txtQuantidade\"><\/span><\/p>  \n        <p><strong>Lote:<\/strong> <span class=\"txtLote\"><\/span><\/p>  \n        <p><strong>Data de Envio:<\/strong> <span class=\"txtDataEnvio\"><\/span><\/p>  \n      <\/div>  \n    <\/div>  \n  <\/div>  \n  \n  <button id=\"btnImprimir\" class=\"botao-imprimir\" style=\"display:none;\" onclick=\"window.print()\">\ud83d\udda8\ufe0f Imprimir<\/button>  \n<\/div>  \n  \n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/jsbarcode@3.11.5\/dist\/JsBarcode.all.min.js\"><\\\/script>  \n  \n<style>  \n#a4 { width: 210mm; height: 297mm; display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start; gap: 10mm; padding: 10mm 0 0 10mm; box-sizing: border-box; }  \n.etiqueta-coluna { border: 2px solid black; padding: 10px; width: 130mm; height: 100mm; background: white; font-family: Arial, sans-serif; box-sizing: border-box; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; }  \n.titulo { font-size: 13px; text-align: center; margin-bottom: 8px; font-weight: bold; }  \n.textoHuman { font-size: 11px; margin: 6px 0; }  \n.botao-imprimir { margin-top: 15px; padding: 8px; }  \n@media print {  \n  @page { size: A4 portrait; margin: 0; }  \n  body { margin: 0; padding: 0; }  \n  body * { visibility: hidden; }  \n  #a4, #a4 * { visibility: visible; }  \n  #a4 { position: absolute; top: 0; left: 0; margin: 0 !important; padding: 10mm 0 0 10mm; width: 210mm; height: 297mm; display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start; gap: 10mm; box-sizing: border-box; }  \n  .botao-imprimir, #gerador-etiqueta form { display: none !important; }  \n}  \n<\/style>  \n  \n<script>  \ndocument.addEventListener('DOMContentLoaded', function() {  \n  const btn = document.getElementById('btnGerar');  \n  const btnImprimir = document.getElementById('btnImprimir');  \n  const mensagemErro = document.getElementById('mensagemErro');  \n  \n  function showError(msg) { console.error(msg); mensagemErro.style.display = 'block'; mensagemErro.innerText = msg; }  \n  function clearError() { mensagemErro.style.display = 'none'; mensagemErro.innerText = ''; }  \n  \n  btn.addEventListener('click', function() {  \n    clearError();  \n    const form = document.getElementById('formEtiqueta');  \n    if (!form.checkValidity()) { showError('Preenche todos os campos obrigat\u00f3rios.'); return; }  \n  \n    const descricao = document.getElementById('descricao').value.trim();  \n    let codigo = document.getElementById('codigo').value.trim();  \n    const quantidade = parseInt(document.getElementById('quantidade').value.trim());  \n    const lote = document.getElementById('lote').value.trim();  \n    const dataEnvio = document.getElementById('dataEnvio').value;  \n  \n    if (codigo.length > 13) { showError('O C\u00f3digo do Artigo n\u00e3o deve ter mais de 13 d\u00edgitos.'); return; }  \n  \n    codigo = codigo.padEnd(18, '0');  \n    const qtdStr = quantidade.toString().padStart(6, '0');  \n  \n    const human = \\`(00) \\${codigo} (3111) \\${qtdStr} (10)\\${lote}\\`;  \n    const machine = \\`00\\${codigo}3111\\${qtdStr}10\\${lote}\\`;  \n  \n    document.querySelectorAll('.textoHuman').forEach(el => el.innerText = human);  \n    document.querySelectorAll('.txtDescricao').forEach(el => el.innerText = descricao);  \n    document.querySelectorAll('.txtQuantidade').forEach(el => el.innerText = quantidade);  \n    document.querySelectorAll('.txtLote').forEach(el => el.innerText = lote);  \n    document.querySelectorAll('.txtDataEnvio').forEach(el => el.innerText = dataEnvio);  \n  \n    document.querySelectorAll('.gs1').forEach(svg => { JsBarcode(svg, machine, { format: \"code128\", lineColor: \"#000\", width: 1.2, height: 60, displayValue: false }); });  \n  \n    document.getElementById('a4').style.display = 'flex';  \n    btnImprimir.style.display = 'inline-block';  \n  });  \n});  \n<\\\/script>  \n`;  \n  \nfunction abrirModalEtiquetas(job) {  \n    const overlay = document.createElement('div');  \n    overlay.className = \"fixed inset-0 bg-slate-900\/80 z-[99999] flex justify-center items-center backdrop-blur-sm p-4 sm:p-6\";  \n    const modal = document.createElement('div');  \n    modal.className = \"bg-white w-full max-w-5xl h-[95vh] rounded-2xl shadow-2xl flex flex-col overflow-hidden animate-fade-in-up\";  \n    const header = document.createElement('div');  \n    header.className = \"px-6 py-4 border-b border-slate-100 bg-white flex justify-between items-center\";  \n    header.innerHTML = `<div><h2 class=\"text-lg font-bold text-slate-800 flex items-center gap-2\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" class=\"text-pink-600\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\"><\/path><\/svg> Impress\u00e3o de Etiquetas<\/h2><p class=\"text-xs text-slate-500 mt-1\">Ref: ${job.reference || job.id}<\/p><\/div>`;  \n    const btnFechar = document.createElement('button');  \n    btnFechar.className = \"p-2 text-slate-400 hover:text-rose-600 rounded-full hover:bg-rose-50 transition-colors border-none cursor-pointer\";  \n    btnFechar.innerHTML = `<svg width=\"24\" height=\"24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"\/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"\/><\/svg>`;  \n    btnFechar.onclick = () => document.body.removeChild(overlay);  \n    header.appendChild(btnFechar);  \n    const iframe = document.createElement('iframe');  \n    iframe.className = \"w-full flex-grow border-none bg-slate-50\";  \n    modal.appendChild(header);  \n    modal.appendChild(iframe);  \n    overlay.appendChild(modal);  \n    document.body.appendChild(overlay);  \n  \n    const doc = iframe.contentWindow.document;  \n    doc.open();  \n    doc.write(HTML_GERADOR_ETIQUETAS);  \n    doc.close();  \n  \n    iframe.onload = () => {  \n        setTimeout(() => {  \n            const innerDoc = iframe.contentWindow.document;  \n            if(!innerDoc) return;  \n            const lbl = job.labelData || {};  \n            const hoje = new Date().toISOString().split('T')[0];  \n            const defaultCod = (job.reference || job.id || '').replace(\/\\D\/g, '').padEnd(13, '0').substring(0, 13);  \n            const campos = {  \n                'descricao': lbl.descricao || `${job.client || 'Cliente'} - ${job.reference || 'Ref'}`,  \n                'codigo': lbl.codigo || defaultCod || '0000000000000',  \n                'quantidade': lbl.quantidade || job.sheets || 1,  \n                'lote': lbl.lote || `LT-${new Date(job.timestamp || Date.now()).getFullYear()}${(new Date(job.timestamp || Date.now()).getMonth()+1).toString().padStart(2,'0')}`,  \n                'dataEnvio': lbl.dataEnvio || job.date || hoje  \n            };  \n            for (const [id, valor] of Object.entries(campos)) {  \n                const input = innerDoc.getElementById(id);  \n                if (input) input.value = valor;  \n            }  \n            const btnGerar = innerDoc.getElementById('btnGerar');  \n            if (btnGerar) btnGerar.click();  \n            const formInterno = innerDoc.getElementById('formEtiqueta');  \n            if(formInterno) formInterno.style.display = 'none';  \n        }, 150);  \n    };  \n}  \n  \n  \ndocument.addEventListener('DOMContentLoaded', function() {  \n      \n    \/\/ Configura\u00e7\u00e3o Firebase  \n    const YOUR_FIREBASE_CONFIG = {  \n        apiKey: \"AIzaSyB85VxQ42UM4ImCT__Fo6miXxyS__z6-40\",  \n        authDomain: \"aplicacao-web-c082b.firebaseapp.com\",  \n        projectId: \"aplicacao-web-c082b\",  \n        storageBucket: \"aplicacao-web-c082b.firebasestorage.app\",  \n        messagingSenderId: \"62510523568\",  \n        appId: \"1:62510523568:web:c908f75d6c8000ff584775\",  \n        measurementId: \"G-K10H7HDS31\"  \n    };  \n  \n    const appId = typeof __app_id !== 'undefined' ? __app_id : 'standalone-decalcer-job-manager';  \n      \n    let db, auth;  \n    let currentUser = null;  \n    let jobs = [], clients = [], formulas = [], orcamentos = [];   \n    let pendingAction = null;  \n    let clientSelectionMode = 'add';  \n    let editingColorId = null;   \n      \n    let currentLabelContext = null;   \n    let currentLabelDataCreate = null;   \n    let currentLabelDataEdit = null;     \n      \n    \/\/ Estado da Visualiza\u00e7\u00e3o (Lista vs Kanban)  \n    let currentViewMode = 'list';  \n    let draggedJobId = null;   \n      \n    let zoomLevel = 1;  \n    let isDragging = false;  \n    let startX, startY, translateX = 0, translateY = 0;  \n  \n    const VALID_SIZES = [\"30 x 15cm\", \"25 x 35cm\", \"30 x 45cm\", \"35 x 50cm\", \"45 x 60cm\", \"50 x 70cm\", \"55 x 75cm\", \"60 x 80cm\"];  \n    const KANBAN_COLUMNS = [\"Aberto\", \"Em Progresso\", \"Concluido\", \"Sem Or\u00e7amento\"];  \n      \n    function showToast(message, type = 'success') {  \n        const container = document.getElementById('toast-container');  \n        if(!container) return;  \n        const toast = document.createElement('div');  \n        toast.className = 'toast ' + type;  \n          \n        let icon = '';  \n        if(type === 'success') icon = '<svg class=\"w-5 h-5 text-emerald-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"\/><\/svg>';  \n        else if(type === 'error') icon = '<svg class=\"w-5 h-5 text-rose-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\/><\/svg>';  \n        else icon = '<svg class=\"w-5 h-5 text-blue-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\/><\/svg>';  \n  \n        toast.innerHTML = icon + '<span>' + message + '<\/span>';  \n        container.appendChild(toast);  \n  \n        setTimeout(() => {  \n            toast.style.animation = 'slideOut 0.3s forwards';  \n            setTimeout(() => toast.remove(), 300);  \n        }, 3000);  \n    }  \n  \n    const logoCont = document.getElementById('logo-container');  \n    if(logoCont) {  \n        const img = document.createElement('img');  \n        img.src = 'https:\/\/www.decalcer.com\/wp-content\/uploads\/2023\/06\/logo-decalcer-768x256.png';  \n        img.alt = 'Logo Decalcer';  \n        img.className = 'w-auto cursor-pointer';   \n        img.style.height = '32px';  \n        img.style.maxHeight = '32px';  \n        img.onerror = function() { this.src = 'https:\/\/placehold.co\/96x24\/cbd5e1\/ffffff?text=LOGO'; };  \n        logoCont.appendChild(img);  \n    }  \n  \n    function getEl(id) { return document.getElementById(id); }  \n  \n    function populateSizeSelects() {  \n        const selects = [getEl('job-size'), getEl('edit-job-size')];  \n        const html = VALID_SIZES.map(s => '<option value=\"' + s + '\">' + s + '<\/option>').join('');  \n        selects.forEach(sel => { if(sel) sel.innerHTML = html; });  \n    }  \n  \n    function startApp() {  \n        if (typeof firebase === 'undefined') {  \n            const loader = getEl('app-loading-indicator');  \n            if(loader) loader.innerHTML = '<span class=\"text-rose-500 font-bold text-sm\">Erro de liga\u00e7\u00e3o. O seu bloqueador de an\u00fancios pode estar a impedir a base de dados. Recarregue a p\u00e1gina.<\/span>';  \n            return;  \n        }  \n  \n        try {  \n            let conf = YOUR_FIREBASE_CONFIG;  \n            if (typeof __firebase_config !== 'undefined' && __firebase_config) {  \n                try { conf = JSON.parse(__firebase_config); } catch(e) {}  \n            }  \n            if (!firebase.apps.length) firebase.initializeApp(conf);  \n            db = firebase.firestore();  \n            auth = firebase.auth();  \n  \n            const loader = getEl('app-loading-indicator');  \n            const main = getEl('main-interface');  \n            if(loader) loader.style.display = 'none';  \n            if(main) main.classList.remove('hidden');  \n  \n            populateSizeSelects();  \n            initAuthLogic();  \n            setupKanbanColumns();  \n  \n            const savedView = localStorage.getItem('decalcer_view_mode');  \n            if(savedView === 'kanban') toggleViewMode('kanban');  \n            else toggleViewMode('list');  \n  \n        } catch(error) {  \n            console.error(\"Erro Cr\u00edtico no Firebase:\", error);  \n            const loader = getEl('app-loading-indicator');  \n            if(loader) loader.innerHTML = '<span class=\"text-rose-500 font-bold text-sm\">Erro interno: ' + error.message + '<\/span>';  \n        }  \n    }  \n  \n    function initAuthLogic() {  \n        auth.onAuthStateChanged((user) => {  \n            currentUser = user;  \n            updateAuthUI();  \n            if (user) {  \n                setupDataListeners();  \n                initMaterialSystem();  \n                toggleLightbox('login-modal', false);  \n            } else {  \n                jobs = []; clients = []; formulas = []; orcamentos = [];  \n                if(getEl('job-count')) getEl('job-count').textContent = 0;  \n                if(getEl('jobs-list')) getEl('jobs-list').innerHTML = '';   \n                if(getEl('no-jobs')) getEl('no-jobs').classList.remove('hidden');  \n                if(getEl('no-jobs').querySelector('p')) getEl('no-jobs').querySelector('p').textContent = \"Por favor, inicie sess\u00e3o para ver os dados.\";  \n                if(getEl('stats-dashboard')) getEl('stats-dashboard').classList.add('hidden');  \n                clearKanbanBoard();  \n            }  \n        });  \n    }  \n  \n    setTimeout(startApp, 200);  \n  \n    \/\/ ==========================================  \n    \/\/ L\u00d3GICA VISTA KANBAN (BOARD)  \n    \/\/ ==========================================  \n  \n    function toggleViewMode(mode) {  \n        currentViewMode = mode;  \n        localStorage.setItem('decalcer_view_mode', mode);  \n  \n        const btnList = getEl('btn-view-list');  \n        const btnKanban = getEl('btn-view-kanban');  \n        const listContainer = getEl('jobs-list');  \n        const kanbanContainer = getEl('kanban-board');  \n  \n        if(mode === 'kanban') {  \n            btnKanban.classList.add('bg-white', 'shadow-sm', 'text-indigo-600');  \n            btnKanban.classList.remove('text-slate-400', 'bg-transparent');  \n            btnList.classList.add('text-slate-400', 'bg-transparent');  \n            btnList.classList.remove('bg-white', 'shadow-sm', 'text-indigo-600');  \n            listContainer.classList.add('hidden');  \n            if(jobs.length > 0) kanbanContainer.classList.remove('hidden');  \n        } else {  \n            btnList.classList.add('bg-white', 'shadow-sm', 'text-indigo-600');  \n            btnList.classList.remove('text-slate-400', 'bg-transparent');  \n            btnKanban.classList.add('text-slate-400', 'bg-transparent');  \n            btnKanban.classList.remove('bg-white', 'shadow-sm', 'text-indigo-600');  \n            kanbanContainer.classList.add('hidden');  \n            if(jobs.length > 0) listContainer.classList.remove('hidden');  \n        }  \n  \n        performSearch();  \n    }  \n  \n    getEl('btn-view-list').addEventListener('click', () => toggleViewMode('list'));  \n    getEl('btn-view-kanban').addEventListener('click', () => toggleViewMode('kanban'));  \n  \n    function setupKanbanColumns() {  \n        const board = getEl('kanban-board');  \n        board.innerHTML = '';  \n          \n        KANBAN_COLUMNS.forEach(status => {  \n            let colorHeader = 'bg-slate-200 text-slate-700';  \n            let dotColor = 'bg-slate-400';  \n              \n            if(status === 'Aberto') { colorHeader = 'bg-sky-100 text-sky-800'; dotColor = 'bg-sky-500'; }  \n            if(status === 'Em Progresso') { colorHeader = 'bg-blue-100 text-blue-800'; dotColor = 'bg-blue-500'; }  \n            if(status === 'Concluido' || status === 'Conclu\u00eddo') { colorHeader = 'bg-emerald-100 text-emerald-800'; dotColor = 'bg-emerald-500'; }  \n            if(status === 'Sem Or\u00e7amento') { colorHeader = 'bg-slate-200 text-slate-800'; dotColor = 'bg-slate-500'; }  \n  \n            const colWrapper = document.createElement('div');  \n            colWrapper.className = \"kanban-column-container w-80 flex-shrink-0 flex flex-col h-full\";  \n            colWrapper.innerHTML = `  \n                <div class=\"flex items-center justify-between mb-3 px-1\">  \n                    <h3 class=\"text-sm font-bold flex items-center gap-2 text-slate-700\">  \n                        <span class=\"w-2.5 h-2.5 rounded-full ${dotColor}\"><\/span>  \n                        ${status}  \n                    <\/h3>  \n                    <span class=\"text-xs font-bold px-2 py-0.5 rounded-full ${colorHeader} col-counter\" data-status=\"${status}\">0<\/span>  \n                <\/div>  \n                <div class=\"kanban-column bg-slate-100 rounded-2xl p-3 flex-1 flex flex-col gap-3 border-2 border-transparent\" data-status=\"${status}\">  \n                <\/div>  \n            `;  \n            board.appendChild(colWrapper);  \n              \n            const columnEl = colWrapper.querySelector('.kanban-column');  \n            columnEl.addEventListener('dragover', handleDragOver);  \n            columnEl.addEventListener('dragenter', handleDragEnter);  \n            columnEl.addEventListener('dragleave', handleDragLeave);  \n            columnEl.addEventListener('drop', handleDrop);  \n        });  \n    }  \n  \n    function clearKanbanBoard() {  \n        document.querySelectorAll('.kanban-column').forEach(col => col.innerHTML = '');  \n        document.querySelectorAll('.col-counter').forEach(cnt => cnt.textContent = '0');  \n    }  \n  \n    function handleDragStart(e) {  \n        if(!currentUser || currentUser.isAnonymous) {  \n            e.preventDefault();  \n            showToast('Precisa fazer login para alterar estados.', 'error');  \n            return;  \n        }  \n        draggedJobId = this.getAttribute('data-id');  \n        e.dataTransfer.effectAllowed = 'move';  \n        setTimeout(() => this.classList.add('is-dragging'), 0);  \n    }  \n  \n    function handleDragEnd(e) {  \n        this.classList.remove('is-dragging');  \n        document.querySelectorAll('.kanban-column').forEach(col => col.classList.remove('drag-over'));  \n        draggedJobId = null;  \n    }  \n  \n    function handleDragOver(e) {  \n        e.preventDefault();   \n        e.dataTransfer.dropEffect = 'move';  \n        return false;  \n    }  \n  \n    function handleDragEnter(e) {  \n        e.preventDefault();  \n        if(draggedJobId) this.classList.add('drag-over');  \n    }  \n  \n    function handleDragLeave(e) {  \n        this.classList.remove('drag-over');  \n    }  \n  \n    function handleDrop(e) {  \n        e.stopPropagation();  \n        this.classList.remove('drag-over');  \n          \n        const newStatus = this.getAttribute('data-status');  \n        if (draggedJobId && newStatus) {  \n            const job = jobs.find(j => j.id === draggedJobId);  \n            if (job && job.status !== newStatus) {  \n                const card = document.querySelector(`.kanban-card[data-id=\"${draggedJobId}\"]`);  \n                if(card) this.appendChild(card);  \n                  \n                getCollectionRef('trabalhos').doc(draggedJobId).update({ status: newStatus })  \n                    .then(() => showToast(`Estado movido para ${newStatus}`, 'info'))  \n                    .catch(err => { showToast('Erro ao mover', 'error'); performSearch(); });  \n            }  \n        }  \n        return false;  \n    }  \n  \n    \/\/ ==========================================  \n    \/\/ L\u00d3GICA DE GEST\u00c3O DE ETIQUETAS  \n    \/\/ ==========================================  \n  \n    function updateLabelBtnUI(btnId, data) {  \n        const btn = getEl(btnId);  \n        if (!btn) return;  \n        if (data && Object.keys(data).length > 0) {  \n            btn.classList.replace('bg-white', 'bg-pink-100');  \n            btn.classList.add('border-pink-300');  \n            btn.textContent = 'Etiquetas Conf... \u2713';  \n        } else {  \n            btn.classList.replace('bg-pink-100', 'bg-white');  \n            btn.classList.remove('border-pink-300');  \n            btn.textContent = 'Configurar Etiquetas';  \n        }  \n    }  \n  \n    function openLabelConfigModal(context) {  \n        currentLabelContext = context;  \n        let data = context === 'create' ? currentLabelDataCreate : currentLabelDataEdit;  \n  \n        if (!data) {  \n            const refEl = context === 'create' ? getEl('job-reference') : getEl('edit-job-reference');  \n            const cliEl = context === 'create' ? getEl('job-client') : getEl('edit-job-client');  \n            const qtyEl = context === 'create' ? getEl('job-sheets') : getEl('edit-job-sheets');  \n            const dateEl = context === 'create' ? getEl('job-date') : getEl('edit-job-date');  \n  \n            const ref = refEl ? refEl.value : '';  \n            const cli = cliEl ? cliEl.value : '';  \n  \n            data = {  \n                descricao: (cli && ref) ? `${cli} - ${ref}` : ref,  \n                codigo: ref.replace(\/\\D\/g, '').padEnd(13, '0').substring(0, 13),  \n                quantidade: qtyEl ? qtyEl.value : 1,  \n                lote: `LT-${new Date().getFullYear()}${(new Date().getMonth()+1).toString().padStart(2,'0')}`,  \n                dataEnvio: dateEl && dateEl.value ? dateEl.value : new Date().toISOString().split('T')[0]  \n            };  \n        }  \n  \n        getEl('label-desc').value = data.descricao || '';  \n        getEl('label-code').value = data.codigo || '';  \n        getEl('label-qty').value = data.quantidade || '';  \n        getEl('label-date').value = data.dataEnvio || '';  \n        getEl('label-lote').value = data.lote || '';  \n  \n        toggleLightbox('label-config-modal', true);  \n    }  \n  \n    getEl('btn-open-label-config-add').addEventListener('click', () => openLabelConfigModal('create'));  \n    getEl('btn-open-label-config-edit').addEventListener('click', () => openLabelConfigModal('edit'));  \n  \n    getEl('label-config-form').addEventListener('submit', (e) => {  \n        e.preventDefault();  \n        const data = {  \n            descricao: getEl('label-desc').value.trim(),  \n            codigo: getEl('label-code').value.trim(),  \n            quantidade: parseInt(getEl('label-qty').value) || 1,  \n            dataEnvio: getEl('label-date').value,  \n            lote: getEl('label-lote').value.trim()  \n        };  \n  \n        if (currentLabelContext === 'create') {  \n            currentLabelDataCreate = data;  \n            updateLabelBtnUI('btn-open-label-config-add', currentLabelDataCreate);  \n        } else {  \n            currentLabelDataEdit = data;  \n            updateLabelBtnUI('btn-open-label-config-edit', currentLabelDataEdit);  \n        }  \n  \n        toggleLightbox('label-config-modal', false);  \n        showToast('Etiquetas configuradas localmente.');  \n    });  \n  \n    getEl('btn-clear-labels').addEventListener('click', () => {  \n        if (currentLabelContext === 'create') {  \n            currentLabelDataCreate = null;  \n            updateLabelBtnUI('btn-open-label-config-add', null);  \n        } else {  \n            currentLabelDataEdit = null;  \n            updateLabelBtnUI('btn-open-label-config-edit', null);  \n        }  \n        toggleLightbox('label-config-modal', false);  \n        showToast('Configura\u00e7\u00e3o de etiquetas reposta para padr\u00e3o.', 'info');  \n    });  \n  \n    getEl('btn-close-label-modal').addEventListener('click', () => {  \n        toggleLightbox('label-config-modal', false);  \n    });  \n  \n    \/\/ ==========================================  \n    \/\/ OUTRAS FUN\u00c7\u00d5ES CORE  \n    \/\/ ==========================================  \n  \n    function createColorRowHTML(mode, index, data = {}) {  \n        const name = data.name || '';  \n        const temp = data.temperature || '';  \n        const comp = data.composition || '';  \n        const hasVariant = data.isContraTipo && data.alternatives && data.alternatives.length > 0;  \n        const btnClass = hasVariant ? '' : 'hidden';  \n  \n        return '<div class=\"color-row group relative bg-white border border-slate-200 p-3 rounded-xl shadow-sm transition-all hover:border-indigo-300\" data-index=\"' + index + '\">' +  \n               '<button type=\"button\" class=\"btn-remove-row absolute -top-2 -right-2 bg-white text-rose-400 border border-slate-200 rounded-full w-6 h-6 flex items-center justify-center shadow-sm hover:text-rose-600 hover:border-rose-300 cursor-pointer z-10\" onclick=\"this.closest(\\'.color-row\\').remove()\">' +  \n               '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"\/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"\/><\/svg>' +  \n               '<\/button>' +  \n               '<div class=\"flex flex-col sm:flex-row gap-3\">' +  \n               '<div class=\"w-full sm:w-1\/3 relative\">' +  \n               '<input type=\"text\" class=\"color-name-input w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm font-semibold focus:bg-white transition-colors\" placeholder=\"Nome da Cor\" list=\"color-suggestions\" value=\"' + name + '\">' +  \n               '<button type=\"button\" class=\"btn-var-trigger ' + btnClass + ' absolute right-1 top-1\/2 -translate-y-1\/2 text-indigo-500 hover:text-indigo-700 p-1 bg-indigo-50 rounded-md hover:bg-indigo-100 transition-colors border-none cursor-pointer\">' +  \n               '<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 3v12\"\/><circle cx=\"18\" cy=\"6\" r=\"3\"\/><circle cx=\"6\" cy=\"18\" r=\"3\"\/><path d=\"M18 9a9 9 0 0 1-9 9\"\/><\/svg>' +  \n               '<\/button><\/div>' +  \n               '<div class=\"w-full sm:w-20\"><input type=\"text\" class=\"color-temp-input w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm text-center focus:bg-white transition-colors\" placeholder=\"Temp\" list=\"temp-suggestions\" value=\"' + temp + '\"><\/div>' +  \n               '<div class=\"w-full flex-1\"><input type=\"text\" class=\"color-comp-input w-full p-2 bg-slate-50 border border-slate-200 rounded-lg text-sm focus:bg-white transition-colors\" placeholder=\"Composi\u00e7\u00e3o...\" value=\"' + comp + '\"><\/div>' +  \n               '<\/div><\/div>';  \n    }  \n  \n    function addColorRow(containerId, mode, data = {}) {  \n        const container = getEl(containerId);  \n        const index = Date.now() + Math.random().toString().slice(2,5);  \n        const div = document.createElement('div');  \n        div.innerHTML = createColorRowHTML(mode, index, data);  \n        const row = div.firstElementChild;  \n        container.appendChild(row);  \n  \n        const nameInput = row.querySelector('.color-name-input');  \n        const tempInput = row.querySelector('.color-temp-input');  \n        const compInput = row.querySelector('.color-comp-input');  \n        const btnVar = row.querySelector('.btn-var-trigger');  \n          \n        nameInput.addEventListener('input', function() { checkColorMatch(this, tempInput, compInput, btnVar); });  \n          \n        if(btnVar) {  \n             btnVar.onclick = () => {  \n                 const match = formulas.find(f => f.name.toLowerCase() === nameInput.value.trim().toLowerCase());  \n                 if(match) openVariantSelectionModal(match, tempInput, compInput);  \n             }  \n        }  \n    }  \n  \n    function checkColorMatch(inputEl, tempEl, compEl, btnVarEl) {  \n        const val = inputEl.value.trim();  \n        if(!val) { if(btnVarEl) btnVarEl.classList.add('hidden'); return; }  \n        const match = formulas.find(f => f.name.toLowerCase() === val.toLowerCase());  \n        if(match) {  \n            const mainComp = match.composition || match.comp || '';  \n            if(!compEl.value) compEl.value = mainComp;  \n            if(!tempEl.value) tempEl.value = match.temperature || '';  \n            if(match.isContraTipo && match.alternatives && match.alternatives.length > 0) {  \n                if(btnVarEl) btnVarEl.classList.remove('hidden');  \n            } else {  \n                if(btnVarEl) btnVarEl.classList.add('hidden');  \n            }  \n        } else {  \n            if(btnVarEl) btnVarEl.classList.add('hidden');  \n        }  \n    }  \n  \n    function collectColorData(containerId) {  \n        const rows = getEl(containerId).querySelectorAll('.color-row');  \n        const colors = [];  \n        rows.forEach(row => {  \n            const n = row.querySelector('.color-name-input').value.trim();  \n            const t = row.querySelector('.color-temp-input').value.trim();  \n            const c = row.querySelector('.color-comp-input').value.trim();  \n            if(n || c) colors.push({ name: n, temperature: t, composition: c });  \n        });  \n        return colors;  \n    }  \n      \n     function openVariantSelectionModal(colorData, tempEl, compEl) {  \n        const list = getEl('variant-options-list');  \n        list.innerHTML = '';   \n        const applyVariant = (compTxt, tempTxt) => {  \n            if(compEl) {  \n                compEl.value = compTxt || '';  \n                compEl.style.backgroundColor = '#ecfdf5';   \n                setTimeout(() => compEl.style.backgroundColor = '', 400);  \n            }  \n            if(tempEl && tempTxt) tempEl.value = tempTxt;  \n            toggleLightbox('variant-selection-modal', false);  \n        };  \n        const mainComp = colorData.composition || colorData.comp || '';   \n        const originalBtn = document.createElement('div');  \n        originalBtn.className = \"p-3 border border-slate-200 rounded-xl hover:bg-indigo-50 cursor-pointer transition-colors group\";  \n        originalBtn.innerHTML = '<div class=\"font-bold text-slate-700 text-sm mb-1\">Original<\/div><div class=\"text-xs text-slate-500\">' + mainComp + '<\/div>';  \n        originalBtn.onclick = () => applyVariant(mainComp, colorData.temperature);  \n        list.appendChild(originalBtn);  \n        if (colorData.alternatives) {  \n            colorData.alternatives.forEach(alt => {  \n                const altBtn = document.createElement('div');  \n                altBtn.className = \"p-3 border border-slate-200 rounded-xl hover:bg-pink-50 cursor-pointer transition-colors group\";  \n                altBtn.innerHTML = '<div class=\"font-bold text-slate-700 text-sm mb-1\">' + alt.description + '<\/div><div class=\"text-xs text-slate-500\">' + alt.composition + '<\/div>';  \n                altBtn.onclick = () => applyVariant(alt.composition, colorData.temperature);  \n                list.appendChild(altBtn);  \n            });  \n        }  \n        toggleLightbox('variant-selection-modal', true);  \n    }  \n  \n    function toggleLightbox(id, show) {  \n        const el = getEl(id);  \n        if(el) {  \n            if(show) {  \n                el.classList.remove('lightbox-hidden');  \n                if(el.firstElementChild && el.id !== 'lightbox-modal') {  \n                    el.firstElementChild.style.opacity = '0';  \n                    setTimeout(() => {  \n                        el.firstElementChild.style.transition = 'opacity 0.2s ease-out';  \n                        el.firstElementChild.style.opacity = '1';  \n                    }, 10);  \n                }  \n            } else {  \n                el.classList.add('lightbox-hidden');  \n            }  \n        }  \n    }  \n  \n    function updateAuthUI() {  \n        const warning = getEl('login-warning');  \n        const content = getEl('app-content');  \n        const matContent = getEl('material-content');  \n        const btn = getEl('btn-login-trigger');  \n        const info = getEl('user-info-display');  \n        const colorBtn = getEl('btn-colors-trigger');   \n        const settingsBtn = getEl('btn-settings-trigger');   \n  \n        const isOfficialUser = currentUser && !currentUser.isAnonymous && currentUser.email;  \n        const currentTab = getEl('tab-materiais').classList.contains('nav-tab-active') ? 'materiais' : 'trabalhos';  \n  \n        if (isOfficialUser) {  \n            if(warning) warning.classList.add('hidden');  \n            \/\/ S\u00f3 mostra o que corresponde \u00e0 tab atual  \n            if(currentTab === 'trabalhos') {  \n                 if(content) content.classList.remove('hidden');  \n                 if(matContent) matContent.classList.add('hidden');  \n            } else {  \n                 if(content) content.classList.add('hidden');  \n                 if(matContent) matContent.classList.remove('hidden');  \n            }  \n            if(colorBtn) colorBtn.classList.remove('hidden');   \n            if(settingsBtn) settingsBtn.classList.remove('hidden');   \n              \n            if(btn) {  \n                btn.textContent = \"Sair\";  \n                btn.classList.remove('bg-slate-800', 'text-white');  \n                btn.classList.add('bg-rose-50', 'text-rose-600', 'hover:bg-rose-100');  \n            }  \n            if(info) info.textContent = currentUser.email;  \n        } else {  \n            if(warning) warning.classList.remove('hidden');  \n            if(content) content.classList.remove('hidden');   \n            if(matContent) matContent.classList.add('hidden');  \n            if(colorBtn) colorBtn.classList.add('hidden');   \n            if(settingsBtn) settingsBtn.classList.add('hidden');   \n            if(btn) {  \n                btn.textContent = \"Login\";  \n                btn.classList.add('bg-slate-800', 'text-white');  \n                btn.classList.remove('bg-rose-50', 'text-rose-600', 'hover:bg-rose-100');  \n            }  \n            if(info) info.textContent = \"\";  \n        }  \n    }  \n  \n    function getCollectionRef(name) {  \n        return db.collection('artifacts\/' + appId + '\/public\/data\/' + name);  \n    }  \n  \n    function setupDataListeners() {  \n        if (!currentUser) return;  \n  \n        getCollectionRef('trabalhos').onSnapshot(snapshot => {  \n              jobs = [];  \n              snapshot.forEach(doc => jobs.push(Object.assign({ id: doc.id }, doc.data())));  \n              jobs.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));  \n              const countEl = getEl('job-count');  \n              if(countEl) countEl.textContent = jobs.length;  \n              performSearch();  \n          }, error => {  \n              console.warn(\"Aviso Leitura Trabalhos:\", error);  \n          });  \n            \n        getCollectionRef('clientes').onSnapshot(snapshot => {  \n              clients = [];  \n              snapshot.forEach(doc => clients.push(Object.assign({ id: doc.id }, doc.data())));  \n              clients.sort((a, b) => (a.name || '').localeCompare(b.name || ''));  \n          }, error => console.warn(\"Erro permiss\u00e3o clientes\"));  \n  \n        getCollectionRef('formulas_cores').onSnapshot(snapshot => {  \n              formulas = [];  \n              snapshot.forEach(doc => formulas.push(Object.assign({ id: doc.id }, doc.data())));  \n              formulas.sort((a, b) => (a.name || '').localeCompare(b.name || ''));  \n              updateDatalist();   \n          }, error => console.warn(\"Erro permiss\u00e3o cores\"));  \n  \n        getCollectionRef('orcamentos').onSnapshot(snapshot => {  \n              orcamentos = [];  \n              snapshot.forEach(doc => orcamentos.push(Object.assign({ id: doc.id }, doc.data())));  \n              performSearch();   \n          }, error => console.warn(\"Erro permiss\u00e3o or\u00e7amentos\"));  \n    }  \n  \n    function updateDatalist() {  \n        const dl = getEl('color-suggestions');  \n        if(!dl) return;  \n        dl.innerHTML = '';  \n        formulas.forEach(f => {  \n            const opt = document.createElement('option');  \n            opt.value = f.name;  \n            dl.appendChild(opt);  \n        });  \n    }  \n  \n    function buildCardHtml(job, isKanban = false) {  \n        let currentStatus = job.status === 'Arquivado' ? 'Sem Or\u00e7amento' : (job.status || 'Aberto');  \n          \n        let statusBadgeClass = \"bg-slate-100 text-slate-600\";  \n        if(currentStatus === 'Aberto') statusBadgeClass = \"bg-sky-100 text-sky-700\";  \n        else if(currentStatus === 'Em Progresso') statusBadgeClass = \"bg-blue-100 text-blue-700\";  \n        else if(currentStatus === 'Concluido' || currentStatus === 'Conclu\u00eddo') statusBadgeClass = \"bg-emerald-100 text-emerald-700\";  \n        else if(currentStatus === 'Sem Or\u00e7amento') statusBadgeClass = \"bg-slate-200 text-slate-800\";  \n  \n        let typeBadge = '';  \n        const jType = job.type || 'Produ\u00e7\u00e3o';  \n        if(jType === 'Ensaio') {  \n            typeBadge = '<span class=\"inline-block px-2.5 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider bg-amber-100 text-amber-700 mb-2 mr-2\">Ensaio<\/span>';  \n        }  \n  \n        const isApproved = orcamentos.some(q =>   \n            ((q.reference === job.reference || q.nome === job.reference || q.name === job.reference) ||   \n             (job.numeroRegisto && (q.reference === job.numeroRegisto || q.nome === job.numeroRegisto || q.name === job.numeroRegisto))) &&  \n            (q.status === 'Aprovado' || q.status === 'Adjudicado' || q.status === 'Aceite')  \n        );  \n  \n        let quoteBadge = isApproved ? '<span class=\"inline-flex items-center gap-1 px-2 py-0.5 rounded border border-emerald-200 bg-emerald-50 text-emerald-700 text-[10px] font-bold uppercase tracking-wider mb-2 mr-2 shadow-sm\" title=\"Or\u00e7amento Aprovado na aplica\u00e7\u00e3o de Or\u00e7amentos\"><svg class=\"w-3 h-3\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"><\/path><\/svg> Or\u00e7amento \u2713<\/span>' : '';  \n  \n        let colorsHtml = '';  \n        if (Array.isArray(job.colors) && job.colors.length > 0) {  \n            const badges = job.colors.slice(0, isKanban ? 3 : 5).map(c => '<span class=\"text-[10px] text-slate-500 bg-slate-50 border border-slate-100 px-1.5 py-0.5 rounded-md flex items-center truncate max-w-full\" title=\"'+c.name+'\">' + c.name + '<\/span>').join('');  \n            const more = job.colors.length > (isKanban ? 3 : 5) ? '<span class=\"text-[10px] text-slate-400 pl-1\">+' + (job.colors.length - (isKanban ? 3 : 5)) + '<\/span>' : '';  \n            colorsHtml = '<div class=\"mt-3 flex flex-wrap gap-1.5 items-center w-full\">' + badges + more + '<\/div>';  \n        }  \n  \n        const editBtnHtml = '<button class=\"btn-open-card p-1.5 bg-white text-slate-600 rounded-full shadow-sm hover:bg-slate-50 transition-colors cursor-pointer\" data-id=\"' + job.id + '\" title=\"Editar\"><svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z\"\/><\/svg><\/button>';  \n        const imgBtnHtml = job.imageUrl ? '<button class=\"btn-view-image-card p-1.5 bg-white text-indigo-600 rounded-full shadow-sm hover:bg-indigo-50 transition-colors cursor-pointer\" data-url=\"' + job.imageUrl + '\" title=\"Ver Imagem\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/svg><\/button>' : '';  \n        const lblBtnHtml = '<button class=\"btn-print-label-card p-1.5 bg-white text-pink-600 rounded-full shadow-sm hover:bg-pink-50 transition-colors cursor-pointer\" data-id=\"' + job.id + '\" title=\"Imprimir Etiquetas\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\"><\/path><\/svg><\/button>';  \n  \n        let cardClass = isKanban   \n            ? `kanban-card bg-white rounded-xl shadow-sm border ${isApproved ? 'border-emerald-300 ring-1 ring-emerald-100' : 'border-slate-200 hover:border-indigo-300'} cursor-grab active:cursor-grabbing transition-colors group flex flex-col relative w-full`  \n            : `bg-white rounded-2xl shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300 border ${isApproved ? 'border-emerald-300 ring-1 ring-emerald-50' : 'border-slate-100'} group flex flex-col h-full overflow-hidden relative w-full`;  \n  \n        return `<div class=\"${cardClass}\" draggable=\"${isKanban ? 'true' : 'false'}\" data-id=\"${job.id}\">  \n            <div class=\"absolute top-0 right-0 p-3 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1 z-10 bg-gradient-to-l from-white via-white to-transparent pl-4\">  \n                ${imgBtnHtml}  \n                ${lblBtnHtml}  \n                ${editBtnHtml}  \n            <\/div>  \n            <div class=\"p-${isKanban ? '4' : '5'} flex-1 cursor-pointer btn-open-card-area min-w-0 overflow-hidden flex flex-col\" data-id=\"${job.id}\">  \n                <div class=\"flex justify-between items-start mb-2 w-full min-w-0\">  \n                    <div class=\"min-w-0 flex-1\">  \n                        ${typeBadge}  \n                        ${quoteBadge}  \n                        ${!isKanban ? `<span class=\"inline-block px-2.5 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider ${statusBadgeClass} mb-2\">${currentStatus}<\/span>` : ''}  \n                          \n                        <div class=\"flex items-center gap-2 w-full\">  \n                            ${job.numeroRegisto ? `<span class=\"text-[10px] font-mono font-bold text-slate-500 bg-slate-100 px-1.5 py-0.5 rounded border border-slate-200 shrink-0\">#${job.numeroRegisto}<\/span>` : ''}  \n                            <h3 class=\"text-${isKanban ? 'base' : 'lg'} font-bold text-slate-800 m-0 leading-tight truncate block\" title=\"${job.reference || '-'}\">${job.reference || '-'}<\/h3>  \n                        <\/div>  \n                    <\/div>  \n                <\/div>  \n                <div class=\"space-y-1.5 mb-2 w-full min-w-0 flex-1 mt-1\">  \n                    <div class=\"flex items-center text-${isKanban ? 'xs' : 'sm'} text-slate-600 font-medium truncate w-full\" title=\"${job.client || '?'}\">${job.client || '?'}<\/div>  \n                    <div class=\"flex items-center text-${isKanban ? 'xs' : 'sm'} text-slate-500 w-full truncate\">  \n                        <span class=\"font-bold text-slate-700 mr-1\">${job.sheets}<\/span>  \n                        <span class=\"text-[10px] text-slate-400 truncate\">(${job.sheetSize || 'S\/ Tam'})<\/span>  \n                    <\/div>  \n                <\/div>  \n                ${job.observations ? `<p class=\"text-[11px] text-slate-400 italic line-clamp-2 border-l-2 border-slate-100 pl-2 mt-2 break-words w-full\" title=\"${job.observations}\">${job.observations}<\/p>` : ''}  \n                ${colorsHtml}  \n            <\/div>  \n            ${job.imageUrl && !isKanban ? '<div class=\"h-1 bg-indigo-500 w-full flex-shrink-0\"><\/div>' : ''}  \n        <\/div>`;  \n    }  \n  \n    function bindCardEvents(containerElement) {  \n        containerElement.querySelectorAll('.btn-open-card, .btn-open-card-area').forEach(btn => {  \n            btn.addEventListener('click', (e) => {  \n                e.stopPropagation();  \n                openEditLightbox(btn.getAttribute('data-id'));  \n            });  \n        });  \n  \n        containerElement.querySelectorAll('.btn-view-image-card').forEach(btn => {  \n            btn.addEventListener('click', (e) => {  \n                e.stopPropagation();  \n                const url = btn.getAttribute('data-url');  \n                if(url) openLightbox(url);  \n            });  \n        });  \n  \n        containerElement.querySelectorAll('.btn-print-label-card').forEach(btn => {  \n            btn.addEventListener('click', (e) => {  \n                e.stopPropagation();  \n                const id = btn.getAttribute('data-id');  \n                const job = jobs.find(j => j.id === id);  \n                if(job) abrirModalEtiquetas(job);  \n            });  \n        });  \n          \n        if(currentViewMode === 'kanban') {  \n            containerElement.querySelectorAll('.kanban-card').forEach(card => {  \n                card.addEventListener('dragstart', handleDragStart);  \n                card.addEventListener('dragend', handleDragEnd);  \n            });  \n        }  \n    }  \n  \n  \n    function performSearch() {  \n        if (!currentUser) return;  \n        const searchVal = getEl('search-input') ? getEl('search-input').value.toLowerCase().trim() : '';  \n        const filterVal = getEl('filter-status') ? getEl('filter-status').value : 'Todos';  \n        const typeVal = getEl('filter-type') ? getEl('filter-type').value : 'Todos';  \n          \n        const filtered = jobs.filter(job => {  \n            if (!job) return false;  \n            let matchesSearch = false;  \n            if (searchVal === '') matchesSearch = true;  \n            else {  \n                const ref = (job.reference || '').toLowerCase();  \n                const idNum = (job.numeroRegisto || '').toLowerCase();  \n                const cli = (job.client || '').toLowerCase();  \n                const obs = (job.observations || '').toLowerCase();  \n                  \n                if (ref.includes(searchVal) || idNum.includes(searchVal) || cli.includes(searchVal) || obs.includes(searchVal)) matchesSearch = true;  \n                if (!matchesSearch && job.colors && Array.isArray(job.colors)) {  \n                    matchesSearch = job.colors.some(c =>   \n                        (c && c.name && c.name.toLowerCase().includes(searchVal)) ||   \n                        (c && c.composition && c.composition.toLowerCase().includes(searchVal))  \n                    );  \n                }  \n            }  \n  \n            const isApproved = orcamentos.some(q =>   \n                ((q.reference === job.reference || q.nome === job.reference || q.name === job.reference) ||   \n                 (job.numeroRegisto && (q.reference === job.numeroRegisto || q.nome === job.numeroRegisto || q.name === job.numeroRegisto))) &&  \n                (q.status === 'Aprovado' || q.status === 'Adjudicado' || q.status === 'Aceite')  \n            );  \n  \n            const status = job.status === 'Arquivado' ? 'Sem Or\u00e7amento' : (job.status || 'Desconhecido');  \n            const jType = job.type || 'Produ\u00e7\u00e3o';  \n              \n            let statusMatch = false;  \n            if (filterVal === 'Todos') {  \n                statusMatch = true;  \n            } else if (filterVal === 'Sem Or\u00e7amento') {  \n                statusMatch = !isApproved || status === 'Sem Or\u00e7amento';  \n            } else {  \n                statusMatch = (status === filterVal);  \n            }  \n              \n            return matchesSearch && statusMatch && (typeVal === 'Todos' || jType === typeVal);  \n        });  \n          \n        if (filtered.length > 0) {  \n            getEl('stats-dashboard').classList.remove('hidden');  \n            const sizeTotals = {};  \n            VALID_SIZES.forEach(s => sizeTotals[s] = 0);  \n            let grandTotal = 0;  \n              \n            filtered.forEach(job => {  \n                const qty = (parseInt(job.sheets) || 0);  \n                grandTotal += qty;  \n                if (job.sheetSize && sizeTotals[job.sheetSize] !== undefined) {  \n                    sizeTotals[job.sheetSize] += qty;  \n                }  \n            });  \n              \n            getEl('total-sheets-badge').textContent = grandTotal + ' Folhas';  \n            const statsCont = getEl('stats-container');  \n            statsCont.innerHTML = '';  \n              \n            const maxVal = Math.max(...Object.values(sizeTotals));  \n  \n            Object.keys(sizeTotals).forEach(size => {  \n                const count = sizeTotals[size];  \n                const percentage = maxVal > 0 ? (count \/ maxVal) * 100 : 0;  \n                const isZero = count === 0;  \n                  \n                const card = document.createElement('div');  \n                card.className = 'p-3 rounded-xl border flex flex-col justify-between transition-all stat-card-enter ' + (isZero ? 'bg-slate-50 border-slate-100 opacity-60' : 'bg-white border-indigo-100 shadow-sm');  \n                card.innerHTML = '<div class=\"flex justify-between items-end mb-2\">' +  \n                    '<span class=\"text-[10px] font-bold uppercase tracking-wider text-slate-500\">' + size.replace('cm','') + '<\/span>' +  \n                    '<span class=\"text-lg font-bold leading-none ' + (isZero ? 'text-slate-400' : 'text-indigo-600') + '\">' + count + '<\/span>' +  \n                    '<\/div>' +  \n                    '<div class=\"w-full h-1.5 bg-slate-100 rounded-full overflow-hidden\">' +  \n                    '<div class=\"h-full bg-indigo-500 rounded-full transition-all duration-500\" style=\"width: ' + percentage + '%\"><\/div>' +  \n                    '<\/div>';  \n                statsCont.appendChild(card);  \n            });  \n        } else {  \n            getEl('stats-dashboard').classList.add('hidden');  \n        }  \n          \n        const listEl = getEl('jobs-list');  \n        const kanbanEl = getEl('kanban-board');  \n          \n        if (filtered.length === 0) {  \n            listEl.innerHTML = '';  \n            clearKanbanBoard();  \n            getEl('no-jobs').classList.remove('hidden');  \n            listEl.classList.add('hidden');  \n            kanbanEl.classList.add('hidden');  \n            return;  \n        }  \n          \n        getEl('no-jobs').classList.add('hidden');  \n          \n        if (currentViewMode === 'list') {  \n            kanbanEl.classList.add('hidden');  \n            listEl.classList.remove('hidden');  \n              \n            let html = '';  \n            filtered.forEach(job => html += buildCardHtml(job, false));  \n            listEl.innerHTML = html;  \n            bindCardEvents(listEl);  \n              \n        } else {  \n            listEl.classList.add('hidden');  \n            kanbanEl.classList.remove('hidden');  \n            clearKanbanBoard();  \n              \n            const columnsData = {};  \n            KANBAN_COLUMNS.forEach(c => columnsData[c] = { count: 0, html: '' });  \n              \n            filtered.forEach(job => {  \n                const st = job.status === 'Arquivado' ? 'Sem Or\u00e7amento' : (job.status || 'Aberto');  \n                if(columnsData[st]) {  \n                    columnsData[st].count++;  \n                    columnsData[st].html += buildCardHtml(job, true);  \n                }  \n            });  \n              \n            KANBAN_COLUMNS.forEach(st => {  \n                const colEl = kanbanEl.querySelector(`.kanban-column[data-status=\"${st}\"]`);  \n                const counterEl = kanbanEl.querySelector(`.col-counter[data-status=\"${st}\"]`);  \n                if(colEl) {  \n                    colEl.innerHTML = columnsData[st].html;  \n                    bindCardEvents(colEl);  \n                }  \n                if(counterEl) counterEl.textContent = columnsData[st].count;  \n            });  \n        }  \n    }  \n  \n  \n    function renderDonutChart(prodSheets, testSheets) {  \n        const container = getEl('stats-donut-chart-container');  \n        if (!container) return;  \n          \n        const total = prodSheets + testSheets;  \n        if (total === 0) {  \n            container.innerHTML = '<p class=\"text-slate-400 text-xs italic\">Sem dados suficientes<\/p>';  \n            return;  \n        }  \n  \n        const prodPct = (prodSheets \/ total) * 100;  \n        const testPct = (testSheets \/ total) * 100;  \n          \n        const svgHTML = `  \n            <div class=\"flex items-center gap-6 w-full\">  \n                <div class=\"relative w-28 h-28 flex-shrink-0\">  \n                    <svg viewBox=\"0 0 42 42\" class=\"w-full h-full -rotate-90 drop-shadow-sm\">  \n                        <!-- Fundo do donut -->  \n                        <circle cx=\"21\" cy=\"21\" r=\"15.9155\" fill=\"transparent\" stroke=\"#f1f5f9\" stroke-width=\"6\"><\/circle>  \n                        <!-- Fatia: Produ\u00e7\u00e3o (Indigo) -->  \n                        <circle cx=\"21\" cy=\"21\" r=\"15.9155\" fill=\"transparent\" stroke=\"#6366f1\" stroke-width=\"6\"   \n                                stroke-dasharray=\"${prodPct} ${100 - prodPct}\" stroke-dashoffset=\"0\" class=\"donut-segment\"><\/circle>  \n                        <!-- Fatia: Ensaios (Amber) -->  \n                        <circle cx=\"21\" cy=\"21\" r=\"15.9155\" fill=\"transparent\" stroke=\"#f59e0b\" stroke-width=\"6\"   \n                                stroke-dasharray=\"${testPct} ${100 - testPct}\" stroke-dashoffset=\"-${prodPct}\" class=\"donut-segment\"><\/circle>  \n                    <\/svg>  \n                    <!-- Texto no centro -->  \n                    <div class=\"absolute inset-0 flex flex-col items-center justify-center\">  \n                        <span class=\"text-sm font-bold text-slate-800 leading-none\">${total}<\/span>  \n                        <span class=\"text-[9px] uppercase font-bold text-slate-400 mt-0.5\">Folhas<\/span>  \n                    <\/div>  \n                <\/div>  \n                  \n                <!-- Legenda do Gr\u00e1fico -->  \n                <div class=\"flex flex-col gap-3 flex-1\">  \n                    <div class=\"flex items-center justify-between group\">  \n                        <div class=\"flex items-center gap-2\">  \n                            <div class=\"w-3 h-3 rounded-full bg-indigo-500 shadow-sm group-hover:scale-110 transition-transform\"><\/div>  \n                            <span class=\"text-xs font-bold text-slate-600\">Produ\u00e7\u00e3o<\/span>  \n                        <\/div>  \n                        <span class=\"text-sm font-bold text-slate-800\">${prodSheets} <span class=\"text-[10px] text-slate-400 font-normal ml-0.5\">(${prodPct.toFixed(0)}%)<\/span><\/span>  \n                    <\/div>  \n                    <div class=\"flex items-center justify-between group\">  \n                        <div class=\"flex items-center gap-2\">  \n                            <div class=\"w-3 h-3 rounded-full bg-amber-500 shadow-sm group-hover:scale-110 transition-transform\"><\/div>  \n                            <span class=\"text-xs font-bold text-slate-600\">Ensaios<\/span>  \n                        <\/div>  \n                        <span class=\"text-sm font-bold text-slate-800\">${testSheets} <span class=\"text-[10px] text-slate-400 font-normal ml-0.5\">(${testPct.toFixed(0)}%)<\/span><\/span>  \n                    <\/div>  \n                <\/div>  \n            <\/div>  \n        `;  \n          \n        container.innerHTML = svgHTML;  \n    }  \n  \n    function openStatsModal() {  \n        populateStatsClientFilter();   \n        toggleLightbox('stats-modal', true);  \n        calculateStatistics();   \n    }  \n  \n    function populateStatsClientFilter() {  \n        const sel = getEl('stats-client-filter');  \n        if(!sel) return;  \n        const currentVal = sel.value;   \n        sel.innerHTML = '<option value=\"\">Todos os Clientes (Vis\u00e3o Geral)<\/option>';  \n        clients.forEach(c => {  \n            const opt = document.createElement('option');  \n            opt.value = c.name;  \n            opt.textContent = c.name;  \n            sel.appendChild(opt);  \n        });  \n        sel.value = \"\";  \n    }  \n      \n    function calculateStatistics() {  \n        const startInput = getEl('stats-date-start');  \n        const endInput = getEl('stats-date-end');  \n        const clientFilter = getEl('stats-client-filter') ? getEl('stats-client-filter').value : '';  \n        const typeFilter = getEl('stats-type-filter') ? getEl('stats-type-filter').value : 'Todos';  \n  \n        let startDate = startInput.value ? new Date(startInput.value) : null;  \n        let endDate = endInput.value ? new Date(endInput.value) : null;  \n          \n        if (endDate) endDate.setHours(23, 59, 59, 999);  \n  \n        const filteredJobs = jobs.filter(job => {  \n            if (clientFilter && job.client !== clientFilter) return false;  \n              \n            const jType = job.type || 'Produ\u00e7\u00e3o';  \n            if (typeFilter !== 'Todos' && jType !== typeFilter) return false;  \n  \n            if (!job.date) return false;  \n            const jobDate = new Date(job.date);  \n            if (startDate && jobDate < startDate) return false;  \n            if (endDate && jobDate > endDate) return false;  \n            return true;  \n        });  \n  \n        let totalSheets = 0;  \n        let totalColors = 0;  \n          \n        let prodSheets = 0;  \n        let testSheets = 0;  \n  \n        const clientsData = {};  \n        const colorsFreq = {};  \n  \n        filteredJobs.forEach(job => {  \n            const sheets = parseInt(job.sheets) || 0;  \n            const client = job.client || 'Sem Cliente';  \n            const jobColors = Array.isArray(job.colors) ? job.colors : [];  \n            const colorCount = jobColors.length;  \n            const jType = job.type || 'Produ\u00e7\u00e3o';  \n  \n            totalSheets += sheets;  \n            totalColors += colorCount;  \n              \n            if(jType === 'Ensaio') testSheets += sheets;  \n            else prodSheets += sheets;  \n  \n            if (!clientsData[client]) {  \n                clientsData[client] = { jobs: 0, sheets: 0, colorVolume: 0 };  \n            }  \n            clientsData[client].jobs += 1;  \n            clientsData[client].sheets += sheets;  \n            clientsData[client].colorVolume += colorCount;  \n  \n            jobColors.forEach(c => {  \n                if(c.name) {  \n                    const cName = c.name.trim();  \n                    colorsFreq[cName] = (colorsFreq[cName] || 0) + 1;  \n                }  \n            });  \n        });  \n  \n        getEl('stats-total-jobs').textContent = filteredJobs.length;  \n        getEl('stats-total-sheets').textContent = totalSheets;  \n        getEl('stats-total-colors').textContent = totalColors;  \n  \n        renderDonutChart(prodSheets, testSheets);  \n  \n        const tbody = getEl('stats-table-body');  \n        tbody.innerHTML = '';  \n        const sortedClients = Object.keys(clientsData).sort((a, b) => clientsData[b].sheets - clientsData[a].sheets);  \n          \n        if (sortedClients.length === 0) {  \n            tbody.innerHTML = '<tr><td colspan=\"4\" class=\"px-6 py-4 text-center text-slate-400 italic\">Sem dados para os filtros selecionados<\/td><\/tr>';  \n        } else {  \n            sortedClients.forEach(client => {  \n                const data = clientsData[client];  \n                const row = '<tr class=\"hover:bg-slate-50 transition-colors\">' +  \n                    '<td class=\"px-4 sm:px-6 py-4 font-medium\">' + client + '<\/td>' +  \n                    '<td class=\"px-2 sm:px-6 py-4 text-center\">' + data.jobs + '<\/td>' +  \n                    '<td class=\"px-2 sm:px-6 py-4 text-center font-bold text-indigo-600\">' + data.sheets + '<\/td>' +  \n                    '<td class=\"px-2 sm:px-6 py-4 text-center\">' + data.colorVolume + '<\/td>' +  \n                    '<\/tr>';  \n                tbody.innerHTML += row;  \n            });  \n        }  \n  \n        renderVisualChart('stats-chart-clients', sortedClients.slice(0, 5).map(c => ({ label: c, value: clientsData[c].sheets })), 'bg-indigo-500');  \n          \n        const sortedColors = Object.keys(colorsFreq).sort((a, b) => colorsFreq[b] - colorsFreq[a]).slice(0, 5);  \n        renderVisualChart('stats-chart-colors', sortedColors.map(c => ({ label: c, value: colorsFreq[c] })), 'bg-pink-500');  \n    }  \n  \n    function renderVisualChart(containerId, data, colorClass) {  \n        const cont = getEl(containerId);  \n        cont.innerHTML = '';  \n        if (data.length === 0) {  \n            cont.innerHTML = '<p class=\"text-xs text-slate-400 italic\">Sem dados dispon\u00edveis<\/p>';  \n            return;  \n        }  \n        const max = Math.max(...data.map(d => d.value));  \n          \n        data.forEach(item => {  \n            const pct = max > 0 ? (item.value \/ max) * 100 : 0;  \n            const bar = '<div class=\"mb-2\"><div class=\"flex justify-between text-xs mb-1\">' +  \n                '<span class=\"font-medium text-slate-600 truncate pr-2 w-3\/4\">' + item.label + '<\/span>' +  \n                '<span class=\"font-bold text-slate-800\">' + item.value + '<\/span>' +  \n                '<\/div><div class=\"w-full bg-slate-100 rounded-full h-2 overflow-hidden\">' +  \n                '<div class=\"h-full ' + colorClass + ' rounded-full\" style=\"width: ' + pct + '%\"><\/div>' +  \n                '<\/div><\/div>';  \n            cont.innerHTML += bar;  \n        });  \n    }  \n  \n    function openEditLightbox(id) {  \n        const job = jobs.find(j => j.id === id);  \n        if(!job) return;  \n        getEl('edit-job-id').value = id;  \n        if (getEl('edit-job-data-entrega')) getEl('edit-job-data-entrega').value = job.dataEntrega || '';\n        if (getEl('edit-job-desenhador'))   getEl('edit-job-desenhador').value   = job.desenhador  || '';\n        if (getEl('edit-job-temperatura'))  getEl('edit-job-temperatura').value  = job.temperatura || '';\n        getEl('edit-job-numero-registo').value = job.numeroRegisto || 'S\/N';  \n        getEl('edit-job-reference').value = job.reference || '';  \n        getEl('edit-job-client').value = job.client || '';  \n        getEl('edit-job-client-display').textContent = job.client || 'Nenhum';  \n        getEl('edit-job-date').value = job.date || '';  \n        getEl('edit-job-type').value = job.type || 'Produ\u00e7\u00e3o';   \n        getEl('edit-job-sheets').value = job.sheets || 0;  \n        getEl('edit-job-size').value = job.sheetSize || VALID_SIZES[0];  \n        getEl('edit-job-operator').value = job.operator || '';  \n        getEl('edit-job-machine').value = job.machine || '';  \n        getEl('edit-job-image-url').value = job.imageUrl || '';  \n        getEl('edit-job-status').value = job.status === 'Arquivado' ? 'Sem Or\u00e7amento' : (job.status || 'Aberto');  \n        getEl('edit-job-observations').value = job.observations || '';  \n          \n        const cont = getEl('colors-container-edit');  \n        cont.innerHTML = '';  \n        if(job.colors && job.colors.length > 0) {  \n            job.colors.forEach((c, i) => addColorRow('colors-container-edit', 'edit', c));  \n        } else {  \n            addColorRow('colors-container-edit', 'edit');  \n        }  \n  \n        currentLabelDataEdit = job.labelData ? { ...job.labelData } : null;  \n        updateLabelBtnUI('btn-open-label-config-edit', currentLabelDataEdit);  \n          \n        toggleLightbox('edit-lightbox-modal', true);  \n    }  \n  \n    if(getEl('colors-container-add')) addColorRow('colors-container-add', 'add');  \n  \n    getEl('btn-add-color-row-create').addEventListener('click', () => addColorRow('colors-container-add', 'add'));  \n    getEl('btn-add-color-row-edit').addEventListener('click', () => addColorRow('colors-container-edit', 'edit'));  \n    getEl('btn-close-variant-modal').addEventListener('click', () => toggleLightbox('variant-selection-modal', false));  \n  \n    getEl('btn-login-trigger').addEventListener('click', () => {  \n        if(currentUser && !currentUser.isAnonymous && currentUser.email) {  \n            confirmAction('Sair', 'Deseja terminar a sess\u00e3o atual?', 'Sair', 'logout');  \n        } else {  \n            toggleLightbox('login-modal', true);  \n        }  \n    });  \n  \n    getEl('login-form').addEventListener('submit', (e) => {  \n        e.preventDefault();  \n        auth.signInWithEmailAndPassword(getEl('login-email').value, getEl('login-password').value)  \n            .then(() => {  \n                toggleLightbox('login-modal', false);  \n                showToast('Login efetuado com sucesso');  \n            })  \n            .catch((err) => {  \n                let msg = \"Erro desconhecido\";  \n                if (err.code === 'auth\/user-not-found') msg = \"Utilizador n\u00e3o encontrado.\";  \n                else if (err.code === 'auth\/wrong-password') msg = \"Password incorreta.\";  \n                else if (err.code === 'auth\/invalid-email') msg = \"Email inv\u00e1lido.\";  \n                else msg = err.message;  \n                showToast(msg, 'error');  \n                const errEl = getEl('login-error');  \n                if(errEl) { errEl.textContent = msg; errEl.classList.remove('hidden'); }  \n            });  \n    });  \n      \n    getEl('btn-toggle-form').addEventListener('click', () => {  \n         if(!currentUser || currentUser.isAnonymous) {  \n             showToast('Por favor inicie sess\u00e3o para criar trabalhos.', 'error');  \n             toggleLightbox('login-modal', true);  \n             return;  \n         }  \n         const f = getEl('job-form');  \n         if(f.classList.contains('hidden')) f.classList.remove('hidden');  \n         else f.classList.add('hidden');  \n    });  \n  \n    \/\/ ==========================================  \n    \/\/ CRIA\u00c7\u00c3O E EDI\u00c7\u00c3O DO TRABALHO  \n    \/\/ ==========================================  \n  \n    getEl('job-form').addEventListener('submit', (e) => {  \n        e.preventDefault();  \n        if(!currentUser || currentUser.isAnonymous) return;  \n        const client = getEl('job-client').value;  \n        if(!client) return showToast('Selecione um cliente', 'error');  \n  \n        const uniqueNum = 'GT-' + Math.floor(100000 + Math.random() * 900000); \/\/ Ex: GT-482910  \n  \n        const colors = collectColorData('colors-container-add');  \n        const data = {  \n            numeroRegisto: uniqueNum,  \n            reference: getEl('job-reference').value.trim(),  \n            client: client,  \n            date: getEl('job-date').value,  \n            type: getEl('job-type').value,   \n            sheets: parseInt(getEl('job-sheets').value) || 0,  \n            sheetSize: getEl('job-size').value,  \n            operator: getEl('job-operator').value.trim(),  \n            machine: getEl('job-machine').value.trim(),  \n            imageUrl: getEl('job-image-url').value.trim(),  \n            status: getEl('job-status').value,  \n            observations: getEl('job-observations').value.trim(),  \n            colors: colors,  \n            labelData: currentLabelDataCreate || null,   \n            dataEntrega: getEl('job-data-entrega') ? getEl('job-data-entrega').value : '',\n            desenhador:  getEl('job-desenhador')   ? getEl('job-desenhador').value.trim()   : '',\n            temperatura: getEl('job-temperatura')  ? getEl('job-temperatura').value.trim()  : '',\n            timestamp: Date.now()  \n        };  \n  \n        getCollectionRef('trabalhos').add(data)  \n          .then(() => {  \n              getEl('job-form').reset();  \n              getEl('job-client').value = '';  \n              getEl('job-client-display').textContent = 'Nenhum';  \n              getEl('colors-container-add').innerHTML = '';  \n              addColorRow('colors-container-add', 'add');  \n                \n              currentLabelDataCreate = null;  \n              updateLabelBtnUI('btn-open-label-config-add', null);  \n  \n              showToast('Trabalho criado: #' + uniqueNum);  \n              getEl('job-form').classList.add('hidden');  \n          })  \n          .catch(err => showToast('Erro ao criar: ' + err.message, 'error'));  \n    });  \n  \n    getEl('edit-job-form').addEventListener('submit', (e) => {  \n        e.preventDefault();  \n        if(!currentUser || currentUser.isAnonymous) return showToast('Sem permiss\u00e3o para editar', 'error');  \n        const id = getEl('edit-job-id').value;  \n        if(!id) return;  \n          \n        \/\/ NOVIDADE: Gera e grava um ID \u00danico para os trabalhos antigos que n\u00e3o o tenham  \n        let currentNumReg = getEl('edit-job-numero-registo').value;  \n        if (!currentNumReg || currentNumReg === 'S\/N' || currentNumReg === 'Sem ID') {  \n            currentNumReg = 'GT-' + Math.floor(100000 + Math.random() * 900000);  \n        }  \n  \n        const colors = collectColorData('colors-container-edit');  \n        const data = {  \n            numeroRegisto: currentNumReg,  \n            reference: getEl('edit-job-reference').value.trim(),  \n            client: getEl('edit-job-client').value.trim(),  \n            date: getEl('edit-job-date').value,  \n            type: getEl('edit-job-type').value,  \n            sheets: parseInt(getEl('edit-job-sheets').value) || 0,  \n            sheetSize: getEl('edit-job-size').value,  \n            operator: getEl('edit-job-operator').value.trim(),  \n            machine: getEl('edit-job-machine').value.trim(),  \n            imageUrl: getEl('edit-job-image-url').value.trim(),  \n            status: getEl('edit-job-status').value,  \n            observations: getEl('edit-job-observations').value.trim(),  \n            colors: colors,  \n            labelData: currentLabelDataEdit || null,\n            dataEntrega: getEl('edit-job-data-entrega') ? getEl('edit-job-data-entrega').value : '',\n            desenhador:  getEl('edit-job-desenhador')   ? getEl('edit-job-desenhador').value.trim()   : '',\n            temperatura: getEl('edit-job-temperatura')  ? getEl('edit-job-temperatura').value.trim()  : ''\n        };  \n          \n        getCollectionRef('trabalhos').doc(id).update(data)  \n          .then(() => {  \n              toggleLightbox('edit-lightbox-modal', false);  \n              showToast('Registo atualizado');  \n          })  \n          .catch(err => showToast('Erro ao atualizar', 'error'));  \n    });  \n      \n    \/\/ Bind Events de Search e Filtros  \n    getEl('search-btn').addEventListener('click', performSearch);  \n    getEl('btn-show-all').addEventListener('click', () => {  \n        getEl('search-input').value = '';  \n        getEl('filter-status').value = 'Todos';  \n        getEl('filter-type').value = 'Todos';  \n        performSearch();  \n    });  \n    getEl('search-input').addEventListener('keypress', (e) => { if(e.key === 'Enter') performSearch(); });  \n    getEl('filter-status').addEventListener('change', performSearch);  \n    getEl('filter-type').addEventListener('change', performSearch);  \n      \n    \/\/ Bind Resto dos Modais  \n    getEl('btn-select-client-add').addEventListener('click', () => { renderClientList(); toggleLightbox('client-modal', true); });  \n    getEl('btn-select-client-edit').addEventListener('click', () => { renderClientList(); toggleLightbox('client-modal', true); });  \n    getEl('client-form-add').addEventListener('submit', (e) => {  \n        e.preventDefault();  \n        const name = getEl('new-client-name').value.trim();  \n        if(!name) return;  \n        getCollectionRef('clientes').add({ name: name, timestamp: Date.now() })  \n          .then(() => { getEl('new-client-name').value = ''; showToast('Cliente adicionado'); });  \n    });  \n    getEl('btn-close-client-modal').addEventListener('click', () => toggleLightbox('client-modal', false));  \n    getEl('btn-colors-trigger').addEventListener('click', () => { renderColorDbList(); toggleLightbox('color-db-modal', true); });  \n    getEl('btn-settings-trigger').addEventListener('click', () => { toggleLightbox('settings-modal', true); });  \n    getEl('btn-close-settings').addEventListener('click', () => { toggleLightbox('settings-modal', false); });  \n    getEl('btn-close-color-modal-top').addEventListener('click', () => toggleLightbox('color-db-modal', false));  \n    getEl('btn-cancel-confirm').addEventListener('click', () => toggleLightbox('confirmation-modal', false));  \n      \n    getEl('confirm-action-button').addEventListener('click', () => {  \n        toggleLightbox('confirmation-modal', false);  \n        if(!pendingAction) return;  \n          \n        if(pendingAction.type === 'logout') {  \n            auth.signOut();  \n        } else if(pendingAction.type === 'delete-job') {  \n            if(!currentUser || currentUser.isAnonymous) return showToast('Sem permiss\u00e3o para remover', 'error');  \n            getCollectionRef('trabalhos').doc(pendingAction.id).delete()  \n              .then(() => { toggleLightbox('edit-lightbox-modal', false); showToast('Registo apagado'); });  \n        } else if(pendingAction.type === 'delete-client') {  \n            getCollectionRef('clientes').doc(pendingAction.id).delete();  \n        } else if(pendingAction.type === 'delete-color') {  \n            getCollectionRef('formulas_cores').doc(pendingAction.id).delete();  \n        } else if(pendingAction.type === 'delete-material') {  \n            if(!currentUser || currentUser.isAnonymous) return showToast('Sem permiss\u00e3o para remover material', 'error');  \n            getCollectionRef('pedidos_material').doc(pendingAction.id).delete()  \n              .then(() => {   \n                  toggleLightbox('material-request-modal', false);  \n                  showToast('Pedido de material apagado', 'success');   \n              });  \n        }  \n    });  \n  \n    getEl('btn-delete-job').addEventListener('click', () => confirmAction('Eliminar Registo', 'Tem a certeza?', 'Eliminar', 'delete-job', getEl('edit-job-id').value));  \n    getEl('btn-close-edit').addEventListener('click', () => toggleLightbox('edit-lightbox-modal', false));  \n    getEl('btn-cancel-edit').addEventListener('click', () => toggleLightbox('edit-lightbox-modal', false));  \n    getEl('btn-cancel-login').addEventListener('click', () => toggleLightbox('login-modal', false));  \n    getEl('btn-view-image-add').addEventListener('click', () => { const url = getEl('job-image-url').value; if(url) openLightbox(url); });  \n    getEl('btn-view-image-edit').addEventListener('click', () => { const url = getEl('edit-job-image-url').value; if(url) openLightbox(url); });  \n    getEl('btn-close-lightbox').addEventListener('click', () => toggleLightbox('lightbox-modal', false));  \n  \n    getEl('btn-open-stats-modal').addEventListener('click', openStatsModal);  \n    getEl('btn-close-stats').addEventListener('click', () => toggleLightbox('stats-modal', false));  \n    getEl('btn-calc-stats').addEventListener('click', calculateStatistics);  \n    getEl('stats-type-filter').addEventListener('change', calculateStatistics);  \n    getEl('btn-stats-all-time').addEventListener('click', () => {  \n        getEl('stats-date-start').value = '';  \n        getEl('stats-date-end').value = '';  \n        calculateStatistics();  \n    });  \n      \n    getEl('btn-print-job').addEventListener('click', () => printJobSheet(getEl('edit-job-id').value));  \n  \n    \/\/ Exporta\u00e7\u00e3o Excel Tintas (CSV)  \n    const btnExportColors = getEl('btn-export-colors-excel');  \n    if (btnExportColors) {  \n        btnExportColors.addEventListener('click', () => {  \n            if (!formulas || formulas.length === 0) {  \n                showToast('N\u00e3o existem tintas para exportar.', 'error');  \n                return;  \n            }  \n  \n            \/\/ UTF-8 BOM para garantir leitura de acentos no Excel  \n            let csvContent = \"\\uFEFF\";   \n            csvContent += \"Nome da Cor;Temperatura;F\u00f3rmula Original;Com Variantes;Variantes Alternativas\\n\";  \n  \n            formulas.forEach(f => {  \n                const name = f.name ? f.name.replace(\/\"\/g, '\"\"') : '';  \n                const temp = f.temperature ? f.temperature.replace(\/\"\/g, '\"\"') : '';  \n                const comp = f.composition ? f.composition.replace(\/\"\/g, '\"\"').replace(\/\\n\/g, ' ') : '';  \n                const isContra = f.isContraTipo ? 'Sim' : 'N\u00e3o';  \n                  \n                let alts = '';  \n                if (f.isContraTipo && Array.isArray(f.alternatives)) {  \n                    alts = f.alternatives.map(a => `${a.description}: ${a.composition}`).join(' | ').replace(\/\"\/g, '\"\"').replace(\/\\n\/g, ' ');  \n                }  \n  \n                \/\/ Usamos ; pois \u00e9 o delimitador padr\u00e3o do Excel em PT  \n                csvContent += `\"${name}\";\"${temp}\";\"${comp}\";\"${isContra}\";\"${alts}\"\\n`;  \n            });  \n  \n            const blob = new Blob([csvContent], { type: 'text\/csv;charset=utf-8;' });  \n            const url = URL.createObjectURL(blob);  \n            const a = document.createElement('a');  \n            a.href = url;  \n            a.download = `Base_Cores_Decalcer_${new Date().toISOString().split('T')[0]}.csv`;  \n            document.body.appendChild(a);  \n            a.click();  \n            document.body.removeChild(a);  \n            URL.revokeObjectURL(url);  \n              \n            showToast('Exporta\u00e7\u00e3o das tintas conclu\u00edda!', 'success');  \n        });  \n    }  \n  \n    \/\/ Funcionalidades Lightbox \/ Zoom  \n    const lbImg = getEl('lightbox-image');  \n    const lbContainer = getEl('lightbox-container');  \n      \n    getEl('btn-zoom-in').addEventListener('click', (e) => { e.stopPropagation(); updateZoom(0.5); });  \n    getEl('btn-zoom-out').addEventListener('click', (e) => { e.stopPropagation(); updateZoom(-0.5); });  \n    getEl('btn-zoom-reset').addEventListener('click', (e) => { e.stopPropagation(); resetZoom(); });  \n  \n    lbContainer.addEventListener('wheel', (e) => {  \n        e.preventDefault();  \n        if(e.deltaY < 0) updateZoom(0.2);  \n        else updateZoom(-0.2);  \n    });  \n  \n    lbContainer.addEventListener('mousedown', (e) => {  \n        if(zoomLevel > 1) {  \n            isDragging = true;  \n            startX = e.clientX - translateX;  \n            startY = e.clientY - translateY;  \n            lbContainer.classList.add('zoom-grabbing');  \n        }  \n    });  \n      \n    window.addEventListener('mouseup', () => {  \n        isDragging = false;  \n        if(lbContainer) lbContainer.classList.remove('zoom-grabbing');  \n    });  \n  \n    window.addEventListener('mousemove', (e) => {  \n        if(!isDragging) return;  \n        e.preventDefault();  \n        translateX = e.clientX - startX;  \n        translateY = e.clientY - startY;  \n        applyTransform();  \n    });  \n  \n    function updateZoom(delta) {  \n        zoomLevel += delta;  \n        if(zoomLevel < 1) zoomLevel = 1;  \n        if(zoomLevel > 5) zoomLevel = 5;  \n        if(zoomLevel === 1) {  \n            translateX = 0; translateY = 0;  \n            lbContainer.classList.remove('zoom-grab');  \n        } else {  \n            lbContainer.classList.add('zoom-grab');  \n        }  \n        getEl('zoom-level').textContent = Math.round(zoomLevel * 100) + '%';  \n        applyTransform();  \n    }  \n  \n    function resetZoom() {  \n        zoomLevel = 1;  \n        translateX = 0; translateY = 0;  \n        getEl('zoom-level').textContent = '100%';  \n        lbContainer.classList.remove('zoom-grab', 'zoom-grabbing');  \n        applyTransform();  \n    }  \n  \n    function applyTransform() {  \n        if(lbImg) lbImg.style.transform = 'translate(' + translateX + 'px, ' + translateY + 'px) scale(' + zoomLevel + ')';  \n    }  \n      \n    getEl('color-form-add').addEventListener('submit', (e) => {  \n        e.preventDefault();  \n        const name = getEl('new-color-name').value.trim();  \n        const temp = getEl('new-color-temp').value.trim();  \n        const comp = getEl('new-color-comp').value.trim();  \n        if(!name || !comp) return;  \n        if(formulas.some(f => f.name.toLowerCase() === name.toLowerCase() && f.id !== editingColorId)) {  \n            showToast('Essa cor j\u00e1 existe', 'error'); return;  \n        }  \n        const isContra = getEl('is-contra-tipo').checked;  \n        let alternatives = [];  \n        if(isContra) {  \n            const altList = getEl('alternatives-list').querySelectorAll('.alternative-item');  \n            altList.forEach(row => {  \n                const desc = row.querySelector('.alt-desc') ? row.querySelector('.alt-desc').value.trim() : '';  \n                const altComp = row.querySelector('.alt-comp') ? row.querySelector('.alt-comp').value.trim() : '';  \n                if(desc || altComp) alternatives.push({ description: desc, composition: altComp });  \n            });  \n        }  \n        const payload = { name: name, temperature: temp, composition: comp, isContraTipo: isContra, alternatives: alternatives, timestamp: Date.now() };  \n        if (editingColorId) {  \n            getCollectionRef('formulas_cores').doc(editingColorId).update(payload)  \n              .then(() => { resetColorForm(); showToast('Cor atualizada'); });  \n        } else {  \n            getCollectionRef('formulas_cores').add(payload)  \n              .then(() => { resetColorForm(); showToast('Cor adicionada'); });  \n        }  \n    });  \n    getEl('btn-cancel-color-edit').addEventListener('click', resetColorForm);  \n    getEl('btn-add-alt').addEventListener('click', () => renderAlternativeRow());  \n    getEl('is-contra-tipo').addEventListener('change', function() {  \n        const section = getEl('alternatives-section');  \n        if(this.checked) {  \n            section.classList.remove('hidden');  \n            if(getEl('alternatives-list').children.length === 0) renderAlternativeRow();  \n        } else section.classList.add('hidden');  \n    });  \n    if(getEl('search-color-db')) getEl('search-color-db').addEventListener('input', renderColorDbList);  \n  \n    function renderClientList() {  \n        const container = getEl('client-list-container');  \n        container.innerHTML = '';  \n        if(clients.length === 0) { getEl('no-clients-msg').classList.remove('hidden'); return; }  \n        getEl('no-clients-msg').classList.add('hidden');  \n        clients.forEach(c => {  \n            const div = document.createElement('div');  \n            div.className = 'flex items-center justify-between p-3 bg-white border border-slate-100 rounded-xl shadow-sm hover:border-indigo-200 hover:bg-indigo-50 transition-colors group';  \n            div.innerHTML = '<div class=\"flex items-center gap-3 overflow-hidden\"><span class=\"text-slate-700 font-medium truncate text-sm\">' + c.name + '<\/span><\/div><div class=\"flex space-x-2\"><button type=\"button\" class=\"btn-use-client px-3 py-1.5 text-xs bg-indigo-600 text-white font-bold rounded-lg hover:bg-indigo-700 border-none cursor-pointer shadow-sm\">Usar<\/button><button type=\"button\" class=\"btn-del-client text-rose-400 hover:text-rose-600 px-2 bg-transparent border-none cursor-pointer\">x<\/button><\/div>';  \n            div.querySelector('.btn-use-client').addEventListener('click', () => {  \n                if(clientSelectionMode === 'add') { getEl('job-client').value = c.name; getEl('job-client-display').textContent = c.name; }   \n                else { getEl('edit-job-client').value = c.name; getEl('edit-job-client-display').textContent = c.name; }  \n                toggleLightbox('client-modal', false);  \n            });  \n            div.querySelector('.btn-del-client').addEventListener('click', () => confirmAction('Remover Cliente', 'Remover \"' + c.name + '\"?', 'Remover', 'delete-client', c.id));  \n            container.appendChild(div);  \n        });  \n    }  \n  \n    function renderColorDbList() {  \n        const container = getEl('color-db-list-container');  \n        container.innerHTML = '';  \n        const filter = getEl('search-color-db') ? getEl('search-color-db').value.toLowerCase() : '';  \n        const visible = formulas.filter(f => f.name.toLowerCase().includes(filter));  \n        if(visible.length === 0) { getEl('no-colors-msg').classList.remove('hidden'); return; }  \n        getEl('no-colors-msg').classList.add('hidden');  \n        visible.forEach(f => {  \n            const div = document.createElement('div');  \n            div.className = 'flex flex-col sm:flex-row sm:items-center justify-between p-4 bg-white border border-slate-100 rounded-2xl shadow-sm hover:border-pink-200 hover:shadow-md transition-all group';  \n            const tempBadge = f.temperature ? '<span class=\"ml-2 text-[10px] text-pink-600 bg-pink-50 px-2 py-0.5 rounded-md font-bold\">' + f.temperature + '<\/span>' : '';  \n            div.innerHTML = '<div class=\"flex-1 min-w-0 mr-2 mb-3 sm:mb-0\"><div class=\"flex items-center flex-wrap gap-y-1\"><span class=\"text-base font-bold text-slate-800\">' + f.name + '<\/span>' + tempBadge + '<\/div><div class=\"text-sm text-slate-500 mt-1.5 whitespace-pre-wrap leading-relaxed border-l-4 border-slate-100 pl-3\">' + f.composition + '<\/div><\/div><div class=\"flex items-center justify-end space-x-3 sm:opacity-0 group-hover:opacity-100 transition-opacity\"><button type=\"button\" class=\"btn-edit-color text-indigo-600 bg-indigo-50 p-2 rounded-lg\">\u270e<\/button><button type=\"button\" class=\"btn-del-color text-rose-600 bg-rose-50 p-2 rounded-lg\">\u2715<\/button><\/div>';  \n            div.querySelector('.btn-edit-color').addEventListener('click', () => {  \n                editingColorId = f.id;  \n                getEl('new-color-name').value = f.name;  \n                getEl('new-color-temp').value = f.temperature || '';  \n                getEl('new-color-comp').value = f.composition;  \n                getEl('is-contra-tipo').checked = f.isContraTipo || false;  \n                getEl('is-contra-tipo').dispatchEvent(new Event('change'));  \n                getEl('alternatives-list').innerHTML = '';  \n                if(f.alternatives) f.alternatives.forEach(alt => renderAlternativeRow(alt.description, alt.composition));  \n                getEl('btn-save-color').textContent = 'Atualizar';  \n                getEl('btn-cancel-color-edit').classList.remove('hidden');  \n                getEl('color-form-add').scrollIntoView({ behavior: 'smooth' });  \n            });  \n            div.querySelector('.btn-del-color').addEventListener('click', () => confirmAction('Apagar F\u00f3rmula', 'Remover \"' + f.name + '\"?', 'Apagar', 'delete-color', f.id));  \n            container.appendChild(div);  \n        });  \n    }  \n  \n    function renderAlternativeRow(desc = '', comp = '') {  \n        const list = getEl('alternatives-list');  \n        const row = document.createElement('div');  \n        row.className = \"alternative-item flex flex-col gap-2 bg-white p-3 rounded-lg border border-indigo-100 relative group\";  \n        row.innerHTML = '<div class=\"flex items-center justify-between gap-2\"><input type=\"text\" value=\"' + desc + '\" placeholder=\"Nome (ex: Lote B)\" class=\"alt-desc w-1\/2 p-2 bg-slate-50 border border-slate-200 rounded-lg text-xs font-bold text-slate-700\"><button type=\"button\" class=\"text-rose-400 hover:text-rose-600 cursor-pointer\" onclick=\"this.closest(\\'.alternative-item\\').remove()\">x<\/button><\/div><textarea placeholder=\"F\u00f3rmula...\" rows=\"2\" class=\"alt-comp w-full p-2.5 bg-slate-50 border border-slate-200 rounded-lg text-xs resize-y\">' + comp + '<\/textarea>';  \n        list.appendChild(row);  \n    }  \n      \n    function resetColorForm() {  \n        getEl('new-color-name').value = '';  \n        getEl('new-color-temp').value = '';  \n        getEl('new-color-comp').value = '';  \n        getEl('is-contra-tipo').checked = false;  \n        getEl('is-contra-tipo').dispatchEvent(new Event('change'));  \n        getEl('btn-save-color').textContent = 'Salvar';  \n        getEl('btn-cancel-color-edit').classList.add('hidden');  \n        editingColorId = null;  \n    }  \n  \n    function confirmAction(title, msg, btnText, type, id) {  \n        getEl('confirm-title').textContent = title;  \n        getEl('confirm-message').textContent = msg;  \n        getEl('confirm-action-button').textContent = btnText;  \n        pendingAction = { type: type, id: id };  \n        toggleLightbox('confirmation-modal', true);  \n    }  \n      \n    function openLightbox(url) {  \n        getEl('lightbox-image').src = url;  \n        zoomLevel = 1;  \n        translateX = 0;  \n        translateY = 0;  \n        getEl('zoom-level').textContent = '100%';  \n        const img = getEl('lightbox-image');  \n        const container = getEl('lightbox-container');  \n        if(img) img.style.transform = 'translate(0px, 0px) scale(1)';  \n        if(container) container.classList.remove('zoom-grab', 'zoom-grabbing');  \n          \n        toggleLightbox('lightbox-modal', true);  \n    }  \n  \n    \/\/ IMPRESS\u00c3O - C\u00d3DIGO SEGURO  \n    function printJobSheet(jobId) {  \n        const job = jobs.find(j => j.id === jobId);  \n        if(!job) return;  \n          \n        let colorsHtml = '';  \n        if(job.colors && job.colors.length > 0) {  \n            colorsHtml = '<table style=\"width:100%; border-collapse: collapse; margin-top: 20px; font-size: 12px; border: 1px solid #e2e8f0;\">' +  \n                '<thead><tr style=\"background-color: #f8fafc; border-bottom: 2px solid #e2e8f0;\">' +  \n                '<th style=\"padding: 8px; text-align: left; color: #64748b;\">COR<\/th>' +  \n                '<th style=\"padding: 8px; text-align: center; color: #64748b;\">TEMP<\/th>' +  \n                '<th style=\"padding: 8px; text-align: left; color: #64748b;\">COMPOSI\u00c7\u00c3O<\/th>' +  \n                '<\/tr><\/thead><tbody>';  \n                  \n            job.colors.forEach(c => {  \n                colorsHtml += '<tr style=\"border-bottom: 1px solid #e2e8f0;\">' +  \n                    '<td style=\"padding: 8px; font-weight: bold;\">' + (c.name || '-') + '<\/td>' +  \n                    '<td style=\"padding: 8px; text-align: center;\">' + (c.temperature || '-') + '<\/td>' +  \n                    '<td style=\"padding: 8px; white-space: pre-wrap;\">' + (c.composition || '-') + '<\/td>' +  \n                    '<\/tr>';  \n            });  \n            colorsHtml += '<\/tbody><\/table>';  \n        } else {  \n             colorsHtml = '<p style=\"color:#94a3b8; font-style:italic; margin-top:10px;\">Sem cores registadas.<\/p>';  \n        }  \n  \n        const dateFormatted = job.date ? new Date(job.date).toLocaleDateString('pt-PT') : '-';  \n        const imgHtml = job.imageUrl ? '<div style=\"margin-top:20px; text-align:center; border: 1px solid #e2e8f0; padding: 10px; border-radius: 8px;\"><img decoding=\"async\" src=\"' + job.imageUrl + '\" style=\"max-width:100%; max-height: 400px; object-fit: contain;\"><\/div>' : '';  \n  \n        const printContent = '<' + '!DOCTYPE html>' +  \n            '<' + 'html lang=\"pt\">' +  \n            '<' + 'head>' +  \n            '<' + 'meta charset=\"utf-8\">' +  \n            '<' + 'title>Ficha de Trabalho - ' + job.reference + '<' + '\/title>' +  \n            '<' + 'link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">' +  \n            '<' + 'style>' +  \n            'body { font-family: \"Inter\", sans-serif; background: white; color: #0f172a; margin: 0; padding: 0; -webkit-print-color-adjust: exact; print-color-adjust: exact; }' +  \n            '@page { size: A4 portrait; margin: 1cm; }' +  \n            '.page-container { max-width: 210mm; margin: 0 auto; padding: 20px; }' +  \n            '<' + '\/style>' +  \n            '<' + '\/head>' +  \n            '<' + 'body>' +  \n            '<div class=\"page-container\">' +  \n            '<div style=\"display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #333; padding-bottom: 15px; margin-bottom: 30px;\">' +  \n            '<div><h1 style=\"margin: 0; font-size: 24px; color: #0f172a;\">Ficha de Trabalho<\/h1><p style=\"margin: 5px 0 0; color: #64748b; font-size: 14px;\">Ref: <strong>' + job.reference + '<\/strong><\/p><\/div>' +  \n            '<div style=\"text-align: right;\"><img decoding=\"async\" src=\"https:\/\/www.decalcer.com\/wp-content\/uploads\/2023\/06\/logo-decalcer-768x256.png\" style=\"height: 30px;\" onerror=\"this.style.display=\\'none\\'\"><p style=\"margin: 5px 0 0; color: #94a3b8; font-size: 12px;\">Data: ' + dateFormatted + '<\/p><\/div>' +  \n            '<\/div>' +  \n            '<div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px;\">' +  \n            '<div><p style=\"margin: 0 0 5px; color: #64748b; font-size: 10px; text-transform: uppercase; font-weight: bold;\">Cliente<\/p><p style=\"margin: 0; font-size: 16px; font-weight: 600;\">' + job.client + '<\/p><\/div>' +  \n            '<div><p style=\"margin: 0 0 5px; color: #64748b; font-size: 10px; text-transform: uppercase; font-weight: bold;\">Estado<\/p><p style=\"margin: 0; font-size: 16px;\">' + (job.status === 'Arquivado' ? 'Sem Or\u00e7amento' : job.status) + '<\/p><\/div>' +  \n            '<div><p style=\"margin: 0 0 5px; color: #64748b; font-size: 10px; text-transform: uppercase; font-weight: bold;\">Operador \/ M\u00e1quina<\/p><p style=\"margin: 0; font-size: 14px;\">' + (job.operator || '-') + ' \/ ' + (job.machine || '-') + '<\/p><\/div>' +  \n            '<div><p style=\"margin: 0 0 5px; color: #64748b; font-size: 10px; text-transform: uppercase; font-weight: bold;\">Formato<\/p><p style=\"margin: 0; font-size: 14px;\">' + job.sheets + ' folhas (' + job.sheetSize + ')<\/p><\/div>' +  \n            '<\/div>' +  \n            (job.observations ? '<div style=\"background-color: #f8fafc; padding: 15px; border-radius: 8px; margin-bottom: 30px; border: 1px solid #e2e8f0;\"><p style=\"margin: 0 0 5px; color: #64748b; font-size: 10px; text-transform: uppercase; font-weight: bold;\">Observa\u00e7\u00f5es<\/p><p style=\"margin: 0; font-size: 14px; white-space: pre-wrap;\">' + job.observations + '<\/p><\/div>' : '') +  \n            '<h3 style=\"margin: 0 0 10px; font-size: 14px; text-transform: uppercase; letter-spacing: 0.05em; color: #334155; border-bottom: 1px solid #e2e8f0; padding-bottom: 5px;\">Especifica\u00e7\u00f5es de Cores<\/h3>' +  \n            colorsHtml +  \n            imgHtml +  \n            '<div style=\"margin-top: 50px; border-top: 1px dashed #cbd5e1; padding-top: 10px; text-align: center; color: #94a3b8; font-size: 10px;\">Impresso a ' + new Date().toLocaleString('pt-PT') + ' | Sistema de Gest\u00e3o Decalcer<\/div>' +  \n            '<\/div>' +  \n            '<' + '\/body>' +  \n            '<' + '\/html>';  \n  \n        const printIframe = document.createElement('iframe');  \n        printIframe.name = \"print_iframe\";  \n        printIframe.style.position = 'absolute';  \n        printIframe.style.top = '-9999px';  \n        printIframe.style.left = '-9999px';  \n        printIframe.style.width = '0px';  \n        printIframe.style.height = '0px';  \n        printIframe.style.border = 'none';  \n        document.body.appendChild(printIframe);  \n  \n        const iframeDoc = printIframe.contentWindow ? printIframe.contentWindow.document : printIframe.contentDocument;  \n        iframeDoc.open();  \n        iframeDoc.write(printContent);  \n        iframeDoc.close();  \n  \n        setTimeout(() => {  \n            printIframe.contentWindow.focus();  \n            printIframe.contentWindow.print();  \n            setTimeout(() => {  \n                if(document.body.contains(printIframe)) { document.body.removeChild(printIframe); }  \n            }, 2000);  \n        }, 500);  \n    }  \n  \n    \/\/ ========================================================================  \n    \/\/ INJECTED: NOVO SISTEMA DE PEDIDOS DE MATERIAL (ARQUITETURA 2026)  \n    \/\/ ========================================================================  \n      \n    let materialRequests = [];  \n    let currentMatTab = 'pendentes';  \n  \n    \/\/ Navega\u00e7\u00e3o Principal (Trabalhos vs Materiais)  \n    const tabTrabalhos = getEl('tab-trabalhos');  \n    const tabMateriais = getEl('tab-materiais');  \n  \n    tabTrabalhos.addEventListener('click', () => {  \n        tabTrabalhos.classList.replace('nav-tab-inactive', 'nav-tab-active');  \n        tabMateriais.classList.replace('nav-tab-active', 'nav-tab-inactive');  \n        updateAuthUI();  \n    });  \n  \n    tabMateriais.addEventListener('click', () => {  \n        tabMateriais.classList.replace('nav-tab-inactive', 'nav-tab-active');  \n        tabTrabalhos.classList.replace('nav-tab-active', 'nav-tab-inactive');  \n        updateAuthUI();  \n    });  \n  \n    \/\/ Sub-navega\u00e7\u00e3o Pedidos de Material  \n    const subPendentes = getEl('subtab-pendentes');  \n    const subEncomendados = getEl('subtab-encomendados');  \n      \n    subPendentes.addEventListener('click', () => {  \n        currentMatTab = 'pendentes';  \n        subPendentes.classList.replace('subtab-inactive', 'subtab-active');  \n        subEncomendados.classList.replace('subtab-active', 'subtab-inactive');  \n        getEl('material-list-pendentes').classList.remove('hidden');  \n        getEl('material-list-encomendados').classList.add('hidden');  \n        renderMaterialRequests();  \n    });  \n  \n    subEncomendados.addEventListener('click', () => {  \n        currentMatTab = 'encomendados';  \n        subEncomendados.classList.replace('subtab-inactive', 'subtab-active');  \n        subPendentes.classList.replace('subtab-active', 'subtab-inactive');  \n        getEl('material-list-encomendados').classList.remove('hidden');  \n        getEl('material-list-pendentes').classList.add('hidden');  \n        renderMaterialRequests();  \n    });  \n  \n   \/\/ Iniciar M\u00f3dulo de Materiais  \n    function initMaterialSystem() {  \n        if (!currentUser) return;  \n          \n        getCollectionRef('pedidos_material').onSnapshot(snapshot => {  \n            materialRequests = [];  \n            snapshot.forEach(doc => materialRequests.push(Object.assign({ id: doc.id }, doc.data())));  \n            materialRequests.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));  \n              \n            \/\/ Contagem segura (protege contra espa\u00e7os em branco no estado)  \n            const pendentesCount = materialRequests.filter(m => (m.status || '').trim() === 'Pendente').length;  \n              \n            \/\/ Atualiza o contador na sub-tab  \n            const countMatPendentes = getEl('count-mat-pendentes');  \n            if (countMatPendentes) countMatPendentes.textContent = pendentesCount;  \n              \n            \/\/ Atualiza o Badge principal no menu do topo  \n            const badge = getEl('badge-pedidos-pendentes');  \n            if (badge) {  \n                if (pendentesCount > 0) {  \n                    badge.textContent = pendentesCount;  \n                    badge.classList.remove('hidden');  \n                    badge.classList.add('flex', 'items-center', 'justify-center'); \/\/ For\u00e7a a exibi\u00e7\u00e3o  \n                } else {  \n                    badge.classList.add('hidden');  \n                    badge.classList.remove('flex', 'items-center', 'justify-center');  \n                }  \n            }  \n              \n            renderMaterialRequests();  \n              \n        }, error => {  \n            console.error(\"Erro ao ler pedidos_material (Verifique as regras do Firestore):\", error);  \n        });  \n    }  \n  \n    \/\/ Renderiza\u00e7\u00e3o dos cart\u00f5es  \n    function renderMaterialRequests() {  \n        const listP = getEl('material-list-pendentes');  \n        const listE = getEl('material-list-encomendados');  \n        const emptyState = getEl('no-materials');  \n          \n        listP.innerHTML = '';  \n        listE.innerHTML = '';  \n  \n        const isPendenteEmpty = materialRequests.filter(m => m.status === 'Pendente').length === 0;  \n        const isEncomendadoEmpty = materialRequests.filter(m => m.status === 'Encomendado').length === 0;  \n  \n        if (currentMatTab === 'pendentes' && isPendenteEmpty) emptyState.classList.remove('hidden');  \n        else if (currentMatTab === 'encomendados' && isEncomendadoEmpty) emptyState.classList.remove('hidden');  \n        else emptyState.classList.add('hidden');  \n  \n        materialRequests.forEach(req => {  \n            const isPendente = req.status === 'Pendente';  \n            let itemsHtml = req.items.map(item => `  \n                <div class=\"flex items-center justify-between text-sm border-b border-slate-100 last:border-0 py-1.5\">  \n                    <span class=\"font-medium text-slate-700 truncate flex-1 pr-2\">${item.descricao}<\/span>  \n                    <span class=\"font-bold text-slate-500 w-12 text-center bg-slate-50 rounded\">${item.quantidade}<\/span>  \n                    <span class=\"text-xs text-slate-400 w-1\/3 text-right truncate pl-2\" title=\"${item.fornecedor}\">${item.fornecedor}<\/span>  \n                <\/div>  \n            `).join('');  \n  \n            const dateStr = req.date ? new Date(req.date).toLocaleDateString('pt-PT') : 'Sem data';  \n  \n            \/\/ Bot\u00e3o de editar (dispon\u00edvel em ambas as abas)  \n            const editBtnHtml = `  \n                <button class=\"btn-edit-mat absolute top-3 right-3 p-1.5 bg-white text-slate-400 hover:text-indigo-600 rounded-md shadow-sm border border-slate-100 opacity-0 group-hover:opacity-100 transition-all cursor-pointer z-20\" data-id=\"${req.id}\" title=\"Editar Pedido\">  \n                    <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z\"\/><\/svg>  \n                <\/button>  \n            `;  \n  \n            const cardHtml = `  \n                <div class=\"bg-white rounded-xl shadow-sm border border-slate-200 p-5 flex flex-col h-full hover:shadow-md transition-shadow relative overflow-hidden group\">  \n                    ${editBtnHtml}  \n                    ${isPendente ? `<div class=\"absolute top-0 right-10 p-3 opacity-0 group-hover:opacity-100 transition-opacity bg-white\/90 backdrop-blur pl-6 rounded-bl-xl z-10\">  \n                        <button class=\"btn-mark-ordered bg-emerald-50 text-emerald-600 hover:bg-emerald-100 px-3 py-1.5 rounded-lg text-xs font-bold border-none cursor-pointer flex items-center gap-1 shadow-sm transition-colors\" data-id=\"${req.id}\">  \n                            <svg class=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"3\" d=\"M5 13l4 4L19 7\"><\/path><\/svg>  \n                            Encomendar  \n                        <\/button>  \n                    <\/div>` : ''}  \n                      \n                    <div class=\"flex justify-between items-start mb-4 pr-6\">  \n                        <div class=\"flex items-center gap-2\">  \n                            <span class=\"w-2.5 h-2.5 rounded-full ${isPendente ? 'bg-amber-400' : 'bg-emerald-400'}\"><\/span>  \n                            <span class=\"text-xs font-bold text-slate-400 uppercase tracking-wider\">${dateStr}<\/span>  \n                        <\/div>  \n                        <span class=\"text-[10px] font-mono text-slate-400 bg-slate-50 px-1.5 py-0.5 rounded border border-slate-100\">  \n                            #${req.id.substring(0,6).toUpperCase()}  \n                        <\/span>  \n                    <\/div>  \n                      \n                    <div class=\"flex-1 space-y-1\">  \n                        ${itemsHtml}  \n                    <\/div>  \n                <\/div>  \n            `;  \n  \n            if (isPendente) listP.innerHTML += cardHtml;  \n            else listE.innerHTML += cardHtml;  \n        });  \n  \n        \/\/ Eventos para o Bot\u00e3o Encomendar  \n        document.querySelectorAll('.btn-mark-ordered').forEach(btn => {  \n            btn.addEventListener('click', (e) => {  \n                const id = e.currentTarget.getAttribute('data-id');  \n                getCollectionRef('pedidos_material').doc(id).update({ status: 'Encomendado' })  \n                    .then(() => showToast('Material marcado como encomendado.', 'success'))  \n                    .catch(() => showToast('Erro ao atualizar.', 'error'));  \n            });  \n        });  \n  \n        \/\/ Eventos para o Bot\u00e3o Editar  \n        document.querySelectorAll('.btn-edit-mat').forEach(btn => {  \n            btn.addEventListener('click', (e) => {  \n                e.stopPropagation();  \n                openEditMaterialModal(e.currentTarget.getAttribute('data-id'));  \n            });  \n        });  \n    }  \n  \n    \/\/ Abre o Modal de Edi\u00e7\u00e3o com os dados preenchidos  \n    function openEditMaterialModal(id) {  \n        const req = materialRequests.find(m => m.id === id);  \n        if (!req) return;  \n  \n        getEl('mat-req-id').value = id;  \n        getEl('mat-req-date').value = req.date || new Date().toISOString().split('T')[0];  \n          \n        getEl('material-modal-title').innerHTML = '<svg class=\"w-5 h-5 text-indigo-600\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"><\/path><\/svg> Editar Pedido de Material';  \n        getEl('btn-submit-mat').textContent = 'Guardar Altera\u00e7\u00f5es';  \n        getEl('btn-delete-mat').classList.remove('hidden');  \n  \n        const container = getEl('material-fields-container');  \n        container.innerHTML = '';  \n          \n        req.items.forEach(item => {  \n            addMaterialFieldRow(item.descricao, item.fornecedor, item.quantidade);  \n        });  \n  \n        toggleLightbox('material-request-modal', true);  \n    }  \n  \n    \/\/ Gest\u00e3o do Bot\u00e3o Novo Pedido  \n    getEl('btn-open-material-modal').addEventListener('click', () => {  \n        getEl('mat-req-id').value = ''; \/\/ Limpa ID (Modo Cria\u00e7\u00e3o)  \n        getEl('mat-req-date').value = new Date().toISOString().split('T')[0];  \n          \n        getEl('material-modal-title').innerHTML = '<svg class=\"w-5 h-5 text-indigo-600\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"><\/path><\/svg> Novo Pedido de Material';  \n        getEl('btn-submit-mat').textContent = 'Submeter Pedido';  \n        getEl('btn-delete-mat').classList.add('hidden');  \n  \n        getEl('material-fields-container').innerHTML = '';  \n        addMaterialFieldRow();  \n        toggleLightbox('material-request-modal', true);  \n    });  \n  \n    getEl('btn-close-material-modal').addEventListener('click', () => {  \n        toggleLightbox('material-request-modal', false);  \n    });  \n  \n    \/\/ Evento de Eliminar no Modal  \n    getEl('btn-delete-mat').addEventListener('click', () => {  \n        const id = getEl('mat-req-id').value;  \n        if (!id) return;  \n        confirmAction('Apagar Pedido', 'Tem a certeza que deseja eliminar este pedido de material? Esta a\u00e7\u00e3o n\u00e3o pode ser revertida.', 'Apagar', 'delete-material', id);  \n    });  \n  \n    \/\/ Linhas din\u00e2micas  \n    function addMaterialFieldRow(desc = '', forn = '', qty = '') {  \n        const container = getEl('material-fields-container');  \n        const row = document.createElement('div');  \n        row.className = \"mat-item-row flex gap-2 bg-slate-50 p-2 rounded-lg border border-slate-200 relative items-center flex-wrap sm:flex-nowrap\";  \n          \n        \/\/ Escape quotes to prevent HTML injection breaks  \n        const safeDesc = desc.replace(\/\"\/g, '&quot;');  \n        const safeForn = forn.replace(\/\"\/g, '&quot;');  \n          \n        row.innerHTML = `  \n            <input type=\"text\" required placeholder=\"Descri\u00e7\u00e3o (ex: Tinta UV Magenta)\" value=\"${safeDesc}\" class=\"mat-desc w-full sm:w-auto sm:flex-[6] p-2.5 bg-white border border-slate-200 rounded text-sm outline-none focus:border-indigo-500\">  \n            <input type=\"text\" placeholder=\"Fornecedor (Opcional)\" value=\"${safeForn}\" class=\"mat-forn w-full sm:w-auto sm:flex-[3] p-2.5 bg-white border border-slate-200 rounded text-sm outline-none focus:border-indigo-500\">  \n            <input type=\"number\" required min=\"1\" placeholder=\"Qtd\" value=\"${qty}\" class=\"mat-qty w-[calc(100%-40px)] sm:w-auto sm:flex-[1] p-2.5 bg-white border border-slate-200 rounded text-sm text-center outline-none focus:border-indigo-500\">  \n            <button type=\"button\" title=\"Remover\" class=\"btn-remove-mat-row shrink-0 w-8 h-8 flex items-center justify-center bg-rose-50 text-rose-500 rounded border border-rose-100 hover:bg-rose-100 hover:text-rose-700 transition-colors cursor-pointer\">  \n                <span class=\"text-sm font-bold\">\u2715<\/span>  \n            <\/button>  \n        `;  \n          \n        row.querySelector('.btn-remove-mat-row').addEventListener('click', () => {  \n            if (container.children.length > 1) row.remove();  \n            else showToast('O pedido deve ter pelo menos um item.', 'error');  \n        });  \n  \n        container.appendChild(row);  \n    }  \n  \n    getEl('btn-add-mat-field').addEventListener('click', () => addMaterialFieldRow());  \n  \n    \/\/ Submiss\u00e3o do Pedido (Cria\u00e7\u00e3o ou Edi\u00e7\u00e3o)  \n    getEl('material-request-form').addEventListener('submit', (e) => {  \n        e.preventDefault();  \n          \n        const id = getEl('mat-req-id').value;  \n        const items = [];  \n        const rows = document.querySelectorAll('.mat-item-row');  \n          \n        let isValid = true;  \n        rows.forEach(row => {  \n            const desc = row.querySelector('.mat-desc').value.trim();  \n            const qty = parseInt(row.querySelector('.mat-qty').value) || 0;  \n            const forn = row.querySelector('.mat-forn').value.trim() || 'S\/ Fornecedor';  \n              \n            if (!desc || qty <= 0) isValid = false;  \n            else items.push({ descricao: desc, quantidade: qty, fornecedor: forn });  \n        });  \n  \n        if (!isValid) return showToast('Preencha as descri\u00e7\u00f5es e quantidades corretamente.', 'error');  \n  \n        \/\/ Modo Edi\u00e7\u00e3o  \n        if (id) {  \n            getCollectionRef('pedidos_material').doc(id).update({  \n                date: getEl('mat-req-date').value,  \n                items: items  \n            }).then(() => {  \n                toggleLightbox('material-request-modal', false);  \n                showToast('Pedido atualizado com sucesso!');  \n            }).catch(err => showToast('Erro ao atualizar: ' + err.message, 'error'));  \n              \n        }   \n        \/\/ Modo Cria\u00e7\u00e3o  \n        else {  \n            const payload = {  \n                date: getEl('mat-req-date').value,  \n                items: items,  \n                status: 'Pendente',  \n                timestamp: Date.now()  \n            };  \n  \n            getCollectionRef('pedidos_material').add(payload)  \n                .then(() => {  \n                    toggleLightbox('material-request-modal', false);  \n                    showToast('Pedido submetido com sucesso!');  \n                    getEl('material-request-form').reset();  \n                      \n                    \/\/ Dispara o E-mail em Background apenas em novas cria\u00e7\u00f5es  \n                    enviarEmailAutomatico(payload.items);  \n                })  \n                .catch(err => showToast('Erro ao submeter: ' + err.message, 'error'));  \n        }  \n    });  \n  \n \/\/ Fun\u00e7\u00e3o de Envio de E-mail Background  \n    \/\/ Usa Web3Forms via form POST + iframe oculto (sem CORS, sem ativa\u00e7\u00e3o pr\u00e9via)  \n    \/\/ CHAVE: obter em https:\/\/web3forms.com com o email gerencia@decalcer.com  \n    const WEB3FORMS_ACCESS_KEY = '623fd7c2-754e-4289-8f3b-b9241b0c9fee';  \n  \n    function enviarEmailAutomatico(itemsList) {  \n        const listaEmail = itemsList  \n            .map(i => `- ${i.quantidade}x  ${i.descricao}  |  Fornecedor: ${i.fornecedor}`)  \n            .join('\\n');  \n  \n        const dataStr = new Date().toLocaleString('pt-PT');  \n  \n        showToast('A enviar notifica\u00e7\u00e3o por email...', 'info');  \n  \n        try {  \n            \/\/ Iframe oculto \u2014 evita redirect da p\u00e1gina ao submeter o form  \n            const iframeId = 'w3f-iframe-' + Date.now();  \n            const iframe = document.createElement('iframe');  \n            iframe.name = iframeId;  \n            iframe.style.cssText = 'display:none;position:absolute;top:-9999px;left:-9999px;width:0;height:0;border:none;';  \n  \n            \/\/ Callback para ler a resposta do Web3Forms dentro do iframe  \n            iframe.onload = function() {  \n                try {  \n                    const body = iframe.contentDocument  \n                        ? iframe.contentDocument.body.innerText  \n                        : (iframe.contentWindow.document.body.innerText || '');  \n  \n                    \/\/ Web3Forms devolve JSON: {\"success\":true} ou {\"success\":false}  \n                    const resp = JSON.parse(body);  \n  \n                    if (resp.success === true) {  \n                        showToast('\u2709\ufe0f Email enviado para gerencia@decalcer.com', 'success');  \n                    } else {  \n                        console.warn('Web3Forms resposta:', resp);  \n                        showToast('\u26a0\ufe0f Pedido guardado, mas falhou o envio do email. Verifique a chave Web3Forms.', 'error');  \n                    }  \n                } catch (e) {  \n                    \/\/ Se n\u00e3o conseguir ler a resposta (cross-origin ap\u00f3s redirect),  \n                    \/\/ assumimos sucesso pois o form chegou ao servidor  \n                    showToast('\u2709\ufe0f Notifica\u00e7\u00e3o enviada para gerencia@decalcer.com', 'success');  \n                }  \n  \n                \/\/ Limpeza  \n                setTimeout(() => {  \n                    if (document.body.contains(form))   document.body.removeChild(form);  \n                    if (document.body.contains(iframe)) document.body.removeChild(iframe);  \n                }, 1000);  \n            };  \n  \n            document.body.appendChild(iframe);  \n  \n            \/\/ Formul\u00e1rio apontado para o iframe  \n            const form = document.createElement('form');  \n            form.action  = 'https:\/\/api.web3forms.com\/submit';  \n            form.method  = 'POST';  \n            form.target  = iframeId;  \n            form.style.display = 'none';  \n  \n            const campos = {  \n                'access_key' : WEB3FORMS_ACCESS_KEY,  \n                'subject'    : '\ud83d\udce6 NOVO PEDIDO DE MATERIAL \u2014 App Decalcer',  \n                'from_name'  : 'App Gest\u00e3o Decalcer',  \n                'message'    : `Novo pedido submetido em ${dataStr}:\\n\\n${listaEmail}`,  \n                \/\/ Desativa o redirect do Web3Forms para que a resposta fique no iframe  \n                'redirect'   : ''  \n            };  \n  \n            Object.entries(campos).forEach(([name, value]) => {  \n                const input = document.createElement('input');  \n                input.type  = 'hidden';  \n                input.name  = name;  \n                input.value = value;  \n                form.appendChild(input);  \n            });  \n  \n            document.body.appendChild(form);  \n            form.submit();  \n  \n        } catch (error) {  \n            console.error('Erro ao enviar email:', error);  \n            showToast('Erro inesperado ao enviar notifica\u00e7\u00e3o.', 'error');  \n        }  \n    }  \n  \n    \/\/ ========================================================================  \n    \/\/ BACKUP E RESTAURO DA BASE DE DADOS  \n    \/\/ ========================================================================  \n  \n    \/\/ Exportar (Backup)  \n    getEl('btn-export-backup').addEventListener('click', async () => {  \n        if (!currentUser || currentUser.isAnonymous) return showToast('Acesso negado.', 'error');  \n          \n        const btn = getEl('btn-export-backup');  \n        const originalText = btn.innerHTML;  \n        btn.innerHTML = '<span class=\"css-spinner w-4 h-4 border-2 border-t-white mr-2\"><\/span> A gerar...';  \n        btn.disabled = true;  \n  \n        try {  \n            const collections = ['trabalhos', 'clientes', 'formulas_cores', 'orcamentos', 'pedidos_material'];  \n            const backupData = {};  \n              \n            for (const colName of collections) {  \n                const snapshot = await getCollectionRef(colName).get();  \n                backupData[colName] = {};  \n                snapshot.forEach(doc => {  \n                    backupData[colName][doc.id] = doc.data();  \n                });  \n            }  \n  \n            const jsonString = JSON.stringify(backupData, null, 2);  \n            const blob = new Blob([jsonString], { type: \"application\/json\" });  \n            const url = URL.createObjectURL(blob);  \n              \n            const a = document.createElement('a');  \n            a.href = url;  \n            a.download = `backup_decalcer_${new Date().toISOString().split('T')[0]}.json`;  \n            document.body.appendChild(a);  \n            a.click();  \n            document.body.removeChild(a);  \n            URL.revokeObjectURL(url);  \n              \n            showToast('Backup conclu\u00eddo com sucesso!', 'success');  \n        } catch (error) {  \n            console.error(error);  \n            showToast('Erro ao gerar backup.', 'error');  \n        } finally {  \n            btn.innerHTML = originalText;  \n            btn.disabled = false;  \n        }  \n    });  \n  \n    \/\/ L\u00f3gica UI de importa\u00e7\u00e3o  \n    const fileInput = getEl('backup-file-input');  \n    const btnTriggerFile = getEl('btn-trigger-file');  \n    const btnImport = getEl('btn-import-backup');  \n    const fileDisplay = getEl('file-name-display');  \n  \n    btnTriggerFile.addEventListener('click', () => fileInput.click());  \n  \n    fileInput.addEventListener('change', (e) => {  \n        if (e.target.files.length > 0) {  \n            fileDisplay.textContent = e.target.files[0].name;  \n            btnImport.disabled = false;  \n        } else {  \n            fileDisplay.textContent = '';  \n            btnImport.disabled = true;  \n        }  \n    });  \n  \n    \/\/ Importar (Restauro)  \n    btnImport.addEventListener('click', () => {  \n        const file = fileInput.files[0];  \n        if (!file) return;  \n  \n        confirmAction(  \n            'Restaurar Base de Dados',   \n            'Tem a certeza? Este processo vai escrever os dados do ficheiro na base de dados (sobrepondo registos com o mesmo ID).',   \n            'Restaurar Dados',   \n            'restore-db',   \n            file  \n        );  \n    });  \n  \n    \/\/ Extens\u00e3o do confirmAction para suportar o restauro e material  \n    const originalConfirmAction = getEl('confirm-action-button');  \n    originalConfirmAction.removeEventListener('click', confirmActionHandler); \/\/ limpamos se existisse para evitar bugs  \n      \n    function confirmActionHandler() {  \n        toggleLightbox('confirmation-modal', false);  \n        if(!pendingAction) return;  \n          \n        if(pendingAction.type === 'logout') auth.signOut();  \n        else if(pendingAction.type === 'delete-job') {  \n            if(!currentUser || currentUser.isAnonymous) return showToast('Sem permiss\u00e3o', 'error');  \n            getCollectionRef('trabalhos').doc(pendingAction.id).delete()  \n              .then(() => { toggleLightbox('edit-lightbox-modal', false); showToast('Registo apagado'); });  \n        } else if(pendingAction.type === 'delete-client') {  \n            getCollectionRef('clientes').doc(pendingAction.id).delete();  \n        } else if(pendingAction.type === 'delete-color') {  \n            getCollectionRef('formulas_cores').doc(pendingAction.id).delete();  \n        } else if(pendingAction.type === 'delete-material') {  \n            if(!currentUser || currentUser.isAnonymous) return showToast('Sem permiss\u00e3o', 'error');  \n            getCollectionRef('pedidos_material').doc(pendingAction.id).delete()  \n              .then(() => {   \n                  toggleLightbox('material-request-modal', false);  \n                  showToast('Pedido apagado com sucesso', 'success');   \n              });  \n        } else if(pendingAction.type === 'restore-db') {  \n            processDatabaseRestore(pendingAction.id); \/\/ O ID aqui transporta o File  \n        }  \n    }  \n      \n    originalConfirmAction.addEventListener('click', confirmActionHandler);  \n  \n    async function processDatabaseRestore(file) {  \n        showToast('A iniciar o restauro...', 'info');  \n        const reader = new FileReader();  \n          \n        reader.onload = async (event) => {  \n            try {  \n                const data = JSON.parse(event.target.result);  \n                const collections = Object.keys(data);  \n                let totalRestored = 0;  \n  \n                for (const colName of collections) {  \n                    const records = data[colName];  \n                    const recordIds = Object.keys(records);  \n                      \n                    \/\/ Em modo de loop para garantir a grava\u00e7\u00e3o um a um  \n                    for (const id of recordIds) {  \n                        await getCollectionRef(colName).doc(id).set(records[id], { merge: true });  \n                        totalRestored++;  \n                    }  \n                }  \n                  \n                showToast(`Restauro conclu\u00eddo! ${totalRestored} registos processados.`, 'success');  \n                toggleLightbox('settings-modal', false);  \n                fileInput.value = '';  \n                btnImport.disabled = true;  \n                fileDisplay.textContent = '';  \n                  \n            } catch (error) {  \n                console.error(\"Erro no restauro:\", error);  \n                showToast('Erro: Ficheiro inv\u00e1lido ou corrompido.', 'error');  \n            }  \n        };  \n          \n        reader.readAsText(file);  \n    }  \n\n\/\/ ============================================================================\n\/\/  INJECTED: GERA\u00c7\u00c3O DAS 3 FICHAS A4 (T\u00e9cnica \/ Produ\u00e7\u00e3o \/ Ecr\u00e3s) + PREVIEW\n\/\/  Bloco 100% aditivo. N\u00c3O altera nenhuma fun\u00e7\u00e3o existente.\n\/\/  Colar imediatamente ANTES do \"});\" final do DOMContentLoaded (linha ~3328).\n\/\/ ============================================================================\n(function () {\n    'use strict';\n\n    var LOGO = 'https:\/\/www.decalcer.com\/wp-content\/uploads\/2023\/06\/logo-decalcer-768x256.png';\n\n    \/\/ ---- helpers -----------------------------------------------------------\n    function esc(v) {\n        if (v === null || v === undefined) return '';\n        return String(v)\n            .replace(\/&\/g, '&amp;').replace(\/<\/g, '&lt;').replace(\/>\/g, '&gt;')\n            .replace(\/\"\/g, '&quot;');\n    }\n    function fmtDate(d) {\n        if (!d) return '__ \/ __ \/ ____';\n        try { return new Date(d).toLocaleDateString('pt-PT'); } catch (e) { return esc(d); }\n    }\n    function getJob(jobId) {\n        \/\/ 'jobs' \u00e9 a vari\u00e1vel global de trabalhos j\u00e1 existente na app\n        return (typeof jobs !== 'undefined') ? jobs.find(function (j) { return j.id === jobId; }) : null;\n    }\n    \/\/ n\u00ba de cores: usa o array colors, sen\u00e3o campo num\u00e9rico de fallback\n    function numCores(job) {\n        if (job.colors && job.colors.length) return job.colors.length;\n        return job.coresTotal || '';\n    }\n\n    \/\/ ---- CSS comum \u00e0s fichas ----------------------------------------------\n    var BASE_CSS =\n        '*{box-sizing:border-box;-webkit-print-color-adjust:exact;print-color-adjust:exact;}' +\n        'body{font-family:\"Inter\",Arial,sans-serif;margin:0;color:#111;font-size:11px;}' +\n        '.sheet{width:210mm;min-height:297mm;padding:10mm;margin:0 auto;background:#fff;page-break-after:always;}' +\n        '.sheet:last-child{page-break-after:auto;}' +\n        '.hd{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid #111;padding-bottom:6px;margin-bottom:10px;}' +\n        '.hd h1{margin:0;font-size:18px;letter-spacing:.02em;}' +\n        '.hd .meta{text-align:right;font-size:10px;color:#444;}' +\n        '.hd img{height:26px;display:block;margin-left:auto;margin-bottom:4px;}' +\n        '.grid{display:grid;gap:6px 10px;margin-bottom:10px;}' +\n        '.fld{border:1px solid #cbd5e1;border-radius:4px;padding:4px 6px;min-height:30px;}' +\n        '.fld .lbl{font-size:8px;text-transform:uppercase;letter-spacing:.05em;color:#64748b;font-weight:700;display:block;margin-bottom:2px;}' +\n        '.fld .val{font-size:12px;font-weight:600;}' +\n        'table{width:100%;border-collapse:collapse;margin-top:4px;}' +\n        'th,td{border:1px solid #94a3b8;padding:3px 4px;font-size:9.5px;text-align:left;vertical-align:top;}' +\n        'th{background:#f1f5f9;text-transform:uppercase;font-size:8px;letter-spacing:.03em;color:#334155;}' +\n        '.foot{margin-top:14px;border-top:1px dashed #94a3b8;padding-top:5px;text-align:center;font-size:8px;color:#94a3b8;}' +\n        '.sec-title{font-size:11px;text-transform:uppercase;letter-spacing:.05em;font-weight:700;border-bottom:1px solid #cbd5e1;padding-bottom:3px;margin:14px 0 4px;color:#0f172a;}' +\n        '.obs{border:1px solid #cbd5e1;border-radius:4px;padding:6px 8px;min-height:34px;white-space:pre-wrap;}' +\n        '@page{size:A4 portrait;margin:0;}' +\n        '@media print{.no-print{display:none!important;}}';\n\n    function fld(lbl, val) {\n        return '<div class=\"fld\"><span class=\"lbl\">' + esc(lbl) + '<\/span>' +\n               '<span class=\"val\">' + esc(val || '') + '<\/span><\/div>';\n    }\n\n    \/\/ ========================================================================\n    \/\/  FICHA 1 \u2014 FICHA T\u00c9CNICA DECALCER (topo + c\u00f3pia ARQUIVO em baixo)\n    \/\/ ========================================================================\n    function buildFichaTecnica(job) {\n        function bloco(tagArquivo) {\n            var rows = '';\n            var lista = (job.colors && job.colors.length) ? job.colors : [{}];\n            var maxLinhas = Math.max(lista.length, 8);\n            for (var i = 0; i < maxLinhas; i++) {\n                var c = lista[i] || {};\n                rows += '<tr>' +\n                    '<td style=\"text-align:center;width:34px;\">' + (i + 1) + '<\/td>' +\n                    '<td>' + esc(c.name || '') + '<\/td>' +\n                    '<td style=\"text-align:center;\">' + esc(c.tramagem || '') + '<\/td>' +\n                    '<td style=\"text-align:center;\">' + esc(c.inclinacao || '') + '<\/td>' +\n                    '<td style=\"text-align:center;\">' + esc(c.seda || '') + '<\/td>' +\n                    '<td style=\"text-align:center;\">' + esc(c.tensao || '') + '<\/td>' +\n                    '<td>' + esc(c.emulsao || '') + '<\/td>' +\n                    '<td style=\"text-align:center;\">' + esc(c.exposicao || '') + '<\/td>' +\n                    '<td style=\"text-align:center;\">' + esc(c.medidaEcra || '') + '<\/td>' +\n                    '<td>' + esc(c.composition || c.observacao || '') + '<\/td>' +\n                    '<\/tr>';\n            }\n            return '<div class=\"hd\">' +\n                    '<div><h1>Ficha T\u00e9cnica' + (tagArquivo ? ' \u2014 ARQUIVO' : '') + '<\/h1>' +\n                    '<div style=\"font-size:10px;color:#444;margin-top:2px;\">Departamento de Desenho e Produ\u00e7\u00e3o Gr\u00e1fica<\/div><\/div>' +\n                    '<div class=\"meta\"><img decoding=\"async\" src=\"' + LOGO + '\" onerror=\"this.style.display=\\'none\\'\">' +\n                    'Ref.\u00aa Decalcer: <b>' + esc(job.reference || '') + '<\/b><br>Ano: <b>' + (new Date(job.date || Date.now()).getFullYear()) + '<\/b><br>Cores: <b>' + esc(numCores(job)) + '<\/b><\/div>' +\n                  '<\/div>' +\n                  '<div class=\"grid\" style=\"grid-template-columns:2fr 1fr 1fr;\">' +\n                    fld('Cliente', job.client) +\n                    fld('Desenhador', job.desenhador) +\n                    fld('Data de Sa\u00edda', fmtDate(job.dataEntrega || job.date)) +\n                  '<\/div>' +\n                  '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr 1fr;\">' +\n                    fld('Formato', job.sheetSize) +\n                    fld('Temperatura', job.temperatura) +\n                    fld('Quantidade (Fls)', job.sheets) +\n                    fld('Tipo', job.type) +\n                  '<\/div>' +\n                  '<div class=\"fld\" style=\"margin-bottom:8px;\"><span class=\"lbl\">Descri\u00e7\u00e3o<\/span>' +\n                    '<span class=\"val\">' + esc(job.reference || '') + '<\/span><\/div>' +\n                  '<table><thead><tr>' +\n                    '<th>Ordem<\/th><th>Cor<\/th><th>Tramag.<\/th><th>Inclin.<\/th><th>Seda<\/th><th>Tens\u00e3o<\/th>' +\n                    '<th>Emuls\u00e3o e Camadas<\/th><th>T. Exposi\u00e7\u00e3o<\/th><th>Medida Ecr\u00e3<\/th><th>Observa\u00e7\u00f5es<\/th>' +\n                  '<\/tr><\/thead><tbody>' + rows + '<\/tbody><\/table>';\n        }\n        return '<div class=\"sheet\">' +\n                  bloco(false) +\n                  '<div style=\"border-top:2px dashed #111;margin:14px 0;\"><\/div>' +\n                  bloco(true) +\n                  '<div class=\"foot\">Decalcer \u2013 Decalques Vitro Unipessoal Lda \u00b7 Impresso ' + new Date().toLocaleString('pt-PT') + '<\/div>' +\n               '<\/div>';\n    }\n\n    \/\/ ========================================================================\n    \/\/  FICHA 2 \u2014 FICHA DE PRODU\u00c7\u00c3O (12 impress\u00f5es)\n    \/\/ ========================================================================\n    function buildFichaProducao(job) {\n        var rows = '';\n        for (var i = 1; i <= 12; i++) {\n            var c = (job.colors && job.colors[i - 1]) ? job.colors[i - 1] : {};\n            rows += '<tr>' +\n                '<td style=\"width:90px;\">' + i + '\u00aa impress\u00e3o<\/td>' +\n                '<td>' + esc(c.name || '') + (c.composition ? ' \u2014 ' + esc(c.composition) : '') + '<\/td>' +\n                '<td><\/td>' +\n                '<td style=\"width:70px;\"><\/td>' +\n                '<\/tr>';\n        }\n        return '<div class=\"sheet\">' +\n                '<div class=\"hd\"><div><h1>Ficha Produ\u00e7\u00e3o<\/h1>' +\n                  '<div style=\"font-size:10px;color:#444;margin-top:2px;\">Sec\u00e7\u00e3o de Produ\u00e7\u00e3o<\/div><\/div>' +\n                  '<div class=\"meta\"><img decoding=\"async\" src=\"' + LOGO + '\" onerror=\"this.style.display=\\'none\\'\">Ref.\u00aa: <b>' + esc(job.reference || '') + '<\/b><\/div><\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr 1fr;\">' +\n                  fld('Data', fmtDate(job.date)) +\n                  fld('Data de entrega', fmtDate(job.dataEntrega)) +\n                  fld('Decor', job.reference) +\n                  fld('Cliente', job.client) +\n                '<\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr;\">' +\n                  fld('Quantidade', job.sheets) +\n                  fld('Formato', job.sheetSize) +\n                  fld('M\u00e1quina', job.machine) +\n                '<\/div>' +\n                '<div class=\"sec-title\">Ensaio de correspond\u00eancia<\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr;\">' +\n                  fld('Data', '') + fld('Nome', job.operator) + fld('Refer\u00eancia', job.reference) +\n                '<\/div>' +\n                '<div class=\"sec-title\">Tabela de impress\u00f5es<\/div>' +\n                '<table><thead><tr><th>Impress\u00f5es<\/th><th>Cores ou tinta usada<\/th><th>Observa\u00e7\u00f5es<\/th><th>Tempo<\/th><\/tr><\/thead><tbody>' +\n                  rows + '<\/tbody><\/table>' +\n                (job.observations ? '<div class=\"sec-title\">Observa\u00e7\u00f5es<\/div><div class=\"obs\">' + esc(job.observations) + '<\/div>' : '') +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr;margin-top:14px;\">' +\n                  fld('Impressor', job.operator) + fld('Data conclus\u00e3o', '') +\n                '<\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr;\">' +\n                  fld('Embalagem', '') + fld('Dimens\u00f5es', '') + fld('Fatura N\u00ba', '') +\n                '<\/div>' +\n                '<div class=\"foot\">Decalcer \u2013 Decalques Vitro Unipessoal Lda \u00b7 Impresso ' + new Date().toLocaleString('pt-PT') + '<\/div>' +\n               '<\/div>';\n    }\n\n    \/\/ ========================================================================\n    \/\/  FICHA 3 \u2014 FICHA DE PRODU\u00c7\u00c3O DE ECR\u00c3S (14 impress\u00f5es)\n    \/\/ ========================================================================\n    function buildFichaEcras(job) {\n        var rows = '';\n        for (var i = 1; i <= 14; i++) {\n            var c = (job.colors && job.colors[i - 1]) ? job.colors[i - 1] : {};\n            rows += '<tr>' +\n                '<td style=\"width:90px;\">' + i + '\u00aa impress\u00e3o<\/td>' +\n                '<td>' + esc(c.name || '') + '<\/td>' +\n                '<td>' + esc(c.medidaEcra || '') + '<\/td>' +\n                '<td style=\"width:70px;\">' + esc(c.exposicao || '') + '<\/td>' +\n                '<\/tr>';\n        }\n        return '<div class=\"sheet\">' +\n                '<div class=\"hd\"><div><h1>Ficha Produ\u00e7\u00e3o de Ecr\u00e3s<\/h1>' +\n                  '<div style=\"font-size:10px;color:#444;margin-top:2px;\">Sec\u00e7\u00e3o de Ecr\u00e3s e Pr\u00e9-Impress\u00e3o<\/div><\/div>' +\n                  '<div class=\"meta\"><img decoding=\"async\" src=\"' + LOGO + '\" onerror=\"this.style.display=\\'none\\'\">Ref.\u00aa: <b>' + esc(job.reference || '') + '<\/b><\/div><\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr 1fr;\">' +\n                  fld('Data', fmtDate(job.date)) +\n                  fld('Data de entrega', fmtDate(job.dataEntrega)) +\n                  fld('Decor', job.reference) +\n                  fld('Cliente', job.client) +\n                '<\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr;\">' +\n                  fld('Quantidade', job.sheets) +\n                  fld('Formato', job.sheetSize) +\n                  fld('M\u00e1quina', job.machine) +\n                '<\/div>' +\n                '<div class=\"sec-title\">Ensaio de correspond\u00eancia<\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr 1fr;\">' +\n                  fld('Data', '') + fld('Nome', job.operator) + fld('Refer\u00eancia', job.reference) +\n                '<\/div>' +\n                '<div class=\"sec-title\">Tabela de ecr\u00e3s<\/div>' +\n                '<table><thead><tr><th>Impress\u00f5es<\/th><th>Cores<\/th><th>Observa\u00e7\u00f5es \/ Medida ecr\u00e3<\/th><th>Tempo<\/th><\/tr><\/thead><tbody>' +\n                  rows + '<\/tbody><\/table>' +\n                (job.observations ? '<div class=\"sec-title\">Observa\u00e7\u00f5es<\/div><div class=\"obs\">' + esc(job.observations) + '<\/div>' : '') +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr 1fr;margin-top:14px;\">' +\n                  fld('Operador', job.operator) + fld('Data conclus\u00e3o', '') +\n                '<\/div>' +\n                '<div class=\"grid\" style=\"grid-template-columns:1fr;\">' + fld('Fatura N\u00ba', '') + '<\/div>' +\n                '<div class=\"foot\">Decalcer \u2013 Decalques Vitro Unipessoal Lda \u00b7 Impresso ' + new Date().toLocaleString('pt-PT') + '<\/div>' +\n               '<\/div>';\n    }\n\n    \/\/ ---- documento completo (3 p\u00e1ginas) -----------------------------------\n    function buildDocumento(job) {\n        return '<!DOCTYPE html><html lang=\"pt\"><head><meta charset=\"utf-8\">' +\n            '<title>Fichas - ' + esc(job.reference || '') + '<\/title>' +\n            '<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">' +\n            '<style>' + BASE_CSS + '<\/style><\/head><body>' +\n            buildFichaTecnica(job) + buildFichaProducao(job) + buildFichaEcras(job) +\n            '<\/body><\/html>';\n    }\n\n    \/\/ ========================================================================\n    \/\/  MODAL DE PR\u00c9-VISUALIZA\u00c7\u00c3O (3 fichas) + bot\u00e3o imprimir\n    \/\/ ========================================================================\n    window.previewFichas = function (jobId) {\n        var job = getJob(jobId);\n        if (!job) { if (typeof showToast === 'function') showToast('Trabalho n\u00e3o encontrado', 'error'); return; }\n\n        var overlay = document.createElement('div');\n        overlay.className = 'fixed inset-0 bg-slate-900\/80 flex flex-col items-center backdrop-blur-sm p-2 sm:p-4';\n        overlay.style.zIndex = '9999999';\n\n        var bar = document.createElement('div');\n        bar.className = 'w-full max-w-5xl bg-white rounded-t-2xl px-4 py-3 flex justify-between items-center shadow-lg';\n        bar.innerHTML =\n            '<div class=\"font-bold text-slate-800\">Pr\u00e9-visualiza\u00e7\u00e3o das Fichas \u00b7 ' + esc(job.reference || '') + '<\/div>' +\n            '<div class=\"flex gap-2\">' +\n              '<button id=\"pf-print\" class=\"px-4 py-2 bg-indigo-600 text-white font-bold rounded-lg border-none cursor-pointer hover:bg-indigo-700\">\ud83d\udda8\ufe0f Imprimir as 3<\/button>' +\n              '<button id=\"pf-close\" class=\"px-3 py-2 bg-slate-100 text-slate-600 rounded-lg border-none cursor-pointer hover:bg-slate-200\">Fechar<\/button>' +\n            '<\/div>';\n\n        var frame = document.createElement('iframe');\n        frame.className = 'w-full max-w-5xl flex-grow bg-slate-200 border-none rounded-b-2xl';\n        frame.style.height = '80vh';\n\n        overlay.appendChild(bar);\n        overlay.appendChild(frame);\n        document.body.appendChild(overlay);\n\n        var doc = frame.contentWindow.document;\n        doc.open(); doc.write(buildDocumento(job)); doc.close();\n\n        bar.querySelector('#pf-close').onclick = function () { document.body.removeChild(overlay); };\n        bar.querySelector('#pf-print').onclick = function () {\n            frame.contentWindow.focus();\n            frame.contentWindow.print();\n        };\n    };\n\n    \/\/ ---- ligar o bot\u00e3o do modal de edi\u00e7\u00e3o (criado no HTML) ----------------\n    function wireButton() {\n        var btn = document.getElementById('btn-print-fichas');\n        if (btn && !btn.dataset.wired) {\n            btn.dataset.wired = '1';\n            btn.addEventListener('click', function () {\n                var id = (document.getElementById('edit-job-id') || {}).value;\n                if (id) window.previewFichas(id);\n            });\n        }\n    }\n    document.addEventListener('click', wireButton, true);\n    wireButton();\n\n})();\n\n\n});   \n<\/script>  \n<\/body>  \n<\/html>\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\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Gest\u00e3o de Trabalhos | Decalcer A iniciar sistema&#8230; Gest\u00e3o de Trabalhos Defini\u00e7\u00f5es Cores Login Total 0 Produ\u00e7\u00e3o Pedidos de Material 0 Por favor, inicie sess\u00e3o para ter acesso total (edi\u00e7\u00e3o e remo\u00e7\u00e3o). Tipo: TodosProdu\u00e7\u00e3oEnsaios Estado: TodosAbertoEm ProgressoConclu\u00eddoSem Or\u00e7amento Filtrar Limpar An\u00e1lise de Produ\u00e7\u00e3o + Estat\u00edsticas Detalhadas 0 Folhas Total + Novo Registo Clique para expandir [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1166","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>GT V2.0 - Decalcer<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.decalcer.com\/en\/gt-v2-0\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GT V2.0 - Decalcer\" \/>\n<meta property=\"og:description\" content=\"Gest\u00e3o de Trabalhos | Decalcer A iniciar sistema&#8230; Gest\u00e3o de Trabalhos Defini\u00e7\u00f5es Cores Login Total 0 Produ\u00e7\u00e3o Pedidos de Material 0 Por favor, inicie sess\u00e3o para ter acesso total (edi\u00e7\u00e3o e remo\u00e7\u00e3o). Tipo: TodosProdu\u00e7\u00e3oEnsaios Estado: TodosAbertoEm ProgressoConclu\u00eddoSem Or\u00e7amento Filtrar Limpar An\u00e1lise de Produ\u00e7\u00e3o + Estat\u00edsticas Detalhadas 0 Folhas Total + Novo Registo Clique para expandir [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.decalcer.com\/en\/gt-v2-0\/\" \/>\n<meta property=\"og:site_name\" content=\"Decalcer\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/decalcer\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-03T07:24:42+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.decalcer.com\/gt-v2-0\/\",\"url\":\"https:\/\/www.decalcer.com\/gt-v2-0\/\",\"name\":\"GT V2.0 - Decalcer\",\"isPartOf\":{\"@id\":\"https:\/\/www.decalcer.com\/#website\"},\"datePublished\":\"2026-02-27T15:50:27+00:00\",\"dateModified\":\"2026-06-03T07:24:42+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.decalcer.com\/gt-v2-0\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.decalcer.com\/gt-v2-0\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.decalcer.com\/gt-v2-0\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"In\u00edcio\",\"item\":\"https:\/\/www.decalcer.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GT V2.0\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.decalcer.com\/#website\",\"url\":\"https:\/\/www.decalcer.com\/\",\"name\":\"Decalcer\",\"description\":\"Decalques cer\u00e2micos\",\"publisher\":{\"@id\":\"https:\/\/www.decalcer.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.decalcer.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.decalcer.com\/#organization\",\"name\":\"Decalcer decalques vitro unipessoal, Lda\",\"url\":\"https:\/\/www.decalcer.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/www.decalcer.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.decalcer.com\/wp-content\/uploads\/2023\/06\/logo-decalcer.png\",\"contentUrl\":\"https:\/\/www.decalcer.com\/wp-content\/uploads\/2023\/06\/logo-decalcer.png\",\"width\":900,\"height\":300,\"caption\":\"Decalcer decalques vitro unipessoal, Lda\"},\"image\":{\"@id\":\"https:\/\/www.decalcer.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/decalcer\",\"https:\/\/www.linkedin.com\/company\/decalcer\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GT V2.0 - Decalcer","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.decalcer.com\/en\/gt-v2-0\/","og_locale":"en_GB","og_type":"article","og_title":"GT V2.0 - Decalcer","og_description":"Gest\u00e3o de Trabalhos | Decalcer A iniciar sistema&#8230; Gest\u00e3o de Trabalhos Defini\u00e7\u00f5es Cores Login Total 0 Produ\u00e7\u00e3o Pedidos de Material 0 Por favor, inicie sess\u00e3o para ter acesso total (edi\u00e7\u00e3o e remo\u00e7\u00e3o). Tipo: TodosProdu\u00e7\u00e3oEnsaios Estado: TodosAbertoEm ProgressoConclu\u00eddoSem Or\u00e7amento Filtrar Limpar An\u00e1lise de Produ\u00e7\u00e3o + Estat\u00edsticas Detalhadas 0 Folhas Total + Novo Registo Clique para expandir [&hellip;]","og_url":"https:\/\/www.decalcer.com\/en\/gt-v2-0\/","og_site_name":"Decalcer","article_publisher":"https:\/\/www.facebook.com\/decalcer","article_modified_time":"2026-06-03T07:24:42+00:00","twitter_card":"summary_large_image","twitter_misc":{"Estimated reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.decalcer.com\/gt-v2-0\/","url":"https:\/\/www.decalcer.com\/gt-v2-0\/","name":"GT V2.0 - Decalcer","isPartOf":{"@id":"https:\/\/www.decalcer.com\/#website"},"datePublished":"2026-02-27T15:50:27+00:00","dateModified":"2026-06-03T07:24:42+00:00","breadcrumb":{"@id":"https:\/\/www.decalcer.com\/gt-v2-0\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.decalcer.com\/gt-v2-0\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.decalcer.com\/gt-v2-0\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"In\u00edcio","item":"https:\/\/www.decalcer.com\/"},{"@type":"ListItem","position":2,"name":"GT V2.0"}]},{"@type":"WebSite","@id":"https:\/\/www.decalcer.com\/#website","url":"https:\/\/www.decalcer.com\/","name":"Decal","description":"Decalques cer\u00e2micos","publisher":{"@id":"https:\/\/www.decalcer.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.decalcer.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/www.decalcer.com\/#organization","name":"Decalcer decalques vitro unipessoal, Lda","url":"https:\/\/www.decalcer.com\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.decalcer.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.decalcer.com\/wp-content\/uploads\/2023\/06\/logo-decalcer.png","contentUrl":"https:\/\/www.decalcer.com\/wp-content\/uploads\/2023\/06\/logo-decalcer.png","width":900,"height":300,"caption":"Decalcer decalques vitro unipessoal, Lda"},"image":{"@id":"https:\/\/www.decalcer.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/decalcer","https:\/\/www.linkedin.com\/company\/decalcer"]}]}},"_links":{"self":[{"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/pages\/1166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/comments?post=1166"}],"version-history":[{"count":89,"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/pages\/1166\/revisions"}],"predecessor-version":[{"id":1857,"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/pages\/1166\/revisions\/1857"}],"wp:attachment":[{"href":"https:\/\/www.decalcer.com\/en\/wp-json\/wp\/v2\/media?parent=1166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}