/**
 * css/estilos.css
 * -----------------------------------------------------------------
 * Hoja de estilos centralizada del CRM. Reemplaza los bloques <style>
 * inline que existían por separado en index.php y dashboard.php.
 * Un solo archivo = un solo lugar para mantener el sistema de diseño
 * (tema dark/light, paleta corporativa #639f38) y para poder invalidar
 * la caché del navegador con un solo query string (?v=timestamp).
 * -----------------------------------------------------------------
 */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

/* =====================================================================
   VARIABLES DE TEMA (Light Luxury / Dark Luxury)
   Fusiona las variables usadas en login (index.php) y dashboard.php.
   MODO CLARO es el predeterminado absoluto en :root — evita el Flash of
   Unstyled/Wrong Theme (FOUC) para el primer paint. El modo oscuro solo
   se activa cuando body[data-theme="dark"] está explícitamente presente
   (ver script de inicialización de tema al inicio de <body> en
   index.php/dashboard.php/clientes.php/gerencia.php).
   ===================================================================== */
:root {
    --color-acento: #2f6b3e;
    --color-acento-claro: #3c8250;
    --color-acento-hover: #3c8250;
    --color-acento-rgb: 47, 107, 62;

    --bg-fondo: #f3f2ed;
    --bg-panel: rgba(255, 255, 255, 0.72);
    --bg-panel-alt: rgba(255, 255, 255, 0.9);
    --bg-input: rgba(255, 255, 255, 0.9);
    --bg-chat: #faf9f5;
    --bg-chat-patron: rgba(0, 0, 0, 0.025);
    --bg-burbuja-cliente: #ffffff;
    --bg-burbuja-propia: rgba(47, 107, 62, 0.1);

    /* FASE 44 — Soft UI: fondo gris súper claro exclusivo del buscador,
       separado de --bg-input (que es blanco casi opaco) para lograr el
       look "pill" plano de buscadores tipo app nativa. */
    --bg-buscador: #f3f4f6;

    --texto-principal: #202420;
    --texto-secundario: #6b7268;
    --texto-oscuro: #202420;

    --borde-sutil: rgba(0, 0, 0, 0.08);
    --borde-glass: rgba(0, 0, 0, 0.05);
    --borde-inner-glow: rgba(255, 255, 255, 0.6);
    --color-error: #c24d4d;
    --color-error-bg: rgba(194, 77, 77, 0.08);

    --sombra-panel: 0 20px 50px rgba(120, 120, 100, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.5);
    --sombra-glow: 0 0 0 1px rgba(var(--color-acento-rgb), 0.12), 0 8px 20px rgba(var(--color-acento-rgb), 0.18);
    --blur-glass: blur(16px);

    --mesh-op-1: 0.09;
    --mesh-op-2: 0.05;

    /* FASE 24 — Profundidad UI: fondo grisáceo detrás de las columnas
       (simula un escritorio) + fondo sólido para las columnas internas,
       que en modo claro pasan de "planas" a sentirse como paneles/
       tarjetas flotantes. En modo oscuro se remapean a los mismos
       valores ya usados (ver body[data-theme="dark"] más abajo). */
    --bg-app-shell: #f4f7f6;
    --bg-panel-solido: #ffffff;

    /* Altura de referencia del nav móvil, usada para calcular el
       padding-bottom del chat y evitar que el input quede tapado.
       Se calculó con margen sobre la altura real (~51px) para cubrir
       variaciones de tamaño de fuente del sistema en distintos equipos.
       Vive fuera de los bloques de color porque no depende del tema. */
    --altura-nav-movil: 64px;
}

body[data-theme="dark"] {
    --color-acento: #639f38;
    --color-acento-claro: #74b344;
    --color-acento-hover: #7ab84a;
    --color-acento-rgb: 99, 159, 56;

    --bg-fondo: #09090b;
    --bg-panel: rgba(20, 21, 24, 0.65);
    --bg-panel-alt: rgba(14, 15, 17, 0.82);
    --bg-input: rgba(255, 255, 255, 0.04);
    --bg-chat: #0c0d0f;
    --bg-chat-patron: rgba(255, 255, 255, 0.025);
    --bg-burbuja-cliente: #17181b;
    --bg-burbuja-propia: rgba(99, 159, 56, 0.16);

    --texto-principal: #f4f5f3;
    --texto-secundario: #8b8f8a;
    --texto-oscuro: #f4f5f3;

    --borde-sutil: rgba(255, 255, 255, 0.08);
    --borde-glass: rgba(255, 255, 255, 0.06);
    --borde-inner-glow: rgba(255, 255, 255, 0.1);
    --color-error: #e07a7a;
    --color-error-bg: rgba(224, 122, 122, 0.1);

    --sombra-panel: 0 30px 90px rgba(0, 0, 0, 0.65), inset 0 1px 0 rgba(255, 255, 255, 0.04);
    --sombra-glow: 0 0 0 1px rgba(var(--color-acento-rgb), 0.15), 0 8px 24px rgba(var(--color-acento-rgb), 0.28);
    --blur-glass: blur(24px);

    --mesh-op-1: 0.16;
    --mesh-op-2: 0.08;

    /* FASE 24 — en oscuro no hace falta un fondo grisáceo adicional: el
       propio --bg-fondo y los paneles translúcidos ya aportan la
       profundidad, así que ambas variables simplemente heredan lo que
       ya existía. */
    --bg-app-shell: var(--bg-fondo);
    --bg-panel-solido: var(--bg-panel);

    /* FASE 44 — en oscuro el gris claro no tiene sentido: se resuelve
       como un realce translúcido muy sutil sobre el panel oscuro. */
    --bg-buscador: rgba(255, 255, 255, 0.05);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
    height: 100%;
    width: 100vw;
    max-width: 100%;
    overflow-x: hidden;
    overscroll-behavior-y: none; /* Mata el efecto "pull to refresh" nativo del celular */
    font-family: 'Inter', 'Segoe UI', Roboto, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    letter-spacing: -0.005em;
    color: var(--texto-principal);
    transition: background 0.25s ease, color 0.25s ease;
}


svg.lucide {
    width: 1em;
    height: 1em;
    stroke-width: 2;
    vertical-align: -0.15em;
}

/* Toggle de tema flotante: se reutiliza igual en login y en dashboard */
#iconoTemaDark  { display: none; }
#iconoTemaLight { display: inline-flex; }
body[data-theme="dark"] #iconoTemaDark   { display: inline-flex; }
body[data-theme="dark"] #iconoTemaLight  { display: none; }

/* =====================================================================
   LOGIN (index.php)
   ===================================================================== */
body.pagina-login {
    background:
        radial-gradient(ellipse 900px 700px at 50% 35%, rgba(var(--color-acento-rgb), var(--mesh-op-1)), transparent 60%),
        radial-gradient(ellipse 700px 600px at 85% 85%, rgba(var(--color-acento-rgb), var(--mesh-op-2)), transparent 55%),
        radial-gradient(ellipse 700px 600px at 10% 90%, rgba(var(--color-acento-rgb), var(--mesh-op-2)), transparent 55%),
        var(--bg-fondo);
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.toggle-tema-flotante {
    position: fixed;
    top: 20px;
    right: 20px;
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-glass);
    color: var(--texto-secundario);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 1.05rem;
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
    z-index: 10;
}

.toggle-tema-flotante:hover {
    color: var(--color-acento);
    border-color: rgba(var(--color-acento-rgb), 0.35);
}

.login-panel {
    width: 100%;
    max-width: 400px;
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-inner-glow);
    border-radius: 20px;
    padding: 36px 28px;
    display: flex;
    flex-direction: column;
    gap: 22px;
    box-shadow: var(--sombra-panel);
    position: relative;
    z-index: 1;
}

.login-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
    margin-bottom: 4px;
}

.login-logo {
    width: 62px;
    height: 62px;
    border-radius: 18px;
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 22px;
    color: #0b0d0c;
    border: 1px solid var(--borde-inner-glow);
    box-shadow: var(--sombra-glow);
}

.login-header h1 { font-size: 1.35rem; font-weight: 700; letter-spacing: -0.02em; }
.login-header p { font-size: 0.85rem; color: var(--texto-secundario); }

.campo { display: flex; flex-direction: column; gap: 6px; }
/* FASE 58 — mismo FIX de especificidad que .visita-estado[hidden]: sin
   esto, un .campo con hidden=true (ej. #campoDetalleOtroPausa cuando el
   motivo no es OTRO) se queda visible porque .campo declara su propio
   "display". */
.campo[hidden] { display: none; }

.campo label {
    font-size: 0.8rem;
    color: var(--texto-secundario);
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 6px;
}

.campo-input-wrap { position: relative; display: flex; align-items: center; }

.campo-input-wrap .icono-campo {
    position: absolute;
    left: 15px;
    color: var(--texto-secundario);
    pointer-events: none;
    transition: color 0.15s ease;
}

.campo-input-wrap input {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 14px 16px 14px 42px;
    color: var(--texto-principal);
    font-size: 0.95rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.25s ease;
}

.campo-input-wrap input:focus {
    border-color: rgba(var(--color-acento-rgb), 0.55);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.16), 0 0 24px rgba(var(--color-acento-rgb), 0.14);
}

.campo-input-wrap input:focus ~ .icono-campo,
.campo-input-wrap:focus-within .icono-campo {
    color: var(--color-acento);
}

.btn-submit {
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    color: #0b0d0c;
    border: 1px solid var(--borde-inner-glow);
    border-radius: 12px;
    padding: 14px 16px;
    font-size: 0.95rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    box-shadow: var(--sombra-glow), inset 0 1px 0 rgba(255, 255, 255, 0.25);
    transition: filter 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
    margin-top: 6px;
}

.btn-submit:hover {
    filter: brightness(1.06);
    box-shadow: 0 0 0 1px rgba(var(--color-acento-rgb), 0.25), 0 12px 32px rgba(var(--color-acento-rgb), 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.btn-submit:active { transform: scale(0.98); }

.alerta-error {
    background: var(--color-error-bg);
    border: 1px solid var(--color-error);
    color: var(--color-error);
    border-radius: 12px;
    padding: 12px 14px;
    font-size: 0.85rem;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.login-footer {
    text-align: center;
    font-size: 0.75rem;
    color: var(--texto-secundario);
    margin-top: 4px;
}

@media (min-width: 480px) {
    .login-panel { padding: 44px 40px; }
}

/* =====================================================================
   DASHBOARD (dashboard.php)
   ===================================================================== */
body.pagina-dashboard {
    background: var(--bg-app-shell);
    overflow: hidden;
}

/* FASE 29 (Paso 3) — dashboard.php volvió a su estado natural: solo el
   layout de 3 columnas estilo WhatsApp Web. El Panel BI (KPIs, filtro
   de fechas, pestañas y gráficas) vive exclusivamente en gerencia.php
   desde esta fase — ver .gerencia-shell y el bloque "PANEL DE BUSINESS
   INTELLIGENCE" más abajo. */
.dashboard-layout {
    display: flex;
    flex-direction: column;
    height: 100vh;
    width: 100%;
    overflow: hidden;
}

.kpi-subtitulo {
    font-size: 0.68rem;
    color: var(--texto-secundario);
    margin-top: 2px;
    font-style: italic;
}

.app-shell {
    display: grid;
    grid-template-columns: 1fr;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
}

/* ----- Menú Global (Offcanvas a la derecha) -----
   FASE 43 — antes era una columna fija de 70px (solo íconos) dentro del
   grid de .app-shell. Ahora es un panel flotante anclado al borde
   derecho de la pantalla, oculto por defecto (translateX 100%) y que se
   desliza a la vista al recibir .menu-open — igual en PC que en móvil,
   por eso ya no necesita reglas específicas por breakpoint como antes. */
.col-sidebar {
    position: fixed;
    top: 0;
    right: 0;
    width: min(300px, 84vw);
    height: 100%;
    height: 100dvh;
    background: var(--bg-panel-solido);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    padding: 16px;
    border-left: 1px solid var(--borde-sutil);
    box-shadow: -8px 0 32px rgba(0, 0, 0, 0.22);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1);
    z-index: 9999;
}

/* FASE 68 — Task 2: scrollbar delgada y discreta (Soft UI), en vez de la
   barra gris por defecto del navegador que desentonaba con el resto del
   panel glassmorphism. Solo WebKit/Blink + Firefox (thin); Safari
   antiguo simplemente conserva su scrollbar nativa, sin romper nada. */
.col-sidebar {
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--color-acento-rgb), 0.4) transparent;
}

.col-sidebar::-webkit-scrollbar { width: 6px; }
.col-sidebar::-webkit-scrollbar-track { background: transparent; }
.col-sidebar::-webkit-scrollbar-thumb {
    background: rgba(var(--color-acento-rgb), 0.35);
    border-radius: 999px;
}
.col-sidebar::-webkit-scrollbar-thumb:hover {
    background: rgba(var(--color-acento-rgb), 0.55);
}

.col-sidebar.menu-open {
    transform: translateX(0);
}

/* Overlay oscuro semitransparente detrás del panel — cubre el resto de
   la pantalla mientras el menú está abierto; clic sobre él lo cierra. */
.menu-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
    z-index: 9998;
}

.menu-overlay.activo {
    opacity: 1;
    visibility: visible;
}

.sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 12px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--borde-sutil);
}

.sidebar-header h2 {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--texto-principal);
}

/* FASE 68 — Task 2: mini tarjeta de identidad, ver comentario en
   dashboard.php junto a .sidebar-perfil. Reutiliza el mismo patrón visual
   de tarjeta con profundidad que .info-perfil/.info-seccion (Fase 44),
   para que el rediseño del sidebar se sienta parte de la misma familia
   Soft UI que el resto del CRM, no un componente aislado. */
.sidebar-perfil {
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-radius: 14px;
    padding: 12px 14px;
    margin-bottom: 8px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
}

.sidebar-perfil-avatar {
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--color-acento), var(--color-acento-claro));
    color: #ffffff;
    font-weight: 800;
    font-size: 0.95rem;
}

.sidebar-perfil-textos { min-width: 0; }

.sidebar-perfil-nombre {
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--texto-principal);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-perfil-rol {
    font-size: 0.72rem;
    color: var(--texto-secundario);
    text-transform: capitalize;
}

/* El botón "x" de cerrar vive dentro de .sidebar-header, no es un acceso
   de navegación — mantiene el tamaño cuadrado estándar de .btn-icono en
   vez de la fila ancho-completo del resto de accesos del menú. Selector
   de 3 clases a propósito: debe ganarle en especificidad a
   ".col-sidebar .btn-icono" (2 clases) sin importar el orden en la hoja. */
.col-sidebar .sidebar-header .btn-icono {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
}

.sidebar-spacer { flex: 1; }

/* FASE 24 — íconos del sidebar: verde corporativo en modo claro, blanco
   en modo oscuro. Hover/.activo invierten a fondo verde + ícono blanco.
   FASE 43 — dejaron de ser botones cuadrados de 34px: ahora son filas de
   ancho completo (ícono + nombre del módulo en texto), requisito de
   legibilidad del rediseño del menú global. */
.col-sidebar .btn-icono {
    width: 100%;
    height: auto;
    justify-content: flex-start;
    gap: 12px;
    padding: 11px 12px;
    border-radius: 12px;
    color: var(--color-acento);
    transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease,
                transform 0.15s ease, box-shadow 0.2s ease;
}

/* FASE 68 — Task 2: micro-interacción sutil (desplazamiento + sombra) al
   pasar el mouse, para que el menú se sienta "vivo" en vez de un simple
   cambio de color plano — mismo criterio de detalle que .btn-accion-visita
   y el resto de botones premium del sistema. */
.col-sidebar .btn-icono:hover {
    transform: translateX(-3px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.col-sidebar .btn-icono:active {
    transform: translateX(-1px) scale(0.99);
}

body[data-theme="dark"] .col-sidebar .btn-icono {
    color: #ffffff;
}

.col-sidebar .btn-icono:hover,
.col-sidebar .btn-icono.activo {
    background: var(--color-acento);
    border-color: var(--color-acento);
    color: #ffffff;
}

.col-sidebar .btn-icono i {
    flex-shrink: 0;
}

.col-sidebar .sidebar-label {
    font-size: 0.86rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ----- Columna izquierda: Buzones ----- */
.col-buzones {
    background: var(--bg-panel-solido);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--borde-sutil);
    box-shadow: 2px 0 12px rgba(0, 0, 0, 0.04);
    height: 100%;
    overflow: hidden;
}

.buzones-header {
    background: var(--bg-panel-alt);
    padding: 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid var(--borde-glass);
    /* FASE 44 — Soft UI: sombra difuminada que eleva el header sobre la
       lista de chats, en vez de depender solo del borde inferior. */
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
    position: relative;
    z-index: 1;
    gap: 8px;
}

.perfil-admin { display: flex; align-items: center; gap: 10px; min-width: 0; }

.avatar-circulo {
    width: 40px;
    height: 40px;
    border-radius: 12px;
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    /* FASE 21: contraste total sobre fondo verde acento — blanco puro
       explícito, nunca heredado, para que ningún tema/tono lo revierta. */
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.9rem;
    flex-shrink: 0;
    border: 1px solid var(--borde-inner-glow);
    box-shadow: var(--sombra-glow);
}

.perfil-admin .perfil-textos { min-width: 0; }

.perfil-admin .nombre {
    font-size: 0.9rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.perfil-admin .rol {
    font-size: 0.72rem;
    color: var(--texto-secundario);
    text-transform: capitalize;
}

.btn-icono {
    background: transparent;
    border: 1px solid transparent;
    color: var(--texto-secundario);
    font-size: 1rem;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border-radius: 9px;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn-icono:hover {
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
    border-color: rgba(var(--color-acento-rgb), 0.25);
}

.buscador-wrap { padding: 14px 16px; position: relative; }

.buscador-wrap .icono-buscar {
    position: absolute;
    left: 30px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--texto-secundario);
    pointer-events: none;
}

/* FASE 44 — Soft UI: sin borde duro, fondo gris súper claro (pill) y
   una sombra interior levísima en vez del contorno de --borde-sutil. */
.buscador-wrap input {
    width: 100%;
    background: var(--bg-buscador);
    border: none;
    border-radius: 24px;
    padding: 12px 16px 12px 40px;
    color: var(--texto-principal);
    font-size: 0.85rem;
    font-family: inherit;
    outline: none;
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.03);
    transition: box-shadow 0.2s ease, background 0.15s ease;
}

.buscador-wrap input:focus {
    background: var(--bg-input);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.03), 0 0 0 4px rgba(var(--color-acento-rgb), 0.14);
}

/* FASE 44 — Soft UI: la lista pasa de filas pegadas con línea divisoria
   dura a tarjetas separadas por "aire" (gap), cada una con fondo sólido
   y esquinas redondeadas, en vez de border-bottom. */
.lista-buzones {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px;
}

.buzon-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    background: var(--bg-panel-solido);
    border-radius: 12px;
    border-left: 3px solid transparent;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.buzon-item:hover,
.buzon-item.activo {
    background: rgba(var(--color-acento-rgb), 0.07);
    border-left: 3px solid var(--color-acento);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
}

.buzon-avatar {
    width: 42px;
    height: 42px;
    border-radius: 12px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--texto-secundario);
    flex-shrink: 0;
}

.buzon-info { flex: 1; min-width: 0; }

/* FASE 21: fila superior del item de buzón — nombre del cliente a la
   izquierda, hora del último mensaje anclada a la derecha. Reemplaza el
   layout anterior donde el nombre ocupaba todo el ancho y el estado
   vivía como texto plano dentro de .meta-linea. */
.buzon-info-fila-superior {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
}

