<?php
// CARGA MAESTRA DE CONFIGURACIÓN Y BRANDING
require_once(__DIR__ . '/core/init.php');

if (ob_get_level() > 0) {
    ob_end_clean();
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Rutas Estratégicas De Servicios <?php echo htmlspecialchars($branding['full_title']); ?></title>
    <meta name="robots" content="noindex, nofollow">
    
    <link rel="icon" type="image/png" href="<?php echo htmlspecialchars($branding['favicon']); ?>">
    <link rel="apple-touch-icon" href="<?php echo htmlspecialchars($branding['favicon']); ?>">
    
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="<?php echo htmlspecialchars($google_font_url); ?>">

    <?php include 'files/gtm-head.php'; ?>
    
    <script src="https://unpkg.com/lucide@latest"></script>
    <script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
    
    <link rel="stylesheet" href="style.css"> 
    <script src="files/header-manager.js"></script>
    
    <style>
        .kanban-list {
            min-height: 150px; 
            transition: background-color 0.2s ease;
        }
        .kanban-list.sortable-ghost {
            opacity: 0.4;
            background-color: #f3f4f6;
        }
        .sortable-drag {
            cursor: grabbing;
        }
        /* Estilo específico para los botones de los modales para que coincidan con la imagen */
        .btn-modal-cancel {
            background-color: var(--color-primary); /* Azul Oscuro */
            color: white;
        }
        .btn-modal-cancel:hover {
            background-color: #0f172a;
        }
        .btn-modal-confirm {
            background-color: var(--color-secondary); /* Rojo */
            color: white;
        }
        .btn-modal-confirm:hover {
            background-color: #991b1b;
        }
    </style>
    
</head>

<body data-page-title="Rutas Estratégicas De Servicios" 
      data-page-subtitle="Optimizador De Eficiencia Para Visitas De Servicios" 
      data-page-icon="git-compare-arrows">
    
    <div id="toast-container" class="toast-container"></div>
    
<?php include 'files/gtm-body.php'; ?> 

<div class="relative min-h-screen md:flex">
    <div id="sidebar-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-30 hidden md:hidden"></div>
    <div id="task-panel-overlay" class="fixed inset-0 bg-black/60 z-40 hidden transition-opacity duration-300"></div>  
    
    <?php include 'menu.php'; ?>
    
    <main class="flex-1 overflow-y-auto">
        <header class="bg-white shadow-sm p-4 flex justify-between items-center sticky top-0 z-20">
            <button id="mobile-menu-button" class="md:hidden text-gray-600 hover:text-gray-800">
                <i data-lucide="menu" class="w-6 h-6"></i>
            </button>
            <div class="page-header-container">
                <h2 id="page-title"></h2>
                <p id="page-subtitle"></p>
            </div>
        </header>

        <div id="content-area" class="p-4 md:p-8">
                
                <div id="create-route-modal" class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50 font-barlow">
                    <div class="modal-dialog relative mx-auto p-0 border-0 shadow-2xl rounded-xl bg-white w-full max-w-md transform transition-all duration-300 scale-95 opacity-0 text-center overflow-hidden">
                        
                        <div class="modal-header-container bg-[var(--color-primary)] p-6">
                            <h3 class="modal-primary-title text-3xl font-black text-[var(--color-highlight)] uppercase leading-none">
                                NUEVA RUTA
                            </h3>
                            <p class="text-sm font-bold text-white/80 uppercase mt-1">SEMANA <span id="modal-week-number" class="text-[var(--color-highlight)]"></span></p>
                        </div>
                        <button id="toggle-view-btn" class="bg-gray-200 hover:bg-gray-300 text-gray-700 font-bold py-2 px-4 rounded-lg text-sm flex items-center gap-2">
    <i data-lucide="list"></i> VISTA COMPACTA
</button>

                        <div class="p-8 space-y-4 text-left">
                            <div>
                                <label class="block text-xs font-bold text-gray-500 uppercase mb-1">Nombre de la Ruta</label>
                                <input type="text" id="new-route-name" placeholder="Ej. Ruta de José" class="w-full p-3 border-2 border-gray-300 rounded-lg focus:border-[var(--color-secondary)] focus:ring-0 outline-none transition-colors font-bold text-gray-700">
                            </div>
                            <div>
                                <label class="block text-xs font-bold text-gray-500 uppercase mb-1">Día Asignado</label>
                                <select id="new-route-day" class="w-full p-3 border-2 border-gray-300 rounded-lg bg-white focus:border-[var(--color-secondary)] focus:ring-0 outline-none transition-colors font-bold text-gray-700">
                                    <option value="">Seleccionar día (Opcional)</option>
                                    <option value="Lunes">Lunes</option><option value="Martes">Martes</option><option value="Miércoles">Miércoles</option><option value="Jueves">Jueves</option><option value="Viernes">Viernes</option><option value="Sábado">Sábado</option><option value="Domingo">Domingo</option>
                                </select>
                            </div>
                            <div class="flex flex-col sm:flex-row justify-center space-y-3 sm:space-y-0 sm:space-x-4 mt-8">
                                <button class="close-modal-btn btn-modal-cancel font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-sm">
                                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                                </button>
                                <button id="save-new-route-btn" class="btn-modal-confirm font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-md">
                                    <i data-lucide="save" class="w-5 h-5"></i> GUARDAR
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <div id="edit-route-modal" class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50 font-barlow">
                    <div class="modal-dialog relative mx-auto p-0 border-0 shadow-2xl rounded-xl bg-white w-full max-w-md transform transition-all duration-300 scale-95 opacity-0 text-center overflow-hidden">
                        
                        <div class="modal-header-container bg-[var(--color-primary)] p-6">
                            <h3 class="modal-primary-title text-3xl font-black text-[var(--color-highlight)] uppercase leading-none">
                                EDITAR RUTA
                            </h3>
                        </div>

                        <div class="p-8 space-y-4 text-left">
                            <div>
                                <label class="block text-xs font-bold text-gray-500 uppercase mb-1">Nombre de la Ruta</label>
                                <input type="text" id="edit-route-name" class="w-full p-3 border-2 border-gray-300 rounded-lg focus:border-[var(--color-secondary)] focus:ring-0 outline-none font-bold text-gray-700">
                            </div>
                            <div>
                                <label class="block text-xs font-bold text-gray-500 uppercase mb-1">Día Asignado</label>
                                <select id="edit-route-day" class="w-full p-3 border-2 border-gray-300 rounded-lg bg-white focus:border-[var(--color-secondary)] focus:ring-0 outline-none font-bold text-gray-700">
                                    <option value="">Seleccionar día (Opcional)</option>
                                    <option value="Lunes">Lunes</option><option value="Martes">Martes</option><option value="Miércoles">Miércoles</option><option value="Jueves">Jueves</option><option value="Viernes">Viernes</option><option value="Sábado">Sábado</option><option value="Domingo">Domingo</option>
                                </select>
                            </div>
                            <input type="hidden" id="current-edit-route-id">
                            <div class="flex flex-col sm:flex-row justify-center space-y-3 sm:space-y-0 sm:space-x-4 mt-8">
                                <button class="close-modal-btn btn-modal-cancel font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-sm">
                                    <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                                </button>
                                <button id="save-edit-route-btn" class="btn-modal-confirm font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-md">
                                    <i data-lucide="save" class="w-5 h-5"></i> GUARDAR
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div id="add-client-modal" class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50 font-barlow">
                    <div class="modal-dialog relative mx-auto p-0 border-0 shadow-2xl rounded-xl bg-white w-full max-w-lg transform transition-all duration-300 scale-95 opacity-0 text-center overflow-hidden">
                        
                        <div class="modal-header-container bg-[var(--color-primary)] p-6">
                            <h3 class="modal-primary-title text-3xl font-black text-[var(--color-highlight)] uppercase leading-none">
                              <i data-lucide="user-plus"></i> <span>AGREGAR CLIENTE</span>
                            </h3>
                            <p class="text-xs font-bold text-gray-200 uppercase mt-2 tracking-wider">BUSCAR EN LA BASE DE DATOS GLOBAL</p>
                        </div>

                        <div class="p-8">
                            <div class="relative mb-4">
                                <i data-lucide="search" class="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400"></i>
                                <input type="text" id="modal-client-search-input" placeholder="Escribe el nombre del cliente..." class="w-full p-3 pl-10 border-2 border-gray-300 rounded-lg focus:border-[var(--color-primary)] focus:ring-0 outline-none font-semibold">
                            </div>
                            
                            <div id="modal-search-results" class="space-y-2 max-h-64 overflow-y-auto border rounded-lg p-2 bg-gray-50 shadow-inner custom-scrollbar text-left">
                                <p class="text-center text-gray-500 p-4 text-sm italic">Los resultados aparecerán aquí...</p>
                            </div>

                            <div class="flex justify-center mt-8">
                                <button class="close-modal-btn btn-modal-cancel font-black py-2.5 px-8 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-sm">
                                    <i data-lucide="x-circle" class="w-5 h-5"></i> CERRAR
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="flex flex-col sm:flex-row justify-between sm:items-center gap-4 mb-6">
                    <div class="bg-white p-2 rounded-lg shadow-md border flex flex-wrap items-center gap-4">
                        <div class="flex items-center gap-2">
                            <span class="font-bold text-lg text-[var(--color-primary)] ml-2 uppercase">SEMANA:</span>
                            <div id="week-filter-container" class="flex items-center gap-1"></div>
                        </div>
                        <h3 id="week-range-display" class="font-black text-xl md:text-2xl uppercase text-[var(--color-secondary)] pr-2"></h3>
                    </div>
                    <button id="create-route-btn" class="bg-[var(--color-secondary)] hover:opacity-90 text-white font-black py-3 px-6 rounded-lg uppercase flex items-center gap-2 shadow-lg hover:shadow-xl transition-all">
                        <i data-lucide="plus-circle" class="w-5 h-5"></i> CREAR NUEVA RUTA
                    </button>
                </div>
                
                <div class="grid grid-cols-1 lg:grid-cols-[theme(spacing.96)_1fr] lg:gap-6 space-y-6 lg:space-y-0 pb-6 pt-2">
                    
                    <div id="clients-source-list" class="flex-shrink-0 w-full lg:w-96 bg-white rounded-xl shadow-md p-4 min-h-[70vh] border-l-4 border-[var(--color-highlight)] flex flex-col">
                        <div class="flex justify-between items-center mb-4 border-b pb-2">
                            <h2 class="text-2xl font-black flex items-center text-[var(--color-primary)] uppercase">
                                <i data-lucide="users" class="w-6 h-6 mr-2 text-[var(--color-highlight)]"></i> PANEL DE RUTAS
                            </h2>
                            <button id="add-client-btn" class="p-2 bg-[var(--color-secondary)] text-white rounded-full hover:opacity-90 transition shadow-md" title="Agregar Cliente al Panel">
                                <i data-lucide="plus" class="w-5 h-5"></i>
                            </button>
                        </div>
                        <div class="relative mb-4">
                            <i data-lucide="search" class="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400"></i>
                            <input type="text" id="client-search-input" placeholder="Filtrar clientes en este panel..." class="w-full p-3 pl-10 border-2 border-gray-300 rounded-lg focus:border-[var(--color-primary)] focus:ring-0 outline-none text-sm">
                        </div>
                        <div id="clients-container" class="space-y-3 h-full overflow-y-auto max-h-[calc(100vh-300px)] kanban-list p-1 custom-scrollbar">
                            <p id="clients-placeholder" class="text-sm text-gray-500 italic p-4 text-center bg-gray-50 rounded border border-dashed border-gray-300">
                                Cargando clientes...
                            </p>
                        </div>
                    </div>
                    
                    <div class="min-w-0 w-full">
                        <div id="routes-kanban-container" class="grid grid-cols-1 md:grid-cols-2 gap-6 w-full"></div>
                    </div>
                </div>

                <div class="mt-8 pt-6 border-t-2 border-gray-200">
                    <h3 class="text-3xl font-black text-[var(--color-primary)] mb-6 flex items-center">
                        <i data-lucide="bar-chart-3" class="w-8 h-8 mr-3 text-[var(--color-highlight)]"></i>RESUMEN SEMANA ACTUAL
                    </h3>
                    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">

                        <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                            <i data-lucide="route" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                            <div>
                                <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Rutas</h3>
                                <p id="summary-routes-count" class="text-5xl font-bold text-[var(--color-primary)]">0</p>
                            </div>
                        </div>

                        <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                            <i data-lucide="clock" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                            <div>
                                <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Tiempo</h3>
                                <p id="summary-total-time" class="text-4xl font-bold text-[var(--color-primary)]">0h 0m</p>
                            </div>
                        </div>

                        <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                            <i data-lucide="wallet" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                            <div>
                                <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Ingreso</h3>
                                <p id="summary-total-value" class="text-4xl font-bold text-[var(--color-primary)]">$0.00</p>
                            </div>
                        </div>

                        <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
                            <i data-lucide="users" class="w-12 h-12 text-[var(--color-secondary)]"></i>
                            <div>
                                <h3 class="text-lg font-black text-gray-500 mb-1 uppercase">Clientes</h3>
                                <p id="summary-clients-assigned" class="text-5xl font-bold text-[var(--color-primary)]">0</p>
                            </div>
                        </div>
                    
                    </div>
                </div>
                
                <div class="mt-8 pt-6 border-t-2 border-gray-200">
                    <h3 class="text-3xl font-black text-[var(--color-primary)] mb-6 flex items-center">
                        <i data-lucide="calendar-days" class="w-8 h-8 mr-3 text-[var(--color-highlight)]"></i>DESGLOSE DIARIO
                    </h3>
                    <div id="daily-summary-container" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-7 gap-4 bg-white p-6 rounded-xl shadow-md border-l-4 border-[var(--color-primary)]"></div>
                </div>
            </div>
        </main>
        
        <div id="client-detail-panel-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-40 transition-opacity duration-300 opacity-0 pointer-events-none"></div>

        <aside id="client-detail-panel" class="fixed top-0 right-0 h-full w-full lg:w-1/3 bg-[var(--color-background)] z-50 transform translate-x-full transition-transform duration-300 ease-in-out shadow-2xl flex flex-col">
            
            <div class="flex flex-col h-full">
                <div class="flex-shrink-0 flex justify-between items-center p-4 border-b border-gray-200 bg-[var(--color-primary)] text-white shadow z-20">
                    <h3 class="text-3xl font-black text-[var(--color-highlight)] flex items-center uppercase truncate">
                        <i data-lucide="user-check" class="w-8 h-8 mr-2 text-white"></i>
                        <span id="panel-client-name">DETALLES</span>
                    </h3>
                    <button id="close-client-detail-panel" class="bg-[var(--color-secondary)] text-white hover:text-[var(--color-highlight)] p-1 rounded-md transition-colors duration-200">
                        <i data-lucide="x" class="w-8 h-8"></i>
                    </button>
                </div>

                <div class="flex-grow overflow-y-auto p-4 space-y-6 relative custom-scrollbar">
                    
                    <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                        <div class="border-b pb-3 mb-4">
                            <h4 class="text-2xl font-black text-[var(--color-secondary)] uppercase flex items-center">
                                <i data-lucide="info" class="w-5 h-5 mr-2"></i>
                                INFORMACIÓN CLAVE
                            </h4>
                        </div>
                        
                        <div class="space-y-2 mb-6">
    <div>
        <span class="text-xs font-bold text-gray-500 uppercase block">Dirección</span>
        <span id="panel-client-address" class="text-sm font-semibold text-gray-800 block mb-2"></span>
        
        <a id="btn-open-maps" href="#" target="_blank" class="hidden w-full bg-blue-50 text-blue-600 border border-blue-200 hover:bg-blue-100 hover:border-blue-300 font-bold py-2.5 px-4 rounded-lg uppercase transition-all duration-200 flex items-center justify-center gap-2 text-sm shadow-sm">
            <i data-lucide="map-pin" class="w-4 h-4"></i> ABRIR EN MAPS
        </a>
    </div>
    
    <div class="mt-4"> <span class="text-xs font-bold text-gray-500 uppercase block">Valor Servicio</span>
        <span id="panel-client-value" class="text-lg font-black text-green-600"></span>
    </div>
</div>

                        <div class="bg-gray-50 p-3 rounded-lg border border-gray-100">
                            <h4 class="text-xs font-bold text-gray-500 uppercase mb-2 flex items-center">
                                <i data-lucide="clock" class="w-4 h-4 mr-1"></i> TIEMPO ESTIMADO
                            </h4>
                            <div class="flex items-center space-x-2">
                                <input type="number" id="input-service-time" class="w-20 p-2 border border-gray-300 rounded-lg text-center font-bold text-lg focus:border-[var(--color-primary)] focus:ring-0 outline-none" min="0" value="0">
                                <span class="text-xs font-bold text-gray-600">MIN</span>
                                <button id="save-service-time-btn" class="ml-auto bg-[var(--color-primary)] hover:bg-gray-800 text-white font-bold uppercase text-xs px-3 py-2 rounded-lg flex items-center gap-1 transition-all shadow-sm disabled:opacity-50 disabled:cursor-not-allowed" disabled>
                                    <i data-lucide="save" class="w-4 h-4"></i> GUARDAR
                                </button>
                            </div>
                            <p id="time-save-status" class="text-xs mt-2 text-[var(--color-secondary)] font-medium text-center hidden">Actualizando...</p>
                        </div>
                    </div>

                    <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                        <div class="border-b pb-3 mb-4">
                            <h4 class="text-2xl font-black text-[var(--color-secondary)] uppercase flex items-center">
                                <i data-lucide="briefcase" class="w-5 h-5 mr-2"></i>
                                SERVICIOS ASIGNADOS
                            </h4>
                        </div>
                        <div id="panel-assigned-services" class="flex flex-wrap gap-2">
                            <p class="text-sm text-gray-500 italic">Cargando servicios...</p>
                        </div>
                    </div>

                    <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                        <div class="border-b pb-3 mb-4">
                            <h4 class="text-2xl font-black text-[var(--color-secondary)] uppercase flex items-center">
                                <i data-lucide="calendar-check" class="w-5 h-5 mr-2"></i>
                                CITAS RECIENTES
                            </h4>
                        </div>
                        <div id="panel-recent-appointments" class="space-y-3">
                            <p class="text-sm text-gray-500 italic">Cargando citas...</p>
                        </div>
                    </div>

                    <div class="bg-white p-4 rounded-xl shadow-md transition duration-300">
                        <div class="border-b pb-3 mb-4">
                            <h4 class="text-2xl font-black text-[var(--color-secondary)] uppercase flex items-center">
                                <i data-lucide="file-text" class="w-5 h-5 mr-2"></i>
                                FACTURAS PENDIENTES
                            </h4>
                        </div>
                        <div id="panel-pending-invoices" class="space-y-3">
                            <p class="text-sm text-gray-500 italic">Cargando facturas...</p>
                        </div>
                    </div>

                </div>
                
                <input type="hidden" id="panel-current-client-id">

                <div class="p-4 bg-gray-100 border-t border-gray-200 flex-shrink-0 z-10"> 
                    <button id="close-panel-btn-fixed" class="w-full bg-[var(--color-primary)] hover:bg-gray-800 text-white font-black py-2 px-4 rounded-lg uppercase flex items-center justify-center gap-2 shadow transition-all">
                        <i data-lucide="eye-off" class="w-5 h-5"></i> CERRAR PANEL
                    </button>
                </div>
            </div>
        </aside>
        
        <div id="generic-confirm-modal" 
             class="fixed inset-0 bg-gray-900 bg-opacity-90 flex items-center justify-center hidden z-50 font-barlow"
             onclick="if(event.target === this) document.querySelector('#generic-confirm-modal .close-modal-btn').click()">
            
            <div class="modal-dialog relative mx-auto p-0 border-0 shadow-2xl rounded-xl bg-white w-full max-w-sm m-4 text-center transform transition-all duration-300 scale-95 opacity-0 overflow-hidden">
                
                <div class="modal-header-container bg-[var(--color-primary)] p-6">
                    <h3 class="modal-primary-title text-4xl font-black text-[var(--color-highlight)] uppercase leading-none">ADVERTENCIA</h3>
                </div>

                <div class="p-8">
                    <div class="flex justify-center mb-6">
                        <i data-lucide="alert-triangle" class="w-16 h-16 text-[var(--color-secondary)]"></i>
                    </div>
                    
                    <p class="text-[var(--color-primary)] mb-6 uppercase text-lg font-bold leading-tight">
                        ¿DESEAS QUITAR A 
                        <span id="confirm-dynamic-name" class="font-black text-[var(--color-secondary)] text-xl inline-block uppercase mx-1"></span>
                        DE LA <span id="confirm-dynamic-detail" class="font-bold text-[var(--color-secondary)] text-lg inline-block"></span>
                        ?
                    </p>

                    <input type="hidden" id="confirm-action-type">
                    <input type="hidden" id="confirm-client-id">
                    <input type="hidden" id="confirm-route-id">
                    <input type="hidden" id="confirm-week-number">

                    <div class="flex flex-col sm:flex-row justify-center space-y-3 sm:space-y-0 sm:space-x-4 mt-6">
                        <button type="button" class="close-modal-btn btn-modal-cancel font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-sm">
                            <i data-lucide="x-circle" class="w-5 h-5"></i> CANCELAR
                        </button>
                        
                        <button id="execute-confirm-btn" type="button" class="btn-modal-confirm font-black py-2.5 px-6 rounded-lg uppercase w-full sm:w-auto flex items-center justify-center gap-2 shadow-md">
                            <i data-lucide="check-circle" class="w-5 h-5"></i> CONFIRMAR
                        </button>
                    </div>
                    
                    <p class="mt-6 uppercase text-xs font-black text-gray-500 tracking-wider"> 
                        ESTA ACCIÓN NO SE PUEDE DESHACER
                    </p>
                </div>
            </div>
        </div>
    </div>
    
<script>
document.addEventListener('DOMContentLoaded', () => {
    function getWeekOfMonth(date) {
        const d = new Date(date);
        const firstDay = new Date(d.getFullYear(), d.getMonth(), 1).getDay();
        const dayOfMonth = d.getDate();
        const offset = (firstDay === 0) ? 6 : firstDay - 1;
        const week = Math.ceil((dayOfMonth + offset) / 7);
        return Math.min(week, 5);
    }

    let draggedItem = null,
        workspaceClients = [],
        masterClientList = [],
        allRoutes = [],
        allAssignments = [],
        selectedWeek = getWeekOfMonth(new Date()); 
    let searchTimeout = null;
    const weekStartDates = getDatesForCurrentMonth();

    const clientsContainer = document.getElementById('clients-container');
    const routesContainer = document.getElementById('routes-kanban-container');
    const createRouteModal = document.getElementById('create-route-modal');
    const editRouteModal = document.getElementById('edit-route-modal');
    const addClientModal = document.getElementById('add-client-modal');
    const genericConfirmModal = document.getElementById('generic-confirm-modal');
    const executeConfirmBtn = document.getElementById('execute-confirm-btn');
    const modalClientSearchInput = document.getElementById('modal-client-search-input');
    const modalSearchResults = document.getElementById('modal-search-results');
    const weekFilterContainer = document.getElementById('week-filter-container');
    const weekRangeDisplay = document.getElementById('week-range-display');
    const mainSearchInput = document.getElementById('client-search-input');

    function showModal(modalId) {
        const modal = document.getElementById(modalId);
        if (!modal) return;
        const modalBox = modal.querySelector('.modal-dialog');
        modal.classList.remove('hidden');
        setTimeout(() => { 
            modalBox.classList.remove('scale-95', 'opacity-0'); 
            modalBox.classList.add('scale-100', 'opacity-100'); 
        }, 50);
        document.body.style.overflow = 'hidden';
        lucide.createIcons();
    }

    function hideModal(modalId) {
        const modal = document.getElementById(modalId);
        if (!modal) return;
        const modalBox = modal.querySelector('.modal-dialog');
        modalBox.classList.remove('scale-100', 'opacity-100');
        modalBox.classList.add('scale-95', 'opacity-0');
        setTimeout(() => {
            modal.classList.add("hidden");
            document.body.style.overflow = "";
        }, 300);
    }

    function hideAllModals() { 
        [createRouteModal, editRouteModal, addClientModal, genericConfirmModal].forEach(m => hideModal(m.id)) 
    }
    
    function getDatesForCurrentMonth() { let e = new Date, t = e.getFullYear(), o = e.getMonth(), n = { 1: {}, 2: {}, 3: {}, 4: {}, 5: {} }, r = new Date(t, o + 1, 0).getDate(); function a(e) { let t = new Date(e.getFullYear(), e.getMonth(), 1).getDay(); return Math.ceil((e.getDate() + (0 === t ? 6 : t - 1)) / 7) } for (let i = 1; i <= r; i++) { let e = new Date(t, o, i), l = a(e); if (l > 0 && l <= 5) { let t = e.toLocaleDateString("es-ES", { weekday: "long" }); n[l][t.charAt(0).toUpperCase() + t.slice(1)] = e.getDate() } } return n }


    const clientDetailPanel = document.getElementById('client-detail-panel');
    const closePanelBtn = document.getElementById('close-client-detail-panel');
    const closePanelBtnFixed = document.getElementById('close-panel-btn-fixed');
    const saveServiceTimeBtn = document.getElementById('save-service-time-btn');
    const inputServiceTime = document.getElementById('input-service-time');
    
    const overlay = document.getElementById('client-detail-panel-overlay');

    function openDetailsPanel() {
        clientDetailPanel.classList.remove('translate-x-full');
        clientDetailPanel.classList.add('translate-x-0');
        overlay.classList.remove('opacity-0', 'pointer-events-none');
        overlay.classList.add('opacity-100');
    }

    function closeDetailsPanel() {
        clientDetailPanel.classList.remove('translate-x-0');
        clientDetailPanel.classList.add('translate-x-full');
        overlay.classList.remove('opacity-100');
        overlay.classList.add('opacity-0', 'pointer-events-none');
    }

    closePanelBtn.addEventListener('click', closeDetailsPanel);
    closePanelBtnFixed.addEventListener('click', closeDetailsPanel);
    overlay.addEventListener('click', closeDetailsPanel);

   async function showClientDetails(clientId, clientName) {
        // 1. Mostrar datos básicos del panel inmediatamente
        document.getElementById('panel-client-name').textContent = clientName;
        document.getElementById('panel-current-client-id').value = clientId;
        openDetailsPanel();
        
        // 2. Resetear estados visuales mientras carga (loading states)
        saveServiceTimeBtn.disabled = true;
        document.getElementById('panel-client-address').textContent = 'Cargando...';
        document.getElementById('panel-client-value').textContent = 'Cargando...';
        inputServiceTime.value = 0;
        document.getElementById('panel-assigned-services').innerHTML = '<p class="text-sm text-gray-500 italic">Cargando servicios...</p>';
        document.getElementById('panel-recent-appointments').innerHTML = '<p class="text-sm text-gray-500 italic">Cargando citas...</p>';
        document.getElementById('panel-pending-invoices').innerHTML = '<p class="text-sm text-gray-500 italic">Cargando facturas...</p>';
        document.getElementById('time-save-status').classList.add('hidden');
        
        // Ocultar botón de mapa por defecto
        const mapsBtn = document.getElementById('btn-open-maps');
        if(mapsBtn) mapsBtn.classList.add('hidden');
        
        try {
            const response = await fetch(`db/client-route-details-read.php?client_id=${clientId}`);
            const data = await response.json();

            if (data.status === 'success' && data.client) { 
                const client = data.client;
                
                // --- CORRECCIÓN: LÓGICA DE DIRECCIÓN Y MAPA ---
                const fullAddress = client.full_address || client.address || '';
                const addressDisplay = document.getElementById('panel-client-address');
                
                if (fullAddress && fullAddress.length > 3) {
                    addressDisplay.textContent = fullAddress;
                    
                    if (mapsBtn) {
                        // URL Estándar de Google Maps Search
                        const encodedAddress = encodeURIComponent(fullAddress);
                        mapsBtn.href = `https://www.google.com/maps/search/?api=1&query=${encodedAddress}`;
                        mapsBtn.classList.remove('hidden');
                    }
                } else {
                    addressDisplay.textContent = 'Sin dirección registrada';
                }
                // ----------------------------------------------

                document.getElementById('panel-client-value').textContent = `$${data.total_service_value}`;
                inputServiceTime.value = client.service_time || 0;
                saveServiceTimeBtn.disabled = false;
                inputServiceTime.dataset.initialValue = client.service_time || 0;

                // --- Renderizar Servicios ---
                const servicesContainer = document.getElementById('panel-assigned-services');
                servicesContainer.innerHTML = '';
                if (data.services && data.services.length > 0) {
                    data.services.forEach(serviceName => {
                        servicesContainer.innerHTML += `<span class="inline-block bg-[var(--color-primary)] text-white text-xs font-semibold px-2.5 py-0.5 rounded-full mr-2 mb-1">${serviceName}</span>`;
                    });
                } else {
                    servicesContainer.innerHTML = '<p class="text-sm text-gray-500 italic">No hay servicios principales asignados.</p>';
                }

                // --- Renderizar Citas ---
                const apptContainer = document.getElementById('panel-recent-appointments');
                apptContainer.innerHTML = '';
                if (data.appointments.length > 0) {
                    data.appointments.forEach(appt => {
                        const statusClass = appt.status === 'confirmed' ? 'bg-blue-100 text-blue-800' : 
                                            appt.status === 'completed' ? 'bg-green-100 text-green-800' : 'bg-[var(--color-secondary)] text-white';
                        apptContainer.innerHTML += `
                            <div class="flex justify-between items-center text-sm border-b pb-1">
                                <span class="font-semibold">${appt.appointment_date} ${appt.appointment_time.substring(0, 5)}</span>
                                <span class="px-2 py-0.5 rounded-full text-xs font-medium ${statusClass}">${appt.status.toUpperCase()}</span>
                            </div>
                        `;
                    });
                } else {
                    apptContainer.innerHTML = '<p class="text-sm text-gray-500 italic">No hay citas recientes (últimos 30 días).</p>';
                }

                // --- Renderizar Facturas ---
                const invoiceContainer = document.getElementById('panel-pending-invoices');
                invoiceContainer.innerHTML = '';
                if (data.invoices.length > 0) {
                    data.invoices.forEach(inv => {
                        invoiceContainer.innerHTML += `
                            <div class="flex justify-between items-center text-sm border-b pb-1">
                                <span class="font-semibold">${inv.external_id} (${inv.invoice_date})</span>
                                <span class="font-bold text-[var(--color-secondary)]">$${parseFloat(inv.total_amount).toFixed(2)}</span>
                            </div>
                        `;
                    });
                } else {
                    invoiceContainer.innerHTML = '<p class="text-sm text-gray-500 italic">No hay facturas pendientes (estado: enviada).</p>';
                }

            } else {
                showToast(data.message || 'Error al cargar detalles del cliente.', 'error');
            }
        } catch (error) {
            console.error("Error en showClientDetails:", error);
            showToast('Error de conexión al obtener detalles.', 'error');
        }
        lucide.createIcons();
    }
    
    inputServiceTime.addEventListener('input', (e) => {
        const value = parseInt(e.target.value);
        const initialValue = parseInt(e.target.dataset.initialValue);
        saveServiceTimeBtn.disabled = isNaN(value) || value < 0 || value === initialValue;
    });

    saveServiceTimeBtn.addEventListener('click', async () => {
        const clientId = document.getElementById('panel-current-client-id').value;
        const newTime = parseInt(inputServiceTime.value);
        
        if (isNaN(newTime) || newTime < 0) {
            showToast('Ingresa un tiempo válido en minutos.', 'error');
            return;
        }

        document.getElementById('time-save-status').textContent = 'Guardando...';
        document.getElementById('time-save-status').classList.remove('hidden', 'text-[var(--color-secondary)]', 'text-green-600');
        document.getElementById('time-save-status').classList.add('text-[var(--color-secondary)]');
        saveServiceTimeBtn.disabled = true;

        const formData = new FormData();
        formData.append('client_id', clientId);
        formData.append('service_time', newTime);

        try {
            const response = await fetch('db/routes-update-client-time.php', { method: 'POST', body: formData });
            const result = await response.json();

            if (result.status === 'success') {
                document.getElementById('time-save-status').textContent = '¡Guardado! Actualizando panel de rutas...';
                
                const clientIndex = masterClientList.findIndex(c => String(c.id) === clientId);
                if (clientIndex !== -1) {
                    masterClientList[clientIndex].service_time = newTime;
                }
                
                updateAllSummariesForCurrentWeek();
                
                inputServiceTime.dataset.initialValue = newTime;
                document.getElementById('time-save-status').textContent = '¡Tiempo de servicio actualizado con éxito!';
                document.getElementById('time-save-status').classList.remove('text-[var(--color-secondary)]');
                document.getElementById('time-save-status').classList.add('text-green-600');
                
                setTimeout(() => {
                    document.getElementById('time-save-status').classList.add('hidden');
                }, 3000);
            } else {
                showToast(result.message, 'error');
                document.getElementById('time-save-status').textContent = 'Error al guardar.';
                document.getElementById('time-save-status').classList.remove('text-[var(--color-secondary)]', 'text-green-600');
                document.getElementById('time-save-status').classList.add('text-[var(--color-secondary)]');
            }
        } catch (err) {
            showToast('Error de conexión al guardar el tiempo.', 'error');
            document.getElementById('time-save-status').textContent = 'Error de conexión.';
            document.getElementById('time-save-status').classList.remove('text-[var(--color-secondary)]', 'text-green-600');
            document.getElementById('time-save-status').classList.add('text-[var(--color-secondary)]');
        }
    });

    function showCustomConfirm(clientName = '', routeName = '', actionType, data = {}) {
        document.getElementById('confirm-dynamic-name').textContent = clientName.toUpperCase();
        document.getElementById('confirm-dynamic-detail').textContent = routeName ? routeName.toUpperCase() : 'PANEL DE RUTAS';
        
        document.getElementById('confirm-action-type').value = actionType;
        document.getElementById('confirm-client-id').value = data.clientId || '';
        document.getElementById('confirm-route-id').value = data.routeId || '';
        document.getElementById('confirm-week-number').value = data.weekNumber || '';
        
        showModal('generic-confirm-modal');
    }

    executeConfirmBtn.addEventListener('click', async () => {
        const actionType = document.getElementById('confirm-action-type').value;
        const clientId = document.getElementById('confirm-client-id').value;
        const routeId = document.getElementById('confirm-route-id').value;
        const weekNumber = document.getElementById('confirm-week-number').value;
        
        hideAllModals();

        if (actionType === 'remove_client_from_route') {
            await handleClientAssignment(clientId, routeId, weekNumber, "delete");
            
        } else if (actionType === 'remove_client_from_workspace') {
            const cardToRemove = document.querySelector(`#clients-container .client-card[data-client-id="${clientId}"]`);
            await handleWorkspaceClient(clientId, "delete", cardToRemove);

        } else if (actionType === 'delete_route') {
            const routeColumn = document.querySelector(`.route-column[data-route-id="${routeId}"]`);
            if (routeColumn) {
                const formData = new FormData();
                formData.append("route_id", routeId);
                try { 
                    const response = await fetch("db/routes-delete.php", { method: "POST", body: formData });
                    const result = await response.json(); 
                    if(result.status === 'success') { 
                        showToast(result.message); 
                        routeColumn.remove();
                        allRoutes = allRoutes.filter(r => String(r.id) !== routeId); 
                        allAssignments = allAssignments.filter(a => String(a.route_id) !== routeId); 
                        updateAllSummariesForCurrentWeek(); 
                    } else { 
                        showToast(result.message, "error"); 
                    } 
                } catch (err) { 
                    showToast("Error de conexión.", "error"); 
                }
            }
        }
    });

    function createClientCard(client, isInstance = false, routeId = 0, weekNumber = 0) {
    const card = document.createElement("div");

    // 1. DEFINICIÓN DE CLASES TAILWIND
    // Clases base (Layout, espaciado, cursor, animación)
    const baseClasses = "flex items-center justify-between gap-2 py-2 px-3 mb-2 rounded-lg shadow-sm border-l-4 cursor-grab active:cursor-grabbing transition-all duration-200 hover:scale-[1.01] hover:shadow-md group relative";
    
    // Clases específicas según el tipo (Ruta vs Panel Origen)
    // Nota: Usamos sintaxis arbitraria [var(--color-x)] para usar tus variables CSS existentes
    const routeClasses = "bg-[var(--color-primary)] text-white border-[var(--color-highlight)]";
    const sourceClasses = "bg-white text-gray-800 border-gray-300 hover:border-[var(--color-secondary)]";

    // Asignar clases finales
    card.className = `${baseClasses} ${isInstance ? routeClasses : sourceClasses}`;
    
    // Atributos de datos necesarios
    card.setAttribute("draggable", true);
    card.dataset.clientId = client.id;

    // 2. CONFIGURACIÓN DE COLORES INTERNOS (Iconos y Textos)
    const iconColor = isInstance ? "text-white/70 hover:text-white" : "text-gray-400 hover:text-[var(--color-primary)]";
    const deleteBtnColor = isInstance ? "text-white/40 hover:text-red-300" : "text-gray-300 hover:text-red-600";
    const textColor = isInstance ? "text-white" : "text-gray-800";
    const separatorColor = isInstance ? "border-white/10" : "border-gray-100";
    const gripColor = isInstance ? "text-white/30" : "text-gray-300";

    // 3. GENERACIÓN DE BOTONES HTML
    const removeFromRouteBtn = isInstance 
        ? `<button class="remove-client-from-route-btn p-1 rounded-md transition-colors ${deleteBtnColor}" title="Quitar de ruta" data-client-id="${client.id}" data-route-id="${routeId}" data-week-number="${weekNumber}">
             <i data-lucide="trash-2" class="w-4 h-4"></i>
           </button>` 
        : "";
        
    const removeFromWorkspaceBtn = !isInstance 
        ? `<button class="remove-client-from-workspace-btn p-1 rounded-md transition-colors ${deleteBtnColor}" title="Quitar del panel" data-client-id="${client.id}">
             <i data-lucide="trash-2" class="w-4 h-4"></i>
           </button>` 
        : "";

    // 4. ESTRUCTURA HTML INTERNA (Todo con Tailwind)
    card.innerHTML = `
        <div class="flex items-center gap-2 overflow-hidden flex-grow select-none">
            <i data-lucide="grip-vertical" class="w-4 h-4 ${gripColor} flex-shrink-0"></i>
            
            <div class="flex flex-col overflow-hidden">
                <span class="font-bold text-sm ${textColor} truncate uppercase tracking-tight leading-none" data-element="name">
                    ${client.name}
                </span>
            </div>
        </div>

        <div class="flex items-center gap-1 flex-shrink-0 pl-2 border-l ${separatorColor}">
            
            <button class="toggle-client-details p-1 rounded-md transition-colors ${iconColor}" title="Ver Detalles">
                <i data-lucide="info" class="w-4 h-4"></i>
            </button>

            ${removeFromRouteBtn}
            ${removeFromWorkspaceBtn}
        </div>
    `;

    // 5. EVENT LISTENERS (Lógica idéntica, no cambia)
    
    // Botón Info
    card.querySelector(".toggle-client-details")?.addEventListener("click", e => { 
         e.stopPropagation(); 
         const clientData = masterClientList.find(c => String(c.id) === card.dataset.clientId);
         if (clientData) showClientDetails(card.dataset.clientId, clientData.name);
    });
    
    // Botón Borrar de Ruta
    card.querySelector(".remove-client-from-route-btn")?.addEventListener("click", e => { 
        e.stopPropagation(); 
        const { clientId, routeId, weekNumber } = e.currentTarget.dataset; 
        const clientData = masterClientList.find(c => String(c.id) === clientId);
        const routeData = allRoutes.find(r => String(r.id) === routeId);
        showCustomConfirm(
            clientData ? clientData.name.toUpperCase() : 'ESTE CLIENTE', 
            routeData ? routeData.route_name.toUpperCase() : 'ESTA RUTA', 
            'remove_client_from_route', 
            { clientId, routeId, weekNumber }
        );
    });

    // Botón Borrar de Workspace
    card.querySelector(".remove-client-from-workspace-btn")?.addEventListener("click", e => { 
        e.stopPropagation(); 
        const clientId = e.currentTarget.dataset.clientId;
        const clientData = masterClientList.find(c => String(c.id) === clientId);
        showCustomConfirm(
            clientData ? clientData.name.toUpperCase() : 'ESTE CLIENTE', 
            'PANEL DE RUTAS', 
            'remove_client_from_workspace', 
            { clientId }
        );
    });

    // Click General (Abre detalles)
    card.addEventListener("click", (e) => {
        if (!e.target.closest('button')) {
            const clientData = masterClientList.find(c => String(c.id) === card.dataset.clientId);
            if (clientData) showClientDetails(card.dataset.clientId, clientData.name);
        }
    });

    // Drag events
    card.addEventListener("dragstart", handleDragStart);
    card.addEventListener("dragend", handleDragEnd);

    lucide.createIcons();
    return card;
}

    function addRouteColumn(route) {
    const column = document.createElement("div");
    column.className = "route-column bg-white rounded-xl shadow-md p-4 h-full border-l-4 border-[var(--color-primary)] flex flex-col";
    column.dataset.routeId = route.id; 
    
    // HTML de la columna (Idéntico al anterior)
    column.innerHTML = `
        <div class="flex-shrink-0">
            <div class="flex justify-between items-start mb-4 border-b pb-2">
                <div class="flex items-start flex-col">
                    <div class="flex items-center">
                        <h2 id="route-title-${route.id}" class="text-2xl font-black text-[var(--color-primary)] mr-2 cursor-grab uppercase">${route.route_name}</h2>
                        <button class="text-[var(--color-secondary)] hover:text-gray-800 edit-route-btn" data-route-id="${route.id}">
                            <i data-lucide="pencil" class="w-4 h-4"></i>
                        </button>
                    </div>
                    <p id="route-day-${route.id}" class="text-sm font-bold uppercase text-gray-500 flex items-center">${route.route_day || "SIN DÍA"}</p>
                </div>
                <button class="text-[var(--color-secondary)] hover:text-[#8d1124] delete-route-btn p-1 transition-colors" data-route-id="${route.id}">
                    <i data-lucide="trash-2" class="w-5 h-5"></i>
                </button>
            </div>
        </div>
        
        <div id="route-list-${route.id}" class="space-y-2 kanban-list p-1 flex-grow overflow-y-auto min-h-[200px] custom-scrollbar" data-route-id="${route.id}">
            <p class="text-sm text-gray-500 italic p-2 bg-gray-50 border border-dashed rounded text-center empty-msg">Arrastra Clientes Aquí</p>
        </div>
        
        <div class="mt-4 pt-2 border-t text-xs flex-shrink-0">
            <div class="flex justify-between items-center text-gray-600"><span class="font-bold">Clientes:</span><span id="kpi-clients-${route.id}" class="font-semibold bg-gray-200 text-gray-800 px-2 py-0.5 rounded-full">0</span></div>
            <div class="flex justify-between items-center text-gray-600 mt-1"><span class="font-bold">Tiempo Estimado:</span><span id="kpi-time-${route.id}" class="font-semibold">0h 0m</span></div>
            <div class="flex justify-between items-center text-[var(--color-primary)] mt-1"><span class="font-bold">Valor Total:</span><span id="kpi-value-${route.id}" class="font-black text-base">$0.00</span></div>
        </div>`;
    
    routesContainer.appendChild(column);
    
    const listEl = column.querySelector(".kanban-list");
    listEl.addEventListener("dragover", handleDragOver);
    listEl.addEventListener("drop", handleDrop);

    // --- CONFIGURACIÓN SORTABLE CON VALIDACIÓN ESTRICTA ---
    new Sortable(listEl, {
        group: 'clients',
        animation: 150,
        ghostClass: 'sortable-ghost',
        dragClass: 'sortable-drag',
        onAdd: async (evt) => {
            const item = evt.item;
            const clientId = item.dataset.clientId;
            const newRouteId = route.id;
            const originList = evt.from; // De dónde viene la tarjeta
            const originRouteId = originList.dataset.routeId; // ID de ruta origen (si existe)

            // 1. VERIFICAR DUPLICADOS (REGLA DE ORO)
            // Buscamos si el cliente YA está asignado a alguna ruta en la memoria local
            const existingAssignment = allAssignments.find(a => String(a.client_id) === String(clientId));

            // CONDICIÓN DE BLOQUEO:
            // Si ya está asignado Y viene del panel principal (no es un movimiento entre rutas)
            if (existingAssignment && !originRouteId) {
                
                // Encontrar nombre de la ruta donde ya está
                const existingRoute = allRoutes.find(r => String(r.id) === String(existingAssignment.route_id));
                const routeName = existingRoute ? existingRoute.route_name.toUpperCase() : "OTRA RUTA";

                // A) Mostrar error visual
                showToast(`🚫 IMPOSIBLE: Este cliente ya está asignado a la ruta "${routeName}".`, 'error');

                // B) REVERTIR LA ACCIÓN FÍSICAMENTE
                // Sortable ya movió el elemento DOM a la nueva lista. Lo devolvemos a la lista de origen.
                originList.appendChild(item);
                
                // C) Cancelar ejecución
                return; 
            }

            // --- Si pasa la validación, continuamos con la lógica normal ---

            // Actualizar botón de borrar visualmente
            const removeBtn = item.querySelector('.remove-client-from-route-btn');
            if (removeBtn) removeBtn.dataset.routeId = newRouteId;

            // Lógica de Base de Datos
            if (originRouteId && originRouteId !== newRouteId) {
                // MOVIMIENTO (Traslado): Borrar de vieja, crear en nueva
                await handleClientAssignment(clientId, originRouteId, selectedWeek, "delete", true);
                await handleClientAssignment(clientId, newRouteId, selectedWeek, "create", true);
            } else {
                // ASIGNACIÓN NUEVA (Desde Panel): Solo crear
                await handleClientAssignment(clientId, newRouteId, selectedWeek, "create");
            }
            
            // Ocultar mensaje "Vacío"
            const emptyMsg = listEl.querySelector('.empty-msg');
            if(emptyMsg) emptyMsg.style.display = 'none';
        },
        onUpdate: (evt) => {
            const clientIds = Array.from(evt.target.children)
                .filter(card => card.classList.contains('client-card'))
                .map(card => card.dataset.clientId);
            handleClientOrderUpdate(route.id, clientIds);
        }
    });

    // Event Listeners de la Columna
    column.querySelector(".edit-route-btn").addEventListener("click", e => { 
        const routeId = e.currentTarget.dataset.routeId, routeData = allRoutes.find(r => String(r.id) === routeId); 
        if(routeData){
            document.getElementById("edit-route-name").value = routeData.route_name; 
            document.getElementById("edit-route-day").value = routeData.route_day || ""; 
            document.getElementById("current-edit-route-id").value = routeData.id; 
            showModal('edit-route-modal');
        } 
    });
    
    column.querySelector(".delete-route-btn").addEventListener("click", e => { 
        const routeId = e.currentTarget.dataset.routeId; 
        const routeData = allRoutes.find(r => String(r.id) === routeId);
        const routeName = routeData ? routeData.route_name.toUpperCase() : 'ESTA RUTA';
        showCustomConfirm('TODOS LOS CLIENTES DE', routeName, 'delete_route', { routeId }); 
    });
}
    
    function renderRoutesForWeek(weekNum) {
        routesContainer.innerHTML = '';
        const weekRoutes = allRoutes.filter(r => String(r.week_number) === String(weekNum));
        
        if (weekRoutes.length === 0) {
            routesContainer.innerHTML = `
                <div class="col-span-1 md:col-span-2 flex flex-col items-center justify-center p-12 bg-white rounded-xl shadow-lg border-2 border-dashed border-gray-300 min-h-[40vh] space-y-4">
                    
                    <i data-lucide="map-pin-off" class="w-16 h-16 text-[var(--color-secondary)]"></i>
                    
                    <h4 class="text-3xl font-black text-[var(--color-primary)] uppercase text-center">
                        SIN RUTAS ASIGNADAS
                    </h4>
                    
                    <p class="text-lg text-gray-600 text-center max-w-lg">
                        No hay rutas estratégicas creadas para la <span class="font-bold text-[var(--color-highlight)]">SEMANA ${weekNum}</span>.
                        Utilice el botón "CREAR NUEVA RUTA" para empezar a optimizar los desplazamientos de su equipo.
                    </p>

                    <button onclick="document.getElementById('create-route-btn').click()" class="bg-gray-100 text-[var(--color-primary)] font-bold py-2 px-4 rounded-lg mt-4 cursor-pointer uppercase hover:bg-gray-200 transition">
                        <i data-lucide="route" class="w-4 h-4 mr-2 inline"></i> ¡COMIENCE A PLANIFICAR!
                    </button>
                </div>
            `;
            lucide.createIcons();
            
        } else {
            weekRoutes.forEach(route => addRouteColumn(route));
        }
        
        renderAssignmentsForWeek(weekNum);
    }

    function renderAssignmentsForWeek(weekNum) {
        document.querySelectorAll('.route-column .client-card').forEach(card => card.remove());
        document.querySelectorAll('.route-column .kanban-list').forEach(list => { 
            if (list.children.length === 0 || (list.children.length === 1 && list.children[0].tagName === 'P')) {
                 list.innerHTML = '<p class="text-sm text-gray-500 italic p-2 bg-gray-50 border border-dashed rounded text-center">Arrastra Clientes Aquí</p>';
            }
        });
        
        const weekAssignments = allAssignments.filter(a => String(a.week_number) === String(weekNum));
        
        const assignmentsByRoute = weekAssignments.reduce((acc, assignment) => {
            if (!acc[assignment.route_id]) acc[assignment.route_id] = [];
            acc[assignment.route_id].push(assignment);
            return acc;
        }, {});

        Object.keys(assignmentsByRoute).forEach(routeId => {
            const routeList = document.getElementById(`route-list-${routeId}`);
            if (routeList) {
                routeList.querySelector('p.italic')?.remove();
                
                const sortedAssignments = assignmentsByRoute[routeId].sort((a, b) => (parseInt(a.order_index) || 0) - (parseInt(b.order_index) || 0));

                sortedAssignments.forEach(assignment => {
                    const client = masterClientList.find(c => String(c.id) === String(assignment.client_id));
                    if (client) {
                        routeList.appendChild(createClientCard(client, true, assignment.route_id, assignment.week_number));
                    }
                });
            }
        });
        
        lucide.createIcons();
        updateAllSummariesForCurrentWeek();
    }

    function updateAllSummariesForCurrentWeek() {
        updateGlobalSummary();
        updateDailySummary();
        updateWeekDisplay();
    }

    function updateGlobalSummary() {
        let routesCount = document.querySelectorAll("#routes-kanban-container .route-column").length;
        document.getElementById("summary-routes-count").textContent = routesCount;
        let clientsCount = 0, totalTime = 0, totalValue = 0;
        document.querySelectorAll(".route-column .client-card").forEach(card => {
            clientsCount++;
            const clientData = masterClientList.find(c => String(c.id) === card.dataset.clientId);
            if (clientData) { totalTime += parseFloat(clientData.service_time) || 0; totalValue += parseFloat(clientData.service_value) || 0; }
        });
        const hours = Math.floor(totalTime / 60), minutes = totalTime % 60;
        document.getElementById("summary-clients-assigned").textContent = clientsCount;
        document.getElementById("summary-total-time").textContent = `${hours}h ${minutes}m`;
        document.getElementById("summary-total-value").textContent = `$${totalValue.toFixed(2)}`;
        document.querySelectorAll(".route-column").forEach(col => updateRouteKPIs(col.dataset.routeId));
    }

    function updateRouteKPIs(routeId) {
        const routeList = document.getElementById(`route-list-${routeId}`);
        if (!routeList) return;
        const clientCards = routeList.querySelectorAll(".client-card"), clientCount = clientCards.length;
        let totalTime = 0, totalValue = 0;
        clientCards.forEach(card => {
            const clientData = masterClientList.find(c => String(c.id) === String(card.dataset.clientId));
            if (clientData) { totalTime += parseFloat(clientData.service_time) || 0; totalValue += parseFloat(clientData.service_value) || 0; }
        });
        const hours = Math.floor(totalTime / 60), minutes = totalTime % 60;
        document.getElementById(`kpi-clients-${routeId}`).textContent = clientCount;
        document.getElementById(`kpi-time-${routeId}`).textContent = `${hours}h ${minutes}m`;
        document.getElementById(`kpi-value-${routeId}`).textContent = `$${totalValue.toFixed(2)}`;
    }

    function updateDailySummary() {
        const daysOfWeek = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"];
        const dailyData = daysOfWeek.reduce((acc, day) => ({...acc, [day]: { value: 0, time: 0 }}), {});
        document.querySelectorAll(".route-column").forEach(routeColumn => {
            const routeData = allRoutes.find(r => String(r.id) === String(routeColumn.dataset.routeId));
            if (routeData) {
                const dayName = daysOfWeek.find(d => (routeData.route_day || "").toLowerCase() === d.toLowerCase());
                if (dayName) {
                    routeColumn.querySelectorAll(".client-card").forEach(clientCard => {
                        const clientData = masterClientList.find(c => String(c.id) === clientCard.dataset.clientId);
                        if (clientData) {
                            dailyData[dayName].value += parseFloat(clientData.service_value) || 0;
                            dailyData[dayName].time += parseFloat(clientData.service_time) || 0;
                        }
                    });
                }
            }
        });
        const maxValue = Math.max(0, ...Object.values(dailyData).map(d => d.value));
        document.getElementById("daily-summary-container").innerHTML = daysOfWeek.map(day => {
            const data = dailyData[day], hours = Math.floor(data.time / 60), minutes = data.time % 60;
            const isTopDay = data.value > 0 && data.value === maxValue;
            return `<div class="daily-summary-card p-4 rounded-xl shadow-md transition flex flex-col justify-between min-h-[120px] ${isTopDay ? "bg-yellow-50 border-2 border-[var(--color-highlight)]" : "bg-white border"}"><div><p class="font-black text-lg text-[var(--color-primary)] uppercase">${day}</p></div><div class="text-right"><p class="font-bold text-2xl text-[var(--color-primary)]">$${data.value.toFixed(2)}</p><p class="text-sm text-gray-500 font-semibold">${hours}h ${minutes}m</p></div></div>`;
        }).join("");
    }
    
    function handleDragStart(e) { draggedItem = e.target; setTimeout(() => e.target.classList.add("opacity-50"), 0) }
    function handleDragEnd(e) { if(draggedItem) draggedItem.classList.remove("opacity-50"); draggedItem = null }
    function handleDragOver(e) { e.preventDefault() }
    
    function handleDrop(e) { 
        e.preventDefault(); 
        const list = e.target.closest(".kanban-list"); 
        if (list && draggedItem) { 
            const clientId = draggedItem.dataset.clientId, 
                  routeId = list.dataset.routeId; 
            if (routeId) {
                handleClientAssignment(clientId, routeId, selectedWeek, "create"); 
            }
        } 
    }

    async function handleWorkspaceClient(clientId, action, element = null) {
        const url = action === 'create' ? 'db/routes-workspace-create.php' : 'db/routes-workspace-delete.php';
        const formData = new FormData();
        formData.append('client_id', clientId);
        try {
            const response = await fetch(url, { method: 'POST', body: formData });
            const result = await response.json();
            if (result.status === 'success') {
                showToast(result.message);
                if (action === 'create') {
                    const clientData = masterClientList.find(c => String(c.id) === String(clientId));
                    if (clientData && !workspaceClients.some(c => String(c.id) === String(clientId))) {
                        workspaceClients.push(clientData);
                        clientsContainer.querySelector('#clients-placeholder')?.remove();
                        clientsContainer.appendChild(createClientCard(clientData));
                        lucide.createIcons();
                    }
                } else if (action === 'delete') {
                    workspaceClients = workspaceClients.filter(c => String(c.id) !== String(clientId));
                    if (element) element.remove();
                    if (workspaceClients.length === 0) {
                        clientsContainer.innerHTML = '<p id="clients-placeholder" class="text-sm text-gray-500 italic p-2 bg-gray-100 rounded border border-dashed text-center">Usa el botón + para agregar clientes.</p>';
                    }
                }
            } else { showToast(result.message, 'error'); }
            return result.status === 'success';
        } catch(err) { showToast('Error de conexión.', 'error'); return false; }
    }

    async function handleClientAssignment(clientId, routeId, weekNumber, action, skipDOM = false) {
    // Evitar duplicados visuales si NO es skipDOM
    if (action === 'create' && !skipDOM) {
        const list = document.getElementById(`route-list-${routeId}`);
        if (list && list.querySelector(`.client-card[data-client-id="${clientId}"]`)) {
             return; // Ya existe visualmente, no hacer nada
        }
    }
    
    const url = action === 'create' ? 'db/routes-clients-create.php' : 'db/routes-clients-delete.php';
    const formData = new FormData();
    formData.append('client_id', clientId);
    formData.append('route_id', routeId);
    formData.append('week_number', weekNumber);
    
    try {
        const response = await fetch(url, { method: 'POST', body: formData });
        const result = await response.json();
        
        if (result.status === 'success') {
            if (!skipDOM) showToast(result.message); // Solo mostrar toast si fue acción manual, no en drag masivo

            // Actualizar arrays globales de datos
            if (action === 'create') {
                // Eliminar cualquier asignación previa idéntica para evitar duplicados en memoria
                allAssignments = allAssignments.filter(a => !(String(a.client_id) === String(clientId) && String(a.route_id) === String(routeId)));
                // Agregar nueva
                allAssignments.push({ client_id: clientId, route_id: routeId, week_number: weekNumber, order_index: 999 }); 
                
                // MANEJO VISUAL (Solo si skipDOM es falso)
                if (!skipDOM) {
                    const client = masterClientList.find(c => String(c.id) === String(clientId));
                    const routeList = document.getElementById(`route-list-${routeId}`);
                    if (client && routeList) {
                        routeList.querySelector('.empty-msg')?.remove(); // Quitar mensaje de vacío
                        // Aquí usamos la función createClientCard compacta que te di antes
                        routeList.appendChild(createClientCard(client, true, routeId, weekNumber));
                        lucide.createIcons();
                    }
                }
            } else if (action === 'delete') {
                allAssignments = allAssignments.filter(a => !(String(a.client_id) === String(clientId) && String(a.route_id) === String(routeId)));
                
                // MANEJO VISUAL (Solo si skipDOM es falso)
                if (!skipDOM) {
                    // Buscar y eliminar la tarjeta específica de esa ruta
                    const routeList = document.getElementById(`route-list-${routeId}`);
                    const cardToRemove = routeList?.querySelector(`.client-card[data-client-id="${clientId}"]`);
                    if (cardToRemove) cardToRemove.remove();
                }
            }
            updateAllSummariesForCurrentWeek();
        } else {
            // Si hay error en la base de datos (ej. "Ya asignado"), revertimos visualmente si es necesario
            if (action === 'create' && !skipDOM) {
                showToast(result.message, 'error');
            } else if(action === 'create' && skipDOM) {
                 // Si fue un drag & drop y falló, deberíamos mostrar el error aunque sea skipDOM
                 console.warn("Error al mover cliente:", result.message);
                 // Opcional: showToast("Error al mover: " + result.message, 'error');
            }
        }
    } catch(err) { 
        showToast('Error de conexión.', 'error'); 
        console.error(err);
    }
}

    async function handleClientOrderUpdate(routeId, clientIds) {
        const formData = new FormData();
        formData.append('route_id', routeId);
        clientIds.forEach(id => formData.append('client_ids[]', id));
        try {
            await fetch('db/routes-clients-update-order.php', { method: 'POST', body: formData });
             clientIds.forEach((cid, index) => {
                 const assignment = allAssignments.find(a => String(a.client_id) === String(cid) && String(a.route_id) === String(routeId));
                 if(assignment) assignment.order_index = index;
             });
        } catch (err) { showToast('Error al guardar el orden.', 'error'); }
    }
    
    function createWeekFilters() {
        if (!weekFilterContainer) return;
        weekFilterContainer.innerHTML = "";
        for (let week = 1; week <= 5; week++) {
            if (weekStartDates[week] && Object.keys(weekStartDates[week]).length > 0) {
                const button = document.createElement("button");
                button.className = "week-filter-btn px-4 py-2 text-sm font-bold rounded-lg transition uppercase border";
                button.dataset.week = week;
                button.textContent = week;
                button.addEventListener("click", async () => {
                    selectedWeek = week;
                    
                    document.querySelectorAll(".week-filter-btn").forEach(btn => {
                        btn.classList.remove("bg-[var(--color-secondary)]", "text-white", "border-[var(--color-secondary)]");
                        btn.classList.add("bg-white", "text-[var(--color-primary)]", "border-gray-200", "hover:bg-gray-50");
                    });
                    button.classList.remove("bg-white", "text-[var(--color-primary)]", "border-gray-200", "hover:bg-gray-50");
                    button.classList.add("bg-[var(--color-secondary)]", "text-white", "border-[var(--color-secondary)]");
                    
                    await loadRoutesAndAssignmentsForWeek(selectedWeek);
                });
                weekFilterContainer.appendChild(button);
            }
        }
        const currentWeekBtn = weekFilterContainer.querySelector(`[data-week='${selectedWeek}']`);
        if(currentWeekBtn) {
            currentWeekBtn.click();
        } else {
             weekFilterContainer.querySelector(`[data-week='1']`)?.click();
        }
    }

    async function loadRoutesAndAssignmentsForWeek(weekNum) {
        try {
            const response = await fetch(`db/routes-read.php?week=${weekNum}`);
            const data = await response.json();
            if (data.status === 'success') {
                allRoutes = data.routes || [];
                allAssignments = data.assignments || [];
                renderRoutesForWeek(weekNum);
                updateWeekDisplay();
            } else { 
                showToast(`Error al cargar datos de la semana: ${data.message}`, 'error'); 
            }
        } catch (error) { 
            showToast("Error de conexión al cargar datos de la semana.", 'error'); 
        }
    }

    function updateWeekDisplay() {
        weekRangeDisplay.textContent = ((week) => { if (!weekStartDates[week]) return ""; const dates = Object.values(weekStartDates[week]).filter(Boolean); if (dates.length === 0) return ""; const min = Math.min(...dates), max = Math.max(...dates); return `Del ${min} al ${max} de ${new Date().toLocaleDateString("es-ES",{month:"long"})}` })(selectedWeek);
        document.querySelectorAll(".route-column").forEach(col => {
            const routeId = col.dataset.routeId, routeData = allRoutes.find(r => String(r.id) === routeId);
            if (routeData) {
                const dayEl = document.getElementById(`route-day-${routeId}`);
                if (dayEl) {
                    const dateNum = weekStartDates[selectedWeek] ? weekStartDates[selectedWeek][routeData.route_day] : "";
                    const dayName = routeData.route_day || "SIN DÍA";
                    const dateBadge = dateNum ? `<span class="ml-2 font-bold text-[var(--color-highlight)] bg-gray-100 px-2 rounded-md border border-gray-200">${dateNum}</span>` : "";
                    dayEl.innerHTML = `${dayName}${dateBadge}`;
                }
            }
        });
    }

    mainSearchInput.addEventListener("input", e => {
        let term = e.target.value.toLowerCase().trim();
        clientsContainer.querySelectorAll(".client-card").forEach(card => {
            const isVisible = card.querySelector('[data-element="name"]').textContent.toLowerCase().includes(term);
            card.style.display = isVisible ? "block" : "none";
        });
    });

    document.getElementById("add-client-btn").addEventListener("click", () => {
        modalClientSearchInput.value = "";
        modalSearchResults.innerHTML = '<p class="text-center text-gray-500 p-4">Escribe un nombre para buscar clientes.</p>';
        showModal('add-client-modal');
        modalClientSearchInput.focus();
    });

    modalClientSearchInput.addEventListener("input", e => {
        clearTimeout(searchTimeout);
        const term = e.target.value.trim();
        if (term.length < 2) {
            modalSearchResults.innerHTML = '<p class="text-center text-gray-500 p-4">Escribe al menos 2 letras.</p>';
            return;
        }
        searchTimeout = setTimeout(async () => {
            modalSearchResults.innerHTML = '<p class="text-center text-gray-500 p-4">Buscando...</p>';
            try {
                const response = await fetch(`db/routes-search-clients.php?term=${encodeURIComponent(term)}`);
                const results = await response.json();
                modalSearchResults.innerHTML = "";
                if (results.length === 0) {
                    modalSearchResults.innerHTML = '<p class="text-center text-gray-500 p-4">No se encontraron resultados.</p>';
                } else {
                    results.forEach(client => {
                        const isAlreadyInWorkspace = workspaceClients.some(c => String(c.id) === String(client.id));
                        const resultDiv = document.createElement('div');
                        resultDiv.className = 'flex justify-between items-center p-3 rounded-lg hover:bg-gray-100 border-b last:border-0 transition-colors';
                        
                        const clientInfoDiv = document.createElement('div');
                        const nameDiv = document.createElement('div');
                        nameDiv.className = 'font-bold text-gray-800';
                        nameDiv.textContent = client.name; 
                        
                        const addressDiv = document.createElement('div');
                        addressDiv.className = 'text-xs text-gray-500';
                        addressDiv.textContent = client.address || 'Sin dirección';
                        
                        clientInfoDiv.appendChild(nameDiv);
                        clientInfoDiv.appendChild(addressDiv);
                        resultDiv.appendChild(clientInfoDiv);
                        
                        const buttonHtml = `<button data-client-id="${client.id}" class="add-client-from-modal-btn p-2 text-white rounded-md transition-colors ${isAlreadyInWorkspace ? 'bg-green-600 cursor-default' : 'bg-[var(--color-secondary)] hover:bg-[#851123]'}" ${isAlreadyInWorkspace ? 'disabled' : ''}><i data-lucide="${isAlreadyInWorkspace ? 'check' : 'plus'}" class="w-5 h-5"></i></button>`;
                        resultDiv.insertAdjacentHTML('beforeend', buttonHtml);
                        
                        modalSearchResults.appendChild(resultDiv);
                        
                        if (!isAlreadyInWorkspace) {
                            resultDiv.querySelector('.add-client-from-modal-btn').addEventListener('click', async (e) => {
                                const button = e.currentTarget;
                                const success = await handleWorkspaceClient(client.id, 'create');
                                if (success) {
                                    // Add client to master list if not already there to prevent issues when adding card
                                    if (!masterClientList.some(c => String(c.id) === String(client.id))) {
                                        masterClientList.push({
                                            id: client.id,
                                            name: client.name,
                                            address: client.address,
                                            service: client.service,
                                            service_time: 0,
                                            service_value: 0
                                        });
                                    }
                                    
                                    button.innerHTML = '<i data-lucide="check" class="w-5 h-5"></i>';
                                    button.disabled = true;
                                    button.classList.remove('bg-[var(--color-secondary)]', 'hover:bg-[#851123]');
                                    button.classList.add('bg-green-600');
                                    lucide.createIcons();
                                }
                            });
                        }
                    });
                    lucide.createIcons();
                }
            } catch (error) { showToast("Error de conexión al buscar.", "error"); }
        }, 300);
    });

    document.getElementById("create-route-btn").addEventListener("click", () => { document.getElementById("modal-week-number").textContent = selectedWeek, showModal('create-route-modal') });
    document.querySelectorAll(".close-modal-btn").forEach(btn => btn.addEventListener("click", hideAllModals));
    document.getElementById("save-new-route-btn").addEventListener("click", async () => { const name = document.getElementById("new-route-name").value.trim(), day = document.getElementById("new-route-day").value; if (!name) return showToast("El nombre de la ruta es obligatorio.", "error"); const formData = new FormData(); formData.append("route_name", name); formData.append("route_day", day); formData.append("week_number", selectedWeek); try { const response = await fetch("db/routes-create.php", { method: "POST", body: formData }); const result = await response.json(); if (result.status === 'success' && result.new_route) { showToast(result.message); allRoutes.push(result.new_route); renderRoutesForWeek(selectedWeek); hideAllModals(); } else { showToast(result.message, "error"); } } catch (err) { showToast("Error de conexión.", "error"); } });
    document.getElementById("save-edit-route-btn").addEventListener("click", async () => { const id = document.getElementById("current-edit-route-id").value, name = document.getElementById("edit-route-name").value.trim(), day = document.getElementById("edit-route-day").value, route = allRoutes.find(r => String(r.id) === String(id)); if (!route || !name) return showToast("El nombre es obligatorio.", "error"); const formData = new FormData(); formData.append("route_id", id); formData.append("route_name", name); formData.append("route_day", day); try { const response = await fetch("db/routes-update.php", { method: "POST", body: formData }); const result = await response.json(); if (result.status === 'success') { showToast(result.message); route.route_name = name; route.route_day = day; document.getElementById(`route-title-${id}`).textContent = name; updateWeekDisplay(); hideAllModals(); } else { showToast(result.message, "error"); } } catch (err) { showToast("Error de conexión.", "error"); } });

    async function loadInitialData() {
        try {
            const response = await fetch(`db/routes-read.php?week=${selectedWeek}`);
            const data = await response.json();
            if (data.status === 'success') {
                allRoutes = data.routes || [];
                masterClientList = data.master_client_list || [];
                workspaceClients = data.workspace_clients || [];
                allAssignments = data.assignments || [];

                clientsContainer.innerHTML = "";
                if (workspaceClients.length > 0) {
                    workspaceClients.forEach(client => clientsContainer.appendChild(createClientCard(client)));
                } else {
                    clientsContainer.innerHTML = '<p id="clients-placeholder" class="text-sm text-gray-500 italic p-4 text-center bg-gray-50 rounded border border-dashed border-gray-300">Usa el botón + para agregar clientes.</p>';
                }
                lucide.createIcons();

                createWeekFilters();
                
                new Sortable(routesContainer, { 
                    group: 'routes',
                    animation: 150, 
                    handle: 'h2', 
                    onEnd: function (evt) { 
                        const routeIds = Array.from(routesContainer.children).map(col => col.dataset.routeId);
                        const formData = new FormData(); 
                        routeIds.forEach(id => formData.append('route_ids[]', id));
                        fetch('db/routes-save-order.php', { method: 'POST', body: formData });
                    } 
                });
            } else { 
                showToast(`Error al cargar: ${data.message}`, 'error'); 
            }
        } catch (error) { 
            showToast("Error de conexión al cargar datos iniciales.", 'error'); 
        }
    }
    
    loadInitialData();
});

document.getElementById('toggle-view-btn').addEventListener('click', function() {
    const container = document.getElementById('routes-kanban-container');
    const icon = this.querySelector('svg'); // O el icono de lucide
    
    container.classList.toggle('view-compact');
    
    // Cambiar texto/icono según estado (opcional)
    if (container.classList.contains('view-compact')) {
        this.innerHTML = '<i data-lucide="layout"></i> VISTA DETALLADA';
    } else {
        this.innerHTML = '<i data-lucide="list"></i> VISTA COMPACTA';
    }
    lucide.createIcons();
});
</script>
<script src="files/toast.js"></script>
</body>
</html>