@charset "UTF-8";
/* ===========================================================================
   SERVICES DESK iTOUCH — hoja de estilo única del sistema
   ---------------------------------------------------------------------------
   Cubre las tres caras del sistema: panel del agente, portal del cliente y
   pantallas de acceso. No hay librerías ni webfonts: todo se apoya en la
   tipografía del sistema operativo para que la carga sea inmediata aun con
   conexiones malas (muchos clientes entran desde el celular en sitio).

   Orden de las secciones
     01. Variables y paleta (modo claro)
     02. Modo oscuro (SOLO variables, nunca reglas sueltas)
     03. Reset moderno
     04. Tipografía base
     05. Utilidades
     06. Cascarón: .app / .lateral / .principal / .topbar / .contenido
     07. Página, migas y encabezados
     08. Tarjetas
     09. Rejillas y flex
     10. Botones
     11. Formularios
     12. Tablas
     13. Elementos sueltos (chip, badge, avatar, aviso, pill…)
     14. Paginación
     15. Tickets (.tk-*)
     16. Componentes de app.js (modal, autocompletar, editor, adjuntos…)
     17. Configuración y pestañas
     18. Portal del cliente
     19. Pantallas de acceso y páginas de error
     20. Reportes y tablero
     21. Responsivo (<=900px y <=600px)
     22. Impresión
   ======================================================================== */


/* ===========================================================================
   01. VARIABLES Y PALETA (modo claro)
   La paleta viene del tema real de itouch.mx. Se declara TODO aquí, incluidas
   las variables "semánticas" (--txt, --sup, --borde…), porque el modo oscuro
   se resuelve redefiniendo únicamente estos valores.
   ======================================================================== */
:root {
    /* --- marca -------------------------------------------------------- */
    --marca: #1e9fd4;          /* turquesa del logo */
    --marca-600: #1786b8;
    --marca-100: #dff3ff;
    --navy: #0a2b3d;
    --navy-2: #0e3a50;
    --oro: #efa524;
    --oro-2: #f6d34b;
    --verde: #2e9e43;
    --vino: #8c1d40;
    --rojo: #cf2e2e;

    /* --- neutros ------------------------------------------------------ */
    --tinta: #0f2733;
    --pizarra: #48606c;
    --tenue: #6b8290;
    --linea: #e3ecf1;
    --fondo: #f2f9fc;
    --papel: #ffffff;

    /* --- geometría ---------------------------------------------------- */
    --radio: 12px;
    --radio-lg: 18px;
    --radio-sm: 8px;
    --radio-pill: 999px;
    --sombra-sm: 0 2px 10px rgba(10, 43, 61, .07);
    --sombra: 0 12px 40px rgba(10, 43, 61, .12);
    --sombra-modal: 0 24px 70px rgba(10, 43, 61, .28);

    /* --- alias semánticos (lo que usan las reglas de abajo) ----------- */
    --txt: var(--tinta);
    --txt-2: var(--pizarra);
    --txt-3: var(--tenue);
    --bg: var(--fondo);
    --sup: var(--papel);           /* superficie principal: tarjetas, tablas */
    --sup-2: #f7fbfd;              /* superficie hundida: cabeceras, rayas   */
    --sup-3: #eef6fa;              /* superficie de realce: hover de filas   */
    --borde: var(--linea);
    --borde-fuerte: #cddde6;
    --enlace: var(--marca-600);
    --anillo: rgba(30, 159, 212, .45);   /* anillo de foco accesible */
    /* Tinta que va ENCIMA del color de marca (botón primario, badge, selección).
       En claro el turquesa es oscuro y pide blanco encima; en modo oscuro el
       turquesa se aclara y el blanco encima se pierde, así que ahí va tinta
       oscura. Es lo mismo que hacen los temas oscuros de iOS y de Material. */
    --marca-texto: #ffffff;
    /* La paloma de las casillas va del color de --marca-texto; como vive
       dentro de un SVG incrustado, viaja como variable y no como regla. */
    --casilla-paloma: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5'/%3E%3C/svg%3E");
    --casilla-guion: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' stroke='%23fff' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M4 8h8'/%3E%3C/svg%3E");

    /* --- barra lateral ------------------------------------------------ */
    --lat-ancho: 248px;
    --lat-fondo: var(--navy);
    --lat-fondo-2: var(--navy-2);
    --lat-texto: #c9e3f0;
    --lat-texto-2: #8fb2c4;
    --lat-activo: rgba(30, 159, 212, .22);
    --lat-borde: rgba(255, 255, 255, .08);

    /* --- barra superior ----------------------------------------------- */
    --top-alto: 62px;
    --top-fondo: rgba(255, 255, 255, .88);

    /* --- estados suaves (fondos de avisos y chips) -------------------- */
    --ok-fondo: #e6f6ea;   --ok-borde: #bfe6c9;   --ok-texto: #1c6c2c;
    --err-fondo: #fdecec;  --err-borde: #f4c9c9;  --err-texto: #a12020;
    --info-fondo: #e6f4fc; --info-borde: #c3e4f5; --info-texto: #135e80;
    --ale-fondo: #fdf3e0;  --ale-borde: #f3ddb0;  --ale-texto: #8a5a06;
    --nota-fondo: #fff8e6; --nota-borde: #f0dca6; /* burbuja de nota privada */

    /* --- tipografía --------------------------------------------------- */
    --fuente: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
              "Helvetica Neue", Arial, "Noto Sans", sans-serif,
              "Apple Color Emoji", "Segoe UI Emoji";
    --fuente-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
                   "Liberation Mono", monospace;

    /* --- movimiento ---------------------------------------------------- */
    --trans: 140ms ease;
    --trans-rapida: 120ms ease;
    --trans-lenta: 160ms ease;

    color-scheme: light;
}


/* ===========================================================================
   02. TEMA CLARO Y OSCURO
   Tres estados, y en este orden de mando:
     1. :root                          -> claro, el punto de partida
     2. sistema en oscuro              -> oscuro, salvo que la persona haya
                                          elegido claro a mano
     3. data-tema="oscuro" en <html>   -> oscuro pase lo que pase
   Se redefinen SOLO variables: cualquier regla nueva de color debe apoyarse en
   una variable para no tener que duplicarse aquí.
   El conmutador vive en la barra superior y recuerda la elección en el propio
   navegador de cada quien (sd.tema en app.js).
   ======================================================================== */
@media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) {
        --marca: #38b4e6;
        --marca-600: #61c6f0;
        --marca-100: #10323f;
        --navy: #071620;
        --navy-2: #0c2634;
        --oro: #f2b54a;
        --oro-2: #f8dd7c;
        --verde: #47b85e;
        --vino: #c05c81;
        --rojo: #ec6060;

        --tinta: #e7f2f8;
        --pizarra: #a9c1ce;
        --tenue: #7f98a6;
        --linea: #1d3b4a;
        --fondo: #081720;
        --papel: #0e2632;

        --sup-2: #12303e;
        --sup-3: #17394a;
        --borde-fuerte: #2a5165;
        --enlace: #6cc9f2;
        --anillo: rgba(56, 180, 230, .55);
        --marca-texto: #06222f;
        --casilla-paloma: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2306222f' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5'/%3E%3C/svg%3E");
        --casilla-guion: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' stroke='%2306222f' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M4 8h8'/%3E%3C/svg%3E");

        --sombra-sm: 0 2px 10px rgba(0, 0, 0, .38);
        --sombra: 0 14px 44px rgba(0, 0, 0, .48);
        --sombra-modal: 0 26px 80px rgba(0, 0, 0, .62);

        --lat-fondo: #061219;
        --lat-fondo-2: #0a2029;
        --lat-texto: #bcd8e6;
        --lat-texto-2: #7e9dae;
        --lat-activo: rgba(56, 180, 230, .20);
        --lat-borde: rgba(255, 255, 255, .06);

        --top-fondo: rgba(14, 38, 50, .88);

        --ok-fondo: #102c1a;   --ok-borde: #23522f;   --ok-texto: #86d99a;
        --err-fondo: #341415;  --err-borde: #5e2426;  --err-texto: #f0a0a0;
        --info-fondo: #0d2c3b; --info-borde: #1d4d64; --info-texto: #93d3ef;
        --ale-fondo: #33260c;  --ale-borde: #5b451a;  --ale-texto: #f0c877;
        --nota-fondo: #2c2510; --nota-borde: #574a1f;

        color-scheme: dark;
    }
}

/* La elección manual gana sobre lo que diga el sistema, en los dos sentidos. */
:root[data-tema="oscuro"] {
        --marca: #38b4e6;
        --marca-600: #61c6f0;
        --marca-100: #10323f;
        --navy: #071620;
        --navy-2: #0c2634;
        --oro: #f2b54a;
        --oro-2: #f8dd7c;
        --verde: #47b85e;
        --vino: #c05c81;
        --rojo: #ec6060;

        --tinta: #e7f2f8;
        --pizarra: #a9c1ce;
        --tenue: #7f98a6;
        --linea: #1d3b4a;
        --fondo: #081720;
        --papel: #0e2632;

        --sup-2: #12303e;
        --sup-3: #17394a;
        --borde-fuerte: #2a5165;
        --enlace: #6cc9f2;
        --anillo: rgba(56, 180, 230, .55);
        --marca-texto: #06222f;
        --casilla-paloma: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2306222f' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5'/%3E%3C/svg%3E");
        --casilla-guion: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' stroke='%2306222f' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M4 8h8'/%3E%3C/svg%3E");

        --sombra-sm: 0 2px 10px rgba(0, 0, 0, .38);
        --sombra: 0 14px 44px rgba(0, 0, 0, .48);
        --sombra-modal: 0 26px 80px rgba(0, 0, 0, .62);

        --lat-fondo: #061219;
        --lat-fondo-2: #0a2029;
        --lat-texto: #bcd8e6;
        --lat-texto-2: #7e9dae;
        --lat-activo: rgba(56, 180, 230, .20);
        --lat-borde: rgba(255, 255, 255, .06);

        --top-fondo: rgba(14, 38, 50, .88);

        --ok-fondo: #102c1a;   --ok-borde: #23522f;   --ok-texto: #86d99a;
        --err-fondo: #341415;  --err-borde: #5e2426;  --err-texto: #f0a0a0;
        --info-fondo: #0d2c3b; --info-borde: #1d4d64; --info-texto: #93d3ef;
        --ale-fondo: #33260c;  --ale-borde: #5b451a;  --ale-texto: #f0c877;
        --nota-fondo: #2c2510; --nota-borde: #574a1f;

        color-scheme: dark;
}

/* Conmutador de tema en la barra superior y en la cabecera del portal. */
.tema-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border: 1px solid var(--borde); border-radius: var(--radio-sm);
    background: var(--sup); color: var(--txt-2); cursor: pointer; transition: var(--trans);
}
.tema-btn:hover { background: var(--sup-2); color: var(--txt); }
.tema-btn:focus-visible { outline: 3px solid var(--anillo); outline-offset: 2px; }
/* Se enseña el icono del tema al que se va a cambiar, no el actual. */
.tema-btn .ico-luna { display: none; }
.tema-btn .ico-sol { display: block; }
@media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) .tema-btn .ico-luna { display: block; }
    :root:not([data-tema="claro"]) .tema-btn .ico-sol { display: none; }
}
:root[data-tema="oscuro"] .tema-btn .ico-luna { display: block; }
:root[data-tema="oscuro"] .tema-btn .ico-sol { display: none; }
:root[data-tema="claro"] .tema-btn .ico-luna { display: none; }
:root[data-tema="claro"] .tema-btn .ico-sol { display: block; }


/* ===========================================================================
   03. RESET MODERNO
   ======================================================================== */
*,
*::before,
*::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd,
ul, ol, pre { margin: 0; }

ul[class], ol[class] { list-style: none; padding: 0; }