.buzon-info .nombre-cliente {
    font-size: 0.88rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.hora-buzon {
    font-size: 0.68rem;
    color: var(--texto-secundario);
    flex-shrink: 0;
    white-space: nowrap;
}

.buzon-info .meta-linea {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    gap: 6px;
    font-size: 0.72rem;
    color: var(--texto-secundario);
    margin-top: 3px;
}

/* FASE 23B: tipo_cliente (Marquetero/Distribuidor) es la dimensión de
   "naturaleza del negocio" — siempre en AZUL, sin distinguir por valor,
   para que se identifique de un vistazo frente a la etiqueta naranja de
   clasificacion_ruta de abajo (misma fila o apiladas). */
.badge-tipo {
    font-size: 0.62rem;
    padding: 4px 10px;
    border-radius: 12px;
    text-transform: uppercase;
    font-weight: 600;
    letter-spacing: 0.03em;
    background: rgba(66, 133, 244, 0.14);
    color: #4f8ef7;
    border: none;
}

/* FASE 44 — en modo claro el azul medio pierde contraste sobre el fondo
   pastel; se oscurece igual que ya hace body[data-theme="light"] más
   abajo con .badge-estado-esperando/atendido. */
body[data-theme="light"] .badge-tipo { color: #1d4ed8; }

/* FASE 23A/23B: clasificación de ruta comercial (logística/segmentación)
   — dimensión INDEPENDIENTE de tipo_cliente, siempre en NARANJA para no
   confundirse con el badge azul de arriba al quedar apilados. */
.badge-ruta {
    font-size: 0.62rem;
    padding: 4px 10px;
    border-radius: 12px;
    text-transform: uppercase;
    font-weight: 600;
    letter-spacing: 0.03em;
    background: rgba(230, 150, 20, 0.14);
    color: #e69614;
    border: none;
    margin-top: 4px;
}

body[data-theme="light"] .badge-ruta { color: #b45f0a; }

/* FASE 21: badge-estado — píldora de color que reemplaza el texto plano
   del estado del chat. Cada estado tiene su propio color semántico;
   'esperando' es el único que además dispara .alerta-sla (icono de
   reloj) cuando pasa el SLA, así que aquí solo se resuelve el color
   base, no la urgencia — esa la sigue marcando .reloj-titilante. */
.badge-estado {
    font-size: 0.62rem;
    padding: 4px 10px;
    border-radius: 999px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: capitalize;
    border: none;
    flex-shrink: 0;
}

.badge-estado-nuevo     { background: rgba(var(--color-acento-rgb), 0.18); color: var(--color-acento); }
.badge-estado-esperando { background: rgba(230, 162, 60, 0.18); color: #c98a2e; }
.badge-estado-atendido  { background: rgba(90, 140, 210, 0.18); color: #4d84c9; }
.badge-estado-cerrado   { background: rgba(139, 143, 138, 0.18); color: var(--texto-secundario); }
.badge-estado-generico  { background: rgba(139, 143, 138, 0.18); color: var(--texto-secundario); }

body[data-theme="light"] .badge-estado-esperando { color: #9c6414; }
body[data-theme="light"] .badge-estado-atendido   { color: #2f5f9c; }

.badge-no-leido {
    background: var(--color-acento);
    color: #0b0d0c;
    font-size: 0.68rem;
    font-weight: 700;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-shadow: 0 2px 8px rgba(var(--color-acento-rgb), 0.4);
}

.sin-datos {
    padding: 30px 16px;
    text-align: center;
    color: var(--texto-secundario);
    font-size: 0.85rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}

/* ----- Columna central: Chat ----- */
.col-chat {
    display: flex;
    flex-direction: column;
    height: 100%;
    /* FASE 24: recorta header/mensajes/input a las esquinas redondeadas
       que aplica el modo "tarjeta" en escritorio (ver media 900px+); no
       afecta el scroll porque ese scroll ya vive dentro de .chat-mensajes,
       no en este contenedor. */
    overflow: hidden;
    background-color: var(--bg-chat);
    background-image: radial-gradient(var(--bg-chat-patron) 1px, transparent 1px);
    background-size: 22px 22px;
    /* FASE 21: ancla de posicionamiento para el pseudo-elemento del fondo
       de marquetería (::before, ver abajo). position:relative + z-index
       crean el contexto de apilamiento que mantiene ese pseudo-elemento
       SIEMPRE detrás de sus hijos (header, mensajes, input), sin tener
       que forzar z-index manualmente en cada uno de ellos. */
    position: relative;
    z-index: 1;
}

/* FASE 21 — Fondo de marquetería. Capa independiente vía pseudo-elemento
   en vez de background-image directo en .chat-mensajes: así el fondo
   cubre TODA la columna del chat de forma consistente (header + mensajes
   + input) en lugar de solo el contenedor de mensajes, y no hay que
   duplicar la imagen ni tocar la transparencia de cada sub-contenedor a
   mano. z-index:-1 dentro del contexto de apilamiento de .col-chat basta
   para que quede debajo de todo sin necesidad de elevar a los hermanos. */
.col-chat::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-image: url('../assets/img/fondo-marqueteria.png');
    background-repeat: repeat;
    background-size: 350px;
    background-blend-mode: multiply;
    /* FIX PC vs Móvil: !important en ambas propiedades para que ninguna
       regla posterior (ni de mayor especificidad) pueda dejar esta capa
       en opacity:0 o devolverla detrás de .col-chat en ningún breakpoint. */
    opacity: 0.12 !important;
    z-index: 0 !important;
    pointer-events: none;
}

/* Tema oscuro: multiply oscurece demasiado sobre fondos ya oscuros, por
   eso se cambia a color-dodge (aclara en vez de oscurecer) con una
   opacidad mucho más baja para que el ícono se insinúe sin lavar el
   contraste de las burbujas. !important porque la base ahora también
   fuerza opacity — sin esto, el tema oscuro quedaría atascado en 0.12. */
body[data-theme="dark"] .col-chat::before {
    background-blend-mode: color-dodge;
    opacity: 0.03 !important;
}

.chat-header {
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    color: var(--texto-principal);
    padding: 14px 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid var(--borde-glass);
    /* FASE 44 — Soft UI: misma sombra de elevación que .buzones-header. */
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
    /* FIX fondo de marquetería: por encima de .col-chat::before (z-index:0). */
    position: relative;
    z-index: 1 !important;
}

.chat-header .titulo-wrap { display: flex; align-items: center; gap: 10px; min-width: 0; }
.chat-header .titulo-textos { min-width: 0; }
.chat-header-acciones { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

.chat-header .titulo-cliente {
    font-size: 0.95rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chat-header .estado-cliente { font-size: 0.72rem; color: var(--color-acento); }

.chat-mensajes {
    flex: 1;
    overflow-y: auto;
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* FIX fondo de marquetería: por encima de .col-chat::before (z-index:0). */
    position: relative;
    z-index: 1 !important;
    /* FASE 21: transparente a propósito — el fondo visible es el
       pseudo-elemento .col-chat::before. `background` (shorthand, no solo
       background-color) + !important porque este contenedor no debe volver
       a heredar NINGÚN fondo sólido — color o imagen — por accidente en un
       futuro parche puntual. */
    background: transparent !important;
}

.burbuja {
    max-width: 70%;
    padding: 10px 14px;
    border-radius: 14px;
    font-size: 0.88rem;
    color: var(--texto-oscuro);
    line-height: 1.45;
    border: 1px solid var(--borde-inner-glow);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.03);
}

.burbuja.cliente {
    background: var(--bg-burbuja-cliente);
    align-self: flex-start;
    border-bottom-left-radius: 3px;
}

.burbuja.propia {
    background: var(--bg-burbuja-propia);
    align-self: flex-end;
    border-bottom-right-radius: 3px;
    border-color: rgba(var(--color-acento-rgb), 0.25);
}

.burbuja .hora {
    display: block;
    font-size: 0.65rem;
    color: var(--texto-secundario);
    margin-top: 4px;
    text-align: right;
}

/* FASE 21 — Contraste de burbujas en [data-theme="light"]:
   - Asesora ("propia"): fondo verde corporativo SÓLIDO + texto blanco puro.
   - Cliente: fondo blanco + texto negro (ya era casi así; se deja explícito).
   El tema oscuro NO se toca — mantiene sus colores actuales (fondo tenue
   con texto claro), tal como pide el requerimiento. */
body[data-theme="light"] .burbuja.propia {
    background: var(--color-acento);
    border-color: var(--color-acento);
    color: #ffffff;
}

body[data-theme="light"] .burbuja.propia .hora {
    color: rgba(255, 255, 255, 0.82);
}

body[data-theme="light"] .burbuja.propia .burbuja-documento {
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.35);
    color: #ffffff;
}

body[data-theme="light"] .burbuja.cliente {
    background: #ffffff;
    color: #000000;
}

.burbuja-imagen {
    max-width: 100%;
    border-radius: 10px;
    display: block;
    margin-bottom: 4px;
    cursor: pointer;
}

.burbuja audio { max-width: 240px; display: block; }

.burbuja-documento {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--texto-principal);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 500;
    background: rgba(var(--color-acento-rgb), 0.08);
    border: 1px solid rgba(var(--color-acento-rgb), 0.25);
    border-radius: 10px;
    padding: 8px 12px;
    transition: background 0.15s ease;
}

.burbuja-documento:hover { background: rgba(var(--color-acento-rgb), 0.14); }

.chat-input-wrap {
    position: relative; /* ancla al menú flotante de plantillas y de emojis */
    /* FIX fondo de marquetería: por encima de .col-chat::before (z-index:0). */
    z-index: 1 !important;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    padding: 12px 16px;
    display: flex;
    align-items: center;
    gap: 10px;
    border-top: 1px solid var(--borde-glass);
    flex-shrink: 0; /* Nunca se comprime, aunque el chat crezca */
    /* FASE 21: nunca envuelve a una segunda línea — sin esto, en pantallas
       angostas el input podía forzar un salto de línea que empujaba el
       botón de enviar fuera del viewport visible. */
    flex-wrap: nowrap;
}

.chat-input-wrap input[type="text"],
.chat-input {
    /* FASE 21: flex 1 1 0% (en vez de flex:1 a secas) + min-width:0 es la
       combinación que realmente permite que un input dentro de un flex
       container se ENCOJA cuando no hay espacio, en vez de imponer su
       ancho intrínseco y desbordar el contenedor — sin min-width:0 el
       navegador nunca deja que el input baje de su ancho de contenido. */
    flex: 1 1 0%;
    min-width: 0;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 24px;
    padding: 13px 18px;
    color: var(--texto-principal);
    font-size: 0.88rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.2s ease;
}

.chat-input-wrap input[type="text"]:focus {
    border-color: rgba(var(--color-acento-rgb), 0.5);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.14), 0 0 18px rgba(var(--color-acento-rgb), 0.12);
}

/* FASE 21 — Botón de emoji (izquierda del input): mismo molde visual de
   .btn-icono, solo se ajusta el tamaño de fuente del carácter 😀 para que
   quede centrado y del mismo tamaño óptico que los íconos Lucide vecinos. */
.icono-emoji-caracter {
    font-size: 1.15rem;
    line-height: 1;
}

/* FASE 21 — Panel flotante del emoji-picker. Reutiliza el mismo patrón
   posicional de .menu-plantillas-flotante (ancla absoluta sobre
   .chat-input-wrap, que ya es position:relative) en vez de un mecanismo
   nuevo de overlay. */
.menu-emoji-flotante {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 12px;
    z-index: 20;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: var(--sombra-panel);
    border: 1px solid var(--borde-inner-glow);
}

.menu-emoji-flotante[hidden] { display: none; }

/* emoji-picker-element expone sus propias custom properties para
   tematizarse sin tocar su Shadow DOM — se mapean a las variables de
   Dark/Light Luxury ya existentes en vez de dejar sus colores por
   defecto, que no combinan con el resto de la interfaz. */
emoji-picker {
    --background: var(--bg-panel-alt);
    --border-color: var(--borde-glass);
    --indicator-color: var(--color-acento);
    --input-border-color: var(--borde-sutil);
    --outline-color: var(--color-acento);
    width: min(320px, calc(100vw - 40px));
    height: 360px;
}

/* FASE 21 — Botón Copiloto IA (✨). Comparte el molde de .btn-icono; el
   acento visual propio (glow sutil) lo distingue del resto de botones
   de la barra sin introducir un componente nuevo. */
.btn-copiloto-ia {
    color: var(--color-acento);
}

.btn-copiloto-ia:hover {
    background: rgba(var(--color-acento-rgb), 0.16);
}

/* Estado de carga: gira el ícono de destellos mientras se espera la
   respuesta del modelo. Reutiliza la animación girar-spin ya definida
   para .spin, en vez de declarar un keyframe duplicado. */
.btn-copiloto-ia.girando i {
    animation: girar-spin 0.9s linear infinite;
}

/* FASE 21 — el botón independiente de Copiloto IA (#btnCopilotoIA) queda
   oculto: la sugerencia de IA se fusionó dentro del flujo del botón de
   enviar/input en esta iteración de UX. La regla .btn-copiloto-ia de
   arriba se conserva (no se borra) porque sigue viva por si el botón
   vuelve a exponerse en una futura fase — solo se apaga su visibilidad. */
#btnCopilotoIA {
    display: none !important;
}

.btn-enviar {
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    border: 1px solid var(--borde-inner-glow);
    color: #0b0d0c;
    width: 42px;
    height: 42px;
    /* FASE 21: piso mínimo de tamaño táctil (44px, estándar de accesibilidad
       móvil) combinado con flex-shrink:0 — así el botón nunca se comprime
       por debajo de un tamaño usable, sin importar cuánto se achique el
       input vecino. */
    min-width: 44px;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-weight: 700;
    cursor: pointer;
    flex-shrink: 0;
    box-shadow: var(--sombra-glow), inset 0 1px 0 rgba(255, 255, 255, 0.25);
    transition: filter 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
}

.btn-enviar:hover {
    filter: brightness(1.06);
    box-shadow: 0 0 0 1px rgba(var(--color-acento-rgb), 0.25), 0 10px 28px rgba(var(--color-acento-rgb), 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.btn-enviar:active { transform: scale(0.95); }

/* ----- Columna derecha: Info Cliente ----- */
.col-info {
    background: var(--bg-panel-solido);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border-left: 1px solid var(--borde-sutil);
    box-shadow: -2px 0 12px rgba(0, 0, 0, 0.04);
    height: 100%;
    overflow-y: auto;
    padding: 26px 18px;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.info-perfil { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }

.info-avatar {
    width: 72px;
    height: 72px;
    border-radius: 20px;
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    /* FASE 21: mismo fix de contraste que .avatar-circulo. */
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    font-weight: 700;
    border: 1px solid var(--borde-inner-glow);
    box-shadow: var(--sombra-glow);
}

.info-perfil .nombre-completo { font-size: 1rem; font-weight: 600; }
.info-perfil .telefono { font-size: 0.8rem; color: var(--texto-secundario); }

.info-seccion h3 {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--texto-secundario);
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
}

.etiquetas-wrap { display: flex; flex-wrap: wrap; gap: 8px; }

.etiqueta {
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
    border: 1px solid rgba(var(--color-acento-rgb), 0.3);
    font-size: 0.72rem;
    padding: 4px 10px;
    border-radius: 8px;
    font-weight: 500;
}

.acciones-rapidas { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.btn-accion {
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    color: var(--texto-principal);
    border-radius: 12px;
    padding: 12px 8px;
    font-size: 0.78rem;
    font-family: inherit;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    transition: border-color 0.15s ease, color 0.15s ease, transform 0.12s ease, box-shadow 0.15s ease;
}

.btn-accion svg { color: var(--color-acento); }

.btn-accion:hover {
    border-color: rgba(var(--color-acento-rgb), 0.4);
    color: var(--color-acento);
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
}

/* ----- Nav móvil ----- */
.nav-movil {
    display: none;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border-top: 1px solid var(--borde-glass);
    /* FASE 44 — Soft UI: sombra invertida (hacia arriba) que separa el
       nav del contenido, en vez de depender solo del borde superior. */
    box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.05);
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    justify-content: space-around;
    align-items: center;
    padding: 8px 0;
    z-index: 50;

    /* CORRECCIÓN CACHÉ/OVERLAP: altura explícita + safe-area-inset-bottom.
       Sin esto, en iPhones con home indicator (gesto, sin botón físico) el
       sistema operativo reserva una franja invisible abajo que no cuenta
       como "viewport útil"; el nav quedaba más alto de lo que CSS calculaba
       y el input de texto terminaba tapado detrás. */
    min-height: calc(var(--altura-nav-movil) + env(safe-area-inset-bottom, 0px));
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    box-sizing: border-box;
}

/* FASE 44 — Soft UI: look "app nativa" — gris frío suave para los
   íconos inactivos (en vez de heredar --texto-secundario, que en modo
   claro tira a verdoso) y verde corporativo fuerte + chip/punto de
   estado para el ícono activo. */
.nav-movil button,
.nav-movil a {
    background: none;
    border: none;
    color: #9ca3af;
    font-size: 0.68rem;
    font-family: inherit;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    cursor: pointer;
    padding: 4px 10px;
    text-decoration: none;
    transition: color 0.15s ease;
    position: relative;
}

.nav-movil svg.lucide {
    padding: 4px 13px;
    border-radius: 12px;
    transition: background-color 0.15s ease;
}

.nav-movil button.activo,
.nav-movil a.activo { color: #166534; font-weight: 600; }

.nav-movil button.activo svg.lucide,
.nav-movil a.activo svg.lucide {
    background-color: rgba(22, 101, 52, 0.12);
}

.nav-movil button.activo::after,
.nav-movil a.activo::after {
    content: '';
    position: absolute;
    bottom: 1px;
    left: 50%;
    transform: translateX(-50%);
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: #166534;
}

/* ----- Responsive Mobile-First ----- */
@media (max-width: 899px) {
    /* FASE 43 — el menú global (.col-sidebar) dejó de vivir dentro del
       grid de .app-shell: ahora es un offcanvas fixed (ver bloque
       "Menú Global" más arriba), idéntico en móvil y en PC. Solo queda
       la vista activa (bandeja/chat/info) ocupando toda la fila. */
    .app-shell {
        grid-template-columns: 1fr;
        position: relative;
    }

    .col-buzones, .col-chat, .col-info {
        display: none;
        width: 100%;
        grid-column: 1;
        grid-row: 1;
    }

    .col-buzones.vista-activa,
    .col-chat.vista-activa,
    .col-info.vista-activa {
        display: flex;
    }

    /* CORRECCIÓN PROBLEMA 1: antes era un valor fijo de 56px que no
       cubría la altura real del nav en todos los dispositivos. Ahora
       usa la misma variable + safe-area que .nav-movil, garantizando
       que el input quede siempre visible por encima del menú, sin
       importar el modelo de teléfono o el tamaño de fuente del sistema. */
    .col-chat.vista-activa {
        /* Fallback para navegadores sin soporte de dvh (se sobreescribe abajo) */
        height: calc(100vh - var(--altura-nav-movil) - env(safe-area-inset-bottom, 0px));
        /* dvh = altura real visible, se recalcula cuando la barra del navegador
           aparece/desaparece. Esto es lo que padding-bottom no podía lograr,
           porque 100vh no se ajusta dinámicamente y nav-movil (fixed) queda
           anclado al viewport visual real, no al layout calculado con vh fijo. */
        height: calc(100dvh - var(--altura-nav-movil) - env(safe-area-inset-bottom, 0px));
        padding-bottom: 0;
    }

    .nav-movil { display: flex; }
}

@media (min-width: 900px) and (max-width: 1199px) {
    .app-shell { grid-template-columns: 300px 1fr; }
    .col-info { display: none; }

    .app-shell.show-info {
        grid-template-columns: 300px 1fr 280px;
    }
    .app-shell.show-info .col-info { display: flex; }
}

@media (min-width: 1200px) {
    .app-shell { grid-template-columns: 350px 1fr; }
    .col-buzones, .col-chat { display: flex; }
    .col-info { display: none; }
    .nav-movil { display: none; }

    .app-shell.show-info {
        grid-template-columns: 350px 1fr 350px;
    }
    .app-shell.show-info .col-info { display: flex; }
}

/* =====================================================================
   FASE 24 — Profundidad UI en escritorio (≥900px): separa las columnas
   con un margen real (grid-gap) para que el fondo grisáceo (--bg-app-shell)
   se vea entre ellas, y les da bordes redondeados + sombra flotante — el
   efecto de "tarjetas/paneles" que en móvil no aplica (ahí las columnas
   se apilan a pantalla completa una por una, sin necesidad de aire extra).
   ===================================================================== */
@media (min-width: 900px) {
    .app-shell {
        gap: 10px;
        padding: 10px;
    }

    .col-buzones,
    .col-chat,
    .col-info {
        height: 100%;
        border-radius: 16px;
        box-shadow: 0 4px 15px rgba(0, 0, 0, 0.03);
    }
}

/* ===================== MODAL: GESTOR DE PLANTILLAS ===================== */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
    padding: 20px;
}

.modal-overlay[hidden] { display: none; }

.modal-panel {
    width: 100%;
    max-width: 460px;
    max-height: 85vh;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-inner-glow);
    border-radius: 18px;
    box-shadow: var(--sombra-panel);
    display: flex;
    flex-direction: column;
    /* FASE 84 — BUGFIX GLOBAL: overflow:hidden acá NUNCA recorta contenido
       real — solo existe para que las esquinas redondeadas del panel
       recorten al .modal-header/.modal-form que viven dentro. El scroll de
       verdad ahora vive en .modal-form (ver más abajo), como ya hacían los
       overrides puntuales #modalGerencia/#modalCerrarChat de las Fases
       22/23A — este fix lo vuelve el comportamiento POR DEFECTO de todo
       modal del CRM en vez de tener que repetir el mismo parche cada vez
       que un formulario nuevo crece más que 85vh. */
    overflow: hidden;
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 18px;
    border-bottom: 1px solid var(--borde-glass);
    flex-shrink: 0;
}

.modal-header h2 {
    font-size: 1rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* FASE 84 — BUGFIX GLOBAL (Missing Vertical Scroll on Modals/Forms):
   .modal-header nunca se encoge (flex-shrink:0 arriba) y .modal-panel
   trae max-height:85vh + overflow:hidden — antes .modal-form también
   tenía flex-shrink:0, así que un formulario más alto que el espacio
   restante simplemente se cortaba en seco contra ese overflow:hidden del
   padre, dejando inputs/el botón Guardar inalcanzables en CUALQUIER
   modal del CRM (Registrar Visita Manual, Editar Cliente, Crear/Editar
   Usuario, etc. — cualquier <form class="modal-form"> es candidato).
   overflow-y:auto + min-height:0 (el min-height es el gotcha real de
   Flexbox: sin él, un hijo flex nunca se encoge por debajo de su
   contenido, así que el overflow-y nunca llega a activarse) hacen que
   SOLO el cuerpo del formulario scrollee — el header queda fijo arriba y
   el botón de submit, al final del form, siempre queda alcanzable
   scrolleando. Reemplaza los parches puntuales de #modalGerencia/
   #modalCerrarChat (Fases 22/23A) como comportamiento por defecto de
   TODO modal — esos 2 overrides quedan intactos pero redundantes. */
.modal-form {
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    overflow-y: auto;
    min-height: 0;
    -webkit-overflow-scrolling: touch;
}

.modal-form input,
.modal-form textarea {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 14px;
    color: var(--texto-principal);
    font-size: 0.88rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.25s ease;
}

.modal-form textarea { resize: vertical; }

.modal-form input:focus,
.modal-form textarea:focus {
    border-color: rgba(var(--color-acento-rgb), 0.55);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.16);
}

.modal-divisor {
    height: 1px;
    background: var(--borde-glass);
    flex-shrink: 0;
}

.lista-plantillas-gestor {
    padding: 10px 18px 18px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.plantilla-item-gestor {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 10px 12px;
}

.plantilla-item-gestor .plantilla-textos { min-width: 0; }

.plantilla-item-gestor .plantilla-titulo {
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 3px;
}

.plantilla-item-gestor .plantilla-preview {
    font-size: 0.75rem;
    color: var(--texto-secundario);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.btn-eliminar-plantilla {
    background: transparent;
    border: 1px solid transparent;
    color: var(--color-error);
    width: 32px;
    height: 32px;
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.btn-eliminar-plantilla:hover {
    background: var(--color-error-bg);
    border-color: var(--color-error);
}

/* ===================== MENÚ FLOTANTE: RESPUESTAS RÁPIDAS EN EL CHAT ===================== */
.menu-plantillas-flotante {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 12px;
    width: min(320px, calc(100vw - 40px));
    max-height: 280px;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-inner-glow);
    border-radius: 14px;
    box-shadow: var(--sombra-panel);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    z-index: 20;
}

.menu-plantillas-flotante[hidden] { display: none; }

.menu-plantillas-header {
    padding: 10px 14px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--texto-secundario);
    border-bottom: 1px solid var(--borde-glass);
    flex-shrink: 0;
}

.menu-plantillas-lista {
    overflow-y: auto;
    padding: 6px;
}

.plantilla-flotante-item {
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    color: var(--texto-principal);
    font-family: inherit;
    padding: 10px;
    border-radius: 9px;
    cursor: pointer;
    transition: background 0.15s ease;
}

.plantilla-flotante-item:hover { background: rgba(var(--color-acento-rgb), 0.1); }

.plantilla-flotante-item .plantilla-flotante-titulo {
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 2px;
}

.plantilla-flotante-item .plantilla-flotante-preview {
    font-size: 0.72rem;
    color: var(--texto-secundario);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.menu-plantillas-vacio {
    padding: 20px 14px;
    text-align: center;
    font-size: 0.8rem;
    color: var(--texto-secundario);
}
/* =====================================================================
   RESPONSIVE — Ajustes de layout móvil (columna de chat / input)
   ===================================================================== */

/* Asegura que el padding interno nunca sume ancho extra a los elementos */
*, *::before, *::after {
    box-sizing: border-box;
}

@media (max-width: 899px) {
    /* Fuerza a las columnas a medir exactamente la pantalla del celular.
       :not(.col-sidebar) es necesario porque la sidebar también es un
       <aside> hijo directo de .app-shell: sin la exclusión, este ancho de
       100vw !important (mayor especificidad que .col-sidebar sola) pisa
       el max-width:150px que la mantiene flotando junto al avatar. */
    .app-shell > section,
    .app-shell > aside:not(.col-sidebar),
    .col-chat,
    .col-buzones,
    .col-info {
        min-width: 0 !important; /* Destruye el ancho mínimo de escritorio */
        max-width: 100vw !important;
        width: 100% !important;
        margin: 0 !important;
    }

    /* Protege la barra inferior de escritura para que no se salga */
    .chat-input-wrap {
        width: 100% !important;
        max-width: 100vw !important;
        box-sizing: border-box !important;
        padding-left: 12px !important;
        padding-right: 12px !important;
    }
    
    /* Protege el encabezado del chat */
    .chat-header {
        width: 100% !important;
        box-sizing: border-box !important;
    }
}

/* FASE 21 — Flexbox roto en móvil (el input aplastaba/expulsaba el botón
   de enviar): breakpoint dedicado más angosto que el de arriba porque
   este problema se agrava específicamente en anchos de celular (≤768px),
   no en tablets. Reduce el padding lateral para ganar espacio horizontal
   real y fuerza font-size:16px en el input — por debajo de 16px, iOS
   Safari hace zoom automático al enfocar el campo, lo cual además
   desalinea el layout con el teclado abierto. */
@media (max-width: 768px) {
    .chat-input-wrap {
        padding: 10px 8px !important;
        gap: 6px !important;
    }

    .chat-input-wrap input[type="text"],
    .chat-input,
    #inputMensaje {
        font-size: 16px !important;
    }
}
/* =====================================================================
   FASE 4 — Tabs de filtro de buzones (reemplaza al buscador)
   ===================================================================== */
.filtros-buzones {
    display: flex;
    gap: 6px;
    padding: 10px 14px;
    overflow-x: auto;
    scrollbar-width: none;
}
.filtros-buzones::-webkit-scrollbar { display: none; }

.filtro-tab {
    flex-shrink: 0;
    background: var(--bg-input);
    border: none;
    color: var(--texto-secundario);
    font-size: 0.72rem;
    font-weight: 600;
    padding: 7px 13px;
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
    font-family: inherit;
    transition: background 0.15s ease, color 0.15s ease;
}

.filtro-tab:hover { color: var(--texto-principal); }

.filtro-tab.activo {
    background: var(--color-acento);
    color: #0b0d0c;
}

/* FASE 44 — Soft UI: los filtros inactivos toman el mismo lenguaje
   pastel que .badge-estado (fondo translúcido del color semántico), en
   vez del gris neutro plano, para leerse de un vistazo. */
.filtro-tab[data-filtro="nuevo"]:not(.activo)     { background: rgba(var(--color-acento-rgb), 0.12); color: var(--color-acento); }
.filtro-tab[data-filtro="esperando"]:not(.activo) { background: rgba(230, 162, 60, 0.14); color: #c98a2e; }
.filtro-tab[data-filtro="atendido"]:not(.activo)  { background: rgba(90, 140, 210, 0.14); color: #4d84c9; }
.filtro-tab[data-filtro="pagados"]:not(.activo)   { background: rgba(99, 159, 56, 0.14); color: #5a8f39; }
.filtro-tab[data-filtro="por_pagar"]:not(.activo) { background: rgba(224, 122, 122, 0.14); color: #c24d4d; }

body[data-theme="light"] .filtro-tab[data-filtro="esperando"]:not(.activo) { color: #9c6414; }
body[data-theme="light"] .filtro-tab[data-filtro="atendido"]:not(.activo)  { color: #2f5f9c; }

/* =====================================================================
   FASE 5 — Candado de asignación exclusiva
   ===================================================================== */
.candado-buzon {
    width: 15px;
    height: 15px;
    color: var(--texto-secundario);
    flex-shrink: 0;
}

.buzon-item.bloqueado { opacity: 0.72; }
.buzon-item.bloqueado .nombre-cliente { color: var(--texto-secundario); }

.chat-input-wrap input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn-icono:disabled,
.btn-enviar:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}
/* =====================================================================
   FASE 6 — Modal de cierre, botón "Marcar Pagado" y badge de cartera
   ===================================================================== */

/* Reutiliza .modal-form pero le faltaba estilo para <select> */
.modal-form select {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 14px;
    color: var(--texto-principal);
    font-size: 0.88rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.25s ease;
}

.modal-form select:focus {
    border-color: rgba(var(--color-acento-rgb), 0.55);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.16);
}

.campos-financieros {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Badge amarillo "Saldo Pendiente" junto al nombre del cliente */
.badge-saldo-pendiente {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: rgba(230, 184, 0, 0.16);
    color: #e6b800;
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 2px 8px;
    border-radius: 999px;
    margin-left: 8px;
    vertical-align: middle;
}

.badge-saldo-pendiente svg { width: 11px; height: 11px; }

/* =====================================================================
   FASE 7 — Perfil enriquecido (columna derecha) y alerta SLA
   ===================================================================== */

.info-stats-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.info-stat {
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 10px;
    text-align: center;
}

.info-stat-valor {
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--color-acento);
}

.info-stat-label {
    font-size: 0.68rem;
    color: var(--texto-secundario);
    margin-top: 2px;
}

/* Alerta SLA: parpadeo suave, no agresivo — comunica urgencia sin
   distraer del resto de la lista. 2s de período es lo bastante lento
   para no sentirse como una notificación de error crítico. */
@keyframes pulso-sla {
    0%, 100% { box-shadow: inset 0 0 0 1px rgba(224, 122, 122, 0.35); }
    50%      { box-shadow: inset 0 0 0 1px rgba(224, 122, 122, 0.85); }
}

.buzon-item.alerta-sla {
    background: rgba(224, 122, 122, 0.06);
    border-left: 3px solid var(--color-error);
    animation: pulso-sla 2s ease-in-out infinite;
}

.buzon-item.alerta-sla:hover {
    background: rgba(224, 122, 122, 0.12);
}

/* =====================================================================
   FASE 8 — Gestor de Etiquetas e input[type=color] moderno
   ===================================================================== */

.modal-divisor {
    height: 1px;
    background: var(--borde-sutil);
    margin: 18px 0;
}

.etiquetas-modal-lista {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 220px;
    overflow-y: auto;
}

.etiqueta-checkbox-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: 10px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    cursor: pointer;
    transition: background 0.15s ease;
}

.etiqueta-checkbox-item:hover { background: var(--bg-panel-alt); }

.etiqueta-checkbox-item input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--color-acento);
    cursor: pointer;
}

.etiqueta-color-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.06);
}

.etiqueta-nombre-texto {
    font-size: 0.85rem;
    color: var(--texto-principal);
}

.campo-etiqueta-nueva {
    display: flex;
    gap: 10px;
    align-items: center;
}

.campo-etiqueta-nueva input[type="text"] { flex: 1; }

/* Input color moderno: se elimina el look nativo cuadrado del navegador
   y se deja un swatch circular consistente con la estética premium. */
input[type="color"] {
    -webkit-appearance: none;
    appearance: none;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 50%;
    padding: 0;
    cursor: pointer;
    background: none;
    flex-shrink: 0;
}
input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; border-radius: 50%; }
input[type="color"]::-webkit-color-swatch { border: 2px solid var(--borde-sutil); border-radius: 50%; }
input[type="color"]::-moz-color-swatch { border: 2px solid var(--borde-sutil); border-radius: 50%; }

/* =====================================================================
   FASE 10 — Deuda total en el perfil y Panel Gerencial
   ===================================================================== */

/* Estados de la tarjeta "Cartera" en el perfil del cliente */
.info-stat.info-stat-alerta .info-stat-valor { color: var(--color-error); }
.info-stat.info-stat-al-dia .info-stat-valor {
    color: var(--texto-secundario);
    font-size: 0.9rem;
}

/* Panel Gerencial: modal más ancho que el resto */
.modal-panel-ancho { max-width: 680px; }

/* Centro de Reportes: cada reporte vive en su propia tarjeta, separada
   visualmente de la otra (Reporte Maestro vs. Reporte Simple). */
.gerencia-reporte-bloque {
    padding: 0 18px 18px;
}

.gerencia-subtitulo {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85rem;
    font-weight: 700;
    padding: 0 18px;
    margin-bottom: 10px;
    color: var(--texto-secundario);
}

.gerencia-reporte-bloque .gerencia-subtitulo { padding: 0; }

/* =====================================================================
   FASE 11 — Rediseño Visual "Ultra Avanzado"
   Más aire, jerarquía tipográfica más profesional y el panel de
   cliente (.col-info) con secciones que se sienten como tarjetas
   independientes. Todo aditivo: no se borra nada de fases anteriores.
   ===================================================================== */

/* ----- Jerarquía tipográfica ----- */
h1, h2, h3 { letter-spacing: -0.01em; }

.gerencia-subtitulo,
.info-seccion h3 {
    font-size: 0.74rem;
    letter-spacing: 0.08em;
}

/* ----- Más aire en encabezados y paneles clave ----- */
.buzones-header { padding: 20px 22px; gap: 12px; }
.chat-header { padding: 18px 22px; }
.col-info { padding: 30px 22px; gap: 28px; }
.modal-panel { padding: 28px; }

/* ----- Logo de empresa (esquina superior izquierda) ----- */
.buzones-header-izq {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

/* FASE 43 — agrupa Cerrar Turno (condicional) + la hamburguesa del Menú
   Global en el extremo derecho del header, como par de hijos flex de
   .buzones-header (que usa justify-content: space-between). */
.buzones-header-der {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.logo-empresa {
    width: 40px;
    height: 40px;
    border-radius: 12px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    border: 1px solid var(--borde-inner-glow);
    box-shadow: var(--sombra-glow);
}

.logo-empresa img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.logo-empresa-fallback {
    display: none; /* Solo se activa vía onerror del <img> si el logo real no existe aún */
    width: 100%;
    height: 100%;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.95rem;
    color: #0b0d0c;
}

.divisor-vertical-header {
    width: 1px;
    height: 28px;
    background: var(--borde-sutil);
    flex-shrink: 0;
}

@media (max-width: 380px) {
    /* En pantallas muy angostas, prioriza el nombre de la asesora
       sobre el logo antes que romper el header a dos líneas. */
    .divisor-vertical-header { display: none; }
    .logo-empresa { width: 34px; height: 34px; }
}

/* ----- Perfil de Cliente 2.0: tarjetas independientes con profundidad ----- */
.info-perfil,
.info-seccion {
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-radius: 16px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}

body[data-theme="light"] .info-perfil,
body[data-theme="light"] .info-seccion {
    box-shadow: 0 4px 14px rgba(120, 120, 100, 0.08);
}

.info-perfil { padding: 22px 16px; }
.info-seccion { padding: 18px 16px; }

/* =====================================================================
   FASE 12 — Página de Gerencia dedicada (gerencia.php)
   Layout propio de una sola columna centrada, sin las 3 columnas del
   dashboard, pensado para que gráficos y tablas respiren.
   ===================================================================== */
body.pagina-gerencia {
    background: var(--bg-app-shell);
    min-height: 100vh;
    overflow-y: auto;
}

.gerencia-shell {
    max-width: 1180px;
    margin: 0 auto;
    padding: 28px 24px 80px;
    display: flex;
    flex-direction: column;
    gap: 26px;
    /* FASE 29 (Paso 3): contenedor principal de gerencia.php ahora que
       aloja el War Room completo (KPIs + pestañas + gráficas) — scroll
       vertical propio explícito y suficiente padding inferior para que
       el contenido nunca quede cortado al hacer scroll hasta el final,
       sobre todo en celular. */
    overflow-y: auto;
}

.gerencia-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

.gerencia-topbar-izq {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}

.gerencia-titulo-grupo h1 { font-size: 1.25rem; font-weight: 700; }
.gerencia-titulo-grupo p {
    font-size: 0.8rem;
    color: var(--texto-secundario);
    margin-top: 2px;
}

.gerencia-topbar-acciones { display: flex; align-items: center; gap: 8px; }

.btn-volver-dashboard {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    color: var(--texto-principal);
    font-size: 0.82rem;
    font-weight: 600;
    padding: 10px 16px;
    border-radius: 12px;
    text-decoration: none;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, transform 0.12s ease;
}

.btn-volver-dashboard:hover {
    border-color: rgba(var(--color-acento-rgb), 0.4);
    color: var(--color-acento);
    transform: translateY(-1px);
}

/* ----- Filtro de fechas global ----- */
.gerencia-filtro-fechas {
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-glass);
    border-radius: 16px;
    padding: 18px 20px;
    display: flex;
    align-items: flex-end;
    gap: 14px;
    flex-wrap: wrap;
    box-shadow: var(--sombra-panel);
}

.gerencia-filtro-campo { display: flex; flex-direction: column; gap: 6px; }
/* FASE 25 — mismo patrón que .modal-overlay[hidden]/.menu-emoji-flotante[hidden]:
   sin esta regla, el atributo [hidden] pierde el empate de especificidad
   contra ".gerencia-filtro-campo { display:flex }" y el navegador lo
   muestra igual (ver #wrapFechaInicioKpi/#wrapFechaFinKpi en dashboard.php). */
.gerencia-filtro-campo[hidden] { display: none; }

.gerencia-filtro-campo label {
    font-size: 0.72rem;
    color: var(--texto-secundario);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.gerencia-filtro-campo input[type="date"] {
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 10px;
    padding: 10px 12px;
    color: var(--texto-principal);
    font-size: 0.85rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.2s ease;
    /* Fuerza el ícono nativo del selector de fecha a un tono visible
       en ambos temas sin depender del user-agent. */
    color-scheme: dark;
}

body[data-theme="light"] .gerencia-filtro-campo input[type="date"] {
    color-scheme: light;
}

.gerencia-filtro-campo input[type="date"]:focus {
    border-color: rgba(var(--color-acento-rgb), 0.5);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.14);
}

/* FASE 23B — reutiliza .gerencia-filtro-campo (label + control) para los
   filtros de select/texto de clientes.php, con el mismo look que ya
   tienen los input[type=date] de arriba. */
.gerencia-filtro-campo select,
.gerencia-filtro-campo input[type="text"] {
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 10px;
    padding: 10px 12px;
    color: var(--texto-principal);
    font-size: 0.85rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.2s ease;
    min-width: 160px;
}

.gerencia-filtro-campo select:focus,
.gerencia-filtro-campo input[type="text"]:focus {
    border-color: rgba(var(--color-acento-rgb), 0.5);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.14);
}

/* Filas de tabla clicables (ej. clientes.php -> abre el Expediente) */
.fila-clickable { cursor: pointer; }
.fila-clickable:hover { background: rgba(var(--color-acento-rgb), 0.08) !important; }

/* =====================================================================
   FASE 24 — Columna "Acciones" del Directorio de Clientes (clientes.php)
   ===================================================================== */
.celda-acciones-cliente {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.btn-accion-cartera,
.btn-accion-expediente {
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    color: var(--texto-principal);
    font-size: 0.72rem;
    font-weight: 600;
    padding: 7px 12px;
    border-radius: 8px;
    cursor: pointer;
    font-family: inherit;
    white-space: nowrap;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn-accion-expediente:hover {
    border-color: rgba(var(--color-acento-rgb), 0.4);
    color: var(--color-acento);
    background: rgba(var(--color-acento-rgb), 0.1);
}

.btn-accion-cartera {
    color: #e6b800;
    border-color: rgba(230, 184, 0, 0.35);
}

.btn-accion-cartera:hover {
    background: rgba(230, 184, 0, 0.14);
    border-color: rgba(230, 184, 0, 0.5);
}

.btn-aplicar-filtro {
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    border: 1px solid var(--borde-inner-glow);
    color: #0b0d0c;
    font-weight: 700;
    font-size: 0.85rem;
    padding: 11px 20px;
    border-radius: 10px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    box-shadow: var(--sombra-glow), inset 0 1px 0 rgba(255, 255, 255, 0.25);
    transition: filter 0.15s ease, transform 0.1s ease;
    font-family: inherit;
}

.btn-aplicar-filtro:hover { filter: brightness(1.06); transform: translateY(-1px); }
.btn-aplicar-filtro:active { transform: scale(0.98); }

/* ----- Tarjetas de resumen ----- */
.gerencia-resumen-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
}

@media (max-width: 900px) { .gerencia-resumen-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .gerencia-resumen-grid { grid-template-columns: 1fr; } }

/* FASE 68 — Task 3: a diferencia de gerencia.php (donde .gerencia-shell ya
   aporta gap entre secciones), .drilldown-tier (visitas_dashboard.php) no
   tiene gap propio — sin este margen, las tarjetas KPI quedarían pegadas
   a la tabla de Jornadas de abajo. Solo 3 tarjetas (no 4): la última
   columna del grid queda vacía en desktop, por diseño. */
#kpiGridJornadasComercial { margin-bottom: 16px; }

.gerencia-resumen-card {
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-glass);
    border-radius: 16px;
    padding: 20px;
    display: flex;
    align-items: center;
    gap: 14px;
    box-shadow: var(--sombra-panel);
}

.gerencia-resumen-icono {
    width: 44px;
    height: 44px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 1.1rem;
}

.gerencia-resumen-card.card-asegurado .gerencia-resumen-icono { background: rgba(var(--color-acento-rgb), 0.16); color: var(--color-acento); }
.gerencia-resumen-card.card-riesgo .gerencia-resumen-icono { background: rgba(230, 184, 0, 0.16); color: #e6b800; }
.gerencia-resumen-card.card-total .gerencia-resumen-icono { background: rgba(99, 160, 200, 0.16); color: #63a0c8; }
.gerencia-resumen-card.card-chats .gerencia-resumen-icono { background: rgba(139, 143, 138, 0.16); color: var(--texto-secundario); }

.gerencia-resumen-valor { font-size: 1.3rem; font-weight: 700; }
.gerencia-resumen-label { font-size: 0.74rem; color: var(--texto-secundario); margin-top: 2px; }

/* =====================================================================
   FASE 29 (Paso 3) — Panel de Business Intelligence (War Room), ahora
   exclusivo de gerencia.php: filtro de fechas + KPIs + sistema de
   pestañas (Financiero/Equipo/Rutas/Insights IA) + gráficas Chart.js.
   Vive directamente dentro de .gerencia-shell, debajo del filtro de
   fechas histórico de la página (ver "FILTRO DE FECHAS" en gerencia.php).
   ===================================================================== */
.bi-dashboard-wrap {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.bi-tabs {
    display: flex;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 5px;
    background: var(--bg-panel-solido);
    border: 1px solid var(--borde-sutil);
    border-radius: 14px;
    overflow-x: auto;
    box-shadow: var(--sombra-panel);
}

.bi-tabs li {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 9px 18px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--texto-secundario);
    border-radius: 10px;
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
    transition: background 0.18s ease, color 0.18s ease;
}

.bi-tabs li:hover { color: var(--color-acento); background: rgba(var(--color-acento-rgb), 0.1); }

.bi-tabs li.active {
    background: var(--color-acento);
    color: #ffffff;
    box-shadow: var(--sombra-glow);
}

.bi-tabs li i { width: 15px; height: 15px; flex-shrink: 0; }

.tab-content { display: none; }

.tab-content.active {
    display: block;
    animation: biTabFadeIn 0.22s ease;
}

@keyframes biTabFadeIn {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Layout genérico "2/3 + 1/3" reutilizado por los sectores Financiero
   (Fase 29 Paso 1) y Equipo (Fase 29 Paso 2): tarjeta grande de gráfico
   a la izquierda, tarjeta pequeña de resumen/tabla a la derecha. */
.bi-grid-2-1 {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 20px;
}

@media (max-width: 900px) {
    .bi-grid-2-1 { grid-template-columns: 1fr; }
}

/* FASE 32 — Grid genérico de 2 columnas iguales (mi_rendimiento.php):
   dona operativa y gráfica de SLA pesan lo mismo, a diferencia de
   .bi-grid-2-1 (2/3 + 1/3) usado en gerencia.php. */
.bi-grid-2-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

@media (max-width: 900px) {
    .bi-grid-2-2 { grid-template-columns: 1fr; }
}

/* FASE 34 — Pila vertical genérica para apilar varios .bi-grid-2-1/2-2 (o
   .bi-card sueltas) dentro de una misma pestaña/vista sin depender de
   márgenes ad-hoc en cada bloque nuevo. */
.bi-secciones {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.bi-card {
    background: var(--bg-panel-solido);
    border: 1px solid var(--borde-sutil);
    border-radius: 16px;
    padding: 18px;
    box-shadow: var(--sombra-panel);
    min-width: 0;
}

/* Sector Rutas (Fase 29 Paso 2): una sola tarjeta centrada, sin grid
   de 2 columnas — el PolarArea ya es autosuficiente visualmente. */
.bi-card-centrada {
    max-width: 640px;
    margin: 0 auto;
}

.bi-card h3 {
    margin: 0 0 14px;
    font-size: 0.92rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--texto-principal);
}

.bi-card h3 i { width: 17px; height: 17px; color: var(--color-acento); }

.bi-chart-wrap {
    position: relative;
    height: 320px;
}

.bi-chart-wrap-doughnut {
    height: 260px;
    display: flex;
    align-items: center;
    justify-content: center;
}

@media (max-width: 520px) {
    .bi-chart-wrap { height: 260px; }
    .bi-chart-wrap-doughnut { height: 220px; }
}

/* FASE 29 (Paso 3) — Diseño móvil del Panel BI en gerencia.php. Breakpoint
   propio (768px) en vez de reutilizar el de 900px de arriba, para que
   quede explícito qué reglas responden a "celular" vs "tablet/panel
   angosto de escritorio". */
@media (max-width: 768px) {
    /* Pestañas deslizables con el dedo en vez de apilarse o desbordar
       el ancho de la pantalla — mismo .bi-tabs, ahora con overflow-x
       reforzado explícitamente para este breakpoint. */
    .bi-tabs {
        overflow-x: auto;
        white-space: nowrap;
        flex-wrap: nowrap;
        -webkit-overflow-scrolling: touch;
    }

    .bi-tabs li { white-space: nowrap; }

    /* Los grids "2/3 + 1/3" (Financiero, Equipo) se apilan: gráfica
       grande arriba, tarjeta pequeña/tabla debajo. */
    .bi-grid-2-1 { grid-template-columns: 1fr; }

    /* Chart.js necesita una altura mínima explícita en el contenedor
       para no aplastarse cuando el ancho se reduce a una sola columna. */
    .bi-chart-wrap,
    .bi-chart-wrap canvas {
        min-height: 250px;
    }
}

/* ----- Paneles genéricos (gráfico y tabla) ----- */
.gerencia-panel {
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-glass);
    border-radius: 18px;
    padding: 24px;
    box-shadow: var(--sombra-panel);
}

.gerencia-panel h2 {
    font-size: 0.95rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 18px;
}

.gerencia-panel h2 svg { color: var(--color-acento); }

.gerencia-grafico-wrap { position: relative; height: 320px; }

/* FASE 74 — Reconciliación de KPIs: resumen "N acciones -> M visitas
   físicas" sobre el Historial de Visitas (ver visitas_dashboard.php /
   js/visitas_dashboard.js pintarResumenSesionesHistorial()). */
.historial-resumen-sesiones {
    margin: 0 0 10px;
    font-size: 0.85rem;
    color: var(--texto-secundario);
}
.historial-resumen-sesiones strong { color: var(--texto-principal); }

/* ----- Tabla de Ranking completa ----- */
.gerencia-tabla-wrap { overflow-x: auto; }

.gerencia-tabla { width: 100%; border-collapse: collapse; font-size: 0.85rem; }

.gerencia-tabla th {
    text-align: left;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--texto-secundario);
    font-weight: 700;
    padding: 10px 14px;
    border-bottom: 1px solid var(--borde-sutil);
    white-space: nowrap;
}

.gerencia-tabla td {
    padding: 13px 14px;
    border-bottom: 1px solid var(--borde-glass);
    white-space: nowrap;
    color: var(--texto-principal);
}

.gerencia-tabla tbody tr:hover { background: rgba(var(--color-acento-rgb), 0.05); }

.gerencia-tabla-puesto {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: rgba(var(--color-acento-rgb), 0.16);
    color: var(--color-acento);
    font-size: 0.72rem;
    font-weight: 700;
}

.gerencia-tabla-dinero { color: var(--color-acento); font-weight: 700; }

.gerencia-tasa-barra { display: flex; align-items: center; gap: 8px; min-width: 120px; }

.gerencia-tasa-track {
    flex: 1;
    height: 6px;
    border-radius: 999px;
    background: var(--bg-input);
    overflow: hidden;
}

.gerencia-tasa-fill {
    height: 100%;
    background: linear-gradient(to right, var(--color-acento-claro), var(--color-acento));
    border-radius: 999px;
}

.gerencia-tasa-texto {
    font-size: 0.78rem;
    font-weight: 700;
    flex-shrink: 0;
    width: 38px;
    text-align: right;
}

/* FASE 34 — Ranking Avanzado (rendimiento_equipo.php): avatar circular +
   nombre en la primera columna, badge de nivel + mini-barra de XP en la
   segunda. Reutiliza .barra-progreso-track/.barra-xp de mi_progreso.php
   con una variante compacta (mini) en vez de la barra grande de esa
   página. */
.gerencia-tabla-asesora {
    display: flex;
    align-items: center;
    gap: 10px;
}

.gerencia-tabla-avatar {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(var(--color-acento-rgb), 0.16);
    color: var(--color-acento);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 700;
}

.gerencia-tabla-nivel {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 90px;
}

.gerencia-tabla-nivel-badge {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--texto-principal);
}

.barra-progreso-track-mini {
    max-width: 90px;
    height: 6px;
}

/* FASE 34 — Heatmap de Actividad estilo GitHub (mi_rendimiento.php):
   auto-fit con un mínimo de 15px por cuadrito, se reacomoda solo según el
   ancho disponible de la tarjeta (móvil vs escritorio). */
.heatmap-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15px, 1fr));
    gap: 3px;
}