body {
    min-height: 100vh;
    margin: 0;
    background: var(--bg);
    color: var(--txt);
    font-family: var(--fuente);
    font-size: 15px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

img, picture, svg, video, canvas {
    display: block;
    max-width: 100%;
}

svg { flex: none; }

/* Los iconos van en bloque por el reset de arriba, que es lo que conviene en
   botones y menús (todos son flex). Pero dentro de un texto corrido —el título
   de una tarjeta, una celda, una etiqueta— un elemento de bloque parte el
   renglón y el icono se queda flotando encima de las palabras. Aquí se vuelve
   a poner en línea. No hace falta excluir los contenedores flex: dentro de un
   flex el navegador convierte inline-block en block otra vez, así que la regla
   sólo actúa donde de verdad estorbaba. */
:is(h1, h2, h3, h4, h5, h6, p, span, small, strong, b, em, li, td, th,
    label, a, button, legend, figcaption, dt, dd) > svg {
    display: inline-block;
    vertical-align: -.15em;
}

input, button, textarea, select {
    font: inherit;
    color: inherit;
}

button { background: none; border: 0; }

table {
    border-collapse: collapse;
    border-spacing: 0;
}

hr {
    border: 0;
    border-top: 1px solid var(--borde);
    margin: 16px 0;
}

/* Quien pide menos movimiento, no recibe animaciones. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Foco visible uniforme. Sólo con teclado, para no ensuciar el ratón. */
:focus-visible {
    outline: 2px solid var(--anillo);
    outline-offset: 2px;
    border-radius: var(--radio-sm);
}
:focus:not(:focus-visible) { outline: none; }

::selection {
    background: var(--marca);
    color: var(--marca-texto);
}

/* Barras de desplazamiento discretas donde el navegador lo permite. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--borde-fuerte) transparent;
}
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--borde-fuerte);
    border: 3px solid transparent;
    background-clip: content-box;
    border-radius: var(--radio-pill);
}
::-webkit-scrollbar-thumb:hover { background-color: var(--tenue); background-clip: content-box; }


/* ===========================================================================
   04. TIPOGRAFÍA BASE
   ======================================================================== */
h1, h2, h3, h4 {
    line-height: 1.25;
    font-weight: 700;
    letter-spacing: -.015em;
    color: var(--txt);
}
h1 { font-size: 1.6rem; }
h2 { font-size: 1.28rem; }
h3 { font-size: 1.08rem; }
h4 { font-size: .98rem; }

p + p { margin-top: .7em; }

a {
    color: var(--enlace);
    text-decoration: none;
    transition: color var(--trans-rapida);
}
a:hover { color: var(--marca); text-decoration: underline; }

small { font-size: .82rem; }

code, kbd, samp, pre { font-family: var(--fuente-mono); font-size: .88em; }

kbd {
    display: inline-block;
    padding: 1px 6px;
    border: 1px solid var(--borde-fuerte);
    border-bottom-width: 2px;
    border-radius: 6px;
    background: var(--sup-2);
    font-size: .8em;
}

blockquote {
    margin: .6em 0;
    padding: .3em 0 .3em 14px;
    border-left: 3px solid var(--borde-fuerte);
    color: var(--txt-2);
}

/* Texto oculto pero accesible para lectores de pantalla. */
.solo-lectores {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}


/* ===========================================================================
   05. UTILIDADES
   ======================================================================== */
.oculto { display: none !important; }
[hidden] { display: none !important; }

.centro { text-align: center; }
.derecha { text-align: right; }
.izquierda { text-align: left; }
.ancho-completo { width: 100%; }

.tenue { color: var(--txt-3); }
.mono { font-family: var(--fuente-mono); font-size: .88em; letter-spacing: -.01em; }
.sep { height: 1px; background: var(--borde); margin: 14px 0; border: 0; }

.negrita { font-weight: 700; }
.chico { font-size: .84rem; }
.mayus { text-transform: uppercase; letter-spacing: .06em; font-size: .72rem; font-weight: 700; }
.recortado {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dos-lineas {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.sin-quiebre { white-space: nowrap; }

.mt-1 { margin-top: 6px; }   .mt-2 { margin-top: 12px; }
.mt-3 { margin-top: 20px; }  .mt-4 { margin-top: 32px; }
.mb-1 { margin-bottom: 6px; }  .mb-2 { margin-bottom: 12px; }
.mb-3 { margin-bottom: 20px; } .mb-4 { margin-bottom: 32px; }
.p-1 { padding: 6px; }   .p-2 { padding: 12px; }
.p-3 { padding: 20px; }  .p-4 { padding: 32px; }

/* Visibilidad por tamaño de pantalla; el cambio real ocurre en la sección 21.
   Se usa 'revert' en vez de 'initial' para devolverle al elemento su display
   natural (block, flex del propio marcado…) y no convertirlo en inline. */
.solo-movil { display: none !important; }
.solo-escritorio { display: revert; }

/* Impide el desplazamiento del fondo cuando hay un modal o el cajón abierto. */
.sd-sin-scroll { overflow: hidden !important; }


/* ===========================================================================
   06. CASCARÓN DE LA APLICACIÓN
   .app es una rejilla de dos columnas: lateral fija + área principal con su
   propio scroll. El body NO hace scroll: así la topbar puede quedarse pegada
   y la lista de tickets desplazarse por su cuenta.
   ======================================================================== */
.app {
    display: grid;
    grid-template-columns: var(--lat-ancho) 1fr;
    transition: grid-template-columns var(--trans-lenta);
    min-height: 100vh;
    min-height: 100dvh;
}

/* --- barra lateral ---------------------------------------------------- */
.lateral {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    width: var(--lat-ancho);
    height: 100vh;
    height: 100dvh;
    padding: 0;
    background: var(--lat-fondo);
    border-right: 1px solid var(--lat-borde);
    color: var(--lat-texto);
    overflow: hidden auto;
    z-index: 60;
}

.lateral-logo {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: var(--top-alto);
    padding: 14px 18px;
    border-bottom: 1px solid var(--lat-borde);
    color: #fff;
    font-weight: 800;
    font-size: 1.02rem;
    letter-spacing: -.02em;
    text-decoration: none;
}
.lateral-logo:hover { color: #fff; text-decoration: none; }
.lateral-logo img { max-height: 34px; width: auto; }
.lateral-logo span { color: var(--marca); }
.lateral-logo small {
    display: block;
    color: var(--lat-texto-2);
    font-weight: 500;
    font-size: .72rem;
    letter-spacing: 0;
}

.lateral-nav {
    flex: 1;
    padding: 12px 10px 20px;
    overflow-y: auto;
}
.lateral-nav h6 {
    margin: 16px 10px 6px;
    color: var(--lat-texto-2);
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
}
.lateral-nav a {
    position: relative;
    display: flex;
    align-items: center;
    gap: 11px;
    margin-bottom: 2px;
    padding: 9px 12px;
    border-radius: var(--radio-sm);
    color: var(--lat-texto);
    font-size: .92rem;
    font-weight: 500;
    text-decoration: none;
    transition: background var(--trans-rapida), color var(--trans-rapida);
}
.lateral-nav a svg { opacity: .75; transition: opacity var(--trans-rapida); }
.lateral-nav a:hover {
    background: rgba(255, 255, 255, .07);
    color: #fff;
    text-decoration: none;
}
.lateral-nav a:hover svg { opacity: 1; }
.lateral-nav a:focus-visible { outline-offset: -2px; }
.lateral-nav a.activo {
    background: var(--lat-activo);
    color: #fff;
    font-weight: 600;
}
.lateral-nav a.activo svg { opacity: 1; color: var(--marca); }
/* Marca de la pestaña activa: barrita a la izquierda. */
.lateral-nav a.activo::before {
    content: "";
    position: absolute;
    left: -10px;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--marca);
}
/* Contador de tickets al final del renglón (sd_contadores). */
.lateral-nav a .cuenta {
    margin-left: auto;
    padding: 1px 7px;
    border-radius: var(--radio-pill);
    background: rgba(255, 255, 255, .12);
    color: var(--lat-texto);
    font-size: .72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.lateral-nav a.activo .cuenta { background: var(--marca); color: var(--marca-texto); }

.lateral-pie {
    padding: 12px 14px;
    border-top: 1px solid var(--lat-borde);
    color: var(--lat-texto-2);
    font-size: .76rem;
}
.lateral-pie a { color: var(--lat-texto); }

/* --- columna principal ------------------------------------------------ */
.principal {
    display: flex;
    flex-direction: column;
    min-width: 0;               /* imprescindible: deja encoger a los hijos */
    min-height: 100vh;
    min-height: 100dvh;
}

.topbar {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: var(--top-alto);
    padding: 10px 22px;
    background: var(--top-fondo);
    border-bottom: 1px solid var(--borde);
    backdrop-filter: saturate(160%) blur(10px);
    -webkit-backdrop-filter: saturate(160%) blur(10px);
}

.topbar-buscar {
    position: relative;
    flex: 1;
    max-width: 520px;
}
.topbar-buscar input {
    width: 100%;
    height: 38px;
    padding: 0 14px 0 38px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-pill);
    background: var(--sup);
    color: var(--txt);
    font-size: .92rem;
    transition: border-color var(--trans), box-shadow var(--trans);
}
.topbar-buscar input::placeholder { color: var(--txt-3); }
.topbar-buscar input:focus {
    border-color: var(--marca);
    box-shadow: 0 0 0 3px var(--anillo);
    outline: none;
}
.topbar-buscar svg {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--txt-3);
    pointer-events: none;
}

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

/* Botón hamburguesa: sólo aparece en pantallas chicas (ver sección 21). */
.topbar-menu {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: var(--radio-sm);
    color: var(--txt-2);
}
.topbar-menu:hover { background: var(--sup-3); color: var(--txt); }

.contenido {
    flex: 1;
    min-width: 0;
    padding: 22px;
}
/* Las pantallas de ticket ocupan todo el alto disponible sin doble scroll. */
.contenido.pleno {
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
}


/* ===========================================================================
   07. PÁGINA, MIGAS Y ENCABEZADOS
   ======================================================================== */
.pag {
    max-width: 1360px;
    margin: 0 auto;
}
.pag-angosta { max-width: 820px; }

.pag-cab {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}
.pag-tit {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: -.02em;
}
.pag-sub {
    margin-top: 2px;
    color: var(--txt-3);
    font-size: .9rem;
}
.pag-acciones {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
    flex-wrap: wrap;
}

.migas {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 10px;
    color: var(--txt-3);
    font-size: .82rem;
}
.migas a { color: var(--txt-3); }
.migas a:hover { color: var(--marca); }
.migas li { display: flex; align-items: center; gap: 6px; }
.migas li + li::before {
    content: "›";
    color: var(--borde-fuerte);
}
.migas [aria-current="page"] { color: var(--txt-2); font-weight: 600; }


/* ===========================================================================
   08. TARJETAS
   ======================================================================== */
.tarjeta {
    display: flex;
    flex-direction: column;
    background: var(--sup);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    box-shadow: var(--sombra-sm);
    overflow: hidden;
}
/* Tarjetas apiladas una tras otra en el flujo normal: se separan solas. */
.tarjeta + .tarjeta { margin-top: 16px; }
/* …pero dentro de una rejilla o de una fila NO, porque esos contenedores ya
   separan con «gap» y el margen se convierte en un empujón hacia abajo: la
   segunda tarjeta de la fila quedaba 16 px más baja que la primera y, como las
   rejillas estiran, además 16 px más corta. Se veía en el tablero, en la base
   de conocimiento del portal y en cualquier fila de dos tarjetas. */
.rejilla > .tarjeta + .tarjeta,
.cfg-rejilla > .tarjeta + .tarjeta,
.portal-kb > .tarjeta + .tarjeta,
.tablero-kpis > .tarjeta + .tarjeta,
.opciones-tarjeta > .tarjeta + .tarjeta,
.tk-props > .tarjeta + .tarjeta,
.flex > .tarjeta + .tarjeta { margin-top: 0; }

.tarjeta-cab {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--borde);
    background: var(--sup-2);
}
.tarjeta-tit {
    margin: 0;
    font-size: .98rem;
    font-weight: 700;
    letter-spacing: -.01em;
}
.tarjeta-cab .pag-acciones,
.tarjeta-cab .acciones { margin-left: auto; }

.tarjeta-cuerpo { flex: 1 1 auto; padding: 18px; }
.tarjeta-cuerpo > :first-child { margin-top: 0; }
/* Cuando la tarjeta queda estirada por la rejilla y lo único que tiene dentro
   es el mensaje de «no hay nada», el mensaje se centra en el hueco en vez de
   quedarse arriba dejando medio metro de blanco debajo. */
.tarjeta-cuerpo > .tabla-vacia:only-child {
    display: grid;
    align-content: center;
    height: 100%;
}

.tarjeta-pie {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 18px;
    border-top: 1px solid var(--borde);
    background: var(--sup-2);
}

/* Tarjeta sin relleno: para meter una tabla de borde a borde. */
.tarjeta-lisa .tarjeta-cuerpo { padding: 0; }

/* Tarjeta con dato grande (tablero). */
.tarjeta-dato { padding: 18px; }
.tarjeta-dato .dato {
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -.03em;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.tarjeta-dato .rotulo {
    color: var(--txt-3);
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
}


/* ===========================================================================
   09. REJILLAS Y FLEX
   ======================================================================== */
.rejilla {
    display: grid;
    gap: 16px;
}
.rej-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Dos columnas desiguales: lo que se escribe manda, lo que se configura
   acompaña. En la ficha de una solución, partir la pantalla por la mitad
   deja el editor estrecho y la columna de ajustes medio vacía. */
.rej-2-1 { grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr); }
.rej-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.rej-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.flex { display: flex; align-items: center; gap: 10px; }
.flex-entre { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.flex-fin { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.flex-col { display: flex; flex-direction: column; }
.flex-arriba { align-items: flex-start; }
.flex-envuelve { flex-wrap: wrap; }
.crece { flex: 1; min-width: 0; }
.ml-auto { margin-left: auto; }
/* Fila centrada que se parte sola en pantallas chicas (botonera del portal). */
.flex-centro { display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; }
.lista-limpia { list-style: none; margin: 0; padding: 0; }
.apagado { opacity: .55; }
.caja-scroll { max-height: 340px; overflow: auto; }
/* Punto de color de las leyendas de las gráficas. */
.punto { display: inline-block; width: 12px; height: 12px; border-radius: 3px; background: var(--marca); }
.punto.verde { background: var(--verde); }

/* Anchos de los controles que van dentro de las tablas de configuración.
   Estaban escritos a mano en cada celda; aquí se cambian de una sola vez. */
.ctrl-xs    { width: 3.4rem; }
.ctrl-num   { width: 5rem; }
.ctrl-color { width: 3rem; padding: 2px; }
.ctrl-sm    { min-width: 7.5rem; }
.ctrl-md    { min-width: 7rem; }
.ctrl-lg    { min-width: 9.5rem; }
.bloque     { display: block; }

.gap-sm { gap: 6px; }
.gap-md { gap: 12px; }
.gap-lg { gap: 20px; }


/* ===========================================================================
   10. BOTONES
   ======================================================================== */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 38px;
    padding: 0 16px;
    border: 1px solid transparent;
    border-radius: var(--radio-sm);
    background: var(--sup);
    color: var(--txt);
    font-size: .9rem;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background var(--trans-rapida), border-color var(--trans-rapida),
                color var(--trans-rapida), box-shadow var(--trans-rapida),
                transform var(--trans-rapida);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--anillo); outline-offset: 2px; }
.btn svg { flex: none; }

.btn-primario {
    background: var(--marca);
    border-color: var(--marca);
    color: var(--marca-texto);
    box-shadow: 0 1px 2px rgba(10, 43, 61, .12);
}
.btn-primario:hover { background: var(--marca-600); border-color: var(--marca-600); color: var(--marca-texto); }

.btn-secundario {
    background: var(--sup);
    border-color: var(--borde-fuerte);
    color: var(--txt);
}
.btn-secundario:hover { background: var(--sup-3); border-color: var(--tenue); }

.btn-peligro {
    background: var(--rojo);
    border-color: var(--rojo);
    color: #fff;
}
.btn-peligro:hover { filter: brightness(.93); color: #fff; }

.btn-fantasma {
    background: transparent;
    border-color: transparent;
    color: var(--txt-2);
}
.btn-fantasma:hover { background: var(--sup-3); color: var(--txt); }

.btn-exito { background: var(--verde); border-color: var(--verde); color: #fff; }
.btn-exito:hover { filter: brightness(.94); color: #fff; }

.btn-sm { height: 31px; padding: 0 11px; font-size: .82rem; border-radius: 7px; }
.btn-lg { height: 46px; padding: 0 24px; font-size: 1rem; border-radius: var(--radio); }
.btn-bloque { display: flex; width: 100%; }

.btn-icono {
    width: 38px;
    padding: 0;
    color: var(--txt-2);
    background: transparent;
    border-color: transparent;
}
.btn-icono:hover { background: var(--sup-3); color: var(--txt); }
.btn-icono.btn-sm { width: 31px; }
.btn-icono.peligro:hover { background: var(--err-fondo); color: var(--rojo); }

.btn[disabled],
.btn:disabled,
[disabled] .btn,
button[disabled],
input[disabled],
select[disabled],
textarea[disabled],
fieldset[disabled] .btn {
    opacity: .5;
    cursor: not-allowed;
    pointer-events: none;
    box-shadow: none;
    transform: none;
}
/* Los campos deshabilitados sí deben poder recibir el cursor de "prohibido". */
input[disabled], select[disabled], textarea[disabled] {
    pointer-events: auto;
    background: var(--sup-2);
}

/* Grupo de botones pegados (filtros rápidos). */
.btn-grupo { display: inline-flex; }
.btn-grupo .btn { border-radius: 0; border-color: var(--borde-fuerte); margin-left: -1px; }
.btn-grupo .btn:first-child { border-radius: var(--radio-sm) 0 0 var(--radio-sm); margin-left: 0; }
.btn-grupo .btn:last-child { border-radius: 0 var(--radio-sm) var(--radio-sm) 0; }
.btn-grupo .btn.activo { background: var(--marca-100); border-color: var(--marca); color: var(--marca-600); z-index: 1; }

/* Botón que está esperando una respuesta del servidor. */
.btn.cargando {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}
.btn.cargando::after {
    content: "";
    position: absolute;
    width: 15px; height: 15px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    color: #fff;
    animation: sd-giro .7s linear infinite;
}
.btn-secundario.cargando::after, .btn-fantasma.cargando::after { color: var(--txt-2); }
@keyframes sd-giro { to { transform: rotate(360deg); } }


/* ===========================================================================
   11. FORMULARIOS
   ======================================================================== */
.campo { margin-bottom: 14px; }
.campo:last-child { margin-bottom: 0; }

.campo-etiqueta {
    display: block;
    margin-bottom: 5px;
    color: var(--txt-2);
    font-size: .84rem;
    font-weight: 600;
}
.campo-ayuda {
    margin-top: 5px;
    color: var(--txt-3);
    font-size: .8rem;
}
.campo-error {
    display: block;
    margin-top: 5px;
    color: var(--rojo);
    font-size: .8rem;
    font-weight: 500;
}
.requerido::after {
    content: " *";
    color: var(--rojo);
    font-weight: 700;
}

.entrada,
.select,
.area {
    display: block;
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--borde-fuerte);
    border-radius: var(--radio-sm);
    background: var(--sup);
    color: var(--txt);
    font-size: .92rem;
    line-height: 1.4;
    transition: border-color var(--trans), box-shadow var(--trans), background var(--trans);
}
.entrada::placeholder, .area::placeholder { color: var(--txt-3); }

.entrada:hover, .select:hover, .area:hover { border-color: var(--tenue); }

.entrada:focus,
.select:focus,
.area:focus {
    border-color: var(--marca);
    box-shadow: 0 0 0 3px var(--anillo);
    outline: none;
}

.entrada[readonly], .area[readonly] { background: var(--sup-2); color: var(--txt-2); }
.entrada.error, .select.error, .area.error { border-color: var(--rojo); }
.entrada.error:focus, .select.error:focus, .area.error:focus { box-shadow: 0 0 0 3px rgba(207, 46, 46, .28); }

.entrada-sm { padding: 5px 9px; font-size: .84rem; border-radius: 7px; }

.select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 34px;
    /* Flecha dibujada en el propio CSS: sin imágenes externas. */
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                      linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 17px) calc(50% + 1px), calc(100% - 12px) calc(50% + 1px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    cursor: pointer;
}
.select[multiple] {
    background-image: none;
    padding-right: 12px;
    min-height: 120px;
}

.area {
    min-height: 96px;
    resize: vertical;
    line-height: 1.55;
}

/* Fila de campos lado a lado. */
.grupo-campos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0 16px;
}
.grupo-campos.dos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grupo-campos.tres { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Campo con icono o botón pegado (buscar, ver contraseña). */
.campo-con-boton { display: flex; }
.campo-con-boton .entrada { border-radius: var(--radio-sm) 0 0 var(--radio-sm); }
.campo-con-boton .btn { border-radius: 0 var(--radio-sm) var(--radio-sm) 0; border-color: var(--borde-fuerte); border-left: 0; }

/* --- casillas y radios ------------------------------------------------ */
/* Sirven tanto si la clase va en el <input> como si va en el <label> que lo
   envuelve; así ninguna vista tiene que adivinar el marcado exacto. */
.casilla,
.radio {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
}
label.casilla, label.radio { padding: 3px 0; font-size: .92rem; }

input.casilla,
.casilla > input[type="checkbox"],
input.radio,
.radio > input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    flex: none;
    width: 18px;
    height: 18px;
    margin: 0;
    border: 1.5px solid var(--borde-fuerte);
    border-radius: 5px;
    background: var(--sup);
    cursor: pointer;
    transition: background var(--trans-rapida), border-color var(--trans-rapida);
}
input.radio, .radio > input[type="radio"] { border-radius: 50%; }

input.casilla:hover,
.casilla > input[type="checkbox"]:hover,
input.radio:hover,
.radio > input[type="radio"]:hover { border-color: var(--marca); }

input.casilla:checked,
.casilla > input[type="checkbox"]:checked {
    background: var(--marca) var(--casilla-paloma) center/13px no-repeat;
    border-color: var(--marca);
}
input.casilla:indeterminate,
.casilla > input[type="checkbox"]:indeterminate {
    background: var(--marca) var(--casilla-guion) center/13px no-repeat;
    border-color: var(--marca);
}
input.radio:checked,
.radio > input[type="radio"]:checked {
    border-color: var(--marca);
    border-width: 5px;
    background: var(--sup);
}
input.casilla:focus-visible,
.casilla > input[type="checkbox"]:focus-visible,
input.radio:focus-visible,
.radio > input[type="radio"]:focus-visible {
    outline: 2px solid var(--anillo);
    outline-offset: 2px;
}

/* Lista de opciones en tarjeta (visibilidad del portal, alcance del agente). */
.opciones-tarjeta { display: grid; gap: 8px; }
.opciones-tarjeta > label {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 11px 13px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-sm);
    background: var(--sup);
    cursor: pointer;
    transition: border-color var(--trans-rapida), background var(--trans-rapida);
}
.opciones-tarjeta > label:hover { border-color: var(--marca); background: var(--sup-2); }
.opciones-tarjeta > label:has(input:checked) { border-color: var(--marca); background: var(--marca-100); }
.opciones-tarjeta strong { display: block; font-size: .9rem; }
.opciones-tarjeta small { color: var(--txt-3); }