.heatmap-dia {
    aspect-ratio: 1 / 1;
    border-radius: 3px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
}

.heatmap-dia[data-nivel="1"] { background: rgba(99, 159, 56, 0.35); border-color: transparent; }
.heatmap-dia[data-nivel="2"] { background: rgba(99, 159, 56, 0.65); border-color: transparent; }
.heatmap-dia[data-nivel="3"] { background: var(--color-acento); border-color: transparent; }

@media (max-width: 700px) {
    .gerencia-shell { padding: 20px 14px 80px; }
    .gerencia-topbar { flex-direction: column; align-items: flex-start; }
    .gerencia-filtro-fechas { width: 100%; }
    .gerencia-topbar-acciones { width: 100%; justify-content: space-between; }
}

/* =====================================================================
   FASE 13 — Capa de Inteligencia Estratégica: botón de Resumen IA
   ===================================================================== */

.btn-ia-resumen {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    background: linear-gradient(135deg, rgba(var(--color-acento-rgb), 0.16), rgba(var(--color-acento-rgb), 0.06));
    border: 1px solid rgba(var(--color-acento-rgb), 0.35);
    color: var(--color-acento);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    padding: 11px 14px;
    border-radius: 12px;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.2s ease, opacity 0.15s ease;
}

.btn-ia-resumen:hover:not(:disabled) {
    background: linear-gradient(135deg, rgba(var(--color-acento-rgb), 0.24), rgba(var(--color-acento-rgb), 0.1));
    box-shadow: 0 0 0 1px rgba(var(--color-acento-rgb), 0.25), 0 8px 20px rgba(var(--color-acento-rgb), 0.18);
    transform: translateY(-1px);
}

.btn-ia-resumen:active:not(:disabled) { transform: scale(0.98); }

.btn-ia-resumen:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
}

.btn-ia-resumen svg {
    width: 16px;
    height: 16px;
    /* Giro sutil mientras está deshabilitado (esperando respuesta del
       endpoint), sin necesitar una clase extra ni JS de animación. */
}

.btn-ia-resumen:disabled svg {
    animation: girar-suave 1.4s linear infinite;
}

@keyframes girar-suave {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

.ia-resumen-estado {
    margin-top: 10px;
    font-size: 0.74rem;
    color: var(--texto-secundario);
    text-align: center;
    line-height: 1.4;
}

.ia-resumen-estado.exito { color: var(--color-acento); }
.ia-resumen-estado.error { color: #e67373; }

/* FIX DEFINITIVO: Habilitar scroll en el perfil del cliente para pantallas móviles */
@media (max-width: 900px) {
    .col-info.vista-activa {
        /* -65px = nav inferior. FASE 43: el menú global ya no vive en su
           propia fila del grid (ahora es un offcanvas fixed), así que no
           hay que descontar su altura aquí. */
        height: calc(100vh - 65px) !important;
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch !important; /* Scroll fluido en iOS */
        padding-bottom: 120px !important; /* Espacio de sobra para que no lo tape el menú móvil */
        display: flex !important;
        flex-direction: column;
    }
}

/* ----- FASE 13: Caja del Resumen Ejecutivo ya generado ----- */
.ia-resumen-caja {
    background: linear-gradient(160deg, rgba(var(--color-acento-rgb), 0.1), rgba(var(--color-acento-rgb), 0.03));
    border: 1px solid rgba(var(--color-acento-rgb), 0.28);
    border-radius: 14px;
    padding: 14px 16px;
    margin-bottom: 12px;
    position: relative;
    overflow: hidden;
}

/* Línea de acento vertical a la izquierda: firma visual de "esto lo
   generó IA", distinguible de una tarjeta de dato normal como
   .info-stat sin depender solo del ícono. */
.ia-resumen-caja::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 3px;
    height: 100%;
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
}

.ia-resumen-caja-header {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-acento);
    margin-bottom: 8px;
}

.ia-resumen-caja-header svg {
    width: 13px;
    height: 13px;
}

.ia-resumen-texto {
    font-size: 0.82rem;
    line-height: 1.55;
    color: var(--texto-secundario);
    margin: 0;
    white-space: pre-line;
}

/* =====================================================================
   EXPEDIENTE DE INTELIGENCIA — Off-Canvas
   -----------------------------------------------------------------
   Estética deliberadamente distinta del resto del CRM (que es Dark
   Luxury): aquí se usa fondo claro fijo, no las variables de tema
   (--bg-panel, etc.), porque el Expediente se piensa como un "dossier"
   o carpeta física — un documento de negocio, no una pantalla de chat.
   Por eso NO reacciona a data-theme="dark"/"light" del resto del CRM.
   ===================================================================== */

.expediente-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 20, 15, 0.55);
    backdrop-filter: blur(2px);
    z-index: 200;
    /* display se maneja vía [hidden] + esta clase, nunca en conflicto:
       ver nota de especificidad de CSS ya documentada en Fase 13
       (mismo motivo por el que app.js fuerza style.display además de
       hidden en otros componentes). */
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
}

.expediente-overlay.abierto {
    opacity: 1;
    pointer-events: auto;
}

.expediente-panel {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 440px;
    max-width: 100vw;
    background: #f7f8f6;
    color: #1c1f1c;
    box-shadow: -12px 0 40px rgba(0, 0, 0, 0.35);
    transform: translateX(100%);
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.expediente-overlay.abierto .expediente-panel {
    transform: translateX(0);
}

@media (max-width: 640px) {
    .expediente-panel {
        width: 100vw;
    }
}

.expediente-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 20px 22px;
    background: #ffffff;
    border-bottom: 1px solid #e4e7e2;
    flex-shrink: 0;
}

.expediente-header h2 {
    font-size: 1.05rem;
    font-weight: 800;
    color: #1c1f1c;
    margin: 0 0 2px 0;
}

.expediente-subtitulo {
    font-size: 0.78rem;
    color: #6b756a;
    margin: 0;
}

.expediente-header .btn-icono {
    background: #f0f2ef;
    border: 1px solid #e4e7e2;
    color: #1c1f1c;
    border-radius: 10px;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s ease;
}
.expediente-header .btn-icono:hover { background: #e4e7e2; }

.expediente-body {
    flex: 1;
    overflow-y: auto;
    padding: 20px 22px 32px;
}

.expediente-seccion {
    margin-bottom: 26px;
}

.expediente-seccion h3 {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 0.82rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #639f38;
    margin: 0 0 12px 0;
}

.expediente-seccion h3 svg { width: 15px; height: 15px; }

/* ----- Biografía IA ----- */
.expediente-biografia {
    background: #ffffff;
    border: 1px solid #e4e7e2;
    border-radius: 12px;
    padding: 14px 16px;
    font-size: 0.85rem;
    line-height: 1.6;
    color: #33372f;
}

/* ----- LTV y Frecuencia ----- */
.expediente-stats-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.expediente-stat {
    background: #ffffff;
    border: 1px solid #e4e7e2;
    border-radius: 12px;
    padding: 14px;
    text-align: center;
}

.expediente-stat-valor {
    font-size: 1.15rem;
    font-weight: 800;
    color: #1c1f1c;
    margin-bottom: 3px;
}

.expediente-stat-label {
    font-size: 0.68rem;
    color: #6b756a;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* ----- Timeline ----- */
.expediente-timeline {
    position: relative;
    padding-left: 22px;
}

.expediente-timeline::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 4px;
    bottom: 4px;
    width: 2px;
    background: #e4e7e2;
}

.timeline-item {
    position: relative;
    padding-bottom: 18px;
}
.timeline-item:last-child { padding-bottom: 0; }

.timeline-item-icono {
    position: absolute;
    left: -22px;
    top: 0;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #639f38;
    color: #ffffff;
    z-index: 1;
}
.timeline-item-icono svg { width: 10px; height: 10px; }

.timeline-item.tipo-resumen_ia .timeline-item-icono,
.timeline-item.tipo-intencion_ia .timeline-item-icono {
    background: #3b6bd6;
}

.timeline-item-card {
    background: #ffffff;
    border: 1px solid #e4e7e2;
    border-radius: 10px;
    padding: 10px 13px;
}

.timeline-item-titulo {
    font-size: 0.8rem;
    font-weight: 700;
    color: #1c1f1c;
    display: flex;
    justify-content: space-between;
    gap: 8px;
}

.timeline-item-monto { color: #639f38; }

.timeline-item-detalle {
    font-size: 0.76rem;
    color: #565f53;
    margin-top: 3px;
    line-height: 1.45;
}

.timeline-item-fecha {
    font-size: 0.68rem;
    color: #9aa197;
    margin-top: 5px;
}

/* ----- Botón "Abrir Expediente" (columna derecha, dark theme) ----- */
.btn-abrir-expediente {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    color: var(--texto-principal);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    padding: 11px 14px;
    border-radius: 12px;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.btn-abrir-expediente:hover {
    background: var(--bg-panel-alt);
    border-color: var(--color-acento);
}

/* =====================================================================
   .filtros-buzones — scroll horizontal funcional en TODOS los dispositivos
   -----------------------------------------------------------------
   Fix anterior: ocultaba la scrollbar por completo (scrollbar-width: none),
   lo que funcionaba en móvil (scroll por touch, sin necesitar indicador
   visual) pero dejaba a los usuarios de mouse/trackpad en laptop sin
   ninguna pista de que había contenido oculto ni una barra que arrastrar.
   Fix actual: se dibuja una scrollbar horizontal delgada (4px) y sutil,
   visible en todo momento, en vez de ocultarla.
   ===================================================================== */

.filtros-buzones {
    display: flex;
    flex-wrap: nowrap;                  /* nunca permite que las pestañas se apilen en 2 líneas */
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;  /* inercia suave en iOS/Safari */
    scroll-snap-type: x proximity;      /* alinea la pestaña al soltar el scroll */

    /* Firefox: scrollbar delgada nativa (no hay pseudo-elemento en Firefox) */
    scrollbar-width: thin;
    scrollbar-color: rgba(99, 159, 56, 0.45) transparent;
}

/* Chrome / Safari / Edge (Chromium): scrollbar horizontal delgada y elegante */
.filtros-buzones::-webkit-scrollbar {
    height: 4px;               /* delgada, como pediste */
    width: auto;
}
.filtros-buzones::-webkit-scrollbar-track {
    background: transparent;
}
.filtros-buzones::-webkit-scrollbar-thumb {
    background: rgba(99, 159, 56, 0.45);   /* tinte del color acento, sutil */
    border-radius: 10px;
}
.filtros-buzones::-webkit-scrollbar-thumb:hover {
    background: rgba(99, 159, 56, 0.7);    /* más visible al pasar el mouse por encima */
}

.filtros-buzones .filtro-tab {
    flex-shrink: 0;             /* cada pestaña conserva su ancho, nunca se comprime */
    scroll-snap-align: start;
}

/* ----- Biografía IA: botón "Generar Perfil con IA" ----- */
.btn-generar-biografia {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    background: linear-gradient(135deg, rgba(99, 159, 56, 0.12), rgba(99, 159, 56, 0.04));
    border: 1px solid rgba(99, 159, 56, 0.35);
    color: #4a7a2a;
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    padding: 12px 14px;
    border-radius: 10px;
    cursor: pointer;
    transition: background 0.15s ease, opacity 0.15s ease;
}
.btn-generar-biografia:hover:not(:disabled) {
    background: linear-gradient(135deg, rgba(99, 159, 56, 0.2), rgba(99, 159, 56, 0.08));
}
.btn-generar-biografia:disabled {
    opacity: 0.65;
    cursor: not-allowed;
}
.btn-generar-biografia svg { width: 15px; height: 15px; }

/* Spinner: reutilizable en cualquier ícono dentro del Off-Canvas */
.icono-girando {
    animation: expediente-girar 0.9s linear infinite;
}
@keyframes expediente-girar {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

.biografia-estado {
    margin-top: 8px;
    font-size: 0.74rem;
    color: #b64f4f;
    text-align: center;
}

/* ----- Biografía IA: texto ya generado ----- */
.expediente-biografia-texto {
    font-size: 0.85rem;
    line-height: 1.65;
    color: #33372f;
}
.expediente-biografia-texto strong {
    color: #3f6b26;
    font-weight: 700;
}

/* =====================================================================
   FASE 14 — Asignación Flexible / Soft Lock
   ===================================================================== */

/* ----- Candado en el buzón (lista izquierda) ----- */
.candado-buzon {
    width: 13px;
    height: 13px;
    color: #d99a3f;
    flex-shrink: 0;
}

.buzon-item.bloqueado {
    opacity: 0.85;
}

/* Nombre de la asesora dueña, mostrado en la meta-línea del buzón
   cuando el chat está tomado por otra persona (ver renderizarListaChats). */
.buzon-tomado-por {
    font-size: 0.68rem;
    color: #d99a3f;
    display: flex;
    align-items: center;
    gap: 3px;
    margin-top: 2px;
}

/* ----- Banner sobre el input de chat: "Este chat lo atiende X" ----- */
.banner-chat-bloqueado {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: rgba(217, 154, 63, 0.14);
    border: 1px solid rgba(217, 154, 63, 0.4);
    border-radius: 12px;
    padding: 10px 14px;
    margin: 0 16px 10px;
    font-size: 0.82rem;
    color: var(--texto-principal);
}

.banner-chat-bloqueado[hidden] {
    display: none;
}

.btn-tomar-control {
    display: flex;
    align-items: center;
    gap: 6px;
    background: #d99a3f;
    color: #1a1500;
    border: none;
    border-radius: 8px;
    padding: 7px 12px;
    font-size: 0.78rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    flex-shrink: 0;
    transition: filter 0.15s ease, transform 0.1s ease;
}

.btn-tomar-control:hover {
    filter: brightness(1.1);
}

.btn-tomar-control:active {
    transform: scale(0.96);
}

.btn-tomar-control svg {
    width: 13px;
    height: 13px;
}

/* ----- Botón "Tomar Chat" en Acciones Rápidas: estado "es tuyo" ----- */
.btn-accion.candado-mio {
    border-color: rgba(var(--color-acento-rgb), 0.5);
    color: var(--color-acento);
}

/* Usado por el spinner de "Analizando chat..." en #btnGenerarResumenIA.
   Si ya tienes .icono-girando (de la Biografía IA) con el mismo keyframe,
   puedes omitir esto y usar esa clase en su lugar — se deja como .spin
   por ser el nombre exacto solicitado. */
.spin {
    animation: girar-spin 0.9s linear infinite;
}
@keyframes girar-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* =====================================================================
   ANIMACIONES DE ALERTA SLA (ABANDONO)
   ===================================================================== */
@keyframes latido-reloj {
    0% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.3); opacity: 0.5; color: #ff0000; }
    100% { transform: scale(1); opacity: 1; }
}
.reloj-titilante {
    color: #dc2626;
    animation: latido-reloj 1s infinite;
    margin-left: 6px;
    vertical-align: middle;
}

@keyframes parpadeo-tab {
    0%, 100% { background-color: transparent; color: inherit; }
    50% { background-color: #fee2e2; color: #dc2626; border-color: #dc2626; }
}
.tab-alerta-roja {
    animation: parpadeo-tab 1.5s infinite !important;
    font-weight: bold;
}

/* =====================================================================
   FASE 16 — PANEL "GESTIÓN DE EQUIPO"
   ---------------------------------------------------------------------
   DECISIÓN DE ARQUITECTURA (por qué NO es un off-canvas nuevo):
   el requerimiento permitía "Off-Canvas o Modal grande". Tu Panel
   Gerencial (Fase 10) ya resolvió exactamente este problema — un panel
   grande, admin-only, con tarjetas de resumen — usando
   .modal-overlay + .modal-panel.modal-panel-ancho. Gestión de Equipo es
   arquitectónicamente el mismo tipo de pantalla (gestión operativa
   gerencial), así que reutiliza ese mismo sistema en vez de crear un
   segundo mecanismo de panel deslizante redundante con el que ya usa
   el Expediente de Inteligencia. Menos CSS, menos superficie de bugs,
   más consistencia visual con lo que Felo ya aprobó.

   Este archivo SOLO agrega lo que no existía: el grid de tarjetas de
   integrantes del equipo, sus badges de rol/estado, y los placeholders
   de métricas de Fase 17. Todo lo demás (overlay, panel, form, campo,
   btn-submit, btn-icono) ya está en tu estilos.css — no se toca.
   ===================================================================== */

/* ----- Toolbar superior del modal (leyenda Tri-Core + botón "Nuevo Usuario") ----- */
.equipo-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

/* FASE 69.14 — Task 2: leyenda de color del Tri-Core System — mismos 3
   colores que el Menú Global (🟣 CRM, 🟠 Field-Ops, 🟢 ERP, ver
   .sidebar-seccion-titulo--crm/--fieldops/--erp), para que quien abre
   Gestión de Equipo reconozca el mismo lenguaje visual del resto del CRM. */
.equipo-leyenda-core {
    display: flex;
    align-items: center;
    gap: 14px;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--texto-secundario);
}
.equipo-leyenda-item { display: inline-flex; align-items: center; gap: 5px; }
.equipo-leyenda-punto {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}
.equipo-leyenda-punto--crm      { background: #9333ea; }
.equipo-leyenda-punto--fieldops { background: #ff8a3d; }
.equipo-leyenda-punto--erp      { background: var(--color-acento); }

.btn-nuevo-usuario {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-radius: 12px;
    border: none;
    background: linear-gradient(135deg, var(--color-acento), #4d7d2a);
    color: #fff;
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    transition: filter 0.15s ease, transform 0.1s ease;
}
.btn-nuevo-usuario:hover { filter: brightness(1.08); }
.btn-nuevo-usuario:active { transform: scale(0.98); }
.btn-nuevo-usuario svg { width: 15px; height: 15px; }

/* ----- Grid de Smart Cards del equipo ----- */
.equipo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 14px;
    max-height: 55vh;
    overflow-y: auto;
    padding-right: 4px;
}

.tarjeta-usuario {
    background: var(--bg-panel);
    border: 1px solid var(--borde-sutil);
    border-radius: 14px;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.tarjeta-usuario.inactiva { opacity: 0.55; }

.tarjeta-usuario-nombre {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--texto-principal);
    margin: 0;
}

.tarjeta-usuario-email {
    font-size: 0.76rem;
    color: var(--texto-secundario);
    margin: 2px 0 0 0;
    word-break: break-all;
}

.tarjeta-usuario-badges {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

/* Reutiliza el patrón visual de .badge-tipo (ya existente para
   Marquetero/Distribuidor) con la misma forma de "pill", pero con su
   propia paleta rol/estado para no pisar esa clase.
   FASE 69.14 — Task 2: paleta alineada 1:1 con los 3 colores del Tri-Core
   System del Menú Global (ver .equipo-leyenda-punto arriba) — antes
   'operario' (ERP) pintaba naranja, el mismo color que 'comercial'
   (Field-Ops), dos módulos completamente distintos indistinguibles a
   simple vista. 'asesora' pasa de gris neutro a morado (CRM); 'admin' se
   independiza a un tono grafito propio (Sistema) para no coincidir con
   el verde ERP que ahora usa 'operario'. */
.badge-rol-admin    { background: rgba(71, 85, 105, 0.18); color: #64748b; }
.badge-rol-asesora  { background: rgba(147, 51, 234, 0.16); color: #9333ea; }
.badge-rol-cartera  { background: rgba(61, 123, 253, 0.16); color: #3d7bfd; }
.badge-rol-operario { background: rgba(var(--color-acento-rgb), 0.18); color: var(--color-acento); }
/* FASE 56 — rol 'comercial' (personal de terreno puro, ver visitas_app.php). */
.badge-rol-comercial { background: rgba(255, 138, 61, 0.18); color: #ff8a3d; }
/* FASE 90 — roles nuevos del WMS "Single Box Identity" — mismo azul-verdoso
   distintivo para los 3, un tono propio que no choca con el verde ERP legado
   de 'operario' ni con ningún otro core existente. */
.badge-rol-jefe-produccion,
.badge-rol-admin-inventario,
.badge-rol-operario-bodega { background: rgba(13, 148, 136, 0.18); color: #0d9488; }
.badge-estado-activo   { background: rgba(99, 159, 56, 0.18); color: #7cc750; }
.badge-estado-inactivo { background: rgba(200, 80, 80, 0.18); color: #e08080; }

body[data-theme="dark"] .badge-rol-admin { color: #94a3b8; }

/* ----- Métricas condicionales por rol (Fase 17 + Fase 69.14 — Task 2) ----- */
.tarjeta-usuario-metricas {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding-top: 10px;
    border-top: 1px dashed var(--borde-sutil);
}

.metrica-placeholder { display: flex; flex-direction: column; gap: 2px; }
/* Métrica única de ancho completo (Operario: Último Movimiento; Admin/
   Cartera: Último Acceso) — sin compañera al lado, mismo grid de 2
   columnas de arriba se le colapsa encima con column: 1 / -1. */
.metrica-placeholder--ancha { grid-column: 1 / -1; }

.metrica-placeholder-label {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--texto-secundario);
}

.metrica-placeholder-valor {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--texto-secundario);
}
.metrica-placeholder-valor.sin-dato::after {
    content: '— (Fase 17)';
    font-weight: 400;
    font-size: 0.7rem;
}

/* ----- Acciones por tarjeta ----- */
.tarjeta-usuario-acciones { display: flex; gap: 8px; margin-top: 4px; }

.tarjeta-usuario-acciones button {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 7px 10px;
    border-radius: 10px;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    border: 1px solid var(--borde-sutil);
    background: var(--bg-input);
    color: var(--texto-principal);
    transition: background 0.15s ease;
}
.tarjeta-usuario-acciones button svg { width: 13px; height: 13px; }

.btn-editar-usuario:hover { background: rgba(var(--color-acento-rgb), 0.14); }

.btn-eliminar-usuario {
    color: #e08080 !important;
    border-color: rgba(224, 128, 128, 0.35) !important;
}
.btn-eliminar-usuario:hover { background: rgba(224, 128, 128, 0.14); }

.btn-reactivar-usuario {
    color: #7cc750 !important;
    border-color: rgba(124, 199, 80, 0.35) !important;
}
.btn-reactivar-usuario:hover { background: rgba(124, 199, 80, 0.14); }

/* ----- Vista previa de rol en vivo (modal de crear/editar) ----- */
.campo-preview-rol {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--bg-input);
    border: 1px dashed var(--borde-sutil);
    margin: -6px 0 4px;
}
.campo-preview-rol-texto {
    font-size: 0.74rem;
    color: var(--texto-secundario);
    line-height: 1.35;
}

/* ----- Mensaje de error del form de crear/editar ----- */
.modal-form-error {
    font-size: 0.78rem;
    color: #e08080;
    margin: 0;
    display: none;
}
.modal-form-error.visible { display: block; }

/* FASE 49 — línea de contexto informativa (no de error) dentro de un
   modal, ej. "referencia + bodega + stock actual" antes del ajuste
   manual de stock. Mismo tamaño que .modal-form-error, tono neutro. */
.modal-form-info {
    font-size: 0.78rem;
    color: var(--texto-secundario);
    margin: 0 0 4px;
}

/* FASE 83 — Registro Manual de Visita: botón "Salir y registrar otro
   cliente" incrustado dentro del aviso del Continuous Loop
   (#registroManualLoopAviso, ver visitas_dashboard.php/js/
   visitas_dashboard.js) — un link de texto, no un botón con chrome
   propio, para no competir visualmente con .btn-submit. */
.btn-link-inline {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    font-weight: 600;
    color: var(--color-primario, #2f6b3e);
    text-decoration: underline;
    cursor: pointer;
}
.btn-link-inline:hover { opacity: 0.8; }

/* =====================================================================
   FIX: MENÚ HEADER RESPONSIVE (Evitar superposición en móviles)
   ===================================================================== */
@media (max-width: 480px) {
    .buzones-header {
        padding: 10px 8px;
        gap: 5px;
    }

    /* Ocultamos el texto del nombre/rol para liberar espacio vital */
    .perfil-textos {
        display: none !important;
    }

    .btn-icono {
        width: 32px;
        height: 32px;
    }
    
    .btn-icono i {
        width: 18px;
        height: 18px;
    }
}

/* =====================================================================
   FASE 17 — RENDIMIENTO EN TARJETAS DE EQUIPO (Frontend)
   ---------------------------------------------------------------------
   Agregar al final de patches_css/equipo.css (o directamente al final
   de tu estilos.css, junto al resto del bloque de Fase 16). No
   modifica ninguna regla existente — .metrica-placeholder-valor y
   .metrica-placeholder-valor.sin-dato ya están definidos y se
   reutilizan tal cual; esto solo agrega los 3 modificadores de color
   del Score IA y el badge nuevo de "chats evaluados".
   ===================================================================== */

/* ----- Código de color del Score IA (criterio de negocio de Felo) ----- */
.metrica-placeholder-valor.score-alto {
    color: #7cc750; /* mismo verde ya usado en .badge-estado-activo */
    font-weight: 800;
}

.metrica-placeholder-valor.score-medio {
    color: #e0a94c; /* naranja — nuevo, no existía en la paleta hasta ahora */
    font-weight: 800;
}

.metrica-placeholder-valor.score-bajo {
    color: #e08080; /* mismo rojo ya usado en .badge-estado-inactivo / .btn-eliminar-usuario */
    font-weight: 800;
}

/* ----- Badge "N chats evaluados" ----- */
.badge-chats-evaluados {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    align-self: flex-start;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--texto-secundario);
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 20px;
    padding: 3px 9px;
    margin-top: -2px; /* pegado visualmente al bloque de métricas de arriba */
}
.badge-chats-evaluados svg { width: 11px; height: 11px; }

/* =====================================================================
   FASE 18 — TRIAGE INTELIGENTE (Alertas VIP y Urgencias)
   ---------------------------------------------------------------------
   100% aditivo. Reutiliza el mismo patrón visual que .reloj-titilante
   (icono ya existente para alerta_sla) para el parpadeo de urgencia —
   consistencia con lo que ya está aprobado en el CRM, en vez de
   inventar una segunda animación de "atención" con timing distinto.
   ===================================================================== */

.icono-prioridad {
    width: 14px;
    height: 14px;
    vertical-align: middle;
    margin-right: 3px;
    flex-shrink: 0;
}

/* Dorado explícito (no var(--color-acento), que es el verde de marca) —
   el dorado es universalmente reconocible como "VIP/premium" y no debe
   confundirse visualmente con el acento de marca de Molduras Tarapacá. */
.icono-vip {
    color: #f4c430;
}

.icono-urgencia {
    color: #e04848;
    animation: parpadeo-urgencia 1s ease-in-out infinite;
}

@keyframes parpadeo-urgencia {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

/* ----- Acento sutil en la tarjeta completa del buzón ----- */
/* Borde izquierdo de color en vez de repintar todo el fondo — se nota
   al escanear la lista rápido (mobile-first: es lo primero que el ojo
   capta en una lista angosta) sin competir visualmente con el badge de
   no-leídos ni con .alerta-sla, que ya usa el borde rojo intermitente
   completo del item. */
.buzon-item.prioridad-vip {
    border-left: 3px solid #f4c430;
}

.buzon-item.prioridad-urgencia {
    border-left: 3px solid #e04848;
}

/* ----- Toast VIP (Gerencia) ----- */
.toasts-container {
    position: fixed;
    top: 18px;
    right: 18px;
    z-index: 500; /* por encima de .expediente-overlay (200) y .modal-overlay (100) */
    display: flex;
    flex-direction: column;
    gap: 10px;
    pointer-events: none; /* el contenedor no bloquea clics; los toasts individuales sí pueden si se necesitara */
}

.toast-vip {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid #f4c430;
    border-radius: 14px;
    box-shadow: var(--sombra-panel);
    padding: 12px 16px;
    max-width: 340px;
    color: var(--texto-principal);
    font-size: 0.85rem;
    opacity: 0;
    transform: translateX(24px);
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.toast-vip.visible {
    opacity: 1;
    transform: translateX(0);
}

.toast-vip svg {
    width: 18px;
    height: 18px;
    color: #f4c430;
    flex-shrink: 0;
}

.toast-vip strong {
    color: #f4c430;
}

@media (max-width: 640px) {
    .toasts-container {
        top: auto;
        bottom: 84px; /* por encima de .nav-movil en mobile */
        right: 12px;
        left: 12px;
    }
    .toast-vip {
        max-width: 100%;
    }
}

/* ----- Toast de éxito genérico (FASE 28 — Centro de Adopción y otras
   confirmaciones suaves). Mismo esqueleto que .toast-vip, con acento
   verde en vez de dorado para transmitir "guardado con éxito". ----- */
.toast-exito {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid #4caf6d;
    border-radius: 14px;
    box-shadow: var(--sombra-panel);
    padding: 12px 16px;
    max-width: 340px;
    color: var(--texto-principal);
    font-size: 0.85rem;
    font-weight: 600;
    opacity: 0;
    transform: translateX(24px);
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.toast-exito.visible {
    opacity: 1;
    transform: translateX(0);
}

.toast-exito svg {
    width: 18px;
    height: 18px;
    color: #4caf6d;
    flex-shrink: 0;
}

@media (max-width: 640px) {
    .toast-exito {
        max-width: 100%;
    }
}

/* =====================================================================
   FASE 19 — PANEL GERENCIAL SUPREMO (Inteligencia Artificial)
   ---------------------------------------------------------------------
   FASE 33 — las tarjetas card-score-ia/card-tiempo, el modal de Coaching
   IA (.coaching-*) y el botón-enlace de asesora (.gerencia-asesora-link)
   se removieron junto con el Ranking de Asesoras legacy de gerencia.php
   (ver docblock de ese archivo). Sobrevive .gerencia-nota-ia: la reutiliza
   ahora js/rendimiento_equipo.js para la columna "Eficiencia" del Top
   Rendimiento, con la misma paleta score-alto/medio/bajo ya aprobada en
   Fase 17 (.metrica-placeholder-valor.score-*).
   ===================================================================== */

/* ----- Columna "Eficiencia"/"Nota IA" en tablas de ranking ----- */
.gerencia-nota-ia {
    font-weight: 800;
    font-size: 0.85rem;
}
.gerencia-nota-ia.score-alto  { color: #7cc750; }
.gerencia-nota-ia.score-medio { color: #e0a94c; }
.gerencia-nota-ia.score-bajo  { color: #e08080; }
.gerencia-nota-ia.sin-dato    { color: var(--texto-secundario); font-weight: 400; }

/* ============================================================
   FASE 40 — Sistema de Strikes: columna "Strikes" del Ranking
   Avanzado (rendimiento_equipo.php). Gris neutro en 0, rojo de
   alerta en 1+ — mismo criterio visual de "algo va mal" que el
   resto de badges de estado de la app.
   ============================================================ */
.badge-strikes {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 24px;
    height: 24px;
    padding: 0 8px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 700;
    background: rgba(128, 128, 128, 0.14);
    color: var(--texto-secundario);
}

.badge-strikes-alerta {
    background: rgba(224, 82, 82, 0.16);
    color: #e05252;
}

/* ============================================================
   FASE 40 — Botón "Cerrar Turno" (dashboard.php, exclusivo de
   asesoras): rojo de advertencia deliberado, destacado en el
   header de la columna de buzones — es una acción disciplinada,
   no una acción neutra más de la barra.
   ============================================================ */
.btn-cerrar-turno {
    display: flex;
    align-items: center;
    gap: 6px;
    background: rgba(224, 82, 82, 0.14);
    border: 1px solid rgba(224, 82, 82, 0.4);
    color: #e05252;
    font-size: 0.74rem;
    font-weight: 700;
    padding: 8px 12px;
    border-radius: 999px;
    cursor: pointer;
    font-family: inherit;
    white-space: nowrap;
    flex-shrink: 0;
    transition: background 0.15s ease, transform 0.12s ease;
}

.btn-cerrar-turno:hover {
    background: rgba(224, 82, 82, 0.24);
    transform: translateY(-1px);
}

.btn-cerrar-turno:disabled {
    opacity: 0.6;
    cursor: default;
    transform: none;
}

.btn-cerrar-turno svg { width: 14px; height: 14px; }

/* ----- Modal de bloqueo estricto (#modalCierreTurno) ----- */
.cierre-turno-aviso {
    color: var(--texto-secundario);
    font-size: 0.88rem;
    line-height: 1.5;
    margin: 4px 0 16px;
    padding: 0 18px;
}

.cierre-turno-aviso strong {
    color: #e05252;
    font-size: 1rem;
}

.cierre-turno-lista-wrap {
    max-height: 320px;
    overflow-y: auto;
    margin-bottom: 16px;
    padding: 0 18px;
}

#modalCierreTurno .btn-accion-ancho {
    margin: 0 18px 18px;
    width: calc(100% - 36px);
}

/* ----- Grid de tarjetas: pasa de 4 a 6 tarjetas -----
   CAMBIO (no aditivo, necesario): con auto-fit el grid absorbe tarjetas
   adicionales sin dejar huecos vacíos en la fila, y las media queries de
   abajo siguen intactas como red de seguridad en móvil. */
.gerencia-resumen-grid {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}

/* =====================================================================
   FASE 20 — Módulo de Cartera, Control de Roles Financieros y
   Sincronización de Pedidos
   ===================================================================== */

/* -----------------------------------------------------------------
   Privacidad por roles: LTV y Ticket Promedio del Expediente de
   Inteligencia se ocultan por completo para 'asesora'. Gating 100% en
   CSS contra el atributo ya expuesto en <body data-usuario-rol="...">
   (dashboard.php) — no depende de que el JS llegue a ejecutarse ni de
   timing de fetch, así que no hay parpadeo del dato sensible antes de
   ocultarlo.
   ----------------------------------------------------------------- */
body[data-usuario-rol="asesora"] .stat-financiero-sensible {
    display: none !important;
}

/* Botón "Historial de Cartera" en Acciones rápidas: mismo look que
   .btn-accion pero a todo el ancho de la columna, porque vive solo en
   su propia sección (no en el grid 2x2 de acciones rápidas). */
.btn-accion-ancho {
    width: 100%;
    flex-direction: row;
    justify-content: center;
    padding: 12px;
}

/* -----------------------------------------------------------------
   Tarjetas de resumen (Total Adeudado / Total Pagado histórico)
   Mismo lenguaje visual que .gerencia-card (Fase 10), en 2 columnas.
   ----------------------------------------------------------------- */
.cartera-resumen-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    padding: 18px;
}

@media (max-width: 480px) {
    .cartera-resumen-grid { grid-template-columns: 1fr; }
}

.cartera-resumen-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px;
    border-radius: 14px;
    border: 1px solid var(--borde-sutil);
    background: var(--bg-input);
}

.cartera-resumen-icono {
    width: 40px;
    height: 40px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.cartera-resumen-valor {
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.2;
    white-space: nowrap;
}

.cartera-resumen-label {
    font-size: 0.68rem;
    color: var(--texto-secundario);
    margin-top: 2px;
}

/* Rojo/ámbar: dinero que falta por cobrar */
.cartera-resumen-adeudado .cartera-resumen-icono {
    background: var(--color-error-bg);
    color: var(--color-error);
}
.cartera-resumen-adeudado .cartera-resumen-valor { color: var(--color-error); }

/* Verde: dinero ya cobrado históricamente */
.cartera-resumen-pagado .cartera-resumen-icono {
    background: rgba(var(--color-acento-rgb), 0.16);
    color: var(--color-acento);
}
.cartera-resumen-pagado .cartera-resumen-valor { color: var(--color-acento); }

/* -----------------------------------------------------------------
   Tabla de pedidos: filas pintadas por estado (Pagado / Pendiente /
   Anulado), con scroll horizontal en móvil en vez de comprimir columnas
   hasta ilegibilidad — mismo criterio Mobile-First del resto del CRM.
   ----------------------------------------------------------------- */
.cartera-tabla-wrap {
    overflow-x: auto;
    padding: 0 18px 18px;
}

.cartera-tabla {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
    min-width: 620px;
}

.cartera-tabla thead th {
    text-align: left;
    padding: 10px 12px;
    color: var(--texto-secundario);
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--borde-sutil);
}

.cartera-tabla tbody td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--borde-sutil);
    color: var(--texto-principal);
    vertical-align: middle;
}

.cartera-tabla tbody tr:last-child td { border-bottom: none; }

/* Verde: pedido saldado por completo */
.cartera-tabla tr.fila-pagado {
    background: rgba(var(--color-acento-rgb), 0.07);
}
.cartera-tabla tr.fila-pagado .cartera-badge-estado {
    background: rgba(var(--color-acento-rgb), 0.18);
    color: var(--color-acento);
}

/* Naranja: pedido con saldo vivo — el mismo naranja ya usado en el
   resto del CRM para estados "en curso" (ver .info-stat-alerta hermano
   #e0a94c), NO el rojo de error puro, para diferenciarlo visualmente
   de un fallo del sistema. */
.cartera-tabla tr.fila-pendiente {
    background: rgba(224, 169, 76, 0.09);
}
.cartera-tabla tr.fila-pendiente .cartera-badge-estado {
    background: rgba(224, 169, 76, 0.2);
    color: #e0a94c;
}
.cartera-tabla tr.fila-pendiente .cartera-celda-saldo {
    color: #e0a94c;
    font-weight: 700;
}

/* Gris: pedido anulado — fuera del flujo de cobro, solo referencia */
.cartera-tabla tr.fila-anulado {
    background: rgba(139, 143, 138, 0.06);
    opacity: 0.7;
}
.cartera-tabla tr.fila-anulado .cartera-badge-estado {
    background: rgba(139, 143, 138, 0.16);
    color: var(--texto-secundario);
}

.cartera-badge-estado {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 0.68rem;
    font-weight: 600;
}

.cartera-celda-acciones {
    display: flex;
    gap: 6px;
    white-space: nowrap;
}

.btn-cartera-accion {
    border: 1px solid var(--borde-sutil);
    background: var(--bg-input);
    color: var(--texto-principal);
    border-radius: 8px;
    padding: 6px 10px;
    font-size: 0.72rem;
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.btn-cartera-accion.btn-abonar:hover {
    border-color: rgba(224, 169, 76, 0.5);
    color: #e0a94c;
}

.btn-cartera-accion.btn-pago-total {
    border-color: rgba(var(--color-acento-rgb), 0.35);
    color: var(--color-acento);
}
.btn-cartera-accion.btn-pago-total:hover {
    background: rgba(var(--color-acento-rgb), 0.14);
    border-color: var(--color-acento);
}

/* ----- Ampliación exclusiva del Modal de Cartera (Fase 20) ----- */
#modalCartera .modal-panel {
    max-width: 1000px !important; /* Extra ancho en PC */
    width: 95%;
}

/* En celulares, la tabla mantendrá su scroll interno de forma elegante */
@media (max-width: 768px) {
    #modalCartera .modal-panel {
        max-width: 100%;
        padding: 15px;
    }
}

/* FIX FASE 22 — el sub-formulario de "Generar Reporte de Pedidos" agrega
   altura extra a #modalGerencia; .modal-panel base trae overflow:hidden,
   así que en pantallas chicas el contenido se corta y no hay forma de
   bajar hasta el botón "Ver reporte". Se fuerza scroll vertical propio. */
#modalGerencia .modal-panel {
    overflow-y: auto !important;
    max-height: 90vh;
    padding-bottom: 20px;
}

/* FIX FASE 23A — los nuevos inputs de "Cantidad de Marcos"/"Varas de
   Moldura" agregaron altura extra a #modalCerrarChat; mismo problema y
   misma solución que #modalGerencia arriba: se fuerza scroll vertical
   propio para que el botón "Confirmar cierre" quede alcanzable en móvil. */
#modalCerrarChat .modal-panel {
    overflow-y: auto !important;
    max-height: 90vh;
    padding-bottom: 20px;
}

/* =====================================================================
   FASE 30 — Asistente Dinámico de Cierre (#modalCierreChat)
   ---------------------------------------------------------------------
   Progressive disclosure: 4 botones grandes en el paso 1; al elegir uno
   se desvanece (opacity 0) y tras la transición se oculta (display via
   [hidden]) mientras el paso 2 hace lo inverso. Mismo patrón para los
   sub-botones (Nuevo Cliente/Cliente Fijo, Rechazo/Por confirmar) y sus
   campos asociados.
   ===================================================================== */
.modal-panel-cierre-pro {
    max-width: 480px;
}

/* FIX (mismo patrón ya documentado en Fase 25, ver
   .gerencia-filtro-campo[hidden] más abajo): cualquier clase que declare
   su propio "display" empata en especificidad con el [hidden] nativo del
   navegador y gana por ser regla de autor — sin este override, estas
   secciones se quedan en el layout (invisibles por opacity pero ocupando
   espacio) en vez de colapsar de verdad cuando JS les pone hidden=true. */
.cierre-pro-paso1[hidden],
.cierre-pro-paso2[hidden],
.cierre-pro-sub[hidden],
.cierre-pro-campos[hidden],
.cierre-pro-hint[hidden] {
    display: none;
}

.cierre-pro-body {
    padding: 18px;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

/* El modal no usa <form class="modal-form"> (necesita <div>s intercambiables
   para el progressive disclosure), así que los campos no heredan el skin de
   .modal-form input/select/textarea — se replica aquí, scoped. */
.cierre-pro-body input,
.cierre-pro-body select,
.cierre-pro-body textarea {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 14px;
    color: var(--texto-principal);
    font-size: 0.88rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.25s ease;
}

.cierre-pro-body textarea { resize: vertical; }

.cierre-pro-body input:focus,
.cierre-pro-body select:focus,
.cierre-pro-body textarea:focus {
    border-color: rgba(var(--color-acento-rgb), 0.55);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.16);
}

.cierre-pro-paso1 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    transition: opacity 0.3s ease;
}

.cierre-pro-paso1.cierre-pro-oculto,
.cierre-pro-sub.cierre-pro-oculto {
    opacity: 0;
    pointer-events: none;
}

.btn-cierre-principal {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 14px;
    padding: 22px 12px;
    color: var(--texto-principal);
    font-size: 0.85rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    text-align: center;
    transition: all 0.3s ease;
}

.btn-cierre-principal:hover {
    border-color: rgba(var(--color-acento-rgb), 0.55);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.14);
    transform: translateY(-2px);
}

.btn-cierre-principal svg {
    width: 26px;
    height: 26px;
    color: var(--color-acento-claro);
}

.cierre-pro-paso2 {
    display: flex;
    flex-direction: column;
    gap: 16px;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.cierre-pro-paso2.cierre-pro-visible { opacity: 1; }

.btn-cierre-volver {
    display: flex;
    align-items: center;
    gap: 6px;
    align-self: flex-start;
    background: none;
    border: none;
    color: var(--texto-secundario);
    font-size: 0.82rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    padding: 4px 0;
    transition: color 0.2s ease;
}

.btn-cierre-volver:hover { color: var(--texto-principal); }
.btn-cierre-volver svg { width: 15px; height: 15px; }

.cierre-pro-sub {
    display: flex;
    flex-direction: column;
    gap: 14px;
    transition: opacity 0.3s ease;
}

.cierre-pro-sub-botones {
    display: flex;
    gap: 10px;
}

.btn-cierre-sub {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 10px;
    color: var(--texto-principal);
    font-size: 0.82rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: all 0.3s ease;
}

.btn-cierre-sub svg { width: 15px; height: 15px; }

.btn-cierre-sub:hover {
    border-color: rgba(var(--color-acento-rgb), 0.5);
}

.btn-cierre-sub.activo {
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    border-color: transparent;
    color: #0b0d0c;
}

.cierre-pro-campos {
    display: flex;
    flex-direction: column;
    gap: 14px;
    opacity: 0;
    max-height: 0;
    overflow: hidden;
    transition: opacity 0.3s ease, max-height 0.3s ease;
}

.cierre-pro-campos.cierre-pro-visible {
    opacity: 1;
    max-height: 600px;
}

.cierre-pro-campos-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 10px;
}

.cierre-pro-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(var(--color-acento-rgb), 0.1);
    border: 1px solid rgba(var(--color-acento-rgb), 0.3);
    border-radius: 10px;
    padding: 10px 12px;
    color: var(--texto-secundario);
    font-size: 0.8rem;
    opacity: 0;
    max-height: 0;
    overflow: hidden;
    transition: opacity 0.3s ease, max-height 0.3s ease;
}

.cierre-pro-hint.cierre-pro-visible {
    opacity: 1;
    max-height: 100px;
}

.cierre-pro-hint svg { width: 15px; height: 15px; flex-shrink: 0; }

.cierre-pro-footer {
    padding: 0 18px 18px;
    flex-shrink: 0;
}

.cierre-pro-footer .btn-submit { width: 100%; margin-top: 0; }

@media (max-width: 640px) {
    #modalCierreChat .modal-panel {
        width: 90%;
        max-height: 85dvh;
    }

    .cierre-pro-body {
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        /* Deja espacio real por si el teclado virtual empuja el viewport;
           dvh en max-height del panel ya se ajusta, esto evita que el
           último campo quede pegado al borde inferior. */
        padding-bottom: 28px;
    }

    .cierre-pro-campos-grid {
        grid-template-columns: 1fr 1fr;
    }
}

/* =====================================================================
   FASE 27 (Paso 1) — "Mi Progreso": santuario gamificado de la asesora
   (mi_progreso.php). Reutiliza .gerencia-shell/.gerencia-panel/
   .gerencia-resumen-grid como base estructural, igual que catalogo.php.
   ===================================================================== */
.progreso-santuario {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 28px;
    text-align: center;
}

.progreso-avatar-wrap {
    position: relative;
    display: flex;
    justify-content: center;
    width: 100%;
}

/* Píldora tipo bocadillo de cómic, flotando sobre el hombro del avatar. */
.progreso-pildora {
    position: absolute;
    top: -6px;
    right: calc(50% - 150px);
    max-width: 200px;
    background: var(--bg-panel-solido);
    border: 1px solid var(--borde-sutil);
    color: var(--texto-principal);
    font-size: 0.8rem;
    font-weight: 600;
    padding: 10px 14px;
    border-radius: 16px 16px 16px 4px;
    box-shadow: var(--sombra-panel);
    z-index: 1;
}

.progreso-barras {
    width: 100%;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.barra-progreso-wrap { display: flex; flex-direction: column; gap: 6px; }

.barra-progreso-etiqueta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--texto-principal);
}

.barra-progreso-etiqueta span:first-child {
    display: flex;
    align-items: center;
    gap: 6px;
}

.barra-progreso-etiqueta svg { width: 15px; height: 15px; }

.barra-progreso-track {
    width: 100%;
    height: 16px;
    border-radius: 999px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    overflow: hidden;
}

.barra-progreso-fill {
    height: 100%;
    border-radius: 999px;
    width: 0%;
    transition: width 1s cubic-bezier(0.22, 1, 0.36, 1);
}

.barra-salud { background: linear-gradient(to right, #e07a4e, #e05656); }
.barra-xp { background: linear-gradient(to right, #e0b83c, #4e9ee0); }

.progreso-racha {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-size: 0.82rem;
    font-weight: 700;
    color: #e0824e;
}

.progreso-racha svg { width: 16px; height: 16px; }

.gerencia-resumen-card.card-sla .gerencia-resumen-icono { background: rgba(99, 160, 200, 0.16); color: #63a0c8; }
.gerencia-resumen-card.card-amabilidad .gerencia-resumen-icono { background: rgba(var(--color-acento-rgb), 0.16); color: var(--color-acento); }
.gerencia-resumen-card.card-ventas-hoy .gerencia-resumen-icono { background: rgba(230, 184, 0, 0.16); color: #e6b800; }

/* FASE 32 — tarjeta "Pedidos Procesados" de mi_rendimiento.php. */
.gerencia-resumen-card.card-pedidos .gerencia-resumen-icono { background: rgba(var(--color-acento-rgb), 0.16); color: var(--color-acento); }

@media (max-width: 480px) {
    .progreso-pildora { right: auto; left: 50%; transform: translateX(calc(-50% + 60px)); }
}

/* FASE 27 (Paso 3) — FIX scroll cortado en móvil: .progreso-shell es el
   contenedor principal de mi_progreso.php (el mismo .gerencia-shell de
   siempre, con esta clase extra SOLO en esta página para no afectar a
   catalogo.php/gerencia.php/reporte_*.php, que comparten la clase base).
   overflow-y:auto asegura que el scroll ocurra dentro del propio
   contenedor, y el padding-bottom extra en móvil evita que la última
   tarjeta de estadísticas quede tapada por la barra de navegación o el
   chrome del navegador al llegar al final del scroll. */
.progreso-shell {
    overflow-y: auto;
}

@media (max-width: 899px) {
    .progreso-shell {
        padding-bottom: 80px;
    }
}

/* FASE 32 — mismo fix de scroll cortado en móvil, aplicado a
   .rendimiento-shell (mi_rendimiento.php). Ver docblock de
   .progreso-shell arriba para el detalle del problema. */
.rendimiento-shell {
    overflow-y: auto;
}

@media (max-width: 899px) {
    .rendimiento-shell {
        padding-bottom: 80px;
    }
}

/* =====================================================================
   FASE 28 — Centro de Adopción: botón "Cambiar Mascota" + modal con la
   cuadrícula de mascotas disponibles (mi_progreso.php). Reutiliza
   .modal-overlay/.modal-panel/.modal-header/.modal-form (mismo patrón
   que los demás modales del CRM).
   ===================================================================== */
.btn-secundario {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    color: var(--texto-principal);
    font-size: 0.82rem;
    font-weight: 600;
    padding: 10px 18px;
    border-radius: 12px;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, transform 0.12s ease;
}

.btn-secundario:hover {
    border-color: rgba(var(--color-acento-rgb), 0.4);
    color: var(--color-acento);
    transform: translateY(-1px);
}

.btn-secundario svg { width: 16px; height: 16px; }

.modal-adopcion-subtitulo {
    font-size: 0.85rem;
    color: var(--texto-secundario);
    text-align: center;
    margin-bottom: 4px;
}

.adopcion-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
}

.adopcion-tarjeta {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    background: var(--bg-panel);
    border: 1px solid var(--borde-glass);
    border-radius: 14px;
    padding: 14px 10px;
    text-align: center;
}

.adopcion-nombre {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--texto-principal);
}

.btn-elegir-mascota {
    width: 100%;
    background: rgba(var(--color-acento-rgb), 0.14);
    color: var(--color-acento);
    border: none;
    font-size: 0.78rem;
    font-weight: 700;
    padding: 8px 12px;
    border-radius: 10px;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.12s ease;
}

.btn-elegir-mascota:hover { background: rgba(var(--color-acento-rgb), 0.24); }
.btn-elegir-mascota:disabled { opacity: 0.6; cursor: not-allowed; }

@media (max-width: 480px) {
    .adopcion-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
}

/* =====================================================================
   FASE 27 (Paso 2) — Widget Flotante: la mascota saluda con IA al
   iniciar la jornada (dashboard.php). "Nace" desde abajo de la pantalla
   con un rebote suave (cubic-bezier con overshoot) al perder la clase
   .oculto, y vuelve a hundirse al cerrarla.
   ===================================================================== */
.mascota-flotante {
    position: fixed;
    bottom: 20px;
    left: 20px;
    z-index: 9999;
    display: flex;
    align-items: flex-end;
    gap: 10px;
    transition: transform 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.mascota-flotante.oculto {
    transform: translateY(200%);
}

/* Globo de cómic: siempre blanco/oscuro a propósito, sin depender del
   tema claro/oscuro del panel — es un elemento lúdico, no un panel de
   datos, y debe leerse igual en ambos modos. */
.mascota-burbuja {
    position: relative;
    max-width: 220px;
    background: #ffffff;
    color: #2b2b2b;
    border-radius: 12px;
    padding: 10px 15px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 30px;
}

/* Flechita del globo apuntando hacia el avatar, que flota a su derecha. */
.mascota-burbuja::after {
    content: '';
    position: absolute;
    right: -9px;
    bottom: 18px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 8px 0 8px 10px;
    border-color: transparent transparent transparent #ffffff;
}

#btnCerrarMascota {
    position: absolute;
    top: 2px;
    right: 6px;
    background: none;
    border: none;
    padding: 0;
    line-height: 1;
    font-size: 1.1rem;
    color: #999;
    cursor: pointer;
}

#btnCerrarMascota:hover {
    color: #444;
}

@media (max-width: 480px) {
    .mascota-flotante { left: 12px; bottom: 12px; gap: 6px; }
    .mascota-burbuja { max-width: 170px; }
}

/* =====================================================================
   FASE 33 — Tarjeta "Coach IA" (mi_rendimiento.php: "Coach IA Personal" /
   rendimiento_equipo.php: "Auditoría IA de Rendimiento"). Borde-degradado
   neón suave para diferenciarla de las tarjetas de datos (.bi-card):
   esto es un consejo cualitativo de IA, no una métrica. El degradado vive
   en el ::before (padding-box vs border-box) para poder tener un fondo
   interior sólido/blur normal encima, sin pelear con box-shadow.
   ===================================================================== */
.coach-ia-card {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 20px 22px;
    border-radius: 18px;
    background: var(--bg-panel-solido);
    box-shadow: var(--sombra-panel);
    overflow: hidden;
    isolation: isolate;
}

.coach-ia-card::before {
    content: '';
    position: absolute;
    inset: 0;
    padding: 1.5px;
    border-radius: inherit;
    background: linear-gradient(135deg,
        rgba(var(--color-acento-rgb), 0.9),
        rgba(99, 160, 200, 0.75),
        rgba(var(--color-acento-rgb), 0.9));
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
    z-index: -1;
}

.coach-ia-card::after {
    content: '';
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse 320px 160px at 100% 0%, rgba(var(--color-acento-rgb), 0.12), transparent 70%),
        radial-gradient(ellipse 280px 160px at 0% 100%, rgba(99, 160, 200, 0.1), transparent 70%);
    pointer-events: none;
    z-index: -1;
}

.coach-ia-icono {
    flex-shrink: 0;
    width: 46px;
    height: 46px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, rgba(var(--color-acento-rgb), 0.2), rgba(99, 160, 200, 0.18));
    color: var(--color-acento);
    box-shadow: 0 0 0 1px rgba(var(--color-acento-rgb), 0.2);
}

.coach-ia-icono svg { width: 22px; height: 22px; }

.coach-ia-cuerpo { min-width: 0; }

.coach-ia-cuerpo h3 {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--texto-principal);
    margin-bottom: 6px;
}

.coach-ia-texto {
    font-size: 0.85rem;
    color: var(--texto-secundario);
    line-height: 1.5;
}

/* Puntitos de "escribiendo..." mientras se simula/espera la respuesta de
   IA — mismo antojo visual que un chat en vivo, para que la espera se
   sienta activa en vez de una pantalla congelada. */
.coach-ia-cargando {
    display: inline-flex;
    gap: 3px;
    margin-right: 6px;
    vertical-align: middle;
}

.coach-ia-cargando span {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--color-acento);
    animation: coachIaParpadeo 1.1s ease-in-out infinite;
}

.coach-ia-cargando span:nth-child(2) { animation-delay: 0.15s; }
.coach-ia-cargando span:nth-child(3) { animation-delay: 0.3s; }

@keyframes coachIaParpadeo {
    0%, 80%, 100% { opacity: 0.25; transform: scale(0.85); }
    40% { opacity: 1; transform: scale(1); }
}

@media (max-width: 520px) {
    .coach-ia-card { flex-direction: column; gap: 12px; }
}

/* FASE 35 — transición suave al inyectar la respuesta real de OpenAI
   (reemplazando los puntitos de "escribiendo...") en .coachIaPersonalTexto/
   .coachIaEquipoTexto. Se re-dispara en cada carga vía remove+reflow+add
   de esta clase (ver js/mi_rendimiento.js y js/rendimiento_equipo.js). */
@keyframes coachIaFadeIn {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: translateY(0); }
}

.coach-ia-fade-in {
    animation: coachIaFadeIn 0.45s ease-out;
}

/* ============================================================
   FASE 39 — Modo Privacidad Global: todo monto ($) de las
   tarjetas KPI de gerencia, mi rendimiento y paneles de clientes
   nace borroso por defecto (ver js/privacidad.js para el toggle
   delegado sobre .toggle-privacidad). .dinero-privado/.dinero-visible
   se alternan sobre el MISMO <span class="monto-blur">, nunca se
   destruye/recrea el nodo, así la transición de blur se anima.
   ============================================================ */
.dinero-privado {
    filter: blur(6px);
    transition: filter 0.3s ease;
    user-select: none;
}

.dinero-visible {
    filter: blur(0);
}

.toggle-privacidad {
    cursor: pointer;
    margin-left: 8px;
    opacity: 0.5;
    transition: opacity 0.2s ease;
}

.toggle-privacidad:hover {
    opacity: 1;
}

/* Filtro de fecha del panel de Clientes/Cartera y del Expediente
   (FASE 39, Tarea 2/3) — mismo look que .kpi-filtros de gerencia.php,
   version compacta para caber dentro del drawer del expediente. */
.expediente-filtro-fecha {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
}

.expediente-filtro-fecha label {
    font-size: 0.78rem;
    color: var(--texto-secundario);
    white-space: nowrap;
}

.expediente-filtro-fecha select {
    flex: 1;
}

/* =====================================================================
   FASE 42 — MAESTRO DE ARTÍCULOS (catalogo_molduras.php)
   ---------------------------------------------------------------------
   Reutiliza el mismo sistema de la Fase 16 (Gestión de Equipo):
   .modal-overlay/.modal-panel/.modal-form/.btn-submit/.campo ya cubren
   el modal de crear/editar, y .gerencia-panel/.gerencia-tabla ya cubren
   el layout de catalogo.php. Este bloque solo agrega lo que no existía:
   el botón "Nueva Moldura" (mismo look que .btn-nuevo-usuario) y las
   acciones por fila de la tabla.
   ===================================================================== */
.molduras-toolbar {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 16px;
}

.btn-nueva-moldura {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-radius: 12px;
    border: none;
    background: linear-gradient(135deg, var(--color-acento), #4d7d2a);
    color: #fff;
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    transition: filter 0.15s ease, transform 0.1s ease;
}
.btn-nueva-moldura:hover { filter: brightness(1.08); }
.btn-nueva-moldura:active { transform: scale(0.98); }
.btn-nueva-moldura svg { width: 15px; height: 15px; }

/* FASE 50 — Importación Masiva CSV: botón secundario Soft UI (verde muy
   sutil), a propósito menos protagónico que .btn-nueva-moldura para no
   competir por atención en la toolbar. */
.btn-importar-csv {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-radius: 12px;
    border: 1px solid rgba(var(--color-acento-rgb), 0.25);
    background: rgba(var(--color-acento-rgb), 0.08);
    color: var(--color-acento);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.1s ease;
}
.btn-importar-csv:hover { background: rgba(var(--color-acento-rgb), 0.15); }
.btn-importar-csv:active { transform: scale(0.98); }
.btn-importar-csv:disabled { opacity: 0.65; cursor: not-allowed; transform: none; }

.molduras-toolbar { gap: 10px; }

.modal-link-ejemplo {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: fit-content;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--color-acento);
    text-decoration: none;
}
.modal-link-ejemplo:hover { text-decoration: underline; }
.modal-link-ejemplo svg { width: 14px; height: 14px; }

.gerencia-tabla-acciones {
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

/* FASE 67 — Columna "Observaciones" del Historial de Visitas: trunca
   comentarios largos con elipsis en vez de estirar la fila; el texto
   completo sigue disponible al pasar el mouse (title nativo del navegador
   no aplica acá porque el contenido ya viene escapado como texto plano). */
.gerencia-tabla-observaciones {
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gerencia-tabla-acciones .btn-icono:hover { color: var(--color-acento); }
.gerencia-tabla-acciones .btn-eliminar-moldura:hover {
    background: rgba(229, 72, 77, 0.12);
    color: var(--color-error, #e5484d);
    border-color: rgba(229, 72, 77, 0.25);
}

/* FASE 49 — Ajuste Manual de Stock: mismo tono ámbar que
   .badge-kardex-ajuste, para asociar visualmente el botón que abre el
   modal de auditoría con el badge que deja en el Kardex. */
.gerencia-tabla-acciones .btn-ajustar-stock:hover {
    background: rgba(217, 164, 6, 0.12);
    color: #d4a017;
    border-color: rgba(217, 164, 6, 0.3);
}

.gerencia-tabla-codigo { font-family: 'Courier New', monospace; letter-spacing: 0.02em; }

/* Sidebar admin-only: separador visual + rótulo corto para agrupar los
   accesos de Master Data de bodega bajo "ERP / INVENTARIO", dentro del
   panel offcanvas (FASE 43 — ya no es un rail angosto de íconos). */
/* =====================================================================
   FASE 56 — Menú Global reorganizado por módulos (CRM & Ventas / ERP &
   Bodega / Field-Ops / Sistema). Reemplaza el antiguo separador único
   ".sidebar-seccion-erp" (Fase 42) por un componente de título de
   sección reutilizable en las 4 categorías, cada una con su propio tinte
   de color (el emoji ya viaja en el HTML, ver dashboard.php) para que el
   ojo agrupe de un vistazo sin necesidad de leer cada rótulo.
   ===================================================================== */
.sidebar-seccion-titulo {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 10px;
    padding-top: 14px;
    border-top: 1px solid var(--borde-sutil);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    color: var(--texto-secundario);
    text-transform: uppercase;
    line-height: 1.2;
}

/* La primera sección (CRM & Ventas) va pegada al header del menú, sin
   línea divisoria duplicada encima (el header ya tiene su propio
   border-bottom, ver .sidebar-header). */
.sidebar-seccion-titulo--primera {
    margin-top: 2px;
    padding-top: 0;
    border-top: none;
}

/* ----- Glassmorphism por sección: fondo translúcido + blur + acento de
   color propio al pasar el mouse / marcar como .activo, en vez del
   fill sólido plano que tenía el menú antes de esta fase. ----- */
.col-sidebar .btn-icono {
    border: 1px solid transparent;
}

.col-sidebar .btn-icono:hover,
.col-sidebar .btn-icono.activo {
    background: rgba(var(--color-acento-rgb), 0.14);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border-color: rgba(var(--color-acento-rgb), 0.32);
    color: var(--color-acento);
}

body[data-theme="dark"] .col-sidebar .btn-icono:hover,
body[data-theme="dark"] .col-sidebar .btn-icono.activo {
    color: var(--color-acento-claro);
}

/* 🟣 CRM & Ventas — violeta, distinto del verde corporativo de ERP para
   que ambas secciones se distingan incluso con la etiqueta oculta. */
.sidebar-seccion-titulo--crm { color: #9333ea; }
.col-sidebar .btn-icono--crm { color: #9333ea; }
.col-sidebar .btn-icono--crm:hover,
.col-sidebar .btn-icono--crm.activo {
    background: rgba(147, 51, 234, 0.14);
    border-color: rgba(147, 51, 234, 0.35);
    color: #9333ea;
}
body[data-theme="dark"] .col-sidebar .btn-icono--crm { color: #c084fc; }
body[data-theme="dark"] .col-sidebar .btn-icono--crm:hover,
body[data-theme="dark"] .col-sidebar .btn-icono--crm.activo { color: #c084fc; }

/* 🟢 ERP & Bodega — reutiliza el verde corporativo (--color-acento), ya
   cubierto por la regla base .btn-icono de arriba; sin modificador extra. */
.sidebar-seccion-titulo--erp { color: var(--color-acento); }

/* 🟠 Field-Ops (Ruta) — mismo naranja que .badge-rol-operario, coherencia
   visual con el resto del ERP de bodega/terreno. */
.sidebar-seccion-titulo--fieldops { color: #ff8a3d; }
.col-sidebar .btn-icono--fieldops { color: #ff8a3d; }
.col-sidebar .btn-icono--fieldops:hover,
.col-sidebar .btn-icono--fieldops.activo {
    background: rgba(255, 138, 61, 0.16);
    border-color: rgba(255, 138, 61, 0.4);
    color: #ff8a3d;
}
body[data-theme="dark"] .col-sidebar .btn-icono--fieldops { color: #ffab73; }
body[data-theme="dark"] .col-sidebar .btn-icono--fieldops:hover,
body[data-theme="dark"] .col-sidebar .btn-icono--fieldops.activo { color: #ffab73; }

/* ⚙️ Sistema — gris neutro, deliberadamente el menos "vistoso" de los 4:
   son controles de administración, no accesos de uso diario. */
.sidebar-seccion-titulo--sistema { color: #6b7280; }
.col-sidebar .btn-icono--sistema { color: #6b7280; }
.col-sidebar .btn-icono--sistema:hover,
.col-sidebar .btn-icono--sistema.activo {
    background: rgba(107, 114, 128, 0.16);
    border-color: rgba(107, 114, 128, 0.4);
    color: #6b7280;
}
body[data-theme="dark"] .col-sidebar .btn-icono--sistema { color: #9ca3af; }
body[data-theme="dark"] .col-sidebar .btn-icono--sistema:hover,
body[data-theme="dark"] .col-sidebar .btn-icono--sistema.activo { color: #9ca3af; }

/* FASE 68 — Task 2: "Cerrar sesión" es la única acción DESTRUCTIVA del
   menú (termina la sesión activa) — se le da un tinte rojo de peligro
   deliberadamente distinto de las 4 categorías de color de arriba, mismo
   criterio de "el rojo siempre es una alerta" que .badge-stock-pill-agotado. */
.col-sidebar .btn-icono--peligro:hover,
.col-sidebar .btn-icono--peligro.activo {
    background: rgba(200, 80, 80, 0.14);
    border-color: rgba(200, 80, 80, 0.35);
    color: #c85050;
}
body[data-theme="dark"] .col-sidebar .btn-icono--peligro:hover,
body[data-theme="dark"] .col-sidebar .btn-icono--peligro.activo { color: #e08080; }

/* =====================================================================
   FASE 45 — KARDEX DE MOVIMIENTOS (kardex.php)
   ---------------------------------------------------------------------
   Página de solo lectura: reutiliza .gerencia-shell/.gerencia-topbar/
   .gerencia-panel/.gerencia-tabla (Fase 44 Soft UI) sin agregar layout
   nuevo. Lo único propio es el badge de tipo_movimiento — misma paleta
   pastel verde/rojo que .badge-estado-activo/inactivo (Fase 16), pero
   con su propia clase para no pisar ese significado (activo/inactivo de
   usuario) con el de entrada/salida de stock.
   ===================================================================== */
.badge-kardex {
    display: inline-flex;
    align-items: center;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding: 3px 10px;
    border-radius: 20px;
    white-space: nowrap;
}
.badge-kardex-entrada { background: rgba(99, 159, 56, 0.18); color: #7cc750; }
.badge-kardex-salida  { background: rgba(200, 80, 80, 0.18); color: #e08080; }
/* FASE 49 — Ajuste Manual de Stock: tono ámbar propio, distinto del
   verde/rojo de entrada/salida, para que un ajuste de auditoría se
   distinga a simple vista de un movimiento normal del Escáner. */
.badge-kardex-ajuste  { background: rgba(217, 164, 6, 0.18); color: #d4a017; }

.kardex-tabla-operario { display: flex; align-items: center; gap: 8px; }

/* =====================================================================
   FASE 46 — Stock Crítico configurable (catalogo_molduras.php) +
   Widget de Alertas de Inventario (gerencia.php)
   ---------------------------------------------------------------------
   badge-stock-critico: pinta stock_actual cuando <= stock_minimo dentro
   de la tabla del Maestro de Artículos. Colores fijos (no siguen el
   token de tema) a propósito: una alerta de "hay que reponer" debe leerse
   igual de urgente en claro y en oscuro, mismo criterio que .badge-kardex.
   ===================================================================== */
.badge-stock-critico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 26px;
    background: #fef2f2;
    color: #991b1b;
    font-weight: 700;
    padding: 2px 9px;
    border-radius: 20px;
}

/* ----- Widget "🚨 Alertas de Inventario" (gerencia.php) -----
   Soft UI: mismo lenguaje visual que .bi-card/.gerencia-resumen-card
   (fondo sólido, borde sutil, radio 16px, sombra difusa), pero con
   fondo explícitamente blanco (--bg-panel-solido) como pidió el
   requerimiento — se adapta solo en oscuro porque ese token ya resuelve
   a --bg-panel ahí (ver :root[data-theme="dark"]). */
.alertas-inventario-wrap {
    background: var(--bg-panel-solido);
    border: 1px solid var(--borde-sutil);
    border-radius: 16px;
    padding: 20px 22px;
    box-shadow: var(--sombra-panel);
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.alertas-inventario-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
}

.alertas-inventario-header h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 1rem;
    font-weight: 700;
}

.alertas-inventario-contador {
    display: inline-flex;
    align-items: center;
    background: #fef2f2;
    color: #991b1b;
    font-size: 0.72rem;
    font-weight: 700;
    padding: 3px 11px;
    border-radius: 999px;
    white-space: nowrap;
}

.alertas-inventario-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px;
}

/* Tarjeta individual de alerta: fondo rojo pastel + texto rojo oscuro,
   colores literales pedidos por el requerimiento (no tokens de tema). */
.alerta-stock-item {
    display: flex;
    align-items: center;
    gap: 12px;
    background: #fef2f2;
    color: #991b1b;
    border-radius: 14px;
    padding: 12px 14px;
}

.alerta-stock-icono {
    flex-shrink: 0;
    width: 34px;
    height: 34px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(153, 27, 27, 0.14);
    color: #991b1b;
}

.alerta-stock-icono svg { width: 18px; height: 18px; }

.alerta-stock-cuerpo { min-width: 0; }

.alerta-stock-referencia {
    font-size: 0.84rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.alerta-stock-detalle {
    font-size: 0.72rem;
    font-weight: 600;
    opacity: 0.85;
    margin-top: 2px;
}

/* Estado "sin alertas": mensaje tranquilizador en verde, mismo
   lenguaje que .badge-estado-activo (Fase 16). */
.alertas-inventario-vacio {
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(99, 159, 56, 0.12);
    color: var(--color-acento);
    font-size: 0.85rem;
    font-weight: 600;
    padding: 14px 16px;
    border-radius: 14px;
}

.alertas-inventario-vacio svg { width: 18px; height: 18px; flex-shrink: 0; }

.alertas-inventario-cargando {
    font-size: 0.85rem;
    color: var(--texto-secundario);
    padding: 6px 2px;
}

/* =====================================================================
   FASE 48 — Panel de Inventario de Bodega (inventario_dashboard.php)
   ---------------------------------------------------------------------
   Home del rol 'operario' tras el login (ver index.php). Reutiliza
   .gerencia-shell/.gerencia-panel/.gerencia-resumen-grid/.gerencia-tabla
   (Soft UI, Fase 44) como el resto de las páginas de datos del CRM; solo
   agrega el buscador en tiempo real y el panel de últimos movimientos,
   que no tenían un patrón visual previo reutilizable.
   ===================================================================== */

/* Buscador de stock: mismo lenguaje "pill" que .buscador-wrap (sidebar
   de chats), pero sin el position:relative acotado a una columna angosta
   — vive suelto dentro de .gerencia-panel, a todo el ancho del panel. */
.buscador-inventario-wrap {
    position: relative;
    margin-bottom: 16px;
}

.buscador-inventario-wrap .icono-buscar {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--texto-secundario);
    pointer-events: none;
}

.buscador-inventario-wrap input {
    width: 100%;
    background: var(--bg-buscador);
    border: none;
    border-radius: 24px;
    padding: 12px 16px 12px 42px;
    color: var(--texto-principal);
    font-size: 0.85rem;
    font-family: inherit;
    outline: none;
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.03);
    transition: box-shadow 0.2s ease, background 0.15s ease;
}

.buscador-inventario-wrap input:focus {
    background: var(--bg-input);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.03), 0 0 0 4px rgba(var(--color-acento-rgb), 0.14);
}

/* Panel "Mis Últimos Movimientos" / "Últimos Movimientos de la Bodega":
   mismas tarjetas de fila que .alerta-stock-item, pero en tono neutro
   (no todo movimiento es una alerta) — el color lo aporta el
   badge-kardex-entrada/salida ya existente (Fase 45) reutilizado tal
   cual. */
.lista-movimientos-recientes {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.movimiento-reciente-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-radius: 14px;
    padding: 12px 16px;
}

.movimiento-reciente-cuerpo { min-width: 0; }

.movimiento-reciente-referencia {
    font-size: 0.84rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.movimiento-reciente-detalle {
    font-size: 0.72rem;
    color: var(--texto-secundario);
    margin-top: 2px;
}

/* =====================================================================
   FASE 52 — Exportación Contable (Reportes CSV)
   -----------------------------------------------------------------
   Botón "gris corporativo" deliberadamente DISTINTO del gradiente verde
   de .btn-aplicar-filtro/.btn-volver-dashboard: exportar es una acción
   secundaria de auditoría, no la acción primaria del panel — el
   contraste visual evita que Gerencia confunda "descargar CSV" con la
   acción principal de cada pantalla (Transferir Cajas, Ir al Escáner).
   ===================================================================== */
.btn-exportar-csv {
    display: flex;
    align-items: center;
    gap: 8px;
    background: linear-gradient(to bottom, #55606b, #3a434c);
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: #f1f3f4;
    font-weight: 700;
    font-size: 0.82rem;
    padding: 10px 16px;
    border-radius: 10px;
    text-decoration: none;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(15, 23, 42, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.12);
    transition: filter 0.15s ease, transform 0.1s ease;
    font-family: inherit;
}

.btn-exportar-csv:hover { filter: brightness(1.12); transform: translateY(-1px); }
.btn-exportar-csv:active { transform: scale(0.98); }

/* =====================================================================
   FASE 52 — "Puente de Cristal": visor de stock de solo lectura para
   asesoras dentro de dashboard.php (#modalConsultaStock).
   ===================================================================== */
.btn-puente-cristal .icono-emoji-caracter { font-size: 1.05rem; }

.consulta-stock-resultados {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-height: 380px;
    overflow-y: auto;
    padding-top: 4px;
}

.consulta-stock-item {
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 14px;
}

.consulta-stock-referencia {
    font-weight: 700;
    font-size: 0.86rem;
    margin-bottom: 8px;
}

.consulta-stock-codigo {
    font-size: 0.7rem;
    color: var(--texto-secundario);
    font-weight: 400;
    margin-left: 6px;
}

.consulta-stock-pildoras {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* Misma forma de "pill" que .badge-rol/.badge-kardex, con su propia
   paleta: disponible (verde) vs. agotado (rojo) por sede, para que la
   asesora identifique de un vistazo dónde SÍ hay stock. */
.badge-stock-pill {
    font-size: 0.72rem;
    font-weight: 700;
    padding: 4px 10px;
    border-radius: 20px;
    white-space: nowrap;
}

.badge-stock-pill-disponible { background: rgba(99, 159, 56, 0.18); color: #7cc750; }
.badge-stock-pill-agotado    { background: rgba(200, 80, 80, 0.18); color: #e08080; }

/* =====================================================================
   FASE 68 — Task 1: Vinculación CRM -> Maestro de Clientes (MDM)
   -----------------------------------------------------------------
   Tarjeta de estado dentro de #colInfo (.cliente-master-vinculo) y lista
   de resultados de búsqueda del modal #modalVincularMaster
   (.cliente-master-resultados). Reutiliza .buscador-inventario-wrap
   (Fase 52) para el input de búsqueda.
   ===================================================================== */
.cliente-master-vinculo {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.cliente-master-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: var(--bg-panel);
    border: 1px solid rgba(var(--color-acento-rgb), 0.3);
    border-radius: 12px;
    padding: 12px 14px;
}

.cliente-master-card-nombre {
    font-weight: 700;
    font-size: 0.88rem;
    color: var(--texto-principal);
    display: flex;
    align-items: center;
    gap: 6px;
}

.cliente-master-card-nombre i {
    color: var(--color-acento);
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.cliente-master-card-detalle {
    font-size: 0.74rem;
    color: var(--texto-secundario);
}

.cliente-master-acciones {
    display: flex;
    gap: 8px;
}

.cliente-master-acciones .btn-accion {
    flex: 1;
}

.cliente-master-resultados {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 380px;
    overflow-y: auto;
    padding-top: 4px;
}

.cliente-master-resultado-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 14px;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
    text-align: left;
    width: 100%;
    font-family: inherit;
    color: inherit;
}

.cliente-master-resultado-item:hover {
    background: rgba(var(--color-acento-rgb), 0.14);
    border-color: rgba(var(--color-acento-rgb), 0.35);
    transform: translateY(-1px);
}

.cliente-master-resultado-nombre {
    font-weight: 700;
    font-size: 0.86rem;
}

.cliente-master-resultado-detalle {
    font-size: 0.72rem;
    color: var(--texto-secundario);
}

/* =====================================================================
   FASE 54 — MICRO-INTERACCIONES "MILLION-DOLLAR FEEL"
   Skeleton loaders (percepción de velocidad), feedback táctil en los
   elementos más pulsados del día, foco visible accesible y respeto por
   prefers-reduced-motion. Todo sobre las variables de tema existentes:
   funciona idéntico en Light Luxury y Dark Luxury sin duplicar reglas.
   ===================================================================== */

/* --- Skeleton shimmer base -------------------------------------------
   El gradiente barre en diagonal sobre un bloque del color del borde
   sutil del tema. background-size 200% + animación de background-position
   = shimmer continuo sin repintar capas (solo composición, GPU-friendly). */
.skeleton {
    position: relative;
    overflow: hidden;
    border-radius: 10px;
    background: var(--borde-sutil);
    background-image: linear-gradient(
        100deg,
        transparent 30%,
        var(--borde-inner-glow) 50%,
        transparent 70%
    );
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
}

@keyframes skeleton-shimmer {
    0%   { background-position: 120% 0; }
    100% { background-position: -80% 0; }
}

/* Silueta de conversación: burbujas alternadas como el chat real. Los
   anchos vienen inline desde app.js para simular mensajes irregulares. */
.skeleton-chat {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 24px 20px;
}

.skeleton-burbuja {
    height: 38px;
    border-radius: 14px;
}

.skeleton-burbuja.entrante { align-self: flex-start; border-bottom-left-radius: 4px; }
.skeleton-burbuja.saliente { align-self: flex-end;   border-bottom-right-radius: 4px; }

/* Silueta del timeline del expediente (Off-Canvas de cliente). */
.skeleton-timeline {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 8px 0;
}

.skeleton-linea { height: 14px; }

/* --- Feedback táctil -------------------------------------------------
   Los dos elementos más pulsados del día (buzones y botones de acción)
   responden al click con una compresión de 150ms: confirmación física
   inmediata de que el gesto fue registrado, antes de que llegue la
   respuesta del servidor. */
.buzon-item:active {
    transform: scale(0.985);
    transition: transform 0.15s ease;
}

button:not(:disabled):active {
    transform: scale(0.97);
    transition: transform 0.15s ease;
}

/* --- Foco visible accesible ------------------------------------------
   Anillo de foco SOLO para navegación por teclado (:focus-visible no
   dispara con click de mouse): imprescindible para operarias que vuelan
   con Tab entre campos, invisible para el resto. */
:focus-visible {
    outline: 2px solid var(--color-acento);
    outline-offset: 2px;
    border-radius: 6px;
}

/* --- Respeto por prefers-reduced-motion ------------------------------
   Usuarios con sensibilidad vestibular (o equipos muy modestos) piden al
   sistema operativo reducir animaciones; el CRM obedece globalmente. El
   skeleton conserva su color base (sigue comunicando "cargando") pero
   deja de brillar. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* =====================================================================
   FASE 54 — RADAR DE FUGA (clientes.php)
   Panel de churn: tarjetas compactas con borde de nivel de riesgo.
   Reutiliza las variables del tema — idéntico en claro y oscuro.
   ===================================================================== */
.radar-fuga-panel {
    margin: 0 0 22px;
    padding: 20px 22px;
    border-radius: 18px;
    background: var(--bg-panel-solido);
    border: 1px solid var(--borde-sutil);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
}

.radar-fuga-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
}

.radar-fuga-header h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 1.05rem;
    color: var(--texto-principal);
}

.radar-fuga-header h2 i { width: 20px; height: 20px; color: var(--color-error); }

.radar-fuga-resumen {
    font-size: 0.85rem;
    color: var(--texto-secundario);
}

.radar-fuga-lista {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 12px;
}

.radar-fuga-card {
    padding: 12px 14px;
    border-radius: 12px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-left-width: 4px;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.radar-fuga-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 22px rgba(0, 0, 0, 0.08);
}

.radar-fuga-card.nivel-critico   { border-left-color: var(--color-error); }
.radar-fuga-card.nivel-en_riesgo { border-left-color: #d9a441; }

.radar-fuga-card-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}

.radar-fuga-card-top strong {
    color: var(--texto-principal);
    font-size: 0.92rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.radar-fuga-badge {
    flex-shrink: 0;
    font-size: 0.7rem;
    font-weight: 600;
    padding: 3px 8px;
    border-radius: 999px;
    background: var(--color-error-bg);
    color: var(--color-error);
}

.radar-fuga-card.nivel-en_riesgo .radar-fuga-badge {
    background: rgba(217, 164, 65, 0.14);
    color: #d9a441;
}

.radar-fuga-detalle {
    font-size: 0.8rem;
    color: var(--texto-secundario);
    line-height: 1.45;
}

/* =====================================================================
   FASE 55 — RUTA INTELIGENTE (Field-Ops / Control de Visitas de Campo)
   ---------------------------------------------------------------------
   Mobile-first ESTRICTO: a diferencia del resto del CRM (escritorio con
   fallback responsivo), visitas_app.php se diseña primero para un
   celular en la calle — un solo flujo vertical, tarjetas Soft UI
   apiladas y botones grandes para el pulgar. El ancho máximo (480px)
   centrado hace que en tablet/escritorio se vea como una app móvil
   flotando en el centro, en vez de estirarse horizontalmente.
   ===================================================================== */
body.pagina-visitas {
    background:
        radial-gradient(ellipse 900px 700px at 50% 0%, rgba(var(--color-acento-rgb), var(--mesh-op-1)), transparent 60%),
        var(--bg-fondo);
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
}

/* FASE 67.5 — Tarea 2: fix de "última tarjeta cortada" en móvil
   (mi_panel_comercial.php, y por extensión visitas_app.php al compartir
   este mismo shell). Causa raíz: `100vh` en navegadores móviles se mide
   contra el viewport MÁS GRANDE posible (como si la barra de
   direcciones/nav inferior estuviera oculta), no contra el espacio
   realmente visible — con el body como único contenedor de scroll, el
   contenido que cae justo en ese margen queda tapado por la barra del
   navegador. Fix: `.visita-shell` pasa a ser un contenedor de altura
   FIJA (100dvh, con 100vh como fallback en navegadores sin soporte para
   dvh) que NO se desplaza a sí mismo; el scroll real ocurre adentro, en
   `.visita-main` (overflow-y: auto) — así `.visita-topbar` queda
   genuinamente anclado arriba (ya no depende de position:sticky) y el
   padding-bottom de `.visita-main` puede garantizar espacio de sobra
   debajo de la última tarjeta. */
.visita-shell {
    max-width: 480px;
    margin: 0 auto;
    height: 100vh;
    height: 100dvh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* FASE 58 — FIX raíz de "vistas superpuestas" en toda la app de Ruta
   Inteligente: prácticamente cada sub-vista de visitas_app.js declara su
   propio "display" (flex/grid) para su estado visible, lo que empata en
   especificidad con el [hidden] nativo del navegador y gana por ser regla
   de autor (mismo patrón ya documentado puntualmente en Fase 25/30 para
   .gerencia-filtro-campo[hidden] / .cierre-pro-paso1[hidden]). En vez de
   perseguir selector por selector cada vez que se agrega un nuevo
   sub-estado (resultados de cliente, chip de cliente seleccionado,
   preview de fotos, etc.), esta única regla de alta especificidad
   garantiza que hidden=true SIEMPRE colapse el elemento en toda la
   pantalla de Ruta Inteligente. Los overrides puntuales que ya existían
   (.visita-estado[hidden], .btn-visita-primario[hidden], etc.) quedan
   igual de válidos y sirven de documentación in situ. */
.visita-shell [hidden] {
    display: none !important;
}

.visita-topbar {
    position: sticky;
    top: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border-bottom: 1px solid var(--borde-sutil);
}

.visita-topbar-titulo { flex: 1; text-align: center; }
.visita-topbar-titulo h1 { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }
.visita-topbar-titulo p { font-size: 0.75rem; color: var(--texto-secundario); }

.visita-main {
    flex: 1;
    min-height: 0; /* imprescindible: sin esto, un flex-item no se encoge por debajo del alto de su contenido y overflow-y:auto nunca entra a jugar */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 16px 16px calc(56px + env(safe-area-inset-bottom, 0px));
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.visita-estado {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* FASE 58 — FIX bug de "vistas superpuestas": mismo patrón ya documentado
   en Fase 25/30 (ver .cierre-pro-paso1[hidden] / .gerencia-filtro-campo[hidden]
   más arriba) — .visita-estado declara su propio "display", así que empata
   en especificidad con el [hidden] nativo del navegador y gana por ser
   regla de autor. Sin este override, mostrarEstado() le pone hidden=true a
   4 de las 5 secciones pero las 5 se quedan visibles y apiladas (loader
   eterno, banner de éxito visible de entrada, botón "Iniciar Jornada"
   encima del hub de jornada activa, etc). */
.visita-estado[hidden] { display: none; }

#estadoVerificando {
    align-items: center;
    justify-content: center;
    padding-top: 80px;
    gap: 16px;
    color: var(--texto-secundario);
    font-size: 0.9rem;
}

.visita-spinner {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 3px solid rgba(var(--color-acento-rgb), 0.2);
    border-top-color: var(--color-acento);
    animation: girar-spin 0.8s linear infinite;
}

.visita-card {
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-inner-glow);
    border-radius: 18px;
    padding: 18px;
    box-shadow: var(--sombra-panel);
}

.visita-card h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--texto-secundario);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 12px;
}

.visita-card h3 i { width: 16px; height: 16px; color: var(--color-acento); }

/* ----- Hero de inicio / éxito ----- */
.visita-card-hero,
.visita-card-exito {
    text-align: center;
    padding: 32px 22px;
    gap: 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.visita-hero-icono,
.visita-exito-icono {
    width: 52px;
    height: 52px;
    color: var(--color-acento);
    margin-bottom: 6px;
}

.visita-card-hero h2,
.visita-card-exito h2 {
    font-size: 1.15rem;
    font-weight: 700;
}

.visita-card-hero p,
.visita-card-exito p {
    font-size: 0.85rem;
    color: var(--texto-secundario);
    margin-bottom: 10px;
}

.btn-visita-primario {
    width: 100%;
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    color: #0b0d0c;
    border: 1px solid var(--borde-inner-glow);
    border-radius: 14px;
    padding: 14px 18px;
    font-size: 0.95rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    box-shadow: var(--sombra-glow), inset 0 1px 0 rgba(255, 255, 255, 0.25);
    transition: filter 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
}

.btn-visita-primario:hover:not(:disabled) { filter: brightness(1.06); }
.btn-visita-primario:active:not(:disabled) { transform: scale(0.98); }

.btn-visita-primario:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    filter: grayscale(0.3);
}

.btn-visita-primario.cargando { opacity: 0.75; cursor: wait; }

/* FASE 58 — mismo FIX de especificidad que .visita-estado[hidden]: sin
   esto, hidden=true en btnNuevaVisita (bloqueo durante una pausa activa)
   no lo oculta de verdad porque .btn-visita-primario declara su propio
   "display". */
.btn-visita-primario[hidden] { display: none; }

.btn-visita-gigante {
    padding: 20px 18px;
    font-size: 1.05rem;
    border-radius: 18px;
}

.visita-emoji { font-size: 1.2rem; }

.visita-nota-gps {
    min-height: 18px;
    font-size: 0.78rem;
    color: var(--texto-secundario);
    text-align: center;
}

.visita-nota-gps.visita-nota-error { color: var(--color-error); font-weight: 600; }

/* FASE 78 — Sync-Down: aviso no bloqueante cuando la lista de clientes de
   la Ruta viene del espejo local de IndexedDB (offline) en vez de una
   respuesta fresca del servidor — ver avisoEspejoLocalHtml() en
   js/visitas_app.js. */
.visita-nota-offline-mirror {
    font-size: 0.78rem;
    color: var(--texto-secundario);
    background: var(--borde-glass);
    border: 1px solid var(--borde-sutil);
    border-radius: 10px;
    padding: 8px 12px;
    margin-bottom: 8px;
}

/* ----- Visitas de Hoy (lista) ----- */
.visita-lista-hoy { display: flex; flex-direction: column; gap: 8px; }

.visita-lista-vacia {
    font-size: 0.82rem;
    color: var(--texto-secundario);
    text-align: center;
    padding: 12px 0;
}

.visita-item-historial {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
}

.visita-item-historial.visita-item-en-curso {
    border-color: rgba(var(--color-acento-rgb), 0.4);
}

.visita-item-icono {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
    flex-shrink: 0;
}
.visita-item-icono i { width: 16px; height: 16px; }

.visita-item-textos { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.visita-item-textos strong { font-size: 0.88rem; }
.visita-item-textos small { font-size: 0.75rem; color: var(--texto-secundario); }

/* =====================================================================
   FASE 67 — mi_panel_comercial.php (Panel Personal del Comercial/Asesora)
   ===================================================================== */

/* ----- FASE 67.5 — Tarea 2: "Mis Métricas", fila de 3 KPIs personales ----- */
.panelcom-kpi-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}
.panelcom-kpi-tile {
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-glass);
    border-radius: 14px;
    padding: 12px 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-align: center;
    box-shadow: var(--sombra-panel);
}
.panelcom-kpi-tile i { width: 18px; height: 18px; color: var(--color-acento); }
.panelcom-kpi-valor { font-size: 1.15rem; font-weight: 700; color: var(--texto-principal); line-height: 1.1; }
.panelcom-kpi-label { font-size: 0.66rem; color: var(--texto-secundario); font-weight: 500; }

/* FASE 69.11 — Task 4: "Mis Acciones Este Mes" — 8 tiles más compactos que
   .panelcom-kpi-tile (más cantidad de datos en el mismo ancho de pantalla
   móvil), reusando el mismo lenguaje visual (glass + acento) en vez de
   inventar un componente aparte. */
.panelcom-seccion-titulo {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--texto-secundario);
    margin: 18px 0 8px;
}
.panelcom-seccion-titulo i { width: 15px; height: 15px; color: var(--color-acento); }
.panelcom-acciones-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
}
@media (max-width: 380px) {
    .panelcom-acciones-grid { grid-template-columns: repeat(2, 1fr); }
}
.panelcom-accion-tile {
    background: var(--bg-panel);
    border: 1px solid var(--borde-glass);
    border-radius: 12px;
    padding: 8px 4px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    text-align: center;
}
.panelcom-accion-valor { font-size: 0.95rem; font-weight: 700; color: var(--color-acento); line-height: 1.1; }
.panelcom-accion-label { font-size: 0.58rem; color: var(--texto-secundario); font-weight: 500; line-height: 1.2; }

/* ----- Pestañas (versión mobile-first, distinta de .visita-tabs que
   asume el padding de un panel de escritorio de 24px) ----- */
.panelcom-tabs {
    display: flex;
    gap: 6px;
    border-bottom: 1px solid var(--borde-sutil);
}
.panelcom-tab-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 4px;
    border: none;
    border-bottom: 2px solid transparent;
    background: transparent;
    color: var(--texto-secundario);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    flex: 1;
    justify-content: center;
}
.panelcom-tab-btn i { width: 16px; height: 16px; }
.panelcom-tab-btn.activa { color: var(--color-acento); border-bottom-color: var(--color-acento); }
.panelcom-tab-panel[hidden] { display: none; }

.panelcom-badge-contador {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--color-error);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
}

/* ----- Tab Historial: filtro de fechas compacto ----- */
.panelcom-filtro-fechas {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    flex-wrap: wrap;
}
.panelcom-filtro-fechas .campo { flex: 1 1 110px; min-width: 110px; }
.panelcom-filtro-fechas .btn-visita-secundario { flex-shrink: 0; padding: 10px 14px; }

/* FASE 84: align-items ya no se define acá — .panelcom-item-historial
   pasa a layout de columna (fila expandible + fotos), ver ese bloque más
   abajo. */
.panelcom-item-historial .visita-item-icono { margin-top: 2px; }
.panelcom-observaciones { color: var(--texto-principal) !important; opacity: 0.85; }

/* ----- Tab Recordatorios: agrupado por cliente ----- */
.panelcom-grupo-pendientes h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.92rem;
    margin: 0 0 10px;
}
.panelcom-grupo-pendientes h3 i { width: 16px; height: 16px; color: var(--color-acento); flex-shrink: 0; }
.panelcom-ruta-chip {
    font-size: 0.68rem;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(var(--color-acento-rgb), 0.14);
    color: var(--color-acento);
}

.panelcom-tarea-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 0;
    border-top: 1px solid var(--borde-sutil);
}
.panelcom-tarea-item:first-of-type { border-top: none; padding-top: 0; }
.panelcom-tarea-texto { min-width: 0; flex: 1; }
.panelcom-tarea-texto p { margin: 0 0 2px; font-size: 0.85rem; color: var(--texto-principal); }
.panelcom-tarea-texto small { font-size: 0.72rem; color: var(--texto-secundario); }

.panelcom-btn-terminado {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    padding: 7px 12px;
    border-radius: 10px;
    border: 1px solid rgba(99, 159, 56, 0.35);
    background: rgba(99, 159, 56, 0.12);
    color: var(--color-acento);
    font-size: 0.75rem;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s ease;
}
.panelcom-btn-terminado:hover { background: rgba(99, 159, 56, 0.22); }
.panelcom-btn-terminado:disabled { opacity: 0.6; cursor: default; }
.panelcom-btn-terminado i { width: 14px; height: 14px; }

/* ----- Estado "En Visita": badge + cronómetro ----- */
.visita-card-checkin { padding: 14px 18px; }

.visita-badge-curso {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--color-acento);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 8px;
}

.visita-badge-curso i { width: 14px; height: 14px; animation: latido-reloj 1.6s ease-in-out infinite; }

.visita-checkin-info {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 0.9rem;
}

#cronometroVisita {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--texto-principal);
}

/* ----- Selector visual de Motivo ----- */
.visita-motivo-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.visita-motivo-opcion {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    text-align: center;
    background: var(--bg-panel-alt);
    border: 1.5px solid var(--borde-sutil);
    border-radius: 14px;
    padding: 16px 8px;
    cursor: pointer;
    color: var(--texto-principal);
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.25;
    transition: border-color 0.15s ease, background 0.15s ease, transform 0.1s ease;
}

.visita-motivo-opcion i { width: 22px; height: 22px; color: var(--texto-secundario); transition: color 0.15s ease; }

.visita-motivo-opcion:active { transform: scale(0.97); }

.visita-motivo-opcion.seleccionado {
    border-color: var(--color-acento);
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
}

.visita-motivo-opcion.seleccionado i { color: var(--color-acento); }

/* ----- Buscador / selección de Cliente ----- */
.visita-resultados-cliente {
    margin-top: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 220px;
    overflow-y: auto;
}

.visita-resultado-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 10px 12px;
    cursor: pointer;
    font-family: inherit;
    color: var(--texto-principal);
}

.visita-resultado-item:hover { border-color: rgba(var(--color-acento-rgb), 0.4); }
.visita-resultado-item i { width: 16px; height: 16px; color: var(--color-acento); flex-shrink: 0; }
.visita-resultado-item span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.visita-resultado-item strong { font-size: 0.85rem; }
.visita-resultado-item small { font-size: 0.72rem; color: var(--texto-secundario); }

.visita-cliente-seleccionado {
    margin-top: 10px;
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(var(--color-acento-rgb), 0.1);
    border: 1px solid rgba(var(--color-acento-rgb), 0.35);
    border-radius: 12px;
    padding: 10px 12px;
    font-size: 0.85rem;
    font-weight: 600;
}

.visita-cliente-seleccionado i:first-child { width: 16px; height: 16px; color: var(--color-acento); flex-shrink: 0; }
.visita-cliente-seleccionado span { flex: 1; min-width: 0; }

.visita-cliente-seleccionado button {
    background: transparent;
    border: none;
    color: var(--texto-secundario);
    cursor: pointer;
    display: flex;
    padding: 2px;
}

.visita-prospecto-wrap { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.visita-prospecto-wrap label { font-size: 0.78rem; color: var(--texto-secundario); font-weight: 500; }

/* FASE 66 — Toggle "Nuevo Prospecto" del Paso 1 del asistente móvil:
   botón de texto discreto, sin el peso visual de un CTA primario, ya que
   es el camino secundario (la mayoría de las visitas son a clientes que
   ya existen en base_datos_clientes). */
.btn-visita-toggle-prospecto {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    margin-top: 12px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px dashed var(--borde-sutil);
    background: transparent;
    color: var(--texto-secundario);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.btn-visita-toggle-prospecto:hover {
    border-color: rgba(var(--color-acento-rgb), 0.4);
    color: var(--color-acento);
    background: rgba(var(--color-acento-rgb), 0.08);
}
.btn-visita-toggle-prospecto i { width: 15px; height: 15px; flex-shrink: 0; }

/* ----- Fotos (cámara forzada) ----- */
.visita-foto-item { margin-bottom: 16px; }
.visita-foto-item:last-child { margin-bottom: 0; }

.visita-foto-label {
    display: block;
    font-size: 0.82rem;
    font-weight: 600;
    margin-bottom: 8px;
}

.visita-obligatorio { color: var(--color-error); font-weight: 500; }
.visita-opcional { color: var(--texto-secundario); font-weight: 500; }

/* FASE 66 QA — Texto de ayuda bajo el título de los pasos de Foto ANTES/
   DESPUÉS, aclarando el propósito de cada evidencia fotográfica. */
.visita-foto-ayuda {
    margin: -6px 0 12px;
    font-size: 0.78rem;
    color: var(--texto-secundario);
}

.visita-foto-boton {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 16px;
    border-radius: 14px;
    border: 1.5px dashed rgba(var(--color-acento-rgb), 0.4);
    background: rgba(var(--color-acento-rgb), 0.05);
    color: var(--color-acento);
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.visita-foto-boton:hover { background: rgba(var(--color-acento-rgb), 0.1); }

.visita-foto-boton.visita-foto-lista {
    border-style: solid;
    border-color: var(--color-acento);
}

.visita-foto-preview {
    display: block;
    width: 100%;
    max-height: 220px;
    object-fit: cover;
    border-radius: 14px;
    margin-top: 10px;
    border: 1px solid var(--borde-sutil);
}

/* ----- Comentarios ----- */
.visita-textarea {
    width: 100%;
    min-height: 90px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 12px 14px;
    color: var(--texto-principal);
    font-size: 0.9rem;
    font-family: inherit;
    resize: vertical;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.25s ease;
}

.visita-textarea:focus {
    border-color: rgba(var(--color-acento-rgb), 0.55);
    box-shadow: 0 0 0 4px rgba(var(--color-acento-rgb), 0.16);
}

.btn-visita-terminar { margin-top: 4px; }

/* FASE 67 — Closed-Loop Task Management: campo "¿Queda pendiente?" del
   Paso 7, con acento ámbar (mismo tono que las alertas de la Fase 49/58)
   para diferenciarlo visualmente de Comentarios — es lo que dispara la
   Alerta Inteligente en la próxima visita a este cliente. */
.visita-campo-pendiente { margin-top: 14px; }
.visita-campo-pendiente label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.82rem;
    font-weight: 600;
    color: #d4a017;
    margin-bottom: 6px;
}
.visita-campo-pendiente label i { width: 15px; height: 15px; flex-shrink: 0; }
.visita-campo-pendiente .visita-textarea { min-height: 70px; border-color: rgba(217, 164, 6, 0.3); }
.visita-campo-pendiente .visita-textarea:focus {
    border-color: rgba(217, 164, 6, 0.6);
    box-shadow: 0 0 0 4px rgba(217, 164, 6, 0.16);
}

@media (min-width: 481px) {
    .visita-shell { border-inline: 1px solid var(--borde-sutil); }
}

/* =====================================================================
   FASE 56 — DASHBOARD GERENCIAL DE CAMPO (visitas_dashboard.php)
   ---------------------------------------------------------------------
   Reutiliza .gerencia-shell/.gerencia-panel/.gerencia-tabla/
   .gerencia-filtro-* (mismo esqueleto que kardex.php/clientes.php);
   aquí solo viven los componentes propios: badge de motivo de visita,
   badge "En curso", botones de acción (Maps/Fotos) y el modal de fotos.
   ===================================================================== */
.badge-motivo-visita {
    display: inline-flex;
    align-items: center;
    font-size: 0.68rem;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 20px;
    white-space: nowrap;
}

.badge-motivo-renovacion  { background: rgba(61, 123, 253, 0.16); color: #3d7bfd; }
.badge-motivo-reposicion  { background: rgba(99, 159, 56, 0.18); color: #7cc750; }
.badge-motivo-cobro       { background: rgba(217, 164, 6, 0.18); color: #d4a017; }
.badge-motivo-prospeccion { background: rgba(147, 51, 234, 0.16); color: #9333ea; }
.badge-motivo-pqr         { background: rgba(200, 80, 80, 0.18); color: #e08080; }
.badge-motivo-pendiente   { background: rgba(139, 143, 138, 0.18); color: var(--texto-secundario); }

.badge-visita-estado {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding: 3px 10px;
    border-radius: 20px;
}

.badge-visita-curso {
    background: rgba(255, 138, 61, 0.18);
    color: #ff8a3d;
}

.badge-visita-curso i { width: 12px; height: 12px; animation: latido-reloj 1.6s ease-in-out infinite; }

.btn-accion-visita {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 9px;
    border: 1px solid var(--borde-sutil);
    background: transparent;
    color: var(--texto-secundario);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn-accion-visita:hover {
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
    border-color: rgba(var(--color-acento-rgb), 0.3);
}

.btn-accion-visita-disabled {
    opacity: 0.35;
    cursor: not-allowed;
}
.btn-accion-visita-disabled:hover { background: transparent; color: var(--texto-secundario); }

/* ----- Modal "Ver fotos de respaldo" ----- */
.visita-fotos-modal-body {
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    overflow-y: auto;
}

.visita-fotos-modal-item {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.visita-fotos-modal-item img {
    width: 100%;
    max-height: 340px;
    object-fit: contain;
    border-radius: 12px;
    border: 1px solid var(--borde-sutil);
    background: var(--bg-fondo);
}

/* =========================================================
   FASE 57 — Field-Ops: Jornada, Modo Offline, UI Secuencial y Live Map
   ========================================================= */

/* ----- Badge de estado de conexión / cola offline ----- */
.visita-offline-badge {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 16px 12px;
    padding: 10px 14px;
    border-radius: 12px;
    background: var(--color-error-bg);
    border: 1px solid rgba(194, 77, 77, 0.3);
    color: var(--color-error);
    font-size: 0.8rem;
    font-weight: 600;
}
.visita-offline-badge i { width: 16px; height: 16px; flex-shrink: 0; }
/* FASE 58 — mismo FIX de especificidad que .visita-estado[hidden] arriba. */
.visita-offline-badge[hidden] { display: none; }
/* FASE 91 — badgeColaMuerta: mismo look, pero clicable (abre detalle +
   reintento de los ítems archivados, ver js/visitas_app.js). */
.visita-offline-badge--clicable { cursor: pointer; }
.visita-offline-badge--clicable:hover { filter: brightness(1.08); }

/* ----- FASE 95 — "Nueva versión disponible": toast/snackbar flotante,
   fijo abajo — NO intrusivo (nunca bloquea el asistente como un modal),
   con margen respecto al borde para no quedar pegado al home indicator de
   iOS/gesto de Android (env(safe-area-inset-bottom), mismo criterio que
   .nav-movil arriba). z-index alto: debe quedar SOBRE el asistente/badges,
   pero los modal-overlay (z-index más alto todavía) igual lo tapan si el
   comercial tiene uno abierto justo en ese momento — intencional, un
   SweetAlert2/modal en curso siempre gana. ----- */
.visita-toast-version {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    z-index: 60;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 14px;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-glass);
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
    max-width: 420px;
    margin: 0 auto;
}
.visita-toast-version[hidden] { display: none; }
.visita-toast-version > i:first-child { width: 18px; height: 18px; flex-shrink: 0; color: var(--color-acento); }
.visita-toast-version span { flex: 1 1 auto; font-size: 0.85rem; font-weight: 600; color: var(--texto-principal); }
/* .btn-visita-primario nace width:100% (pensado para pantallas completas
   del wizard) — dentro del toast necesita encogerse a su contenido, nunca
   ocupar toda la fila. */
.visita-toast-version .btn-visita-primario { width: auto; flex-shrink: 0; padding: 8px 14px; font-size: 0.82rem; border-radius: 10px; }
.visita-toast-version #btnCerrarToastVersion { flex-shrink: 0; }

/* ----- FASE 99 — Monitor de Hardware: aviso de saturación severa (calor/
   memoria). Mismo layout fixed/no-intrusivo que .visita-toast-version de
   arriba, pero apilado MÁS ARRIBA (bottom mayor) para que ambos avisos
   puedan convivir en pantalla sin taparse si coinciden — y con acento en
   ámbar (advertencia de hardware), nunca el acento de marca de arriba. ----- */
.visita-toast-hardware {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: calc(78px + env(safe-area-inset-bottom, 0px));
    z-index: 60;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 14px;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid #e0a94c;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
    max-width: 420px;
    margin: 0 auto;
}
.visita-toast-hardware[hidden] { display: none; }
.visita-toast-hardware > i:first-child { width: 18px; height: 18px; flex-shrink: 0; color: #e0a94c; }
.visita-toast-hardware span { flex: 1 1 auto; font-size: 0.82rem; font-weight: 600; color: var(--texto-principal); line-height: 1.3; }
.visita-toast-hardware #btnCerrarAvisoHardware { flex-shrink: 0; }

/* ----- Botón secundario (Finalizar Jornada, dentro de una card) ----- */
.btn-visita-secundario {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin-top: 12px;
    padding: 10px 16px;
    border-radius: 12px;
    border: 1px solid var(--borde-sutil);
    background: transparent;
    color: var(--texto-secundario);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.btn-visita-secundario:hover { border-color: var(--color-error); color: var(--color-error); }

/* ----- FASE 58 — Motor de Pausas: indicador + botón toggle Pausar/Reanudar ----- */
.visita-pausa-indicador {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    padding: 8px 12px;
    border-radius: 10px;
    background: rgba(245, 158, 11, 0.14);
    border: 1px solid rgba(245, 158, 11, 0.35);
    color: #f59e0b;
    font-size: 0.82rem;
    font-weight: 700;
}
.visita-pausa-indicador i { width: 16px; height: 16px; flex-shrink: 0; }
.visita-pausa-indicador[hidden] { display: none; }
#cronometroPausa { font-variant-numeric: tabular-nums; }

.btn-visita-pausa.en-pausa {
    border-color: rgba(245, 158, 11, 0.5);
    color: #f59e0b;
}
.btn-visita-pausa.en-pausa:hover { border-color: #f59e0b; color: #f59e0b; }

.visita-card-jornada { margin-bottom: 4px; }

/* ----- Asistente secuencial: cabecera + cronómetro ----- */
.visita-wizard-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 4px 4px 8px;
    font-size: 0.9rem;
    font-weight: 700;
}
.visita-wizard-cronometro {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--color-acento);
}

/* ----- Cada paso del asistente: aparece con una pequeña animación al revelarse ----- */
.visita-paso { animation: visita-paso-aparece 0.3s ease; }
@keyframes visita-paso-aparece {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.visita-paso-numero {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--color-acento);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 800;
    margin-right: 4px;
}

/* ----- Selects Soft UI (Tipo / Motivo de Visita) ----- */
.visita-select {
    width: 100%;
    padding: 12px 14px;
    border-radius: 12px;
    border: 1px solid var(--borde-sutil);
    background: var(--bg-fondo);
    color: var(--texto-principal);
    font-size: 0.9rem;
    font-family: inherit;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7268' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    padding-right: 36px;
}
.visita-select:focus {
    outline: none;
    border-color: rgba(var(--color-acento-rgb), 0.55);
    box-shadow: 0 0 0 3px rgba(var(--color-acento-rgb), 0.14);
}

.btn-visita-paso-continuar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin-top: 12px;
    padding: 12px 16px;
    border-radius: 12px;
    border: none;
    background: linear-gradient(to bottom, var(--color-acento-claro), var(--color-acento));
    color: #fff;
    font-size: 0.88rem;
    font-weight: 700;
    cursor: pointer;
    transition: filter 0.15s ease, transform 0.1s ease, opacity 0.15s ease;
}
.btn-visita-paso-continuar:hover:not(:disabled) { filter: brightness(1.06); }
.btn-visita-paso-continuar:active:not(:disabled) { transform: scale(0.98); }
.btn-visita-paso-continuar:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-visita-paso-continuar i { width: 16px; height: 16px; }

/* ----- Badge de TIPO (tabla admin) ----- */
.badge-tipo-visita {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 3px 10px;
    border-radius: 20px;
    background: rgba(var(--color-acento-rgb), 0.14);
    color: var(--color-acento);
    white-space: nowrap;
}

/* FASE 69.9 — Task 2: color premium Soft UI por TIPO en Historial de
   Visitas (visitas_dashboard.php) — un color de acento distinto por
   valor, mismo tratamiento visual (fondo translúcido 14% + texto sólido)
   que el badge neutro de arriba, para que se sienta parte de la misma
   familia y no un componente aparte. Ver pintarBadgeTipo() en
   js/visitas_dashboard.js. */
.badge-tipo-visita--visita  { background: rgba(34, 197, 94, 0.16);  color: #15803d; }
.badge-tipo-visita--cumple  { background: rgba(217, 164, 6, 0.18);  color: #a16207; }
.badge-tipo-visita--llamada { background: rgba(37, 99, 235, 0.16);  color: #1d4ed8; }
.badge-tipo-visita--puntos  { background: rgba(147, 51, 234, 0.16); color: #7e22ce; }
.badge-tipo-visita--pedido  { background: rgba(234, 88, 12, 0.16);  color: #c2410c; }

body[data-theme="dark"] .badge-tipo-visita--visita  { background: rgba(34, 197, 94, 0.22);  color: #4ade80; }
body[data-theme="dark"] .badge-tipo-visita--cumple  { background: rgba(217, 164, 6, 0.26);  color: #facc15; }
body[data-theme="dark"] .badge-tipo-visita--llamada { background: rgba(37, 99, 235, 0.24);  color: #60a5fa; }
body[data-theme="dark"] .badge-tipo-visita--puntos  { background: rgba(147, 51, 234, 0.24); color: #c084fc; }
body[data-theme="dark"] .badge-tipo-visita--pedido  { background: rgba(234, 88, 12, 0.24);  color: #fb923c; }

/* ----- Pestañas de visitas_dashboard.php ----- */
.visita-tabs {
    display: flex;
    gap: 6px;
    padding: 0 24px;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--borde-sutil);
}

.visita-tab-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border: none;
    background: transparent;
    color: var(--texto-secundario);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.visita-tab-btn i { width: 16px; height: 16px; }
.visita-tab-btn:hover { color: var(--color-acento); }
.visita-tab-btn.activa { color: var(--color-acento); border-bottom-color: var(--color-acento); }

.visita-tab-panel { padding: 0 24px 24px; }
.visita-tab-panel[hidden] { display: none; }

/* =====================================================================
   FASE 67.5 — Tarea 5: Drill-Down de 3 Niveles ("Comerciales")
   ===================================================================== */
.drilldown-breadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 16px;
    font-size: 0.85rem;
}
.drilldown-breadcrumb-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: none;
    background: transparent;
    color: var(--texto-secundario);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 8px;
}
.drilldown-breadcrumb-item:hover { background: rgba(var(--color-acento-rgb), 0.1); }
.drilldown-breadcrumb-item.activo { color: var(--color-acento); cursor: default; }
.drilldown-breadcrumb-item.activo:hover { background: transparent; }
.drilldown-breadcrumb-item i { width: 14px; height: 14px; }
.drilldown-breadcrumb-separador { display: inline-flex; align-items: center; gap: 4px; }
.drilldown-breadcrumb-separador i { width: 14px; height: 14px; color: var(--texto-secundario); }
.drilldown-breadcrumb-separador[hidden] { display: none; }

.drilldown-tier[hidden] { display: none; }

/* Filas clicables de las tablas Tier 1/Tier 2 (drill-down real, no solo
   un botón de "ver más" — toda la fila es el affordance). */
.fila-clicable { cursor: pointer; }
.fila-clicable:hover { background: rgba(var(--color-acento-rgb), 0.06); }

/* Punto verde "en vivo" junto al nombre de un comercial con jornada
   activa AHORA MISMO, en la tabla del Tier 1 — mismo criterio de color
   que el marcador Activo del Mapa en Vivo. */
.punto-estado-vivo {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #22c55e;
    box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.25);
}

/* Encabezado del Tier 3 (línea de tiempo de una Jornada): mismo criterio
   visual que el header del acordeón de las Fases 59/60. */
.timeline-jornada-header {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--borde-sutil);
}
.timeline-jornada-header h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 1rem;
    margin: 0;
}
.timeline-jornada-header h3 i { width: 18px; height: 18px; color: var(--color-acento); }
.timeline-jornada-header span { font-size: 0.82rem; color: var(--texto-secundario); }
.timeline-jornada-header .accordion-jornada-ubicacion { width: fit-content; margin-top: 4px; }

/* ----- Mapa en Vivo (Leaflet) ----- */
.visita-mapa-panel { padding: 20px; }
.visita-mapa-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}
.visita-mapa-header h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.95rem;
    font-weight: 700;
}
.visita-mapa-header h3 i { width: 18px; height: 18px; color: var(--color-acento); }
.visita-mapa-actualizacion { font-size: 0.78rem; color: var(--texto-secundario); }

.visita-mapa-contenedor {
    width: 100%;
    height: 480px;
    border-radius: 14px;
    overflow: hidden;
    border: 1px solid var(--borde-sutil);
}

.visita-mapa-nota { margin-top: 10px; font-size: 0.78rem; color: var(--texto-secundario); }

/* Leaflet no conoce las variables de tema del CRM: se fuerza un fondo
   consistente para que el contenedor no "parpadee" en blanco puro antes
   de que las teselas de OpenStreetMap terminen de cargar. */
.leaflet-container { background: var(--bg-fondo); font-family: inherit; }

/* ----- Badges de alerta (Analítica de Clientes) ----- */
.badge-alerta-cliente {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.72rem;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 20px;
    white-space: nowrap;
}
.badge-alerta-cliente i { width: 12px; height: 12px; }
.badge-alerta-rojo     { background: var(--color-error-bg); color: var(--color-error); }
.badge-alerta-verde    { background: rgba(99, 159, 56, 0.16); color: var(--color-acento); }
.badge-alerta-amarillo { background: rgba(217, 164, 6, 0.16); color: #d4a017; }

/* FASE 67.5 — Tarea 3: columna RECORDATORIOS del Historial de Visitas
   admin (ajax/get_visitas_admin.php LEFT JOIN tareas_pendientes). */
.celda-recordatorio {
    display: flex;
    flex-direction: column;
    gap: 3px;
    max-width: 200px;
}
.celda-recordatorio-texto {
    font-size: 0.78rem;
    color: var(--texto-principal);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gerencia-tabla-sin-dato { color: var(--texto-secundario); }
.badge-pendiente {
    display: inline-flex;
    align-items: center;
    width: fit-content;
    font-size: 0.65rem;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 20px;
    letter-spacing: 0.02em;
}
.badge-pendiente-activo     { background: rgba(217, 164, 6, 0.16); color: #d4a017; }
.badge-pendiente-terminado  { background: rgba(99, 159, 56, 0.16); color: var(--color-acento); }

/* FASE 67 — Semáforo de Abandono (Control de Visitas / SLA Management):
   punto de color + etiqueta, mismo criterio semántico de
   .badge-alerta-cliente pero con 3 niveles en vez de 2. */
.semaforo-abandono {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
}
.semaforo-abandono-punto {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.06);
}
.semaforo-verde    .semaforo-abandono-punto { background: var(--color-acento); }
.semaforo-amarillo .semaforo-abandono-punto { background: #d4a017; }
.semaforo-rojo .semaforo-abandono-punto { background: var(--color-error); }
.semaforo-verde    { color: var(--color-acento); }
.semaforo-amarillo { color: #d4a017; }
.semaforo-rojo { color: var(--color-error); }

/* =========================================================
   FASE 59/60 — Línea de Tiempo Vertical
   ---------------------------------------------------------
   Componente visual .timeline-vertical: un punto con ícono sobre un riel
   vertical continuo (::before de cada .timeline-item conecta con el
   siguiente) — Pausas naranjas, Visitas azules, Check-in verde, Fin de
   Jornada gris. Originalmente vivía dentro del cuerpo desplegable de un
   acordeón por comercial (Fases 59/60); ese acordeón se retiró en la
   Fase 67.5 al reemplazar la pestaña plana "Historial de Comerciales"
   por el Drill-Down de 3 niveles (ver Tier 3 en js/visitas_dashboard.js,
   renderizarTimelineJornada) — el componente de timeline en sí se
   reutiliza tal cual, solo cambió quién lo monta y con qué datos.
   ========================================================= */

.accordion-jornada-ubicacion {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.76rem;
    font-weight: 700;
    color: var(--color-acento);
    text-decoration: none;
    white-space: nowrap;
    padding: 5px 10px;
    border-radius: 20px;
    background: rgba(var(--color-acento-rgb), 0.1);
    transition: background-color 0.15s ease;
}

.accordion-jornada-ubicacion:hover { background: rgba(var(--color-acento-rgb), 0.18); }

.accordion-jornada-ubicacion-disabled {
    color: var(--texto-secundario);
    background: transparent;
    cursor: default;
}

/* ----- Línea de tiempo vertical ----- */
.timeline-vertical { padding: 18px 20px 20px 20px; }

.timeline-item {
    position: relative;
    display: flex;
    gap: 16px;
    padding-bottom: 26px;
}

.timeline-item:last-child { padding-bottom: 0; }

.timeline-item:not(:last-child)::before {
    content: '';
    position: absolute;
    top: 34px;
    bottom: -26px;
    left: 15px;
    width: 2px;
    background: var(--borde-sutil);
}

.timeline-marcador {
    position: relative;
    z-index: 1;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.timeline-marcador i { width: 16px; height: 16px; }

.timeline-item-inicio      .timeline-marcador { background: rgba(34, 197, 94, 0.16); color: #22c55e; box-shadow: 0 0 0 1px rgba(34, 197, 94, 0.4); }
.timeline-item-pausa       .timeline-marcador { background: rgba(245, 158, 11, 0.16); color: #f59e0b; box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.4); }
.timeline-item-visita      .timeline-marcador { background: rgba(59, 130, 246, 0.16); color: #3b82f6; box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.4); }
.timeline-item-fin-jornada .timeline-marcador { background: rgba(100, 116, 139, 0.16); color: #64748b; box-shadow: 0 0 0 1px rgba(100, 116, 139, 0.4); }

.timeline-tarjeta {
    flex: 1;
    min-width: 0;
    background: var(--bg-panel);
    border: 1px solid var(--borde-sutil);
    border-left: 3px solid transparent;
    border-radius: 14px;
    padding: 12px 16px;
}

.timeline-item-inicio      .timeline-tarjeta { border-left-color: #22c55e; }
.timeline-item-pausa       .timeline-tarjeta { border-left-color: #f59e0b; }
.timeline-item-visita      .timeline-tarjeta { border-left-color: #3b82f6; }
.timeline-item-fin-jornada .timeline-tarjeta { border-left-color: #64748b; }

.timeline-tarjeta-cabecera {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
}

.timeline-hora {
    font-variant-numeric: tabular-nums;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--texto-secundario);
}

.timeline-titulo { font-size: 0.9rem; font-weight: 700; }

.timeline-detalle {
    margin: 4px 0 0;
    font-size: 0.82rem;
    color: var(--texto-secundario);
}

/* ----- DataTables: alinear su UI (buscador, paginación) al tema del CRM ----- */
.dataTables_wrapper { color: var(--texto-principal); font-size: 0.85rem; }
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
    background: var(--bg-fondo);
    border: 1px solid var(--borde-sutil);
    border-radius: 8px;
    color: var(--texto-principal);
    padding: 5px 8px;
}
.dataTables_wrapper .dataTables_paginate .paginate_button {
    color: var(--texto-principal) !important;
    border-radius: 8px !important;
    border: 1px solid transparent !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current {
    background: var(--color-acento) !important;
    border-color: var(--color-acento) !important;
    color: #fff !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
    background: rgba(var(--color-acento-rgb), 0.14) !important;
    border-color: rgba(var(--color-acento-rgb), 0.3) !important;
    color: var(--color-acento) !important;
}

/* ----- FASE 66 — DataTables Buttons (Excel/PDF/Print) de base_datos_clientes.php ----- */
.dt-toolbar-superior {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 12px;
}
.dt-toolbar-superior .dt-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.dt-toolbar-superior .btn-dt-export {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border-radius: 10px;
    border: 1px solid var(--borde-sutil);
    background: var(--bg-tarjeta);
    color: var(--texto-principal);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.dt-toolbar-superior .btn-dt-export:hover {
    background: rgba(var(--color-acento-rgb), 0.12);
    border-color: rgba(var(--color-acento-rgb), 0.3);
    color: var(--color-acento);
}
.dt-toolbar-superior .btn-dt-export svg,
.dt-toolbar-superior .btn-dt-export i { width: 14px; height: 14px; }

/* ----- FASE 67 — Multi-Filtro Dinámico de base_datos_clientes.php ----- */
.master-filtros-grid {
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-glass);
    border-radius: 16px;
    padding: 18px 20px;
    margin-bottom: 16px;
    display: flex;
    align-items: flex-end;
    gap: 14px;
    flex-wrap: wrap;
    box-shadow: var(--sombra-panel);
}
.master-filtros-grid .gerencia-filtro-campo { min-width: 150px; flex: 1 1 150px; }
.master-filtros-grid #btnLimpiarFiltrosMaster { flex-shrink: 0; }

/* =====================================================================
   FASE 65 — DIRECTORIO DE CLIENTES POR RUTA (directorio_clientes.php)
   ---------------------------------------------------------------------
   Reutiliza el sistema ya existente: .gerencia-shell/.gerencia-panel,
   .gerencia-resumen-grid (KPIs), .modal-overlay/.modal-form/.btn-submit
   (modal), .buscador-inventario-wrap (buscador) y .filtro-tab (pestañas)
   ya cubren casi todo. Este bloque solo agrega lo que no existía: la
   toolbar de dos columnas, la variante grande de .filtro-tab con badge
   de conteo, y el drag & drop del CSV con su spinner de progreso.
   ===================================================================== */

.directorio-toolbar {
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
}
.directorio-toolbar .buscador-inventario-wrap {
    flex: 1;
    min-width: 220px;
    max-width: 380px;
    margin-bottom: 0;
}

.directorio-rutas-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 18px;
}

.filtro-tab--ruta {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 16px;
    font-size: 0.8rem;
}

.tab-count-badge {
    background: rgba(127, 127, 127, 0.2);
    color: inherit;
    border-radius: 999px;
    padding: 1px 8px;
    font-size: 0.68rem;
    font-weight: 800;
    line-height: 1.5;
}
.filtro-tab--ruta.activo .tab-count-badge {
    background: rgba(255, 255, 255, 0.3);
}

.dropzone-csv {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 36px 20px;
    border: 2px dashed rgba(var(--color-acento-rgb), 0.35);
    border-radius: 16px;
    background: rgba(var(--color-acento-rgb), 0.04);
    cursor: pointer;
    text-align: center;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.dropzone-csv:hover,
.dropzone-csv.dropzone-csv--sobre {
    border-color: var(--color-acento);
    background: rgba(var(--color-acento-rgb), 0.09);
}
.dropzone-csv-icono { width: 34px; height: 34px; color: var(--color-acento); }
.dropzone-csv-texto { font-size: 0.85rem; color: var(--texto-secundario); font-weight: 600; }
.dropzone-csv.dropzone-csv--con-archivo .dropzone-csv-texto { color: var(--texto-principal); }

.dropzone-csv-progreso {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    margin-top: 12px;
    border-radius: 12px;
    background: rgba(var(--color-acento-rgb), 0.08);
    color: var(--color-acento);
    font-size: 0.8rem;
    font-weight: 600;
}
.dropzone-csv-progreso[hidden] { display: none; }
.dropzone-csv-progreso .icono-girando { width: 18px; height: 18px; flex-shrink: 0; }
.dt-body-center { text-align: center; }

/* =========================================================================
   FASE 69 — Smart Field Data Digitalization, Secure Vault & Audit Engine
   ========================================================================= */

/* ----- Botón "Actualizar Base de Datos" (hub móvil): mismo look que
   .btn-visita-secundario pero con acento verde en vez de rojo en hover —
   no es una acción destructiva como "Finalizar Jornada". ----- */
.btn-visita-secundario--acento:hover {
    border-color: var(--color-acento);
    color: var(--color-acento);
}

/* ----- Task 2 (Fase 69.5): segundo cumpleaños opcional, revelado por
   btnAgregarCumpleanosExtra — mismo espaciado que .visita-prospecto-wrap. ----- */
.visita-cumpleanos-extra { margin-top: -6px; display: flex; flex-direction: column; gap: 14px; }

/* ----- Task 3: formulario de actualización dentro de .visita-card — reusa
   los estilos de input de .modal-form (fuera de un modal real esta vez),
   pero sin su padding propio: .visita-card ya trae el suyo, y sumarlos
   duplicaría el espaciado. ----- */
.visita-card .modal-form { padding: 0; }

/* ----- FASE 69.16 — Unified Update Flow (Task 1/4): acordeón del
   sub-formulario embebido de "Actualizar Base de Datos" dentro del Paso 7
   del asistente de visita — mismo patrón de acordeón CSS suave que
   .cierre-pro-campos (max-height + opacity, sin JS de animación) para que
   aparecer/desaparecer se sienta fluido en celular y nunca "salte". Colapsado
   por defecto (motivo distinto de "Actualizar Base de Datos", o sin cliente
   real seleccionado); .visita-actualizar-cliente-visible lo revela cuando
   sincronizarSubformActualizarCliente() (js/visitas_app.js) decide que
   aplica. ----- */
.visita-actualizar-cliente-embed {
    display: flex;
    flex-direction: column;
    gap: 14px;
    opacity: 0;
    max-height: 0;
    overflow: hidden;
    margin-top: 0;
    transition: opacity 0.35s ease, max-height 0.45s ease, margin-top 0.45s ease;
}
.visita-actualizar-cliente-embed.visita-actualizar-cliente-visible {
    opacity: 1;
    max-height: 3200px;
    margin-top: 6px;
}
.visita-actualizar-cliente-titulo {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding-top: 14px;
    border-top: 1px dashed var(--borde-sutil);
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--color-acento);
}
.visita-actualizar-cliente-titulo i { width: 18px; height: 18px; flex-shrink: 0; }
#notaActualizarClienteSinMaster {
    display: flex;
    align-items: center;
    gap: 6px;
}
#notaActualizarClienteSinMaster i { width: 15px; height: 15px; flex-shrink: 0; }

/* ----- Task 4: separador de sección dentro del modal Quick-Edit ----- */
.modal-form-seccion {
    margin: 4px 0 -4px;
    padding-top: 14px;
    border-top: 1px solid var(--borde-sutil);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--texto-secundario);
}

/* ----- Task 3: switch "¿Requiere Facturación Electrónica?" ----- */
.campo-switch {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 12px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
}
.campo-switch label { flex: 1; font-weight: 600; color: var(--texto-principal); margin: 0; }
.campo-switch input[type="checkbox"] {
    width: 22px;
    height: 22px;
    accent-color: var(--color-acento);
    cursor: pointer;
    flex-shrink: 0;
}

/* ----- Task 5: Modal "Historial de Cambios" (timeline de auditoria_clientes) ----- */
.historial-timeline-wrap { max-height: 60vh; overflow-y: auto; padding: 4px 2px; }
.historial-vacio { color: var(--texto-secundario); font-size: 0.85rem; text-align: center; padding: 24px 0; }

.historial-timeline { display: flex; flex-direction: column; gap: 14px; }

.historial-item {
    display: flex;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 12px;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
}
.historial-item-icono {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
}
.historial-item-icono i { width: 16px; height: 16px; }
.historial-item-cuerpo { flex: 1; min-width: 0; }
.historial-item-cabecera {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
    flex-wrap: wrap;
}
.historial-item-cabecera strong { color: var(--texto-principal); font-size: 0.88rem; }
.historial-item-cabecera span { color: var(--texto-secundario); font-size: 0.76rem; }
.historial-item-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.historial-item-lista li { font-size: 0.8rem; color: var(--texto-secundario); }
.historial-item-lista li strong { color: var(--texto-principal); }
.historial-item-lista em { color: var(--texto-secundario); font-style: italic; }

/* =========================================================================
   FASE 69.6 — Street Reality, Exception Flows & Hyper-Personalized Wellbeing
   ========================================================================= */

/* ----- Task 5: tarjeta de Bienestar Diario, sobre "Iniciar Jornada" ----- */
.visita-card-bienestar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px 20px;
    background: linear-gradient(135deg, rgba(var(--color-acento-rgb), 0.14), rgba(var(--color-acento-rgb), 0.04));
    border: 1px solid rgba(var(--color-acento-rgb), 0.28);
}
.visita-bienestar-icono {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(var(--color-acento-rgb), 0.18);
    color: var(--color-acento);
}
.visita-bienestar-icono i { width: 20px; height: 20px; }
.visita-bienestar-mensaje {
    margin: 0;
    font-size: 0.88rem;
    font-weight: 600;
    line-height: 1.45;
    color: var(--texto-principal);
}

/* ----- Task 4: excepción SEDE (nota informativa del paso especial) ----- */
#pasoSedeExcepcion .visita-foto-ayuda { margin-bottom: 4px; }

/* ----- Task 6: badge "Excepción SEDE" en el Historial de Visitas admin ----- */
.badge-cliente-sede {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(245, 158, 11, 0.16);
    border: 1px solid rgba(245, 158, 11, 0.4);
    color: #b8790a;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    vertical-align: middle;
}
.badge-cliente-sede i { width: 11px; height: 11px; }

/* =========================================================================
   FASE 69.7 — Operational Discipline & Persistent Wellbeing
   ========================================================================= */

/* ----- Task 3: "Cerrar Sesión" en el topbar móvil — mismo tinte de peligro
   que .col-sidebar .btn-icono--peligro (dashboard.php), reescalado para el
   topbar de visitas_app.php (no vive dentro de .col-sidebar). ----- */
.visita-topbar .btn-icono--peligro:hover {
    background: rgba(200, 80, 80, 0.14);
    border-color: rgba(200, 80, 80, 0.35);
    color: #c85050;
}
body[data-theme="dark"] .visita-topbar .btn-icono--peligro:hover { color: #e08080; }
.btn-cargando-silencioso { opacity: 0.5; pointer-events: none; }

/* ----- Task 5: KPI de Faltas/Strikes (rojo/advertencia) ----- */
.panelcom-kpi-tile--peligro { border-color: rgba(200, 80, 80, 0.35); }
.panelcom-kpi-tile--peligro i,
.panelcom-kpi-tile--peligro .panelcom-kpi-valor { color: #c85050; }
body[data-theme="dark"] .panelcom-kpi-tile--peligro i,
body[data-theme="dark"] .panelcom-kpi-tile--peligro .panelcom-kpi-valor { color: #e08080; }

/* ----- Task 5: columna "Strikes" en la grilla admin de Comerciales ----- */
.gerencia-tabla-strikes-cero { color: var(--texto-secundario); }
.gerencia-tabla-strikes-alerta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 9px;
    border-radius: 999px;
    background: rgba(200, 80, 80, 0.14);
    border: 1px solid rgba(200, 80, 80, 0.35);
    color: #c85050;
    font-weight: 700;
}
body[data-theme="dark"] .gerencia-tabla-strikes-alerta { color: #e08080; }

/* =====================================================================
   FASE 69.8 — Analítica de Eventos + Continuous Loop (visitas_app.php)
   ---------------------------------------------------------------------
   Task 2: grid táctil de Tipo (5 tarjetas Soft UI, cada una con su propio
   acento de color vía --acento-tipo-rgb, mismo criterio rgba(var(...))
   que --color-acento-rgb en el resto del archivo) + grid de Motivo
   (lista de botones dependiente del Tipo) + toggles estilo iOS para las
   10 "Acciones Realizadas". Task 4: modal "Continuous Loop".
   ===================================================================== */

/* ----- Task 2: grid táctil de Tipo ----- */
.visita-tipo-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    margin-bottom: 4px;
}
.visita-tipo-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 92px;
    padding: 14px 10px;
    border-radius: 16px;
    border: 2px solid var(--borde-sutil);
    background: var(--bg-fondo);
    color: var(--texto-principal);
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    transition: transform 0.12s ease, border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.visita-tipo-card:active { transform: scale(0.96); }
.visita-tipo-card .visita-tipo-icono { display: flex; align-items: center; justify-content: center; }
.visita-tipo-card .visita-tipo-icono i { width: 26px; height: 26px; color: rgb(var(--acento-tipo-rgb)); }
/* FASE 69.17 — Task 1: con la 6ta tarjeta ("Actualizar Base de Datos") el
   grid de 2 columnas queda parejo en 3 filas completas — ya no hay hueco
   impar que forzar a ancho completo (antes la 5ta/Puntos lo necesitaba). */

.visita-tipo-card--visita  { --acento-tipo-rgb: var(--color-acento-rgb); }
.visita-tipo-card--cumple  { --acento-tipo-rgb: 214, 83, 143; }
.visita-tipo-card--llamada { --acento-tipo-rgb: 59, 130, 246; }
.visita-tipo-card--pedido  { --acento-tipo-rgb: 232, 130, 58; }
.visita-tipo-card--puntos  { --acento-tipo-rgb: 201, 151, 31; }
.visita-tipo-card--actualizarbd { --acento-tipo-rgb: 32, 156, 145; }
/* Variantes más claras en modo oscuro — mismo criterio de contraste que
   .gerencia-tabla-strikes-alerta más arriba (color fijo, no derivado de
   --color-acento, así que necesita su propio ajuste por tema). */
body[data-theme="dark"] .visita-tipo-card--cumple  { --acento-tipo-rgb: 232, 121, 172; }
body[data-theme="dark"] .visita-tipo-card--llamada { --acento-tipo-rgb: 96, 165, 250; }
body[data-theme="dark"] .visita-tipo-card--pedido  { --acento-tipo-rgb: 251, 158, 88; }
body[data-theme="dark"] .visita-tipo-card--puntos  { --acento-tipo-rgb: 224, 176, 60; }
body[data-theme="dark"] .visita-tipo-card--actualizarbd { --acento-tipo-rgb: 45, 191, 178; }

.visita-tipo-card:hover { border-color: rgba(var(--acento-tipo-rgb), 0.55); }
.visita-tipo-card:focus-visible { outline: 2px solid rgb(var(--acento-tipo-rgb)); outline-offset: 2px; }
.visita-tipo-card.activa {
    border-color: rgb(var(--acento-tipo-rgb));
    background: rgba(var(--acento-tipo-rgb), 0.14);
    box-shadow: 0 0 0 3px rgba(var(--acento-tipo-rgb), 0.22);
}

/* ----- Task 2: grid táctil de Motivo (dependiente del Tipo) ----- */
.visita-motivo-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 4px;
}
.visita-motivo-card {
    display: flex;
    align-items: center;
    text-align: left;
    min-height: 52px;
    padding: 12px 16px;
    border-radius: 14px;
    border: 2px solid var(--borde-sutil);
    background: var(--bg-fondo);
    color: var(--texto-principal);
    font-family: inherit;
    font-size: 0.88rem;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease, transform 0.1s ease, color 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.visita-motivo-card:active { transform: scale(0.98); }
.visita-motivo-card:hover { border-color: rgba(var(--color-acento-rgb), 0.5); }
.visita-motivo-card:focus-visible { outline: 2px solid var(--color-acento); outline-offset: 2px; }
.visita-motivo-card.activa {
    border-color: var(--color-acento);
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
}
/* "Cerrado / No se encuentra cliente" (Ghost Flow, ver MOTIVO_GHOST en
   js/visitas_app.js): borde punteado para diferenciarla visualmente de
   las gestiones "normales" antes incluso de tocarla. */
.visita-motivo-card--fantasma { border-style: dashed; }
.visita-motivo-card--fantasma.activa {
    border-color: var(--color-error);
    background: var(--color-error-bg);
    color: var(--color-error);
    border-style: solid;
}

/* ----- Task 2: Acciones Realizadas — 10 toggles estilo iOS -----
   Rojo/izquierda = NO (default, sin marcar) — Verde/derecha = SI. Tap
   target completo (toda la fila, no solo el switch) para usuarios
   mayores, con micro-interacción de "pulso" al cambiar (ver
   .visita-toggle-pulso, disparada por JS junto con navigator.vibrate). */
.visita-toggle-lista { display: flex; flex-direction: column; gap: 10px; margin-bottom: 4px; }
.visita-toggle-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    min-height: 56px;
    padding: 12px 16px;
    border-radius: 14px;
    background: var(--bg-fondo);
    border: 1px solid var(--borde-sutil);
    cursor: pointer;
    transition: transform 0.12s ease;
    -webkit-tap-highlight-color: transparent;
}
.visita-toggle-item.visita-toggle-pulso { transform: scale(0.985); }
.visita-toggle-texto { flex: 1; font-size: 0.86rem; font-weight: 600; color: var(--texto-principal); }
.visita-toggle-switch { position: relative; flex-shrink: 0; width: 54px; height: 32px; }
.visita-toggle-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 1;
}
.visita-toggle-riel {
    position: absolute;
    inset: 0;
    background: var(--color-error);
    border-radius: 999px;
    transition: background 0.2s ease;
}
.visita-toggle-bola {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    transition: transform 0.2s ease;
}
.visita-toggle-input:checked ~ .visita-toggle-riel { background: var(--color-acento); }
.visita-toggle-input:checked ~ .visita-toggle-riel .visita-toggle-bola { transform: translateX(22px); }
.visita-toggle-input:focus-visible ~ .visita-toggle-riel { outline: 2px solid var(--color-acento); outline-offset: 2px; }

/* FASE 69.13 — Task 3: disparador del "Ghost Flow 2.0" (accion_no_atiende /
   accion_no_atiende_cumple, ver aplicarGhostFlowVisual() en
   js/visitas_app.js) — borde punteado para diferenciarlo del resto de
   toggles antes incluso de tocarlo, mismo lenguaje visual que
   .visita-motivo-card--fantasma. Al marcarse en SI, el resto de la lista
   de su grupo queda oculta (atributo [hidden] nativo, ver el fix
   ".visita-shell [hidden]" de más arriba en este archivo). */
.visita-toggle-item--fantasma { border-style: dashed; }
.visita-toggle-item--fantasma:has(.visita-toggle-input:checked) {
    border-color: var(--color-error);
    background: var(--color-error-bg);
    border-style: solid;
}

/* ----- Task 4: modal "Continuous Loop" ----- */
.visita-modal-continuar { max-width: 400px; }
.visita-continuar-body {
    padding: 20px 18px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    text-align: center;
}
.visita-continuar-body p { font-size: 0.95rem; color: var(--texto-principal); line-height: 1.5; }
.visita-continuar-botones { display: flex; flex-direction: column; gap: 10px; }
.visita-continuar-botones .btn-visita-primario,
.visita-continuar-botones .btn-visita-secundario { margin-top: 0; width: 100%; }

/* =========================================================================
   FASE 69.9 — Task 4: "La Radiografía del Cliente" (Offcanvas)
   -------------------------------------------------------------------------
   Sidebar deslizante desde la derecha (a diferencia de .modal-overlay/
   .modal-panel, centrados) — mismo criterio visual "premium enterprise" del
   resto del panel (glass + sombra), pero con más espacio vertical para un
   historial completo de gestiones sin sentirse una ventana emergente
   angosta.
   ========================================================================= */
.radiografia-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    z-index: 110;
    display: flex;
    justify-content: flex-end;
}
.radiografia-overlay[hidden] { display: none; }

.radiografia-panel {
    width: 100%;
    max-width: 560px;
    height: 100%;
    background: var(--bg-panel-alt);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border-left: 1px solid var(--borde-inner-glow);
    box-shadow: -12px 0 32px rgba(0, 0, 0, 0.22);
    display: flex;
    flex-direction: column;
    animation: radiografiaEntrada 0.25s ease;
}
@keyframes radiografiaEntrada {
    from { transform: translateX(24px); opacity: 0; }
    to   { transform: translateX(0); opacity: 1; }
}

.radiografia-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 20px 22px;
    border-bottom: 1px solid var(--borde-glass);
    flex-shrink: 0;
}
.radiografia-eyebrow {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-acento);
    margin-bottom: 4px;
}
.radiografia-eyebrow i { width: 14px; height: 14px; }
.radiografia-header h2 { font-size: 1.2rem; color: var(--texto-principal); line-height: 1.3; }

.radiografia-body {
    flex: 1;
    overflow-y: auto;
    padding: 20px 22px 32px;
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.radiografia-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8rem;
    color: var(--texto-secundario);
    margin: -4px 0 12px;
}
.radiografia-hint i { width: 14px; height: 14px; color: var(--color-acento); }

.radiografia-seccion-titulo {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--texto-secundario);
    margin-bottom: 10px;
}
.radiografia-seccion-titulo i { width: 15px; height: 15px; color: var(--color-acento); }

.radiografia-ficha-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px 16px;
}
.radiografia-ficha-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.radiografia-ficha-label { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--texto-secundario); }
.radiografia-ficha-valor { font-size: 0.88rem; color: var(--texto-principal); font-weight: 600; overflow-wrap: break-word; }

.radiografia-kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
    gap: 10px;
}
.radiografia-kpi-tile {
    background: rgba(var(--color-acento-rgb), 0.08);
    border: 1px solid rgba(var(--color-acento-rgb), 0.16);
    border-radius: 12px;
    padding: 12px 14px;
    text-align: center;
}
.radiografia-kpi-valor { font-size: 1.3rem; font-weight: 800; color: var(--color-acento); line-height: 1.1; }
.radiografia-kpi-label { font-size: 0.68rem; color: var(--texto-secundario); margin-top: 4px; }

/* FASE 69.10 — Task 4: rediseño del timeline como un riel vertical real
   (punto + línea conectora) en vez de tarjetas simplemente apiladas — la
   lectura cronológica de un vistazo era el pedido explícito de esta
   tarea, y un riel es el lenguaje visual estándar para "línea de tiempo"
   (mismo concepto que .timeline-vertical de Jornadas, adaptado acá con su
   propio namespace porque el contenido/densidad es distinto). */
.radiografia-timeline {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding-left: 24px;
}
.radiografia-timeline::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 6px;
    bottom: 6px;
    width: 2px;
    background: linear-gradient(to bottom, rgba(var(--color-acento-rgb), 0.4), rgba(var(--color-acento-rgb), 0.06));
    border-radius: 2px;
}
.radiografia-item {
    position: relative;
    border: 1px solid var(--borde-glass);
    border-radius: 12px;
    padding: 12px 14px;
    background: rgba(var(--color-acento-rgb), 0.03);
}
.radiografia-item::before {
    content: '';
    position: absolute;
    left: -20px;
    top: 16px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--color-acento);
    border: 2px solid var(--bg-panel-alt);
    box-shadow: 0 0 0 2px rgba(var(--color-acento-rgb), 0.3);
}
.radiografia-item-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.radiografia-item-fecha { font-size: 0.78rem; font-weight: 700; color: var(--texto-principal); }
.radiografia-item-asesora {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.74rem;
    color: var(--texto-secundario);
}
.radiografia-item-asesora i { width: 12px; height: 12px; color: var(--color-acento); flex-shrink: 0; }
.radiografia-item-motivo { font-size: 0.82rem; color: var(--texto-principal); margin: 4px 0; }
.radiografia-item-comentarios { font-size: 0.78rem; color: var(--texto-secundario); font-style: italic; margin: 4px 0; }
.radiografia-item-acciones { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.radiografia-chip-accion {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 0.64rem;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 20px;
    background: rgba(34, 197, 94, 0.16);
    color: #15803d;
    white-space: nowrap;
}
.radiografia-chip-accion i { width: 10px; height: 10px; }
body[data-theme="dark"] .radiografia-chip-accion { background: rgba(34, 197, 94, 0.22); color: #4ade80; }

/* ----- Task 4: Header Summary — badges de Semáforo/Última Visita/Última
   Actualización, fijos justo debajo del nombre del cliente (visibles sin
   scrollear el body del Offcanvas). ----- */
.radiografia-header-resumen {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}
.radiografia-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.7rem;
    font-weight: 600;
    padding: 3px 10px;
    border-radius: 20px;
    background: rgba(var(--color-acento-rgb), 0.08);
    color: var(--texto-secundario);
    white-space: nowrap;
}
.radiografia-pill i { width: 12px; height: 12px; }
.radiografia-pill-semaforo-verde { background: rgba(34, 197, 94, 0.14); color: #15803d; }
.radiografia-pill-semaforo-amarillo { background: rgba(234, 179, 8, 0.16); color: #a16207; }
.radiografia-pill-semaforo-rojo { background: rgba(239, 68, 68, 0.14); color: #b91c1c; }
body[data-theme="dark"] .radiografia-pill-semaforo-verde { background: rgba(34, 197, 94, 0.22); color: #4ade80; }
body[data-theme="dark"] .radiografia-pill-semaforo-amarillo { background: rgba(234, 179, 8, 0.24); color: #facc15; }
body[data-theme="dark"] .radiografia-pill-semaforo-rojo { background: rgba(239, 68, 68, 0.24); color: #f87171; }

@media (max-width: 640px) {
    .radiografia-panel { max-width: 100%; }
    .radiografia-ficha-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   FASE 69.10 — Task 3: Calificación de Experiencia (5 estrellas)
   -------------------------------------------------------------------------
   SweetAlert2 con estrellas táctiles grandes (visitas_app.php /
   mostrarCalificacionExperiencia en js/visitas_app.js) — tap targets de
   52-64px (más grandes que el mínimo de 44px recomendado para accesibilidad
   táctil, pensado para usuarios mayores en campo con guantes/pantallas
   sucias), con un "pop" elástico al seleccionar en vez de solo cambiar de
   color, para que se sienta una interacción nativa, no un formulario web.
   ========================================================================= */
.swal-calificacion-popup { border-radius: 22px !important; }

.calificacion-subtitulo {
    font-size: 0.92rem;
    color: var(--texto-secundario);
    margin: 0 0 18px;
}

.calificacion-estrellas {
    display: flex;
    justify-content: center;
    gap: 4px;
}

.calificacion-estrella {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    width: 52px;
    height: 52px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #d1d5db;
    transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1), color 0.15s ease;
}
.calificacion-estrella svg {
    width: 34px;
    height: 34px;
    stroke-width: 1.75;
    transition: fill 0.15s ease, stroke 0.15s ease;
}
.calificacion-estrella:hover { color: #fbbf24; }
.calificacion-estrella:active { transform: scale(0.85); }

.calificacion-estrella-activa {
    color: #f59e0b;
    animation: calificacionEstrellaPop 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.calificacion-estrella-activa svg { fill: #f59e0b; stroke: #f59e0b; }

@keyframes calificacionEstrellaPop {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.35); }
    100% { transform: scale(1); }
}

body[data-theme="dark"] .calificacion-estrella { color: #4b5563; }
body[data-theme="dark"] .calificacion-estrella-activa { color: #fbbf24; }
body[data-theme="dark"] .calificacion-estrella-activa svg { fill: #fbbf24; stroke: #fbbf24; }

@media (min-width: 420px) {
    .calificacion-estrella { width: 60px; height: 60px; }
    .calificacion-estrella svg { width: 40px; height: 40px; }
}

/* ----- Task 4: badge de estrellas ya calificadas, dentro del timeline
   de la Radiografía del Cliente (visitas_dashboard.php) — de solo lectura,
   sin interacción, así que reusa el mismo color dorado pero sin los
   estados hover/active de arriba. ----- */
.radiografia-item-calificacion {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-top: 6px;
}
.radiografia-item-calificacion svg { width: 14px; height: 14px; stroke: #f59e0b; }
.radiografia-item-calificacion .estrella-llena svg { fill: #f59e0b; }
.radiografia-item-calificacion .estrella-vacia svg { stroke: var(--borde-glass); }

/* =====================================================================
   FASE 69.15 — Monitor de Telemetría ("La Caja Negra") — monitor_telemetria.php
   ---------------------------------------------------------------------
   Semáforo de 3 colores, consistente en TODA la pantalla (tarjetas de
   comercial, mini-badges y puntos del timeline): mismo verde/naranja/rojo
   ya aprobados en el resto del CRM (.badge-estado-activo/inactivo,
   .score-alto/medio/bajo) — no se inventa una paleta nueva.
   ===================================================================== */

.telemetria-leyenda {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--texto-secundario);
    flex-wrap: wrap;
}

.telemetria-leyenda-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.telemetria-dot {
    display: inline-flex;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

.telemetria-dot--info    { background: #7cc750; }
.telemetria-dot--warning { background: #e0a94c; }
.telemetria-dot--error   { background: #e05252; }

/* ----- Layout maestro-detalle: comerciales a la izquierda (ancho fijo,
   denso), Journey Timeline ocupando el resto. ----- */
.telemetria-layout {
    display: grid;
    grid-template-columns: 320px 1fr;
    gap: 20px;
    align-items: start;
}

@media (max-width: 900px) {
    .telemetria-layout { grid-template-columns: 1fr; }
}

.telemetria-panel-comerciales,
.telemetria-panel-timeline {
    display: flex;
    flex-direction: column;
    gap: 12px;
    max-height: calc(100vh - 220px);
}

.telemetria-contador-total {
    font-weight: 400;
    color: var(--texto-secundario);
    font-size: 0.8rem;
}

.telemetria-lista-comerciales {
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
    padding-right: 4px;
}

/* ----- Tarjeta de comercial: botón denso, no una fila de tabla — pensada
   para escanear 20-30 comerciales de un vistazo, severidad primero (ver
   el ORDER BY de ajax/get_telemetria.php). ----- */
.telemetria-tarjeta-comercial {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    text-align: left;
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 12px;
    padding: 10px 12px;
    cursor: pointer;
    font: inherit;
    color: var(--texto-principal);
    transition: border-color 0.15s ease, background 0.15s ease;
}

.telemetria-tarjeta-comercial:hover {
    border-color: rgba(var(--color-acento-rgb), 0.4);
}

.telemetria-tarjeta-comercial--activa {
    background: rgba(var(--color-acento-rgb), 0.1);
    border-color: var(--color-acento);
}

.telemetria-tarjeta-comercial-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.telemetria-tarjeta-comercial-nombre {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    font-size: 0.88rem;
}

.telemetria-icono-alerta { width: 14px; height: 14px; stroke: #e05252; flex-shrink: 0; }

.telemetria-tarjeta-comercial-badges {
    display: flex;
    gap: 6px;
}

.telemetria-mini-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 26px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
}

.telemetria-mini-badge--info    { background: rgba(124, 199, 80, 0.16); color: #5a8f39; }
.telemetria-mini-badge--warning { background: rgba(224, 169, 76, 0.18); color: #c98a2e; }
.telemetria-mini-badge--error   { background: rgba(224, 82, 82, 0.16); color: #e05252; }

body[data-theme="dark"] .telemetria-mini-badge--info { color: #7cc750; }

/* ----- Journey Timeline (panel derecho) ----- */
.telemetria-timeline-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
}

.telemetria-resumen-timeline {
    font-size: 0.78rem;
    color: var(--texto-secundario);
}

.telemetria-timeline {
    overflow-y: auto;
    padding-right: 4px;
}

.telemetria-evento {
    display: flex;
    gap: 12px;
}

.telemetria-evento-linea {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
}

.telemetria-evento-dot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    flex-shrink: 0;
}

.telemetria-evento-dot svg { width: 14px; height: 14px; }

.telemetria-evento-dot.telemetria-dot--info    { background: rgba(124, 199, 80, 0.18); color: #5a8f39; }
.telemetria-evento-dot.telemetria-dot--warning { background: rgba(224, 169, 76, 0.2); color: #c98a2e; }
.telemetria-evento-dot.telemetria-dot--error   { background: rgba(224, 82, 82, 0.18); color: #e05252; }

.telemetria-evento-conector {
    flex: 1;
    width: 2px;
    background: var(--borde-sutil);
    margin: 4px 0;
    min-height: 16px;
}

.telemetria-evento:last-child .telemetria-evento-conector { display: none; }

.telemetria-evento-cuerpo {
    flex: 1;
    min-width: 0;
    padding-bottom: 20px;
}

.telemetria-evento-cabecera {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.telemetria-evento-hito {
    font-weight: 700;
    font-size: 0.88rem;
    font-family: 'Courier New', monospace;
    letter-spacing: 0.01em;
}

.telemetria-evento--warning .telemetria-evento-hito { color: #c98a2e; }
.telemetria-evento--error .telemetria-evento-hito   { color: #e05252; }

.telemetria-evento-hora {
    font-size: 0.76rem;
    color: var(--texto-secundario);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.telemetria-evento-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 4px;
    font-size: 0.75rem;
    color: var(--texto-secundario);
}

.telemetria-evento-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.telemetria-evento-meta-item svg { width: 12px; height: 12px; }

.telemetria-btn-contexto {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-top: 8px;
    background: none;
    border: 1px dashed var(--borde-sutil);
    border-radius: 8px;
    padding: 4px 10px;
    font-size: 0.72rem;
    color: var(--texto-secundario);
    cursor: pointer;
    font: inherit;
}

.telemetria-btn-contexto:hover {
    border-color: var(--color-acento);
    color: var(--color-acento);
}

.telemetria-btn-contexto svg { width: 12px; height: 12px; }

.telemetria-contexto-json {
    margin-top: 8px;
    background: var(--bg-fondo);
    border: 1px solid var(--borde-sutil);
    border-radius: 8px;
    padding: 10px 12px;
    font-size: 0.72rem;
    font-family: 'Courier New', monospace;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 260px;
    overflow-y: auto;
    color: var(--texto-principal);
}

/* =====================================================================
   FASE 71 — Capa Semántica & Sentry-Grade UX (monitor_telemetria.php)
   ---------------------------------------------------------------------
   Extiende el sistema de la FASE 69.15 de arriba: el "Diagnóstico
   Amigable" pasa a ser el titular de cada evento (grande, en español),
   el hito técnico baja a un detalle secundario, y el JSON crudo se
   traslada del <pre> inline a un modal dedicado — mismo patrón visual
   .modal-overlay/.modal-panel ya usado en el resto del CRM (ver
   clientes.php/mi_progreso.php), en una variante más ancha para código.
   ===================================================================== */

/* ----- Filtros avanzados: Usuario (texto) + Severidad (select), a la
   par del selector de fecha ya existente — instantáneos, 100% client-side
   sobre lo ya cargado, sin ida y vuelta al servidor. ----- */
.telemetria-filtro-busqueda {
    position: relative;
    display: flex;
    align-items: center;
}

.telemetria-filtro-busqueda svg {
    position: absolute;
    left: 11px;
    width: 14px;
    height: 14px;
    color: var(--texto-secundario);
    pointer-events: none;
}

.telemetria-filtro-busqueda input[type="text"] {
    padding-left: 32px;
}

/* ----- Semáforo por comercial: reutiliza .telemetria-dot--info/warning/
   error (mismo verde/amarillo/rojo ya aprobado) como punto de estado
   junto al nombre, calculado server-side sobre la categoría amigable de
   CADA hito del día (ver ajax/get_telemetria.php), no solo el nivel
   crudo — así un GPS apagado (nivel=ERROR, categoría=Usuario) no pinta
   a alguien de rojo "Falla Crítica" sin serlo. ----- */
.telemetria-tarjeta-comercial-semaforo {
    flex-shrink: 0;
}

.telemetria-lista-comerciales .sin-datos--filtro {
    padding: 20px 10px;
}

/* ----- Badge de categoría amigable: mismo titular en la tarjeta del
   evento y dentro del modal de detalles técnicos. ----- */
.telemetria-categoria-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    white-space: nowrap;
}

.telemetria-categoria-badge--exito     { background: rgba(124, 199, 80, 0.16); color: #5a8f39; }
.telemetria-categoria-badge--ambiental { background: rgba(224, 169, 76, 0.18); color: #c98a2e; }
.telemetria-categoria-badge--usuario   { background: rgba(99, 143, 224, 0.18); color: #3d6fd6; }
.telemetria-categoria-badge--critica   { background: rgba(224, 82, 82, 0.16); color: #e05252; }

body[data-theme="dark"] .telemetria-categoria-badge--exito   { color: #7cc750; }
body[data-theme="dark"] .telemetria-categoria-badge--usuario { color: #7ea3f2; }

/* ----- Diagnóstico Amigable: el titular real de cada evento — el hito
   técnico crudo (.telemetria-evento-hito) baja de prioridad visual. ----- */
.telemetria-evento-cabecera {
    align-items: center;
}

.telemetria-diagnostico {
    margin: 8px 0 2px;
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--texto-principal);
}

.telemetria-evento-hito-tecnico {
    font-size: 0.7rem;
    font-family: 'Courier New', monospace;
    color: var(--texto-secundario);
    background: var(--bg-input);
    border: 1px solid var(--borde-sutil);
    border-radius: 6px;
    padding: 1px 6px;
}

.telemetria-btn-contexto {
    border-color: rgba(var(--color-acento-rgb), 0.35);
    color: var(--color-acento);
}

/* ----- Modal "Ver Detalles Técnicos": mismo .modal-overlay/.modal-panel
   de siempre, en una variante más ancha para leer JSON cómodamente. ----- */
.telemetria-modal-panel {
    max-width: 640px;
}

.telemetria-modal-cuerpo {
    padding: 18px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* ----- FASE 92 — Human-Readable Telemetry Translator -----
   Badge de categoría, centrado arriba de las 2 secciones de texto llano. */
#telemetriaModalBadgeWrap {
    display: flex;
    justify-content: center;
}

/* "Diagnóstico Sencillo" / "Posible Solución": mismo layout de tarjeta,
   acento de color distinto (neutro/azul = qué pasó, verde = qué hacer) —
   siempre lo PRIMERO que ve gerencia, antes de cualquier dato técnico. */
.telemetria-modal-seccion {
    padding: 14px 16px;
    border-radius: 14px;
    border: 1px solid var(--borde-sutil);
    background: var(--bg-input);
}

.telemetria-modal-seccion h3 {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0 0 6px;
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.telemetria-modal-seccion h3 svg { width: 15px; height: 15px; flex-shrink: 0; }

.telemetria-modal-seccion p {
    margin: 0;
    font-size: 0.94rem;
    line-height: 1.5;
    color: var(--texto-principal);
}

.telemetria-modal-seccion--diagnostico {
    border-left: 4px solid #3d6fd6;
}
.telemetria-modal-seccion--diagnostico h3 { color: #3d6fd6; }

.telemetria-modal-seccion--solucion {
    border-left: 4px solid #5a8f39;
}
.telemetria-modal-seccion--solucion h3 { color: #5a8f39; }

body[data-theme="dark"] .telemetria-modal-seccion--diagnostico h3 { color: #7ea3f2; }
body[data-theme="dark"] .telemetria-modal-seccion--diagnostico { border-left-color: #7ea3f2; }
body[data-theme="dark"] .telemetria-modal-seccion--solucion h3 { color: #7cc750; }
body[data-theme="dark"] .telemetria-modal-seccion--solucion { border-left-color: #7cc750; }

/* "Ver Código Técnico (Solo Programadores)": <details> nativo, plegado por
   defecto (ver abrirModalDetalle() en js/monitor_telemetria.js) — mismo
   contenido de siempre (ficha + JSON), solo que ya no es lo primero que se ve. */
.telemetria-modal-tecnico {
    border: 1px dashed var(--borde-sutil);
    border-radius: 12px;
    padding: 10px 14px;
}

.telemetria-modal-tecnico summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--texto-secundario);
    list-style: none;
}

.telemetria-modal-tecnico summary::-webkit-details-marker { display: none; }

.telemetria-modal-tecnico summary svg { width: 14px; height: 14px; }

.telemetria-modal-tecnico[open] summary { margin-bottom: 12px; }

.telemetria-modal-tecnico-cuerpo {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.telemetria-modal-ficha {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px;
}

.telemetria-modal-ficha-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.telemetria-modal-ficha-item span:first-child {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--texto-secundario);
    font-weight: 600;
}

.telemetria-modal-ficha-item span:last-child {
    font-size: 0.82rem;
    color: var(--texto-principal);
    word-break: break-word;
}

.telemetria-modal-json-titulo {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--texto-secundario);
}

.telemetria-modal-json-titulo svg { width: 14px; height: 14px; }

.telemetria-modal-json {
    background: var(--bg-fondo);
    border: 1px solid var(--borde-sutil);
    border-radius: 10px;
    padding: 14px;
    font-size: 0.78rem;
    font-family: 'Courier New', monospace;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 320px;
    overflow-y: auto;
    color: var(--texto-principal);
}

/* =====================================================================
   FASE 84 — Directorio 360° (directorio_360.php) + Historial Expandido
   con Lazy-Loaded Media (mi_panel_comercial.php). Reutiliza el shell
   .visita-shell/.visita-topbar/.visita-main y .campo-input-wrap ya
   existentes — solo se agregan los componentes nuevos: buscador global,
   tarjetas de resultado, la hoja inferior de la Ficha Clínica, la línea
   de tiempo paginada, los bloques de fotos lazy y el lightbox.
   ===================================================================== */

/* Spinner chico — mismo giro que .visita-spinner pero para usarse
   inline junto a texto ("Buscando...", "Cargando más..."). */
.visita-spinner-chico {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid rgba(var(--color-acento-rgb), 0.25);
    border-top-color: var(--color-acento);
    animation: girar-spin 0.8s linear infinite;
    vertical-align: -2px;
    margin-right: 4px;
}

/* ----- Buscador global ----- */
.d360-buscador-card { display: flex; flex-direction: column; gap: 8px; }
.d360-ayuda-busqueda { font-size: 0.75rem; color: var(--texto-secundario); margin: 0; }

.d360-resultados { display: flex; flex-direction: column; gap: 8px; }

.d360-resultado-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 12px;
    border-radius: 14px;
    background: var(--bg-panel);
    backdrop-filter: var(--blur-glass);
    -webkit-backdrop-filter: var(--blur-glass);
    border: 1px solid var(--borde-inner-glow);
    box-shadow: var(--sombra-panel);
    text-align: left;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    font-family: inherit;
    color: inherit;
}
.d360-resultado-item:active { transform: scale(0.98); }

.d360-resultado-icono {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
    flex-shrink: 0;
}
.d360-resultado-icono i { width: 18px; height: 18px; }

.d360-resultado-textos { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.d360-resultado-textos strong { font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.d360-resultado-textos small { font-size: 0.75rem; color: var(--texto-secundario); }
.d360-resultado-asignado { color: var(--color-acento) !important; font-weight: 600; }

.d360-resultado-chevron { width: 18px; height: 18px; color: var(--texto-secundario); flex-shrink: 0; }

/* ----- Ficha Clínica: Hoja Inferior (Bottom Sheet nativo) -----
   Deliberadamente NO reutiliza .modal-overlay/.modal-panel (centrado,
   pensado para escritorio): en un celular en la calle, una hoja que
   sube desde el borde inferior y se desliza con el pulgar para cerrar
   se siente como una app nativa — el patrón que pide el enunciado de
   Fase 2 en vez de un modal clásico. */
.d360-hoja-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 600; /* por encima de .visita-shell y de cualquier otro overlay del módulo de campo */
    display: flex;
    align-items: flex-end;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.28s ease;
}
.d360-hoja-overlay.activa { opacity: 1; }
.d360-hoja-overlay[hidden] { display: none; }

.d360-hoja {
    width: 100%;
    max-width: 480px; /* mismo ancho de referencia que .visita-shell */
    max-height: 88vh;
    background: var(--bg-panel-solido);
    border-radius: 22px 22px 0 0;
    box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.25);
    display: flex;
    flex-direction: column;
    transform: translateY(100%);
    transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
    overscroll-behavior: contain;
}
.d360-hoja-overlay.activa .d360-hoja { transform: translateY(0); }

.d360-hoja-handle {
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: var(--borde-sutil);
    margin: 10px auto 2px;
    flex-shrink: 0;
    touch-action: none;
}

.d360-hoja-header {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 6px 16px 10px;
    border-bottom: 1px solid var(--borde-sutil);
    flex-shrink: 0;
}
.d360-hoja-header-textos { flex: 1; min-width: 0; }
.d360-hoja-header-textos h2 {
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0 0 6px;
    overflow-wrap: break-word;
}

.d360-hoja-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.d360-chip {
    font-size: 0.68rem;
    font-weight: 600;
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--bg-buscador);
    color: var(--texto-secundario);
}
.d360-chip-acento { background: rgba(var(--color-acento-rgb), 0.14); color: var(--color-acento); }

.d360-hoja-datos {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--borde-sutil);
    flex-shrink: 0;
}
.d360-hoja-dato { display: flex; align-items: center; gap: 8px; font-size: 0.82rem; color: var(--texto-principal); }
.d360-hoja-dato i { width: 15px; height: 15px; color: var(--color-acento); flex-shrink: 0; }

.d360-hoja-body { overflow-y: auto; padding: 14px 16px 26px; flex: 1; }

.d360-timeline-titulo {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--texto-secundario);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 12px;
}
.d360-timeline-titulo i { width: 15px; height: 15px; color: var(--color-acento); }
.d360-timeline-total { font-weight: 500; text-transform: none; letter-spacing: normal; }

/* ----- Línea de tiempo ----- */
.d360-timeline { display: flex; flex-direction: column; gap: 10px; }

.d360-timeline-item {
    display: flex;
    gap: 10px;
    padding: 10px;
    border-radius: 14px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-sutil);
}
.d360-timeline-item--cancelada { opacity: 0.65; }

.d360-timeline-icono {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--color-acento-rgb), 0.12);
    color: var(--color-acento);
    flex-shrink: 0;
}
.d360-timeline-icono i { width: 15px; height: 15px; }

.d360-timeline-contenido { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }

.d360-timeline-cabecera {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    background: none;
    border: none;
    padding: 0;
    text-align: left;
    font-family: inherit;
    color: inherit;
    cursor: default;
}
.d360-timeline-cabecera[data-toggle-fotos]:not([data-toggle-fotos=""]) { cursor: pointer; }

.d360-timeline-cabecera-textos { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.d360-timeline-cabecera-textos strong { font-size: 0.85rem; }
.d360-timeline-cabecera-textos small { font-size: 0.73rem; color: var(--texto-secundario); }

.d360-timeline-chevron {
    width: 16px;
    height: 16px;
    color: var(--texto-secundario);
    flex-shrink: 0;
    transition: transform 0.2s ease;
}
.d360-timeline-chevron--abierto { transform: rotate(180deg); }

.d360-timeline-comentario {
    font-size: 0.78rem;
    color: var(--texto-principal);
    opacity: 0.85;
    margin: 0;
}

.d360-acciones-wrap { display: flex; flex-wrap: wrap; gap: 5px; }
.d360-accion-chip {
    font-size: 0.66rem;
    font-weight: 600;
    padding: 2px 7px;
    border-radius: 999px;
    background: rgba(var(--color-acento-rgb), 0.1);
    color: var(--color-acento);
}

.d360-timeline-fin {
    text-align: center;
    font-size: 0.75rem;
    color: var(--texto-secundario);
    padding: 10px 0 0;
    margin: 0;
}
.d360-timeline-centinela { text-align: center; font-size: 0.75rem; color: var(--texto-secundario); min-height: 4px; }

/* ----- Fotos lazy-loaded (dentro de una tarjeta de línea de tiempo) ----- */
.d360-fotos-wrap {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 8px;
    margin-top: 2px;
}
.d360-fotos-skeleton {
    grid-column: 1 / -1;
    font-size: 0.75rem;
    color: var(--texto-secundario);
    padding: 8px 0;
}
.d360-fotos-vacio { grid-column: 1 / -1; font-size: 0.75rem; color: var(--texto-secundario); margin: 0; }

.d360-foto-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    font-family: inherit;
}
.d360-foto-item img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 10px;
    border: 1px solid var(--borde-sutil);
    background: var(--bg-buscador);
}
.d360-foto-item span {
    font-size: 0.62rem;
    color: var(--texto-secundario);
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ----- Lightbox de foto a pantalla completa ----- */
.d360-lightbox {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.92);
    z-index: 700; /* por encima de .d360-hoja-overlay */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.d360-lightbox[hidden] { display: none; }
.d360-lightbox img { max-width: 100%; max-height: 100%; border-radius: 8px; object-fit: contain; }
.d360-lightbox-cerrar {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    border: none;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
.d360-lightbox-cerrar i { width: 20px; height: 20px; }

/* ----- FASE 84 — mi_panel_comercial.php: Historial Expandido -----
   .panelcom-item-historial pasa de <div> estático a <button> expandible
   — mismo look de .visita-item-historial, con un chevron que solo
   aparece cuando esa visita tiene evidencia fotográfica
   (tiene_fotos=true, ver ajax/get_mi_historial_visitas.php). */
.panelcom-item-historial {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
}

.panelcom-item-historial-fila {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    background: none;
    border: none;
    padding: 0;
    text-align: left;
    font-family: inherit;
    color: inherit;
    cursor: default;
}
.panelcom-item-historial-fila--expandible { cursor: pointer; }

.panelcom-item-chevron {
    width: 16px;
    height: 16px;
    color: var(--texto-secundario);
    flex-shrink: 0;
    transition: transform 0.2s ease;
}
.panelcom-item-chevron--abierto { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
    .d360-hoja, .d360-timeline-chevron, .panelcom-item-chevron { transition: none !important; }
}

/* =========================================================
   FASE 90 — WMS "Single Box Identity": componentes compartidos por
   inventario_dashboard.php, inventario_ingreso.php,
   inventario_lote_detalle.php, inventario_solicitudes.php e
   inventario_picking.php. Reutilizan .gerencia-shell/.gerencia-panel/
   .gerencia-tabla/.modal-overlay (ya establecidos) — solo lo específico
   de "caja física" e "identidad de lote" vive acá.
   ========================================================= */

/* Estado de una caja física (cajas_inventario.estado). */
.badge-caja-en-bodega  { background: rgba(99, 159, 56, 0.18); color: #7cc750; }
.badge-caja-produccion { background: rgba(230, 184, 0, 0.18); color: #e6b800; }
.badge-caja-vendido    { background: rgba(71, 85, 105, 0.18); color: #64748b; }

/* Estado de una solicitud de producción (solicitudes_produccion.estado). */
.badge-solicitud-activa     { background: rgba(61, 123, 253, 0.16); color: #3d7bfd; }
.badge-solicitud-completada { background: rgba(99, 159, 56, 0.18); color: #7cc750; }
.badge-solicitud-cancelada  { background: rgba(200, 80, 80, 0.18); color: #e08080; }

/* Código de Registro Maestro ('ING-1045'): protagonista visual de
   inventario_ingreso.php justo tras crear el grupo — es lo que la
   persona va a copiar/imprimir en el DLabel de las cajas. */
.wms-codigo-maestro {
    font-family: 'Courier New', monospace;
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    color: var(--color-acento);
}

/* Tarjeta de desglose por ubicación física (View 2 — Batch Detail). */
.wms-ubicacion-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-radius: 12px;
    background: var(--fondo-tarjeta, rgba(0, 0, 0, 0.03));
    border: 1px solid var(--borde-suave, rgba(0, 0, 0, 0.06));
}
.wms-ubicacion-item + .wms-ubicacion-item { margin-top: 8px; }
.wms-ubicacion-item-nombre { font-weight: 600; }
.wms-ubicacion-item-cantidad { font-weight: 700; color: var(--color-acento); }

body[data-theme="dark"] .wms-ubicacion-item {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.08);
}

/* Panel de resultado tras crear un Registro Maestro (inventario_ingreso.php)
   o de confirmación de picking (inventario_picking.php) — protagoniza el
   código generado, con espacio propio para no competir con el formulario. */
.wms-resultado-panel {
    margin-top: 20px;
    padding: 20px;
    border-radius: 14px;
    background: rgba(var(--color-acento-rgb), 0.06);
    border: 1px solid rgba(var(--color-acento-rgb), 0.18);
    text-align: center;
}
.wms-resultado-panel[hidden] { display: none; }
.wms-resultado-panel .gerencia-topbar-acciones {
    justify-content: center;
    margin-top: 12px;
}

/* Bloque "Generar Etiquetas QR" dentro del panel de éxito de
   inventario_ingreso.php — separado del código maestro con su propio
   borde superior para no competir visualmente con él. */
.wms-panel-etiquetas {
    margin-top: 18px;
    padding-top: 18px;
    border-top: 1px dashed rgba(var(--color-acento-rgb), 0.25);
}
.wms-etiquetas-form {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 10px;
}
.wms-etiquetas-form .campo { flex: 0 0 auto; text-align: left; }
.wms-etiquetas-form input[type="number"] {
    width: 140px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid rgba(0, 0, 0, 0.12);
    font-size: 15px;
    font-weight: 700;
    font-family: inherit;
    color: var(--texto-principal, inherit);
    background: var(--fondo-tarjeta, #fff);
}
.wms-etiquetas-form .btn-submit { width: auto; margin: 0; white-space: nowrap; }

/* Botón "Imprimir etiquetas" por fila en la tabla de Últimos Registros
   Maestro (reimpresión de un lote ya creado). */
.btn-imprimir-fila {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 8px;
    background: rgba(var(--color-acento-rgb), 0.1);
    color: var(--color-acento);
    text-decoration: none;
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
}
.btn-imprimir-fila:hover { background: rgba(var(--color-acento-rgb), 0.18); }
.btn-imprimir-fila svg { width: 14px; height: 14px; }

/* =========================================================================
   FASE 99 — admin_monitoreo_dispositivos.php ("Rescate Quirúrgico" Dashboard)
   Reutiliza .gerencia-shell/.gerencia-topbar/.bi-card/.sin-datos/.spin ya
   existentes (mismo criterio que monitor_telemetria.php) — solo se agregan
   las clases propias de la grilla de tarjetas y el semáforo de 4 estados
   (verde/amarillo/rojo/gris — el "gris" de desconectado es propio de este
   panel, monitor_telemetria.php no lo necesita).
   ========================================================================= */

.dispositivos-auto-refresh {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--texto-secundario);
    padding: 6px 10px;
    border-radius: 20px;
    background: var(--bg-panel-alt);
    border: 1px solid var(--borde-glass);
}
.dispositivos-auto-refresh i { width: 13px; height: 13px; color: #7cc750; }

.dispositivos-leyenda {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    padding: 10px 4px 4px;
    font-size: 0.8rem;
    color: var(--texto-secundario);
}
.dispositivos-leyenda-item { display: inline-flex; align-items: center; gap: 6px; }

.dispositivos-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}
.dispositivos-dot--rojo     { background: #e05252; }
.dispositivos-dot--amarillo { background: #e0a94c; }
.dispositivos-dot--verde    { background: #7cc750; }
.dispositivos-dot--gris     { background: #9aa1ac; }

.dispositivos-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 16px;
    margin-top: 10px;
}

.dispositivos-card--rojo     { border-color: rgba(224, 82, 82, 0.4); }
.dispositivos-card--amarillo { border-color: rgba(224, 169, 76, 0.4); }
.dispositivos-card--gris     { opacity: 0.68; }

.dispositivos-card-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}
.dispositivos-card-header h3 { margin: 0; font-size: 0.95rem; flex: 1 1 auto; }

.dispositivos-badge-linea {
    font-size: 0.7rem;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 20px;
    white-space: nowrap;
}
.dispositivos-badge-linea.en-linea    { background: rgba(124, 199, 80, 0.16); color: #5a8f39; }
.dispositivos-badge-linea.fuera-linea { background: rgba(154, 161, 172, 0.18); color: var(--texto-secundario); }

.dispositivos-card-cuerpo {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 12px;
}
.dispositivos-metrica {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.82rem;
    color: var(--texto-principal);
}
.dispositivos-metrica i { width: 15px; height: 15px; flex-shrink: 0; color: var(--texto-secundario); }
.dispositivos-metrica span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dispositivos-detalle-hardware {
    font-size: 0.74rem;
    color: #c98a2e;
    background: rgba(224, 169, 76, 0.12);
    padding: 6px 8px;
    border-radius: 8px;
    margin-top: 2px;
}

.dispositivos-btn-rescate {
    width: 100%;
    justify-content: center;
}
.dispositivos-btn-rescate:disabled { opacity: 0.65; cursor: not-allowed; }

/* ----- FASE 99 (Task 2) — "Asistente de Soluciones": el guion exacto que
   el admin puede copiar/pegar por WhatsApp, un color por urgencia — mismo
   trío que el semáforo de arriba (rojo=crítico, ámbar=advertencia), más un
   azul informativo propio para "sin señal" (no es una falla, no amerita
   el mismo rojo/ámbar de "algo anda mal con el hardware"). ----- */
.dispositivos-tip {
    font-size: 0.78rem;
    line-height: 1.4;
    padding: 8px 10px;
    border-radius: 10px;
    margin-bottom: 10px;
    border-left: 3px solid transparent;
}
.dispositivos-tip--critico  { background: rgba(224, 82, 82, 0.12);  border-left-color: #e05252; color: #b3453f; }
.dispositivos-tip--offline  { background: rgba(90, 140, 220, 0.12); border-left-color: #5a8cdc; color: #3d6bb3; }
.dispositivos-tip--bateria  { background: rgba(224, 169, 76, 0.14); border-left-color: #e0a94c; color: #a4711f; }
body[data-theme="dark"] .dispositivos-tip--critico { color: #ff8f87; }
body[data-theme="dark"] .dispositivos-tip--offline { color: #9dc0f5; }
body[data-theme="dark"] .dispositivos-tip--bateria { color: #f0c581; }