/* --- interruptor ------------------------------------------------------ */
.interruptor {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    user-select: none;
    font-size: .92rem;
}
input.interruptor,
.interruptor > input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex: none;
    width: 42px;
    height: 24px;
    margin: 0;
    border: 0;
    border-radius: var(--radio-pill);
    background: var(--borde-fuerte);
    cursor: pointer;
    transition: background var(--trans);
}
input.interruptor::after,
.interruptor > input[type="checkbox"]::after {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
    transition: transform var(--trans);
}
input.interruptor:checked,
.interruptor > input[type="checkbox"]:checked { background: var(--marca); }
input.interruptor:checked::after,
.interruptor > input[type="checkbox"]:checked::after { transform: translateX(18px); }
input.interruptor:focus-visible,
.interruptor > input[type="checkbox"]:focus-visible { outline: 2px solid var(--anillo); outline-offset: 2px; }

/* Renglón de ajuste: texto a la izquierda, interruptor a la derecha. */
.ajuste {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 13px 0;
    border-bottom: 1px solid var(--borde);
}
.ajuste:last-child { border-bottom: 0; }
.ajuste .ajuste-txt { flex: 1; min-width: 0; }
.ajuste .ajuste-txt strong { display: block; font-size: .92rem; }
.ajuste .ajuste-txt small { color: var(--txt-3); }

/* Campo de archivo nativo, discreto. */
input[type="file"].entrada { padding: 7px 10px; }
input[type="file"]::file-selector-button {
    margin-right: 10px;
    padding: 5px 12px;
    border: 1px solid var(--borde-fuerte);
    border-radius: 7px;
    background: var(--sup-2);
    color: var(--txt);
    font-size: .84rem;
    font-weight: 600;
    cursor: pointer;
}
input[type="color"].entrada { padding: 3px; height: 38px; cursor: pointer; }

/* Medidor de fuerza de contraseña (instalador, perfil, portal). */
.fuerza { display: flex; gap: 4px; margin-top: 7px; }
.fuerza i {
    flex: 1;
    height: 4px;
    border-radius: 2px;
    background: var(--borde);
    transition: background var(--trans);
}
.fuerza.n1 i:nth-child(1) { background: var(--rojo); }
.fuerza.n2 i:nth-child(-n+2) { background: var(--oro); }
.fuerza.n3 i:nth-child(-n+3) { background: var(--marca); }
.fuerza.n4 i { background: var(--verde); }


/* ===========================================================================
   12. TABLAS
   ======================================================================== */
.tabla {
    width: 100%;
    background: var(--sup);
    font-size: .9rem;
}
.tabla th,
.tabla td {
    padding: 11px 14px;
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--borde);
}
.tabla thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--sup-2);
    color: var(--txt-3);
    font-size: .74rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    white-space: nowrap;
}
.tabla tbody tr:last-child td { border-bottom: 0; }
.tabla td.num, .tabla th.num { text-align: right; font-variant-numeric: tabular-nums; }
.tabla td.acciones { width: 1%; white-space: nowrap; text-align: right; }
.tabla td a { font-weight: 600; }

.tabla-hover tbody tr { transition: background var(--trans-rapida); }
.tabla-hover tbody tr:hover { background: var(--sup-3); }
.tabla-hover tbody tr.sel { background: var(--marca-100); }

.tabla-compacta th,
.tabla-compacta td { padding: 7px 10px; font-size: .86rem; }

.tabla-rayada tbody tr:nth-child(even) { background: var(--sup-2); }

/* Envoltura para tablas anchas: se desplaza sola en horizontal y NO obliga a
   la página entera a desplazarse. Las tablas dentro de .tabla-scroll quedan
   fuera del patrón de "tarjetas apiladas" de la sección 21. */
.tabla-scroll {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    /* Mismo truco que en las pestañas: las sombras de los lados sólo aparecen
       cuando la tabla no cabe. Sin ellas, una columna cortada por el borde
       parece un error y no una tabla que se puede recorrer. */
    background:
        linear-gradient(to right, var(--sup) 40%, transparent) left center / 30px 100% no-repeat local,
        linear-gradient(to left,  var(--sup) 40%, transparent) right center / 30px 100% no-repeat local,
        radial-gradient(farthest-side at 0 50%, rgba(10, 43, 61, .16), transparent) left center / 10px 100% no-repeat scroll,
        radial-gradient(farthest-side at 100% 50%, rgba(10, 43, 61, .16), transparent) right center / 10px 100% no-repeat scroll;
}
.tabla-scroll::-webkit-scrollbar { height: 8px; }
.tabla-scroll::-webkit-scrollbar-thumb { border-radius: 8px; background: var(--borde-fuerte); }

/* Igual que .tabla-scroll, pero SÓLO de 601 px para arriba: por debajo la tabla
   se convierte en tarjetas apiladas (ver la sección responsiva) y ahí no hay
   nada que desplazar. Es la caja que se le pone a las listas normales para que
   en una ventana a medias no se queden columnas escondidas detrás del borde de
   la tarjeta, que recorta. */
.tabla-caja {
    width: 100%;
    overflow-x: auto;
    scrollbar-width: thin;
    background:
        linear-gradient(to right, var(--sup) 40%, transparent) left center / 30px 100% no-repeat local,
        linear-gradient(to left,  var(--sup) 40%, transparent) right center / 30px 100% no-repeat local,
        radial-gradient(farthest-side at 0 50%, rgba(10, 43, 61, .16), transparent) left center / 10px 100% no-repeat scroll,
        radial-gradient(farthest-side at 100% 50%, rgba(10, 43, 61, .16), transparent) right center / 10px 100% no-repeat scroll;
}
.tabla-caja::-webkit-scrollbar { height: 8px; }
.tabla-caja::-webkit-scrollbar-thumb { border-radius: 8px; background: var(--borde-fuerte); }

.tabla-vacia {
    padding: 46px 22px;
    color: var(--txt-3);
    text-align: center;
}
.tabla-vacia svg { margin: 0 auto 12px; opacity: .4; }
.tabla-vacia strong {
    display: block;
    margin-bottom: 4px;
    color: var(--txt-2);
    font-size: 1rem;
}
.tabla-vacia p { max-width: 420px; margin: 0 auto; font-size: .88rem; }
.tabla-vacia .btn { margin-top: 14px; }

/* Encabezado ordenable. La flecha se dibuja con caracteres, sin iconos. */
.th-orden {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
}
.th-orden:hover { color: var(--marca); text-decoration: none; }
.th-orden::after {
    content: "↕";
    opacity: .35;
    font-size: .9em;
}
.th-orden.asc::after { content: "↑"; opacity: 1; color: var(--marca); }
.th-orden.desc::after { content: "↓"; opacity: 1; color: var(--marca); }


/* ===========================================================================
   13. ELEMENTOS SUELTOS
   ======================================================================== */
/* Chip de estado/prioridad. El color llega desde PHP en la variable --c
   (chipEstado / chipPrioridad). Se declara un color de reserva por si el
   navegador no soporta color-mix. */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-pill);
    background: var(--sup-2);
    color: var(--c, var(--txt-2));
    font-size: .78rem;
    font-weight: 700;
    line-height: 1.5;
    white-space: nowrap;
}
@supports (background: color-mix(in srgb, red 10%, transparent)) {
    .chip {
        background: color-mix(in srgb, var(--c, var(--tenue)) 13%, transparent);
        border-color: color-mix(in srgb, var(--c, var(--tenue)) 32%, transparent);
        /* El texto NO va del color puro que eligió quien configuró el catálogo:
           un ámbar sobre fondo claro daba 2:1 de contraste y un vino sobre fondo
           oscuro 1.6:1, ilegibles los dos. Mezclado a medias con la tinta del
           tema, el mismo color se oscurece en claro y se aclara en oscuro y pasa
           de 4.5:1 sin cambiar de tono. El punto de la izquierda sigue llevando
           el color exacto, así que la clave visual no se pierde. */
        color: color-mix(in srgb, var(--c, var(--tenue)) 50%, var(--txt));
    }
}
/* Punto de color a la izquierda: ayuda a distinguir estados en daltonismo. */
.chip::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--c, var(--tenue));
}
.chip.sin-punto::before { display: none; }
/* Chips de estado con significado. Antes cada vista escribía el color a mano
   («--c:#cf2e2e»), y ese rojo de modo claro se quedaba igual en modo oscuro,
   donde apenas se distingue del fondo. */
.chip-ok      { --c: var(--verde); }
.chip-alerta  { --c: var(--oro); }
.chip-peligro { --c: var(--rojo); }
.chip-neutro  { --c: var(--tenue); }

.chip-sm { padding: 1px 8px; font-size: .72rem; }
.chip-sm::before { width: 6px; height: 6px; }

.badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: var(--radio-pill);
    background: var(--rojo);
    color: #fff;
    font-size: .72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.badge.gris { background: var(--borde-fuerte); color: var(--txt-2); }
.badge.marca { background: var(--marca); color: var(--marca-texto); }
.badge.verde { background: var(--verde); }
.badge.oro { background: var(--oro); color: #4a3200; }

.pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 10px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-pill);
    background: var(--sup-2);
    color: var(--txt-2);
    font-size: .78rem;
    font-weight: 600;
}
.pill a { color: inherit; }
.pill .quitar { color: var(--txt-3); cursor: pointer; font-weight: 700; }
.pill .quitar:hover { color: var(--rojo); }

/* Avatar con iniciales. El color de fondo lo fija PHP con --c (colorDe). */
.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--c, var(--marca));
    color: #fff;
    font-size: .8rem;
    font-weight: 700;
    letter-spacing: .02em;
    text-transform: uppercase;
    overflow: hidden;
    user-select: none;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar-sm { width: 26px; height: 26px; font-size: .68rem; }
.avatar-lg { width: 52px; height: 52px; font-size: 1.1rem; }

/* Pila de avatares (agentes de un grupo). */
.avatares { display: flex; }
.avatares .avatar + .avatar { margin-left: -9px; box-shadow: 0 0 0 2px var(--sup); }

/* --- avisos ----------------------------------------------------------- */
.aviso {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 15px;
    margin-bottom: 16px;
    border: 1px solid var(--borde);
    border-left-width: 3px;
    border-radius: var(--radio-sm);
    background: var(--sup-2);
    color: var(--txt-2);
    font-size: .9rem;
}
.aviso svg { flex: none; margin-top: 1px; }
.aviso strong { font-weight: 700; }
.aviso p { margin: 0; }
.aviso .cerrar { margin-left: auto; color: inherit; opacity: .6; cursor: pointer; }
.aviso .cerrar:hover { opacity: 1; }

.aviso-ok     { background: var(--ok-fondo);   border-color: var(--ok-borde);   border-left-color: var(--verde); color: var(--ok-texto); }
.aviso-error  { background: var(--err-fondo);  border-color: var(--err-borde);  border-left-color: var(--rojo);  color: var(--err-texto); }
.aviso-info   { background: var(--info-fondo); border-color: var(--info-borde); border-left-color: var(--marca); color: var(--info-texto); }
.aviso-alerta { background: var(--ale-fondo);  border-color: var(--ale-borde);  border-left-color: var(--oro);   color: var(--ale-texto); }

/* Aviso flotante que dispara app.js (copiar, subida terminada…). */
.brindis {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 400;
    display: flex;
    align-items: center;
    gap: 9px;
    max-width: 340px;
    padding: 11px 16px;
    border-radius: var(--radio);
    background: var(--navy);
    color: #fff;
    font-size: .88rem;
    box-shadow: var(--sombra);
    animation: sd-sube var(--trans-lenta);
}
.brindis.error { background: var(--rojo); }
.brindis.ok { background: var(--verde); }
@keyframes sd-sube {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}

/* Etiquetas de ticket. */
.etiqueta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 9px;
    border: 1px dashed var(--borde-fuerte);
    border-radius: var(--radio-pill);
    background: var(--sup-2);
    color: var(--txt-2);
    font-size: .74rem;
    font-weight: 600;
}
.etiqueta:hover { border-color: var(--marca); color: var(--marca); text-decoration: none; }

/* Barra de progreso genérica (SLA, reportes). */
.progreso {
    height: 6px;
    border-radius: 3px;
    background: var(--borde);
    overflow: hidden;
}
.progreso > i {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: var(--marca);
    transition: width var(--trans-lenta);
}
.progreso.verde > i { background: var(--verde); }
.progreso.oro > i { background: var(--oro); }
.progreso.rojo > i { background: var(--rojo); }

/* Marca de vencimiento. */
.vence-ok { color: var(--verde); font-weight: 600; }
.vence-cerca { color: var(--oro); font-weight: 600; }
.vence-tarde { color: var(--rojo); font-weight: 700; }

/* Esqueleto de carga. */
.esqueleto {
    border-radius: var(--radio-sm);
    background: linear-gradient(90deg, var(--sup-2) 25%, var(--sup-3) 37%, var(--sup-2) 63%);
    background-size: 400% 100%;
    animation: sd-brillo 1.3s ease infinite;
    color: transparent !important;
}
@keyframes sd-brillo {
    from { background-position: 100% 50%; }
    to   { background-position: 0 50%; }
}


/* ===========================================================================
   14. PAGINACIÓN
   ======================================================================== */
.paginacion {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    padding: 14px 4px;
}
.paginacion .info {
    margin-right: auto;
    color: var(--txt-3);
    font-size: .84rem;
}
.paginacion a,
.paginacion span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 32px;
    padding: 0 9px;
    border: 1px solid var(--borde);
    border-radius: 7px;
    background: var(--sup);
    color: var(--txt-2);
    font-size: .85rem;
    font-weight: 600;
    text-decoration: none;
}
.paginacion a:hover { border-color: var(--marca); color: var(--marca); text-decoration: none; }
.paginacion .activo {
    background: var(--marca);
    border-color: var(--marca);
    color: var(--marca-texto);
}
.paginacion .inerte { opacity: .4; pointer-events: none; }


/* Selector de «cuántos por pantalla». Son enlaces, no un <select>: la política
   de seguridad del sitio no deja guiones en línea y así funciona sin JavaScript. */
.por-pagina {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: .82rem;
}
.por-pagina > span:first-child { margin-right: 5px; color: var(--txt-3); }
.por-pagina a,
.por-pagina .activo {
    padding: 3px 9px;
    border: 1px solid transparent;
    border-radius: var(--radio-sm);
    color: var(--txt-2);
    text-decoration: none;
    font-weight: 600;
}
.por-pagina a:hover {
    border-color: var(--borde-fuerte);
    background: var(--sup-3);
    text-decoration: none;
}
.por-pagina .activo {
    border-color: var(--marca);
    background: var(--marca);
    color: var(--marca-texto);
}


/* ===========================================================================
   15. TICKETS
   Pantalla de dos columnas: lista a la izquierda, detalle a la derecha. Cada
   columna se desplaza por su cuenta para no perder el encabezado del ticket.
   ======================================================================== */
.tk-cols {
    display: grid;
    /* La LISTA manda y se lleva el ancho sobrante; los filtros se quedan en una
       columna angosta a la derecha. Antes era al revés. */
    grid-template-columns: minmax(0, 1fr) minmax(255px, 320px);
    gap: 0;
    flex: 1;
    min-height: 0;
    background: var(--bg);
}

/* --- filtros ---------------------------------------------------------- */
.tk-filtros {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 10px 14px;
    border-bottom: 1px solid var(--borde);
    background: var(--sup);
}
.tk-filtros .select,
.tk-filtros .entrada { width: auto; min-width: 130px; padding: 5px 9px; font-size: .84rem; }
.tk-filtros .select { padding-right: 30px; }
.tk-filtros .crece { flex: 1; }
.tk-filtros-panel {
    display: grid;
    /* Una sola columna: los filtros van en línea, uno debajo del otro. En dos
       columnas se leían en zigzag y costaba encontrar el que uno buscaba. */
    grid-template-columns: minmax(0, 1fr);
    /* align-content: start es imprescindible: el panel es un hijo estirado de
       la rejilla, y sin esto el navegador reparte el alto sobrante entre los
       renglones y deja huecos enormes entre un grupo de filtros y el otro. */
    align-content: start;
    gap: 16px;
    padding: 14px 16px;
    border-left: 1px solid var(--borde);
    background: var(--sup-2);
    overflow-y: auto;
}
.tk-filtros-panel > .campo { min-width: 0; margin-bottom: 0; }

/* Barra de filtros de las listas (contactos, empresas, agentes, portal).
   Los controles nacen a lo ancho del formulario; dentro de una barra tienen que
   encogerse, o cada uno se lleva su propio renglón. */
.barra-filtros {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 16px;
}
.barra-filtros .entrada,
.barra-filtros .select { width: auto; min-width: 170px; }
.barra-filtros .crece { flex: 1 1 240px; min-width: 0; width: auto; }
.barra-filtros .btn { flex: none; }
/* Cada opción en su propio renglón: mezclar chips de anchos distintos en una
   misma línea se ve accidental. */
.tk-filtros-panel .casilla { display: flex; }
.tk-filtros-panel .chip { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* --- lista ------------------------------------------------------------ */
.tk-lista {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--sup);
    overflow-y: auto;
}
.tk-lista-cab {
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 14px;
    border-bottom: 1px solid var(--borde);
    background: var(--sup-2);
    color: var(--txt-3);
    font-size: .78rem;
    font-weight: 600;
}

.tk-fila {
    display: flex;
    gap: 11px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--borde);
    border-left: 3px solid transparent;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--trans-rapida), border-color var(--trans-rapida);
}
.tk-fila:hover { background: var(--sup-3); text-decoration: none; }
.tk-fila:focus-visible { outline-offset: -2px; }
.tk-fila.sel {
    background: var(--marca-100);
    border-left-color: var(--marca);
}
.tk-fila.no-leido .tk-asunto { font-weight: 800; }
.tk-fila.no-leido::after {
    content: "";
    align-self: center;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--marca);
}
.tk-fila-cuerpo { flex: 1; min-width: 0; }

.tk-asunto {
    display: block;
    margin-bottom: 3px;
    color: var(--txt);
    font-size: .92rem;
    font-weight: 600;
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.tk-fila:hover .tk-asunto { color: var(--marca-600); }

.tk-meta {
    display: flex;
    align-items: center;
    gap: 4px 8px;
    flex-wrap: wrap;
    color: var(--txt-3);
    font-size: .78rem;
}
/* Cada dato es una caja que no se parte por dentro. Sin esto el separador «·»
   y el icono se quedaban en un renglón y el texto caía al siguiente. */
.tk-meta > * {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    max-width: 100%;
    white-space: nowrap;
}
.tk-meta svg { flex: none; }
.tk-meta .folio {
    font-family: var(--fuente-mono);
    font-weight: 700;
    color: var(--txt-2);
}
.tk-meta .sep-punto::before { content: "·"; margin-right: 3px; }

/* --- panel de detalle -------------------------------------------------- */
.tk-panel {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    background: var(--bg);
    overflow-y: auto;
}
.tk-panel-cab {
    position: sticky;
    top: 0;
    z-index: 4;
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 15px 20px;
    border-bottom: 1px solid var(--borde);
    background: var(--sup);
}
.tk-panel-cab h1 {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.3;
}
.tk-panel-cab .folio {
    color: var(--txt-3);
    font-family: var(--fuente-mono);
    font-size: .82rem;
    font-weight: 700;
}
.tk-panel-cab .acciones { display: flex; gap: 6px; margin-left: auto; }
.tk-panel-cuerpo {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 20px;
    padding: 20px;
    align-items: start;
}

/* --- hilo de conversación ---------------------------------------------- */
.tk-hilo {
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-width: 0;
}

.tk-msg {
    position: relative;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
    box-shadow: var(--sombra-sm);
    overflow: hidden;
}
/* Entrante = lo que escribe el cliente. Se alinea a la izquierda y se queda
   con el fondo neutro para que se lea como "lo recibido". */
.tk-msg.entrante {
    margin-right: 40px;
    border-left: 3px solid var(--borde-fuerte);
}
/* Saliente = respuesta del agente. Ligeramente teñida de marca y recorrida a
   la derecha, como en un chat. */
.tk-msg.saliente {
    margin-left: 40px;
    border-left: 3px solid var(--marca);
    background: var(--marca-100);
}
/* Nota privada: ámbar claro, nunca se confunde con algo que vio el cliente. */
.tk-msg.nota {
    margin-left: 24px;
    border-left: 3px solid var(--oro);
    background: var(--nota-fondo);
    border-color: var(--nota-borde);
}
/* Renglones del sistema: cambio de estado, asignación, fusiones. */
.tk-msg.sistema {
    margin: 0 24px;
    padding: 7px 12px;
    border: 0;
    border-radius: var(--radio-pill);
    background: transparent;
    box-shadow: none;
    color: var(--txt-3);
    font-size: .82rem;
    text-align: center;
}
.tk-msg.sistema::before,
.tk-msg.sistema::after { content: none; }

.tk-msg-cab {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--borde);
    background: rgba(0, 0, 0, .02);
    font-size: .84rem;
}
.tk-msg.nota .tk-msg-cab { border-bottom-color: var(--nota-borde); }
.tk-msg-cab .quien { flex: none; font-weight: 700; color: var(--txt); white-space: nowrap; }
.tk-msg-cab .para {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--txt-3);
}
.tk-msg-cab .cuando { margin-left: auto; color: var(--txt-3); white-space: nowrap; }
.tk-msg-cab .acciones { display: flex; gap: 2px; }

.tk-msg-cuerpo {
    padding: 14px 16px;
    font-size: .93rem;
    line-height: 1.6;
    overflow-wrap: anywhere;
}
.tk-msg-cuerpo > :first-child { margin-top: 0; }
.tk-msg-cuerpo > :last-child { margin-bottom: 0; }
.tk-msg-cuerpo p { margin: 0 0 .7em; }
.tk-msg-cuerpo img { max-width: 100%; height: auto; border-radius: var(--radio-sm); }
.tk-msg-cuerpo ul, .tk-msg-cuerpo ol { margin: 0 0 .7em; padding-left: 22px; }
.tk-msg-cuerpo li { list-style: initial; }
.tk-msg-cuerpo ol li { list-style: decimal; }
.tk-msg-cuerpo blockquote {
    margin: .6em 0;
    padding-left: 12px;
    border-left: 3px solid var(--borde-fuerte);
    color: var(--txt-3);
}
.tk-msg-cuerpo pre {
    padding: 11px 13px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-sm);
    background: var(--sup-2);
    overflow-x: auto;
}
.tk-msg-cuerpo code {
    padding: 1px 5px;
    border-radius: 5px;
    background: var(--sup-3);
}
.tk-msg-cuerpo pre code { padding: 0; background: none; }
.tk-msg-cuerpo table { width: 100%; margin: .6em 0; font-size: .9em; }
.tk-msg-cuerpo th, .tk-msg-cuerpo td { padding: 6px 9px; border: 1px solid var(--borde); }
/* La parte citada del correo se pliega para que el hilo no crezca sin control. */
.tk-msg-cuerpo .citado { display: none; }
.tk-msg-cuerpo.abierto .citado { display: block; opacity: .7; }
.tk-msg-mas {
    display: inline-flex;
    padding: 0 8px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-pill);
    background: var(--sup-2);
    color: var(--txt-3);
    font-size: .8rem;
    letter-spacing: .1em;
    cursor: pointer;
}
.tk-msg-mas:hover { border-color: var(--marca); color: var(--marca); }

/* Estado de envío del mensaje (cola de correo). */
.tk-msg-envio {
    padding: 6px 14px;
    border-top: 1px solid var(--borde);
    background: var(--sup-2);
    font-size: .78rem;
    color: var(--txt-3);
}
.tk-msg-envio.error { background: var(--err-fondo); color: var(--err-texto); }
.tk-msg-envio.pendiente { background: var(--ale-fondo); color: var(--ale-texto); }

/* --- adjuntos del mensaje ---------------------------------------------- */
.tk-adjuntos {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 11px 14px;
    border-top: 1px solid var(--borde);
    background: var(--sup-2);
}
.tk-adjuntos a,
.tk-adjuntos .adj {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    max-width: 260px;
    padding: 6px 11px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-sm);
    background: var(--sup);
    color: var(--txt-2);
    font-size: .82rem;
    font-weight: 600;
    text-decoration: none;
}
.tk-adjuntos a:hover { border-color: var(--marca); color: var(--marca); text-decoration: none; }
.tk-adjuntos .nom {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tk-adjuntos .peso { color: var(--txt-3); font-weight: 500; font-size: .76rem; }
.tk-adjuntos img.miniatura {
    width: 34px;
    height: 34px;
    border-radius: 6px;
    object-fit: cover;
}

/* --- caja de respuesta -------------------------------------------------- */
.tk-editor {
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
    box-shadow: var(--sombra-sm);
    overflow: hidden;
}
.tk-editor.enfocado {
    border-color: var(--marca);
    box-shadow: 0 0 0 3px var(--anillo);
}
/* En modo nota, toda la caja se tiñe de ámbar: imposible equivocarse. */
.tk-editor.modo-nota { background: var(--nota-fondo); border-color: var(--nota-borde); }
.tk-editor-pestanas {
    display: flex;
    gap: 2px;
    padding: 8px 10px 0;
    border-bottom: 1px solid var(--borde);
    background: var(--sup-2);
}
.tk-editor.modo-nota .tk-editor-pestanas { background: transparent; border-bottom-color: var(--nota-borde); }
.tk-editor-cab {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 9px 12px;
    border-bottom: 1px solid var(--borde);
    font-size: .85rem;
}
.tk-editor-cab .etq { color: var(--txt-3); font-weight: 600; }
.tk-editor-cab input {
    flex: 1;
    min-width: 120px;
    border: 0;
    background: transparent;
    font-size: .88rem;
    outline: none;
}
.tk-editor-pie {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 10px 12px;
    border-top: 1px solid var(--borde);
    background: var(--sup-2);
}
.tk-editor.modo-nota .tk-editor-pie { background: transparent; border-top-color: var(--nota-borde); }
.tk-editor-pie .btn-primario { margin-left: auto; }

/* --- panel de propiedades ---------------------------------------------- */
.tk-props {
    position: sticky;
    top: 12px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-width: 0;
}
.tk-props .tarjeta-cuerpo { padding: 14px; }
.tk-props .campo { margin-bottom: 11px; }
.tk-props .campo-etiqueta { font-size: .78rem; }
.tk-props .select,
.tk-props .entrada { padding: 6px 10px; font-size: .87rem; }
.tk-props .select { padding-right: 30px; }

/* Ficha del solicitante dentro del panel. */
.tk-contacto {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 13px 14px;
    border-bottom: 1px solid var(--borde);
}
.tk-contacto .datos { min-width: 0; }
.tk-contacto strong {
    display: block;
    font-size: .92rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tk-contacto small {
    color: var(--txt-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
}

/* Línea de tiempo de actividad (sd_actividad). */
.tk-actividad { padding: 4px 0; }
.tk-actividad li {
    position: relative;
    padding: 7px 0 7px 20px;
    color: var(--txt-2);
    font-size: .84rem;
    line-height: 1.45;
}
.tk-actividad li::before {
    content: "";
    position: absolute;
    left: 4px;
    top: 14px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--borde-fuerte);
}
.tk-actividad li::after {
    content: "";
    position: absolute;
    left: 7px;
    top: 21px;
    bottom: -7px;
    width: 1px;
    background: var(--borde);
}
.tk-actividad li:last-child::after { content: none; }
.tk-actividad .cuando { display: block; color: var(--txt-3); font-size: .76rem; }

/* Barra flotante de acciones masivas (la enciende app.js). */
.sel-barra {
    position: fixed;
    left: 50%;
    bottom: 22px;
    z-index: 300;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    border-radius: var(--radio-pill);
    background: var(--navy);
    color: #fff;
    box-shadow: var(--sombra);
    transform: translate(-50%, 130%);
    opacity: 0;
    pointer-events: none;
    transition: transform var(--trans-lenta), opacity var(--trans-lenta);
}
.sel-barra.visible {
    transform: translate(-50%, 0);
    opacity: 1;
    pointer-events: auto;
}
.sel-barra .conteo { font-weight: 700; font-variant-numeric: tabular-nums; }
.sel-barra .btn {
    height: 30px;
    padding: 0 12px;
    border-color: rgba(255, 255, 255, .25);
    background: rgba(255, 255, 255, .12);
    color: #fff;
    font-size: .82rem;
}
.sel-barra .btn:hover { background: rgba(255, 255, 255, .22); }
.sel-barra .btn-peligro { background: var(--rojo); border-color: var(--rojo); }
.sel-barra .select { height: 30px; padding: 0 28px 0 10px; font-size: .82rem; }


/* ===========================================================================
   16. COMPONENTES DE app.js
   ======================================================================== */

/* --- velo compartido (modal y cajón lateral) ---------------------------- */
.velo {
    position: fixed;
    inset: 0;
    z-index: 90;
    background: rgba(10, 43, 61, .55);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--trans-lenta), visibility var(--trans-lenta);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}
.velo.visible { opacity: 1; visibility: visible; }

/* --- modal -------------------------------------------------------------- */
.modal {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(10, 43, 61, .55);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--trans-lenta), visibility var(--trans-lenta);
}
.modal.abierto { opacity: 1; visibility: visible; }

.modal-caja {
    width: min(560px, 100%);
    max-height: calc(100vh - 40px);
    display: flex;
    flex-direction: column;
    border: 1px solid var(--borde);
    border-radius: var(--radio-lg);
    background: var(--sup);
    box-shadow: var(--sombra-modal);
    transform: translateY(12px) scale(.985);
    transition: transform var(--trans-lenta);
    overflow: hidden;
}
.modal.abierto .modal-caja { transform: none; }
.modal-caja.ancha { width: min(860px, 100%); }
.modal-caja.angosta { width: min(420px, 100%); }

.modal-cab {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--borde);
}
.modal-cab h2 { margin: 0; font-size: 1.05rem; font-weight: 700; }
.modal-cab .btn-icono { margin-left: auto; }

.modal-cuerpo {
    padding: 20px;
    overflow-y: auto;
    font-size: .93rem;
    line-height: 1.6;
}
.modal-cuerpo > :first-child { margin-top: 0; }
.modal-cuerpo > :last-child { margin-bottom: 0; }

.modal-pie {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 9px;
    padding: 14px 20px;
    border-top: 1px solid var(--borde);
    background: var(--sup-2);
}
.modal-pie .izq { margin-right: auto; }

/* Modal de confirmación destructiva: cabecera roja discreta. */
.modal-caja.peligro .modal-cab {
    background: var(--err-fondo);
    border-bottom-color: var(--err-borde);
    color: var(--err-texto);
}

/* --- autocompletado de contactos ---------------------------------------- */
.ac-caja { position: relative; }

.ac-lista {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 5px);
    z-index: 120;
    max-height: 290px;
    padding: 5px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
    box-shadow: var(--sombra);
    overflow-y: auto;
}
.ac-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radio-sm);
    cursor: pointer;
}
.ac-item .datos { min-width: 0; flex: 1; }
.ac-item strong {
    display: block;
    font-size: .89rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ac-item small {
    display: block;
    color: var(--txt-3);
    font-size: .78rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ac-item:hover,
.ac-item.sel { background: var(--marca-100); }
.ac-item.sel strong { color: var(--marca-600); }

.ac-nuevo {
    border-top: 1px solid var(--borde);
    margin-top: 4px;
    padding-top: 9px;
    color: var(--marca-600);
    font-weight: 600;
}
.ac-vacio,
.ac-cargando {
    padding: 12px 10px;
    color: var(--txt-3);
    font-size: .86rem;
    text-align: center;
}

/* --- editor enriquecido -------------------------------------------------- */
.ed-barra {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
    padding: 6px 8px;
    border-bottom: 1px solid var(--borde);
    background: var(--sup-2);
}
.tk-editor.modo-nota .ed-barra { background: transparent; border-bottom-color: var(--nota-borde); }
.ed-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 6px;
    color: var(--txt-2);
    font-size: .88rem;
    font-weight: 700;
    cursor: pointer;
    transition: background var(--trans-rapida), color var(--trans-rapida);
}
.ed-btn:hover { background: var(--sup-3); color: var(--txt); }
.ed-btn.activo { background: var(--marca-100); color: var(--marca-600); }
.ed-btn[data-cmd="italic"] { font-style: italic; }
.ed-btn[data-cmd="underline"] { text-decoration: underline; }
.ed-sep {
    width: 1px;
    height: 18px;
    margin: 0 5px;
    background: var(--borde);
}

.ed-area {
    min-height: 130px;
    max-height: 460px;
    padding: 13px 15px;
    font-size: .93rem;
    line-height: 1.6;
    overflow-y: auto;
    outline: none;
    overflow-wrap: anywhere;
}
.ed-area:empty::before {
    content: attr(data-vacio);
    color: var(--txt-3);
    pointer-events: none;
}
.ed-area > :first-child { margin-top: 0; }
.ed-area p { margin: 0 0 .6em; }
.ed-area ul, .ed-area ol { margin: 0 0 .6em; padding-left: 22px; }
.ed-area li { list-style: initial; }
.ed-area ol li { list-style: decimal; }
.ed-area blockquote {
    margin: .5em 0;
    padding-left: 12px;
    border-left: 3px solid var(--borde-fuerte);
    color: var(--txt-2);
}
.ed-area pre {
    padding: 10px 12px;
    border-radius: var(--radio-sm);
    background: var(--sup-2);
    overflow-x: auto;
}
.ed-area code { padding: 1px 5px; border-radius: 5px; background: var(--sup-3); }
.ed-area img { max-width: 100%; border-radius: var(--radio-sm); }

/* --- zona de adjuntos ---------------------------------------------------- */
.adj-zona {
    padding: 12px 14px;
    border-top: 1px dashed var(--borde-fuerte);
    background: var(--sup-2);
    transition: background var(--trans), border-color var(--trans);
}
.tk-editor.modo-nota .adj-zona { background: transparent; border-top-color: var(--nota-borde); }
.adj-zona.arrastrando {
    background: var(--marca-100);
    border-color: var(--marca);
    box-shadow: inset 0 0 0 2px var(--marca);
}
.adj-suelta {
    display: flex;
    align-items: center;
    gap: 9px;
    color: var(--txt-3);
    font-size: .84rem;
}
.adj-suelta small { margin-left: auto; text-align: right; }
.adj-suelta .btn { margin-left: auto; }
.adj-abrir { color: var(--marca-600); font-weight: 600; cursor: pointer; text-decoration: underline; }

.adj-lista { display: grid; gap: 7px; margin-top: 10px; }
.adj-lista:empty { margin-top: 0; }

.adj-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 11px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-sm);
    background: var(--sup);
    font-size: .85rem;
}
.adj-item .nom {
    flex: 1;
    min-width: 0;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.adj-item .peso { color: var(--txt-3); font-size: .78rem; white-space: nowrap; }
.adj-item.error { border-color: var(--err-borde); background: var(--err-fondo); color: var(--err-texto); }
.adj-item.error .peso { color: inherit; }
.adj-item .quitar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 6px;
    color: var(--txt-3);
    cursor: pointer;
}
.adj-item .quitar:hover { background: var(--err-fondo); color: var(--rojo); }

.adj-barra {
    width: 90px;
    height: 5px;
    border-radius: 3px;
    background: var(--borde);
    overflow: hidden;
}
.adj-barra > i {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 3px;
    background: var(--marca);
    transition: width var(--trans-rapida) linear;
}
.adj-item.listo .adj-barra { display: none; }

/* --- retroalimentación de "copiar" --------------------------------------- */
[data-copiar] { position: relative; }
[data-copiar].copiado::after {
    content: "Copiado";
    position: absolute;
    left: 50%;
    bottom: calc(100% + 7px);
    transform: translateX(-50%);
    z-index: 20;
    padding: 3px 9px;
    border-radius: 6px;
    background: var(--navy);
    color: #fff;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    pointer-events: none;
    animation: sd-sube var(--trans-lenta);
}


/* ===========================================================================
   17. CONFIGURACIÓN Y PESTAÑAS
   ======================================================================== */
.cfg-rejilla {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
}

.cfg-tarjeta {
    display: flex;
    gap: 13px;
    padding: 17px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
    box-shadow: var(--sombra-sm);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--trans), transform var(--trans), box-shadow var(--trans);
}
.cfg-tarjeta:hover {
    border-color: var(--marca);
    box-shadow: var(--sombra);
    transform: translateY(-2px);
    text-decoration: none;
}
.cfg-tarjeta .icono {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--marca-100);
    color: var(--marca-600);
}
/* La etiqueta del final («3 grupos activos») se pega abajo, para que en una
   fila de tarjetas queden todas a la misma altura aunque los textos midan
   distinto. */
.cfg-tarjeta .pill { margin-top: auto; }
.cfg-tarjeta strong { display: block; margin-bottom: 2px; font-size: .95rem; }
.cfg-tarjeta small { color: var(--txt-3); font-size: .82rem; line-height: 1.45; }

/* Menú lateral de configuración (parte _partes/menu_config.php). */
.cfg-menu {
    position: sticky;
    top: 12px;
    padding: 8px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
}
.cfg-menu h6 {
    margin: 12px 10px 5px;
    color: var(--txt-3);
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
}
.cfg-menu h6:first-child { margin-top: 4px; }
.cfg-menu a {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 10px;
    border-radius: var(--radio-sm);
    color: var(--txt-2);
    font-size: .88rem;
    font-weight: 500;
    text-decoration: none;
    transition: background var(--trans-rapida), color var(--trans-rapida);
}
.cfg-menu a:hover { background: var(--sup-3); color: var(--txt); text-decoration: none; }
.cfg-menu a.activo {
    background: var(--marca-100);
    color: var(--marca-600);
    font-weight: 700;
}

/* Dos columnas para las pantallas de configuración con menú. */
.cfg-cols {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

/* --- pestañas ------------------------------------------------------------ */
.pestanas {
    display: flex;
    gap: 3px;
    border-bottom: 1px solid var(--borde);
    margin-bottom: 18px;
    overflow-x: auto;
    scrollbar-width: thin;
    /* Sombras de desplazamiento: aparecen SOLAS cuando la tira no cabe, porque
       las capas «local» viajan con el contenido y descubren a las «scroll».
       Sin esto la última pestaña se corta sin que nada avise de que hay más. */
    background:
        linear-gradient(to right, var(--pestanas-fondo, var(--bg)) 40%, transparent) left center / 34px 100% no-repeat local,
        linear-gradient(to left,  var(--pestanas-fondo, var(--bg)) 40%, transparent) right center / 34px 100% no-repeat local,
        radial-gradient(farthest-side at 0 50%, rgba(10, 43, 61, .16), transparent) left center / 11px 90% no-repeat scroll,
        radial-gradient(farthest-side at 100% 50%, rgba(10, 43, 61, .16), transparent) right center / 11px 90% no-repeat scroll;
}
.pestanas::-webkit-scrollbar { height: 6px; }
.pestanas::-webkit-scrollbar-thumb { border-radius: 6px; background: var(--borde-fuerte); }
/* Dentro de una tarjeta el fondo es otro; se avisa con la variable. */
.tarjeta .pestanas, .tarjeta-cuerpo .pestanas { --pestanas-fondo: var(--sup); }
.pestana {
    position: relative;
    padding: 9px 14px;
    border: 0;
    border-radius: var(--radio-sm) var(--radio-sm) 0 0;
    background: transparent;
    color: var(--txt-3);
    font-size: .89rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    transition: color var(--trans-rapida), background var(--trans-rapida);
}
.pestana:hover { background: var(--sup-3); color: var(--txt); text-decoration: none; }
.pestana.activa { color: var(--marca-600); }
.pestana.activa::after {
    content: "";
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: -1px;
    height: 2px;
    border-radius: 2px 2px 0 0;
    background: var(--marca);
}
.pestana .cuenta {
    margin-left: 6px;
    padding: 0 6px;
    border-radius: var(--radio-pill);
    background: var(--sup-3);
    font-size: .72rem;
    font-variant-numeric: tabular-nums;
}
.panel[hidden] { display: none; }

/* Pestañas dentro del editor de ticket (Responder / Nota / Reenviar). */
.tk-editor-pestanas .pestana { padding: 7px 13px; font-size: .85rem; }
.tk-editor-pestanas .pestana.activa { color: var(--marca-600); }
.tk-editor.modo-nota .tk-editor-pestanas .pestana.activa { color: var(--ale-texto); }
.tk-editor.modo-nota .tk-editor-pestanas .pestana.activa::after { background: var(--oro); }


/* ===========================================================================
   18. PORTAL DEL CLIENTE
   El portal se ve como un sitio público: sin barra lateral, ancho contenido y
   colores que el administrador puede cambiar (portal_color) sobre --marca.
   ======================================================================== */
.portal {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--bg);
}

.portal-cab {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 22px;
    border-bottom: 1px solid var(--borde);
    background: var(--top-fondo);
    -webkit-backdrop-filter: saturate(160%) blur(10px);
    backdrop-filter: saturate(160%) blur(10px);
}
.portal-cab .marca {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--txt);
    font-weight: 800;
    font-size: 1.02rem;
    text-decoration: none;
}
.portal-cab .marca img { max-height: 36px; width: auto; }
.portal-cab nav {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
}
.portal-cab nav a {
    padding: 7px 12px;
    border-radius: var(--radio-sm);
    color: var(--txt-2);
    font-size: .9rem;
    font-weight: 600;
    text-decoration: none;
}
.portal-cab nav a:hover { background: var(--sup-3); color: var(--txt); text-decoration: none; }
.portal-cab nav a.activo { color: var(--marca-600); background: var(--marca-100); }

.portal-hero {
    padding: 54px 22px 46px;
    border-radius: var(--radio-lg);
    overflow: hidden;
    background:
        radial-gradient(1100px 380px at 50% -80px, rgba(30, 159, 212, .28), transparent 70%),
        linear-gradient(160deg, var(--navy) 0%, var(--navy-2) 100%);
    color: #fff;
    text-align: center;
}
.portal-hero h1 {
    max-width: 760px;
    margin: 0 auto;
    color: #fff;
    font-size: clamp(1.5rem, 4vw, 2.15rem);
    font-weight: 800;
    letter-spacing: -.03em;
}
.portal-hero p {
    max-width: 620px;
    margin: 10px auto 0;
    color: rgba(255, 255, 255, .82);
    font-size: 1.02rem;
}
.portal-hero .buscador {
    position: relative;
    max-width: 620px;
    margin: 24px auto 0;
}
.portal-hero .buscador input {
    width: 100%;
    height: 50px;
    padding: 0 18px 0 46px;
    border: 1px solid rgba(255, 255, 255, .2);
    border-radius: var(--radio-pill);
    background: rgba(255, 255, 255, .96);
    /* Color fijo a propósito: este campo va SIEMPRE sobre el fondo oscuro del
       hero, en los dos temas. Con var(--tinta) el texto se volvía casi blanco
       en modo oscuro y se perdía sobre el blanco del propio campo. */
    color: #0f2733;
    font-size: 1rem;
    box-shadow: var(--sombra);
}
.portal-hero .buscador input::placeholder { color: #6b8290; }
.portal-hero .buscador input:focus { outline: 3px solid rgba(255, 255, 255, .45); }
.portal-hero .buscador svg {
    position: absolute;
    left: 17px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--tenue);
}
.portal-hero .acciones {
    display: flex;
    justify-content: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 20px;
}
.portal-hero .btn-secundario {
    background: rgba(255, 255, 255, .12);
    border-color: rgba(255, 255, 255, .3);
    color: #fff;
}
.portal-hero .btn-secundario:hover { background: rgba(255, 255, 255, .22); }

.portal-cuerpo {
    flex: 1;
    width: 100%;
    max-width: 1060px;
    margin: 0 auto;
    padding: 30px 22px 50px;
}
.portal-cuerpo section + section { margin-top: 34px; }
.portal-cuerpo h2 { margin-bottom: 14px; font-size: 1.22rem; }

.portal-kb {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 16px;
}
.portal-kb a,
.portal-kb .kb-tarjeta {
    display: block;
    padding: 18px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
    box-shadow: var(--sombra-sm);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--trans), transform var(--trans), box-shadow var(--trans);
}
.portal-kb a:hover {
    border-color: var(--marca);
    box-shadow: var(--sombra);
    transform: translateY(-2px);
    text-decoration: none;
}
.portal-kb strong { display: block; margin-bottom: 5px; font-size: 1rem; }
.portal-kb small { color: var(--txt-3); font-size: .85rem; line-height: 1.5; }
.portal-kb .cuenta { margin-top: 9px; color: var(--marca-600); font-size: .8rem; font-weight: 700; }

/* Artículo de la base de conocimiento. */
.kb-articulo {
    max-width: 760px;
    font-size: 1rem;
    line-height: 1.7;
}
.kb-articulo h2 { margin: 1.4em 0 .5em; font-size: 1.2rem; }
.kb-articulo h3 { margin: 1.2em 0 .4em; font-size: 1.05rem; }
.kb-articulo p { margin-bottom: .9em; }
.kb-articulo ul, .kb-articulo ol { margin: 0 0 1em; padding-left: 24px; }
.kb-articulo li { list-style: initial; margin-bottom: .3em; }
.kb-articulo ol li { list-style: decimal; }
.kb-articulo img { border-radius: var(--radio); margin: 1em 0; }
.kb-util {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 30px;
    padding: 16px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
}

.portal-pie {
    padding: 24px 22px;
    border-top: 1px solid var(--borde);
    background: var(--sup);
    color: var(--txt-3);
    font-size: .84rem;
    text-align: center;
}
.portal-pie a { color: var(--txt-2); }
.portal-pie .marca-pie { margin-top: 6px; font-size: .78rem; opacity: .8; }

/* Lista de tickets del cliente en el portal. */
.portal-tickets { display: grid; gap: 10px; }
.portal-ticket {
    display: flex;
    /* En fila, explícito: estas tarjetas llevan también la clase .tarjeta, que
       es «column», y heredarla convertía el align-items de abajo en un centrado
       horizontal — el título y el resumen aparecían a media tarjeta en todas
       las listas del portal. */
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--trans), box-shadow var(--trans);
}
.portal-ticket:hover { border-color: var(--marca); box-shadow: var(--sombra-sm); text-decoration: none; }
.portal-ticket .datos { flex: 1; min-width: 0; }
.portal-ticket strong { display: block; font-size: .95rem; }
.portal-ticket small { color: var(--txt-3); font-size: .8rem; }


/* ===========================================================================
   19. PANTALLAS DE ACCESO Y ERROR (layouts "acceso" y "limpio")
   ======================================================================== */
.acceso {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 26px 18px;
    background:
        radial-gradient(900px 420px at 50% -140px, rgba(30, 159, 212, .22), transparent 70%),
        var(--bg);
}
.acceso-caja {
    width: min(420px, 100%);
    padding: 30px;
    border: 1px solid var(--borde);
    border-radius: var(--radio-lg);
    background: var(--sup);
    box-shadow: var(--sombra);
}
.acceso-logo {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    margin-bottom: 22px;
    text-align: center;
}
.acceso-logo img { max-height: 46px; width: auto; }
.acceso-logo strong { font-size: 1.15rem; font-weight: 800; letter-spacing: -.02em; }
.acceso-logo small { color: var(--txt-3); }
.acceso-caja .btn-bloque { margin-top: 6px; }
.acceso-pie {
    margin-top: 18px;
    color: var(--txt-3);
    font-size: .85rem;
    text-align: center;
}
.acceso-pie a { font-weight: 600; }

.error-pag {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 30px;
    text-align: center;
}
.error-pag .codigo {
    font-size: 4.4rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.05em;
    color: var(--marca);
}
.error-pag h1 { margin: 10px 0 6px; font-size: 1.3rem; }
.error-pag p { max-width: 460px; color: var(--txt-3); }
.error-pag .btn { margin-top: 20px; }


/* ===========================================================================
   20. TABLERO Y REPORTES
   ======================================================================== */
.tablero-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 14px;
    margin-bottom: 20px;
}
.kpi {
    padding: 16px 18px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    background: var(--sup);
    box-shadow: var(--sombra-sm);
}
.kpi {
    display: flex;
    flex-direction: column;
}
.kpi .rotulo {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    /* Dos renglones reservados siempre: así los números de toda la fila quedan
       a la misma altura aunque unos rótulos sean más largos que otros. */
    min-height: 2.4em;
    color: var(--txt-3);
    font-size: .78rem;
    font-weight: 700;
    line-height: 1.2;
    text-transform: uppercase;
    letter-spacing: .05em;
}
.kpi .rotulo svg { flex: none; margin-top: 1px; }
.kpi .valor {
    margin-top: 6px;
    font-size: 1.9rem;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
}
.kpi .pie { margin-top: 3px; color: var(--txt-3); font-size: .8rem; }
/* Valores que son texto y no un número («menos de un minuto») no pueden ir al
   tamaño de titular: se salen de la tarjeta. */
.kpi .valor.texto { font-size: 1.12rem; line-height: 1.25; letter-spacing: 0; }
.kpi.alerta .valor { color: var(--rojo); }
.kpi.bien .valor { color: var(--verde); }

/* Gráfica de barras dibujada con divs: sin librerías. */
/* Escala de la gráfica: sin ella, un periodo con pocos tickets se veía como un
   rectángulo vacío con dos barritas en una esquina, sin manera de saber cuánto
   valía el alto. Las guías se dibujan con un degradado repetido, sin más HTML. */
.grafica-escala {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 4px;
    color: var(--txt-3);
    font-size: .72rem;
}
.grafica {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    height: 160px;
    padding-top: 10px;
    border-bottom: 1px solid var(--borde-fuerte);
    background: repeating-linear-gradient(
        to top,
        transparent 0,
        transparent calc(25% - 1px),
        var(--borde) calc(25% - 1px),
        var(--borde) 25%
    );
}
.grafica .barra {
    flex: 1;
    min-width: 6px;
    border-radius: 4px 4px 0 0;
    background: var(--marca);
    opacity: .85;
    transition: opacity var(--trans-rapida);
}
.grafica .barra:hover { opacity: 1; }
.grafica-ejes {
    display: flex;
    gap: 6px;
    margin-top: 6px;
    color: var(--txt-3);
    font-size: .7rem;
}
.grafica-ejes span { flex: 1; text-align: center; }

/* Barras horizontales de distribución (por agente, por grupo). */
.barras { display: grid; gap: 10px; }
.barras .fila { display: grid; grid-template-columns: 150px 1fr 52px; align-items: center; gap: 10px; }
.barras .etq { font-size: .85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barras .num { text-align: right; font-size: .85rem; font-weight: 700; font-variant-numeric: tabular-nums; }


/* --- importación de contactos y empresas -------------------------------- */
.imp-resumen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
}
.imp-cifra {
    padding: 14px 16px;
    border: 1px solid var(--borde);
    border-left: 3px solid var(--borde-fuerte);
    border-radius: var(--radio);
    background: var(--sup);
}
.imp-cifra strong {
    display: block;
    font-size: 1.7rem;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
}
.imp-cifra span { color: var(--txt-3); font-size: .82rem; }
.imp-cifra.ok  { border-left-color: var(--verde); }
.imp-cifra.ok strong { color: var(--verde); }
.imp-cifra.err { border-left-color: var(--rojo); }
.imp-cifra.err strong { color: var(--rojo); }

/* El mapeo: una tarjeta por columna del archivo. */
.imp-mapa {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
    gap: 12px;
}
.imp-col .campo-etiqueta {
    display: block;
    margin-bottom: 5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Los tres pasos de la pantalla de inicio. */
.pasos-importar { margin: 0; padding-left: 20px; }
.pasos-importar li { margin-bottom: 12px; }
.pasos-importar li:last-child { margin-bottom: 0; }


/* ===========================================================================
   21. RESPONSIVO
   ======================================================================== */

/* --- hasta 1200 px: el panel de propiedades del ticket baja ------------- */
@media (max-width: 1200px) {
    .tk-panel-cuerpo { grid-template-columns: minmax(0, 1fr); }
    .tk-props { position: static; }
    .rej-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- hasta 1050 px ------------------------------------------------------ */
@media (max-width: 1050px) {
    .cfg-cols { grid-template-columns: minmax(0, 1fr); }
    .cfg-menu { position: static; }
    .rej-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tk-cols { grid-template-columns: minmax(280px, 340px) minmax(0, 1fr); }
}

/* ---------------------------------------------------------------------------
   De 901 px para arriba la barra se puede PLEGAR a un riel de iconos. El estado
   vive en <html data-lateral="mini">, que pone lateral.js antes de pintar nada.
   Basta con cambiar --lat-ancho: es la única fuente del ancho, la usan la
   rejilla .app y la propia .lateral.
   ------------------------------------------------------------------------ */
@media (min-width: 901px) {
    :root[data-lateral="mini"] { --lat-ancho: 68px; }

    :root[data-lateral="mini"] .lateral-nav { padding: 12px 8px 20px; }
    :root[data-lateral="mini"] .lateral-nav a { justify-content: center; gap: 0; padding: 11px 0; }

    /* El nombre se recorta pero NO se quita: display:none se lo escondería
       también al lector de pantalla, y entonces el menú no se podría usar. */
    :root[data-lateral="mini"] .lateral-nav a > span {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
    :root[data-lateral="mini"] .lateral-nav a .cuenta { display: none; }
    :root[data-lateral="mini"] .lateral-nav a.activo::before { left: -8px; }

    :root[data-lateral="mini"] .lateral-logo { justify-content: center; padding: 14px 8px; }
    :root[data-lateral="mini"] .lateral-logo-txt { display: none; }
    :root[data-lateral="mini"] .lateral-logo img { max-height: 26px; }
    :root[data-lateral="mini"] .lateral-pie { display: none; }

    /* El icono del botón gira para decir hacia dónde va a moverse la barra. */
    :root[data-lateral="mini"] .topbar-menu .ico-plegar { transform: none; }
}

/* El botón de la barra superior: en escritorio pliega, en móvil abre el cajón.
   Por eso enseña un icono u otro según el ancho. */
.topbar-menu .ico-menu { display: none; }
.topbar-menu .ico-plegar { display: inline-flex; transform: rotate(180deg); transition: transform var(--trans); }
@media (max-width: 900px) {
    .topbar-menu .ico-menu { display: inline-flex; }
    .topbar-menu .ico-plegar { display: none; }
}

/* La marca corta («iT») sólo se ve cuando la barra está en riel y no hay logo. */
.lateral-logo-mini { display: none; font-weight: 800; font-size: 1.05rem; }
:root[data-lateral="mini"] .lateral-logo-mini { display: inline; }

/* ---------------------------------------------------------------------------
   Hasta 900 px: la barra lateral deja de ocupar columna y se vuelve un cajón
   deslizante. app.js le pone la clase .abierta y enciende el velo (.velo).
   ------------------------------------------------------------------------ */
@media (max-width: 900px) {
    .app { grid-template-columns: minmax(0, 1fr); }

    .lateral {
        position: fixed;
        top: 0;
        left: 0;
        height: 100vh;
        height: 100dvh;
        transform: translateX(-100%);
        transition: transform var(--trans-lenta);
        box-shadow: none;
        z-index: 100;
    }
    .lateral.abierta {
        transform: none;
        box-shadow: var(--sombra);
    }

    /* El botón hamburguesa sólo existe aquí. */
    .topbar-menu { display: inline-flex; }
    .topbar { padding: 10px 14px; }
    .topbar-buscar { max-width: none; }

    .contenido { padding: 16px 14px; }

    .solo-movil { display: revert !important; }
    .solo-escritorio { display: none !important; }

    /* Los tickets pasan a una sola columna: se ve la lista o el detalle,
       nunca los dos a la vez. La vista marca cuál con .ver-panel. */
    .tk-cols { grid-template-columns: minmax(0, 1fr); }
    /* En una sola columna los filtros van arriba: al final de una lista larga
       nadie los encontraría. El marcado sigue igual; sólo cambia el orden. */
    .tk-filtros-panel { order: -1; border-left: 0; border-bottom: 1px solid var(--borde); overflow: visible; }
    .tk-cols.ver-panel .tk-lista { display: none; }
    .tk-cols:not(.ver-panel) .tk-panel { display: none; }
    .tk-panel-cuerpo { padding: 14px; gap: 14px; }
    .tk-msg.entrante { margin-right: 0; }
    .tk-msg.saliente { margin-left: 12px; }
    .tk-msg.nota { margin-left: 8px; }

    .pag-cab { gap: 10px; }
    .pag-acciones { width: 100%; margin-left: 0; }
    .rej-2, .rej-2-1, .rej-3, .rej-4 { grid-template-columns: minmax(0, 1fr); }
    .grupo-campos.dos, .grupo-campos.tres { grid-template-columns: minmax(0, 1fr); }

    .modal { padding: 0; align-items: flex-end; }
    .modal-caja {
        width: 100%;
        max-height: 92vh;
        border-radius: var(--radio-lg) var(--radio-lg) 0 0;
        transform: translateY(100%);
    }
}

/* ---------------------------------------------------------------------------
   Hasta 600 px: las tablas se vuelven tarjetas apiladas.
   PATRÓN: cada <td> debe traer data-label="Encabezado de la columna"; el
   pseudo-elemento ::before lo imprime a la izquierda y el valor queda a la
   derecha. El <thead> se esconde (queda accesible para lectores de pantalla
   porque sólo se recorta visualmente). Una tabla que NO deba transformarse se
   envuelve en .tabla-scroll y conserva su desplazamiento horizontal.
   Ejemplo de marcado:
       <td data-label="Folio">#1042</td>
   ------------------------------------------------------------------------ */
@media (max-width: 600px) {
    body { font-size: 14.5px; }

    .contenido { padding: 12px 10px; }
    .topbar { gap: 8px; padding: 8px 10px; }
    .tarjeta-cuerpo { padding: 14px; }
    .tarjeta-cab, .tarjeta-pie { padding: 12px 14px; }

    .tabla { display: block; }
    .tabla thead {
        position: absolute;
        width: 1px; height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
    }
    .tabla tbody,
    .tabla tr,
    .tabla td { display: block; width: auto; }
    .tabla tr {
        margin-bottom: 10px;
        padding: 4px 0;
        border: 1px solid var(--borde);
        border-radius: var(--radio);
        background: var(--sup);
        box-shadow: var(--sombra-sm);
    }
    .tabla td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 14px;
        padding: 7px 13px;
        border-bottom: 0;
        text-align: right;
    }
    .tabla td::before {
        content: attr(data-label);
        flex: none;
        color: var(--txt-3);
        font-size: .74rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: .05em;
        text-align: left;
    }
    /* Celdas sin etiqueta (acciones, casilla de selección) ocupan el ancho. */
    .tabla td:not([data-label])::before { content: none; }
    .tabla td.acciones {
        justify-content: flex-end;
        width: auto;
        padding-top: 9px;
        border-top: 1px solid var(--borde);
    }
    /* La celda marcada como .celda-tit es el título de la tarjeta. */
    .tabla td.celda-tit {
        font-size: 1rem;
        font-weight: 700;
        text-align: left;
    }
    .tabla td.celda-tit::before { content: none; }

    /* Escape del patrón: una tabla envuelta en .tabla-scroll se queda como
       tabla de verdad y se desplaza en horizontal (reportes, bitácora). */
    .tabla-scroll .tabla { display: table; }
    .tabla-scroll .tabla thead {
        position: static;
        width: auto; height: auto;
        clip: auto;
        clip-path: none;
    }
    .tabla-scroll .tabla tbody { display: table-row-group; }
    .tabla-scroll .tabla tr {
        display: table-row;
        margin: 0;
        padding: 0;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }
    .tabla-scroll .tabla td {
        display: table-cell;
        padding: 7px 10px;
        border-bottom: 1px solid var(--borde);
        text-align: left;
    }
    .tabla-scroll .tabla td::before { content: none; }

    .tabla-caja { overflow-x: visible; background: none; }

    .paginacion { justify-content: center; }
    .paginacion .info { width: 100%; margin: 0 0 8px; text-align: center; }

    .portal-hero { padding: 34px 16px 30px; }
    .portal-cuerpo { padding: 20px 14px 36px; }
    .portal-cab { padding: 10px 14px; }
    .portal-cab nav a { padding: 6px 9px; font-size: .85rem; }

    .acceso-caja { padding: 22px 18px; }

    .sel-barra {
        left: 10px;
        right: 10px;
        bottom: 10px;
        transform: translateY(130%);
        border-radius: var(--radio);
        justify-content: center;
        flex-wrap: wrap;
    }
    .sel-barra.visible { transform: none; }

    .tk-editor-pie .btn { flex: 1; }
    .tk-editor-pie .btn-primario { margin-left: 0; }

    .tablero-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .barras .fila { grid-template-columns: 100px 1fr 42px; }
}

/* Pantallas muy angostas: un KPI por renglón. */
@media (max-width: 380px) {
    .tablero-kpis { grid-template-columns: minmax(0, 1fr); }
}


/* La tarjeta plegable de «empresas sin dominio»: es una <details>, así que su
   cabecera tiene que anunciarse como pulsable. Va aquí y no en la vista porque
   en este proyecto los estilos no viven dentro del HTML. */
.dom-resumen { cursor: pointer; list-style: none; }
.dom-resumen::-webkit-details-marker { display: none; }
.dom-resumen:hover .tarjeta-tit { color: var(--enlace); }


/* Las carpetas dentro de una categoría del portal. Un título discreto con una
   línea encima: separa los grupos sin competir con el título de la categoría. */
.kb-carpeta { margin-top: 28px; }
.kb-carpeta-tit {
    margin: 0 0 .5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--borde);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--txt-2);
}
.kb-carpeta > .tenue { margin: -.25rem 0 .75rem; }


/* ===========================================================================
   21 bis. SOLUCIONES DENTRO DEL TICKET
   El buscador que vive debajo del editor de respuesta. Cerrado ocupa una
   línea: el 90 % de las respuestas se escriben a mano y no debe estorbar.
   ======================================================================== */
/* El enlace discreto del pie de cada burbuja saliente. Aparece al pasar el
   ratón por el mensaje: siempre visible convertiría el hilo en un muestrario
   de botones. En táctil no hay ratón, así que ahí se queda visible. */
.tk-msg-acciones {
    margin: .4rem 0 0;
    font-size: .78rem;
    opacity: 0;
    transition: opacity 120ms ease;
}
.tk-msg-acciones a {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    color: var(--txt-3);
    text-decoration: none;
}
.tk-msg-acciones a:hover { color: var(--enlace); text-decoration: underline; }
.tk-msg:hover .tk-msg-acciones,
.tk-msg-acciones:focus-within { opacity: 1; }

@media (hover: none) {
    .tk-msg-acciones { opacity: 1; }
}

.sol-picker {
    border-top: 1px solid var(--borde);
    background: var(--sup-2);
}
.sol-picker > summary {
    display: flex;
    align-items: center;
    gap: .45rem;
    padding: .5rem .75rem;
    cursor: pointer;
    list-style: none;
    font-size: .86rem;
    color: var(--txt-2);
}
.sol-picker > summary::-webkit-details-marker { display: none; }
.sol-picker > summary:hover { color: var(--enlace); }
.sol-picker[open] > summary {
    border-bottom: 1px solid var(--borde);
    color: var(--txt);
    font-weight: 600;
}
.sol-picker-cuerpo { padding: .65rem .75rem .5rem; }
.sol-picker-pie { margin: .5rem 0 0; }

/* Alto máximo con desplazamiento propio: con veinte artículos, el botón de
   Enviar quedaría fuera de la pantalla si la lista creciera sin freno. */
.sol-picker-lista {
    margin-top: .5rem;
    max-height: 260px;
    overflow-y: auto;
}
.sol-picker-lista[aria-busy="true"] { opacity: .5; }

.sol-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .5rem .6rem;
    border: 1px solid var(--borde);
    border-radius: var(--radio-sm);
    background: var(--sup);
}
.sol-item + .sol-item { margin-top: .4rem; }
.sol-item:hover { border-color: var(--borde-fuerte); }

.sol-item-datos { min-width: 0; }          /* sin esto el texto largo no recorta */
.sol-item-datos strong {
    display: block;
    font-size: .88rem;
    line-height: 1.3;
}
.sol-item-datos small {
    display: block;
    margin-top: .1rem;
    color: var(--txt-3);
    font-size: .78rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sol-item-acciones {
    display: flex;
    gap: .3rem;
    flex-shrink: 0;
}

@media (max-width: 560px) {
    .sol-item { flex-direction: column; align-items: stretch; }
    .sol-item-acciones { justify-content: flex-end; }
}


/* ===========================================================================
   21 ter. REMISIONES
   El recuadro de firma, los renglones y la hoja que se imprime.
   ======================================================================== */

/* Quién entrega: no es un campo, es un dato. Se pinta como tal. */
.rem-fijo {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin: 0;
    padding: .55rem .75rem;
    border: 1px dashed var(--borde);
    border-radius: var(--radio-sm);
    background: var(--sup-2);
}

.rem-lineas .rem-col-cant { width: 7.5rem; }
.rem-lineas td { vertical-align: middle; }

/* La caja del autocompletado del destino cuelga del input, no de la tarjeta. */
.rem-sugiere { position: relative; }
.rem-sugiere > .ac-lista {
    position: absolute;
    left: 0; right: 0; top: calc(100% + 2px);
    z-index: 40;
}

/* --------------------------------------------------------- LA FIRMA ------ */

/* Proporción fija 900×320, la misma del lienzo: si la caja y el lienzo no
   coinciden, el trazo aparece desplazado del dedo.
   Y un ancho máximo, porque en una pantalla grande un recuadro de firma de
   1200 px de ancho se ve ridículo y encima invita a firmar en grande. */
.rem-pad {
    position: relative;
    max-width: 620px;
    aspect-ratio: 900 / 320;
    border: 2px dashed var(--borde-fuerte);
    border-radius: var(--radio);
    background: #ffffff;        /* siempre blanco: se firma con tinta negra */
    overflow: hidden;
}
.rem-pad canvas {
    display: block;
    width: 100%;
    height: 100%;
    /* Sin esto, en un teléfono el dedo desplaza la página en vez de dibujar. */
    touch-action: none;
    cursor: crosshair;
}
.rem-pad-linea {
    position: absolute;
    left: 8%; right: 8%; bottom: 22%;
    border-top: 1px solid #c9d6de;
    pointer-events: none;
}
.rem-pad-pista {
    position: absolute;
    left: 0; right: 0; bottom: 10%;
    text-align: center;
    color: #9bb0bc;
    font-size: .85rem;
    letter-spacing: .04em;
    pointer-events: none;
}
.rem-firma-caja.rem-firmada .rem-pad { border-style: solid; border-color: var(--marca); }

/* --------------------------------- LA PANTALLA DE SÓLO FIRMAR ------------ */

/* Se abre con el cascarón limpio y se le pasa el aparato a otra persona: todo
   lo que hay aquí tiene que caber de un vistazo y poder tocarse con el dedo.
   
   Y VA SIEMPRE EN CLARO, con los colores escritos a mano. El cascarón limpio no
   carga tema.js —a propósito: tiene que poder pintarse aunque la base falle—,
   así que la página sigue al modo del SISTEMA. Con el teléfono en oscuro, el
   recuadro del resumen tenía fondo claro fijo y letra heredada casi blanca:
   contraste 1.09:1, o sea que el cliente firmaba sin poder leer su nombre ni lo
   que estaba aceptando — justo lo único que esta pantalla existe para evitar.
   Fondo fijo y letra fija van SIEMPRE juntos; es la misma red que ya llevan
   .rem-imprimir y .rem-hoja. */
.rem-firmar {
    max-width: 760px;
    margin: 0 auto;
    padding: 4px 0 28px;
    color-scheme: light;
    background: #ffffff;
    color: #0f2733;
}
.rem-firmar .tenue { color: #6b8290; }
/* Los botones de esta pantalla también: el fantasma y el secundario sacan su
   color del tema, y sobre el blanco fijo de aquí salían lavados. */
.rem-firmar .btn-fantasma { color: #48606c; }
.rem-firmar .btn-secundario {
    background: #ffffff;
    border-color: #cddde6;
    color: #0f2733;
}

.rem-firmar-cab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding-bottom: 10px;
    margin-bottom: 14px;
    border-bottom: 2px solid #0f2733;
}
.rem-firmar-cab small { display: block; color: #6b8290; font-size: .7rem; letter-spacing: .08em; }
.rem-firmar-cab strong { display: block; font-size: 1.3rem; line-height: 1.2; color: #0f2733; }

.rem-firmar-resumen {
    padding: 14px 16px;
    border: 1px solid #e3ecf1;
    border-radius: 10px;
    background: #f7fbfd;
    color: #0f2733;
    margin-bottom: 18px;
}
.rem-firmar-resumen .tenue { color: #6b8290; }
.rem-firmar-quien { margin: 0 0 .2em; font-size: 1.05rem; color: #0f2733; }
.rem-firmar-lineas { margin: 10px 0; font-size: .92rem; }
.rem-firmar-lineas td { border: 0; border-top: 1px solid #e3ecf1; padding: 5px 6px; color: #0f2733; }
.rem-firmar-lineas .rem-c { width: 4.5rem; text-align: right; font-weight: 600; }

.rem-firmar-pide { margin: 0 0 .6em; font-weight: 600; color: #0f2733; }

/* El recuadro grande: en esta pantalla la firma es lo único que hay, así que
   puede ocupar todo el ancho. */
.rem-pad-grande { max-width: none; }

.rem-firmar-botones {
    display: flex;
    gap: 12px;
    margin-top: 14px;
}
.rem-firmar-botones .btn { flex: 1; justify-content: center; }
.rem-firmar-botones .btn[disabled] { opacity: .45; cursor: not-allowed; }

/* ------------------------------- LOS DOS CAMINOS DE LA FICHA ------------- */

.rem-caminos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px;
}
.rem-camino .btn { width: 100%; justify-content: center; }
.rem-camino p { margin: .6rem 0 0; }
.rem-acciones .btn-lg { min-width: 14rem; justify-content: center; }

/* La vista previa.
   El ancho NO es uno cómodo: es el del papel de verdad. Una hoja carta mide
   8.5 pulgadas = 816 px a 96 ppp, menos los 14 mm de margen por lado que fija
   @page, quedan ~710 px de contenido. Con cualquier otro ancho la tabla se
   recoloca y la previa dejaría de enseñar lo que sale de la impresora, que es
   justo lo único que esta tarjeta promete. Si no cabe, se desplaza. */
/* overflow-x: auto obliga al navegador a calcular TAMBIÉN overflow-y: auto, y
   eso recortaba la hoja por abajo. Con «clip» en el eje vertical se desplaza en
   horizontal sin convertirse en una caja con barra lateral propia. */
.rem-previa { background: var(--sup-2); overflow-x: auto; overflow-y: clip; }
.rem-previa .rem-hoja {
    background: #ffffff;
    color: #0f2733;
    /* 752 = 710 de texto + 40 de relleno + 2 de borde.
       El ancho que importa es el del CONTENIDO, no el de la caja: con
       box-sizing:border-box, poner 710 aquí dejaba la columna en 668 px —un 6 %
       menos que el papel— y los renglones largos cortaban en otro sitio que en
       la impresión. Una previa que parte distinto no es una previa. */
    width: 752px;
    margin: 0 auto;
    padding: 18px 20px 22px;
    box-shadow: var(--sombra-sm);
}
.rem-previa .rem-hoja .tenue { color: #6b8290; }

/* En pantallas estrechas se encoge entera en vez de partirse: sigue siendo la
   misma hoja, sólo que más chica.
   
   Con «zoom» y no con «transform». transform encoge lo que se PINTA pero no la
   caja que el documento ocupa, así que sobraba el 38 % de la altura y había que
   compensarlo con un margen negativo... en porcentaje, que en CSS se resuelve
   contra el ANCHO del contenedor, nunca contra el alto. El resultado era un
   hueco en blanco de hasta 586 px con una remisión larga, y un recorte con una
   corta. zoom sí recoloca, y la tarjeta se ajusta sola.
   
   El umbral es 775 px y no 820: a 820 la hoja todavía cabía entera, y encoger
   algo que cabe sólo lo hace más difícil de leer. */
@media (max-width: 775px) {
    .rem-previa .rem-hoja { zoom: .62; }
}

/* El hueco para firmar con pluma en la hoja impresa sin firma digital. */
.rem-hoja-hueco { display: block; height: 46px; }

/* La firma ya guardada, en la ficha. Fondo blanco fijo por lo mismo: el PNG
   lleva trazo negro con transparencia y en modo oscuro se perdería. */
.rem-firma-img {
    display: block;
    max-width: 420px;
    width: 100%;
    background: #ffffff;
    border: 1px solid var(--borde);
    border-radius: var(--radio-sm);
    padding: 6px;
}

/* ------------------------------------------------------- LA HOJA --------- */

/* EN PANTALLA, LA HOJA MIDE LO QUE MIDE EL PAPEL.
   752 = 710 de texto + 40 de relleno + 2 de borde, los mismos de la previa.
   Antes la página de impresión se veía a 816 px en pantalla —más ancha que la
   caja de una hoja carta con sus márgenes—, así que la previa, la pantalla de
   impresión y el papel enseñaban tres anchos distintos. Al imprimir, el @media
   print de abajo quita borde y relleno y deja que la hoja llene la caja que
   fija @page. */
.rem-imprimir .rem-hoja { width: 752px; }

/* LA HOJA ES PAPEL, SIEMPRE.
   Era la única pantalla que debía verse como papel y la única que no lo
   forzaba: heredaba las variables del tema, así que con el sistema en oscuro
   se abría una página negra en la que la firma —trazo negro con fondo
   transparente— desaparecía, y la conclusión natural de quien la abría era
   «se perdió la firma». Aquí se declaran los colores a mano, sin tokens. */
.rem-imprimir {
    max-width: 860px;
    margin: 0 auto;
    color-scheme: light;
    color: #0f2733;
}
.rem-imprimir .rem-hoja { background: #ffffff; color: #0f2733; }
.rem-imprimir .rem-hoja .tenue { color: #6b8290; }

.rem-hoja {
    border: 1px solid #d8e3ea;
    border-radius: 6px;
    padding: 18px 20px 22px;
    margin: 0 0 14px;
}
.rem-hoja-cab {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 18px;
    border-bottom: 2px solid #0f2733;
    padding-bottom: 10px;
    margin-bottom: 14px;
}
.rem-hoja-marca { display: flex; align-items: flex-start; gap: 12px; }
.rem-hoja-marca strong { display: block; font-size: 1.05rem; }
.rem-hoja-marca small { display: block; color: #6b8290; font-size: .78rem; }
.rem-hoja-logo { max-height: 44px; width: auto; }
.rem-hoja-folio { text-align: right; flex-shrink: 0; }
.rem-hoja-folio small { display: block; color: #6b8290; font-size: .72rem; letter-spacing: .08em; }
.rem-hoja-folio strong { display: block; font-size: 1.35rem; line-height: 1.2; }
.rem-cancelada {
    display: inline-block;
    margin-top: 4px;
    padding: 1px 8px;
    border: 2px solid #cf2e2e;
    border-radius: 4px;
    color: #cf2e2e;
    font-weight: 700;
    font-size: .74rem;
    letter-spacing: .1em;
}

/* LAS DOS TABLAS DE LA HOJA SE PINTAN SOLAS, sin depender del cascarón.
   Los bordes venían de los estilos en línea de _layout/limpio.php, que sólo
   existen en la pantalla de impresión: en la vista previa —que va con el
   cascarón del agente— las tablas salían sin una sola raya, o sea que la previa
   NO enseñaba lo que se iba a imprimir, que es lo único que promete. */
.rem-hoja table { border-collapse: collapse; width: 100%; }
.rem-hoja th,
.rem-hoja td {
    border: 1px solid #e3ecf1;
    padding: 6px 9px;
    text-align: left;
    vertical-align: top;
}

.rem-hoja-datos { margin-bottom: 12px; font-size: .9rem; }
.rem-hoja-datos th {
    width: 7.5rem;
    background: #f2f9fc;
    font-size: .74rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: #48606c;
    vertical-align: top;
}
.rem-hoja-lineas { font-size: .92rem; }
.rem-hoja-lineas .rem-c { width: 5.5rem; text-align: right; }
.rem-hoja-nota { font-size: .86rem; margin: 0 0 14px; }

.rem-hoja-firma {
    position: relative;
    margin: 26px auto 0;
    max-width: 330px;
    text-align: center;
}
.rem-hoja-rubrica {
    display: block;
    max-height: 90px;
    width: auto;
    margin: 0 auto -8px;
    /* Fondo blanco explícito: el PNG lleva trazo negro sobre transparencia, y
       sin esto se pierde sobre cualquier fondo oscuro. Es la misma red que ya
       llevaban .rem-pad y .rem-firma-img. */
    background: #ffffff;
}
.rem-hoja-raya { display: block; border-top: 1px solid #0f2733; margin: 0 0 4px; }
.rem-hoja-firma strong { display: block; font-size: .92rem; }
.rem-hoja-firma small { display: block; color: #6b8290; font-size: .72rem; }
.rem-hoja-pie {
    margin: 16px 0 0;
    text-align: right;
    color: #6b8290;
    font-size: .72rem;
    letter-spacing: .04em;
}
.rem-corte {
    text-align: center;
    color: #9bb0bc;
    font-size: .7rem;
    letter-spacing: .05em;
    margin: 0 0 14px;
}

@media print {
    /* Los botones y el aviso de arriba no son parte del documento. */
    .rem-no-papel { display: none !important; }
    .rem-imprimir { max-width: none; }
    /* Sin borde ni redondeo: la línea de corte ya separa las dos copias, y un
       marco impreso se ve como un error de maquetación.
       Y SIN «break-inside: avoid»: con cuarenta renglones el navegador intentaba
       no partir la copia, la empujaba entera a la página siguiente y allí la
       partía igual — dejando la primera hoja casi en blanco y gastando el doble
       de papel. Lo que de verdad hay que mantener junto es cada renglón y el
       bloque de la firma, no la copia entera. */
    /* En papel manda @page: la hoja llena la caja de la página, sin el ancho
       fijo que se le pone en pantalla ni el marco, que impreso parece un error
       de maquetación. */
    .rem-hoja,
    .rem-imprimir .rem-hoja { width: auto; border: 0; padding: 0; margin: 0 0 10mm; break-inside: auto; }
    .rem-hoja-lineas,
    .rem-hoja-lineas tbody { break-inside: auto; page-break-inside: auto; }
    .rem-hoja-lineas tr { break-inside: avoid; page-break-inside: avoid; }
    .rem-hoja-lineas thead { display: table-header-group; }
    .rem-hoja-firma { break-inside: avoid; page-break-inside: avoid; }
    .rem-corte { margin: 0 0 10mm; color: #999; }
    .rem-hoja-datos th { background: #f0f0f0 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}


/* ===========================================================================
   22. IMPRESIÓN
   Se imprime el contenido, nunca el cascarón. Pensado para la vista
   /agente/ticket/{id}/imprimir y para el detalle del ticket.
   ======================================================================== */
@media print {
    :root {
        --sup: #fff;
        --sup-2: #fff;
        --sup-3: #fff;
        --bg: #fff;
        --txt: #000;
        --txt-2: #333;
        --txt-3: #555;
        --borde: #ccc;
        --borde-fuerte: #999;
        --sombra-sm: none;
        --sombra: none;
    }

    body { background: #fff; color: #000; font-size: 11.5pt; }

    .app { display: block; }

    /* Fuera todo lo que no es contenido. */
    .lateral,
    .topbar,
    .velo,
    .modal,
    .sel-barra,
    .brindis,
    .tk-filtros,
    .tk-filtros-panel,
    .tk-lista,
    .tk-editor,
    .adj-zona,
    .paginacion,
    .pag-acciones,
    .migas,
    .btn,
    .btn-icono,
    .pestanas,
    .cfg-menu,
    .portal-cab nav,
    .no-imprimir { display: none !important; }

    .principal, .contenido, .contenido.pleno {
        display: block;
        padding: 0;
        overflow: visible;
    }

    .tk-cols { display: block; }
    .tk-panel, .tk-panel-cuerpo {
        display: block;
        padding: 0;
        overflow: visible;
    }
    .tk-panel-cab {
        position: static;
        padding: 0 0 10px;
        border-bottom: 1px solid #999;
    }

    .tarjeta, .tk-msg {
        border: 1px solid #bbb;
        box-shadow: none;
        break-inside: avoid;
        page-break-inside: avoid;
    }
    .tk-msg { margin: 0 0 10pt !important; }
    .tk-msg.saliente, .tk-msg.nota { background: #fff; }
    .tk-msg.nota { border-left: 3px solid #999; }
    .tk-msg-cab { background: #f4f4f4; }
    .tk-msg-cuerpo .citado { display: block; }

    .tk-props { display: block; page-break-before: auto; }
    .tabla thead th { position: static; background: #f4f4f4; color: #000; }

    /* Los enlaces impresos muestran su destino, salvo los internos. */
    a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: .8em;
        color: #555;
        word-break: break-all;
    }

    h1, h2, h3, h4 { break-after: avoid; page-break-after: avoid; }
    table, figure, blockquote { break-inside: avoid; }

    /* Carta, no A4: es el papel de aquí. Sin esto el navegador usa el tamaño
       que tenga configurado el sistema y la hoja sale descolocada. */
    @page { size: letter; margin: 14mm; }
}

/* ---------------------------------------------------------------------------
   Tarjetas de Configuración todavía no publicadas ("Próximamente").
   Vivía repetido en dos vistas; el diseño va aquí, que es donde se cambia una
   sola vez. -------------------------------------------------------------- */
/* Estado apagado de las tarjetas que aún no llevan a ningún lado. Va aquí y no
   en app.css porque se apoya en un atributo, no en una clase nueva: sin esto la
   tarjeta se levantaría al pasar el ratón y parecería que se puede pulsar. */
[data-cfg-pendiente] { opacity: .6; cursor: default; }
[data-cfg-pendiente]:hover { border-color: var(--borde); box-shadow: var(--sombra-sm); transform: none; }
