/* ================================================================
   MexCloud — Hoja de componentes (sobre los tokens del tema)
   Reutilizable por datos1 y adm. Solo tokens semánticos (--color-*,
   --radius-*, etc.), nunca colores crudos. Respeta prefers-reduced-motion.
   ================================================================ */

*, *::before, *::after { box-sizing: border-box; }

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

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--font-size);
    line-height: var(--line-height);
    color: var(--color-text);
    background: var(--color-bg);
    -webkit-font-smoothing: antialiased;
}

a { color: var(--color-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

/* `--font-title` es por defecto la misma del cuerpo: sin un tema que la redefina esto no
   cambia nada. «Vainilla» la cambia a Fraunces, que es lo que le da su carácter. */
h1, h2, h3, h4 { margin: 0 0 0.5em; font-weight: 600; line-height: 1.25; font-family: var(--font-title); }
h1 { font-size: var(--t-3xl); }
h2 { font-size: var(--t-2xl); }
h3 { font-size: var(--t-xl); }
p { margin: 0 0 1em; }
small, .texto-muted { color: var(--color-text-muted); }
.texto-peligro { color: var(--color-danger); }
.texto-ok { color: var(--color-success); }
.file-list-table tbody tr.enlace-expirado { opacity: 0.6; }
code, kbd { font-family: var(--font-mono); font-size: 0.9em; }

:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ---- Botones ---- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
    padding: 0.5rem 1rem; font: inherit; font-weight: 500; line-height: 1;
    border: 1px solid transparent; border-radius: var(--radius-md);
    background: var(--color-surface-2); color: var(--color-text);
    cursor: pointer; transition: background var(--transition), border-color var(--transition);
    text-decoration: none;
}
.btn:hover { background: var(--color-border); text-decoration: none; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.btn-primary { background: var(--color-primary); color: var(--color-primary-fg); }
.btn-primary:hover { background: var(--color-primary-h); }
.btn-danger { background: var(--color-danger); color: #fff; }
.btn-ghost { background: transparent; border-color: var(--color-border); }
.btn-icono { padding: 0.5rem; }
.btn-sm { padding: 0.3rem 0.6rem; font-size: var(--t-md); }

/* ---- Formularios ---- */
.campo { margin-bottom: 1rem; }
.campo > label { display: block; margin-bottom: 0.35rem; font-weight: 500; color: var(--color-text-2); }
.input, .select, .textarea {
    width: 100%; padding: 0.55rem 0.75rem; font: inherit;
    color: var(--color-text); background: var(--color-surface);
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
    transition: border-color var(--transition);
}
.input:focus, .select:focus, .textarea:focus { border-color: var(--color-primary); outline: none; }
.textarea { min-height: 5rem; resize: vertical; }

/* ---- Tarjetas ---- */
.card {
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
    padding: 1.25rem;
}
.card + .card { margin-top: 1rem; }
.card-titulo { margin: 0 0 1rem; font-size: var(--t-xl); font-weight: 600; font-family: var(--font-title); }

/* ---- Ancho de trabajo para formularios ----
   Un formulario de dos campos estirado a lo ancho de un monitor de 27" no se
   lee ni se opera: el ojo va del rótulo al campo cruzando media pantalla, y el
   botón queda a un palmo de donde se estaba escribiendo.
   Se acota a una medida de trabajo; las LISTAS y las tablas no llevan esto,
   porque ahí el ancho sí se aprovecha (más columnas visibles, menos scroll).

   OJO con el `min(…, 100%)` de las tres reglas de abajo, que no es adorno:
   `max-width: 78rem` a secas dice «puedes crecer HASTA 1248 px», no «no pases
   de tu hueco». En el móvil, con una tabla ancha dentro —la de usuarios en
   Administración—, el contenedor se estiraba hasta el ancho de la tabla y
   arrastraba consigo la página entera: se desplazaba de lado TODA la pantalla
   en vez de la tabla sola. Con `min(…, 100%)` nunca supera su hueco y el
   desplazamiento vuelve a ocurrir donde debe, dentro de `.tabla-scroll`. */
.card-forma { max-width: min(52rem, 100%); }

/* Y en las pantallas de configuración —Mi perfil— el contenido entero es de
   ese tipo, así que se acota una vez arriba en lugar de tarjeta por tarjeta. */
/* Ancho de trabajo de Configuración. Subió de 56 a 62rem cuando entró la
   sección de «Notificaciones»: las seis pestañas piden 896 px puestas en un
   renglón y con 56rem solo quedaban 848 útiles, así que la última se partía.
   Sigue acotado —que era el punto: los formularios no se estiran a lo ancho
   del monitor—, solo que ahora la cota cabe lo que hay dentro. */
.contenido-forma { width: 100%; max-width: min(62rem, 100%); margin-inline: auto; }

/* Los paneles con formularios Y listas —Administración— se centran ENTEROS, en
   vez de centrar cada tarjeta por su cuenta. Probadas las dos: centrando solo
   los formularios, estos quedan flotando en medio mientras las listas siguen
   pegadas al borde, y el ojo no encuentra un margen izquierdo donde apoyarse.
   Con la columna centrada, todo empieza en la misma línea. */
.contenido-panel { width: 100%; max-width: min(78rem, 100%); margin-inline: auto; }
/* ⚠️ LA BARRA A LA ORILLA DEL NAVEGADOR (Jore, 2026-09-29). Cuando el `main` que
   DESPLAZA (`.contenido`, con su overflow-y) lleva además un ancho máximo, la caja
   de desplazamiento se angosta y su barra queda a media pantalla, junto al
   contenido. Por eso ahí el main va a todo lo ancho y el ancho de lectura se
   logra con el RELLENO de los lados: el contenido queda igual de centrado (o
   igual de a la izquierda, en la Ayuda) y la barra, en la orilla. */
.contenido.contenido-panel { max-width: none; margin-inline: 0; padding-inline: max(var(--contenido-pad), calc((100% - 78rem) / 2 + var(--contenido-pad))); }
.contenido.contenido-forma { max-width: none; margin-inline: 0; padding-inline: max(var(--contenido-pad), calc((100% - 62rem) / 2 + var(--contenido-pad))); }

/* El `width: 100%` de las dos reglas de arriba tampoco es adorno. Estos `main`
   son ítems de un grid, y `margin-inline: auto` en un ítem de grid no lo centra
   estirado: le da ancho AJUSTADO A SU CONTENIDO. Resultado: cada sección de
   Administración medía distinto —según lo ancha que fuera su tabla o su
   formulario— y, al estar centrada, la fila de pestañas se desplazaba de lado
   cada vez que se cambiaba de sección. Con `width: 100%` el ancho es siempre el
   mismo (su tope, o el hueco si es menor) y nada baila al navegar. */

/* Pestañas de sección de Administración: centradas y con su ancho natural.
   Centradas de verdad se puede porque el contenedor ya no cambia de tamaño; si
   siguiera ajustándose al contenido, centrarlas habría AMPLIFICADO el salto en
   vez de arreglarlo. */
.tabs-panel { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4rem; }
.tabs-panel .btn { white-space: nowrap; }

/* ---- Pestañas de sección (Configuración) ----
   Todas del mismo ancho. Con anchos naturales, «Cuenta» medía un tercio que
   «Dispositivos y aplicaciones» y la fila parecía bailar al pasar de una a
   otra. El texto se centra y, si no cabe, se parte: prefiero un rótulo en dos
   líneas a cuatro botones de tamaños distintos. */
/* Cada pestaña mide LO QUE DICE, y crece para llenar el renglón.
   Antes se repartían el ancho a partes iguales (grid de columnas 1fr), así que
   a «Cuenta» le sobraba sitio mientras «Dispositivos y aplicaciones» se partía
   en tres líneas en cuanto aparecía la barra de desplazamiento y se estrechaba
   el contenido. Repartir por igual castiga siempre al rótulo más largo, y
   ensanchar el contenedor solo lo aplaza hasta la siguiente sección que se
   añada. Si de plano no caben, se pasan a otro renglón: mejor dos renglones de
   pestañas que una pestaña de tres líneas.
   Los anchos no bailan al cambiar de sección porque `btn-primary` solo cambia
   colores, no el tipo ni el relleno. */
.tabs-seccion { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.tabs-seccion .btn { flex: 1 1 auto; white-space: nowrap; text-align: center; }

/* ---- Insignias / estados ---- */
.badge {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.15rem 0.5rem; font-size: var(--t-sm); font-weight: 600;
    border-radius: var(--radius-full); background: var(--color-surface-2); color: var(--color-text-2);
}
.badge-exito { background: color-mix(in srgb, var(--color-success) 18%, transparent); color: var(--color-success); }
.badge-alerta { background: color-mix(in srgb, var(--color-warning) 20%, transparent); color: var(--color-warning); }
.badge-peligro { background: color-mix(in srgb, var(--color-danger) 18%, transparent); color: var(--color-danger); }

/* ---- Barra de progreso / uso de cuota ---- */
.progress { height: 8px; background: var(--color-surface-2); border-radius: var(--radius-full); overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--color-primary); transition: width var(--transition); }
.progress.alto > span { background: var(--color-warning); }
.progress.lleno > span { background: var(--color-danger); }

/* ---- Layout app-shell ---- */
/* Altura fija del shell: navbar + sidebar quedan fijos y cada .contenido
   scrollea por dentro (necesario para el breadcrumb sticky y el render
   incremental). 100dvh respeta la barra dinámica del navegador en móvil. */
.app { height: 100vh; height: 100dvh; display: grid; grid-template-rows: auto 1fr; }
.navbar {
    display: flex; align-items: center; gap: 1rem; padding: 0 1rem;
    min-height: var(--navbar-height); flex-wrap: wrap; row-gap: 0.4rem;
    background: var(--color-surface); border-bottom: 1px solid var(--color-border);
    /* ⚠️ POR ENCIMA de la cabecera del gestor (z-index 30, y 45 en móvil): esa
       cabecera es sticky y hace CONTEXTO DE APILADO, así que con la barra en
       20 el menú de cuentas se dibujaba DEBAJO y no se podía pulsar —tercera
       vez que esta misma cabecera muerde—. Los modales viven en 70+ y siguen
       ganando. */
    position: sticky; top: 0; z-index: 50;
}
.navbar .crece { flex: 1; }
.app-cuerpo { display: grid; grid-template-columns: var(--sidebar-width) 1fr; min-height: 0; }
/* Solo el GESTOR lleva tirador (la columna de 5px de en medio). Va acotado a él
   a propósito: `.app-cuerpo` lo usan casi todas las pantallas y meterles una
   columna de más les mandaría el contenido principal a 5px de ancho. */
.cuerpo-gestor { grid-template-columns: var(--sidebar-width) 5px 1fr; }
.sidebar-sep, .panel-sep { background: var(--color-border); cursor: col-resize; }
.panel-sep:hover, .panel-sep:active { background: var(--color-primary); }
.sidebar-sep:hover, .sidebar-sep:active { background: var(--color-primary); }
/* Los tres tiradores de columna (archivos, chat/notas y los del correo) miden 5 px
   a la vista, pero se agarran en una franja más ancha e invisible: con el dedo, en
   la tableta, 5 px no se atinan. `touch-action: none` hace que el arrastre sea del
   tirador y no un desplazamiento de la página (si no, el navegador se lo quedaba
   y mandaba pointercancel a medio camino). */
.sidebar-sep, .panel-sep, .buzon-sep { position: relative; z-index: 3; touch-action: none; }
.sidebar-sep::before, .panel-sep::before, .buzon-sep::before {
    content: ''; position: absolute; top: 0; bottom: 0; left: -5px; right: -5px;
}
@media (pointer: coarse) {
    .sidebar-sep::before, .panel-sep::before, .buzon-sep::before { left: -14px; right: -14px; }
    /* Con el dedo no hay cursor que avise de que ahí se agarra: una agarradera. */
    .sidebar-sep::after, .panel-sep::after, .buzon-sep::after {
        content: ''; position: absolute; top: 50%; left: 50%; width: 9px; height: 44px;
        transform: translate(-50%, -50%); border-radius: 5px; pointer-events: none;
        background: var(--color-surface); border: 2px solid var(--color-border);
        box-sizing: border-box;
    }
    .sidebar-sep:active::after, .panel-sep:active::after, .buzon-sep:active::after { border-color: var(--color-primary); }
}
.sidebar {
    background: var(--color-sidebar-bg); color: var(--color-sidebar-fg);
    padding: 0.75rem; overflow-y: auto;
}
.sidebar a { display: block; padding: 0.5rem 0.75rem; border-radius: var(--radius-md); color: var(--color-sidebar-fg); }
.sidebar a:hover { background: rgba(255,255,255,0.06); text-decoration: none; }
.sidebar a.activo { background: var(--color-sidebar-act); color: #fff; }
/* El padding inferior también reserva sitio para el banner de vaciado, que FLOTA
   sobre el contenido (ver --alto-vaciado en app.js): si no, los últimos renglones
   de la lista quedan debajo de él y no hay forma de desplazarse hasta ellos. */
/* ⚠️ EL RELLENO SUPERIOR VA EN UNA VARIABLE porque hay barras `sticky` que
   necesitan saberlo: `top: 0` pega a la caja de RELLENO, no al borde del
   contenedor, así que el `padding-top` queda por encima y por ese hueco se ve
   pasar la lista. Se compensa con un `top` negativo del mismo valor, y con la
   variable no pueden separarse (móvil usa 1rem, escritorio 1.5rem). */
.contenido { --contenido-pad: 1.5rem; padding: var(--contenido-pad); padding-bottom: max(1.5rem, calc(var(--alto-vaciado, 0px) + 0.4rem)); overflow-y: auto; }

/* ---- Marca ---- */
.marca { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 700; color: var(--color-text); }
/* Logo del navbar = botón de Inicio (marca = home) */
.marca-inicio { cursor: pointer; border-radius: var(--radius-md); padding: 0.15rem 0.25rem; transition: opacity 0.12s; }
.marca-inicio:hover { opacity: 0.8; }
.marca-inicio:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.marca svg, .marca img { flex: none; display: block; }
.marca .wordmark { font-size: var(--t-xl); letter-spacing: -0.01em; font-family: var(--font-title); }

/* Bloque de usuario (icono + nombre + salir) en la cabecera. En escritorio va
   a la derecha; en móvil sube al renglón de la marca (ver media query). */
.nav-usuario { display: inline-flex; align-items: center; gap: 0.6rem; min-width: 0; }
.nav-usuario .usuario-nombre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Pestañas de módulo ancladas a la DERECHA: su posición NO depende del ancho variable
   del título («MexCloud · Módulo»), así no se mueven al cambiar de módulo. El margen
   automático a la izquierda de las pestañas absorbe el cambio de ancho del título. */
.navbar .nav-tabs { order: 2; margin-left: auto; }
/* ⚠️ EL BOTÓN TIENE QUE ESTAR POSICIONADO, o su globo se va a la esquina.
   `.nav-badge` es `position: absolute`, así que se coloca contra el ancestro
   POSICIONADO más cercano. Sin esto, el botón no lo es y el globo subía hasta
   `.navbar` —que sí lo es, por su `position: sticky`— y aparecía en la esquina
   superior derecha de la ventana, recortado por el borde: se veía media bolita
   roja lejísimos de «Mensajes». En el móvil no pasaba porque el globo va dentro
   de `.tabbar-ic`, que sí lleva `position: relative`. */
.navbar .nav-tabs .btn { position: relative; }
.navbar .nav-usuario { order: 4; margin-left: 0.75rem; }

/* Solo-móvil: oculto en escritorio. `!important` para ganarle al `display` de
   componentes que la usan (`.accion-sel`, `.btn-icono`) definidos más abajo con la
   misma especificidad; simétrico a `.solo-escritorio` (ver media query). */
.solo-movil { display: none !important; }
.hamburguesa { order: 0; }
.drawer-fondo { position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,0.45); display: flex; }
.drawer {
    width: min(80vw, 18rem); background: var(--color-surface); height: 100%;
    box-shadow: 2px 0 16px rgba(0,0,0,0.3); display: flex; flex-direction: column;
    padding: 0.75rem; gap: 0.25rem; overflow-y: auto;
}
.drawer-item {
    display: flex; align-items: center; gap: 0.75rem; width: 100%;
    padding: 0.8rem 0.9rem; border-radius: var(--radius-md); border: 0;
    background: transparent; color: var(--color-text); cursor: pointer; font-size: var(--t-lg);
}
.drawer-item:hover { background: var(--color-surface-2); }
.drawer-item.activo { background: var(--color-primary); color: #fff; }
.drawer-item svg { width: 1.3rem; height: 1.3rem; flex: none; }
.drawer-sep { height: 1px; background: var(--color-border); margin: 0.5rem 0.4rem; }
/* Título del drawer = botón de Inicio (marca = home) */
.drawer-titulo {
    display: flex; align-items: center; gap: 0.6rem; width: 100%;
    padding: 0.6rem 0.9rem; margin-bottom: 0.3rem; border: 0; border-radius: var(--radius-md);
    background: transparent; color: var(--color-text); cursor: pointer; font-weight: 700; font-size: var(--t-xl);
}
.drawer-titulo svg { width: 1.6rem; height: 1.6rem; flex: none; }
.drawer-titulo:hover { background: var(--color-surface-2); }
.drawer-titulo.activo { color: var(--color-primary); }

/* ---- Menús desplegables anclados (Agregar / Ver) ---- */
/* ⚠️ EL `min-width`/`min-height` NO ES DECORATIVO. Alpine ignora
   `@click.outside` cuando el elemento mide 0×0 (`if (el.offsetWidth < 1 &&
   el.offsetHeight < 1) return;` en su código). Varios de estos menús tienen
   como único hijo visible un botón `.solo-escritorio`, así que EN EL TELÉFONO
   el envoltorio se queda sin tamaño, el manejador no corre y el menú abierto
   ya no se cierra tocando fuera — que es como se cierra un menú en un móvil.
   Lo reportó Jore con el de «Modelos», que es el único que se puede abrir
   desde el menú ☰. Un píxel invisible devuelve el comportamiento. */
.menu-wrap { position: relative; display: inline-flex; z-index: 40; min-width: 1px; min-height: 1px; }

/* ── Menú contextual (clic derecho, escritorio) ──────────────────────────
   La capa atrapa el siguiente clic (cerrar); el menú se ancla al cursor en
   fixed y el JS lo recoloca para que no se salga de la pantalla. */
.ctx-capa { position: fixed; inset: 0; z-index: 90; }
.ctx-menu { position: fixed; display: block; }
/* Un menú no es texto. El de la pulsación larga se abre con el dedo AÚN
   apoyado, y Android tomaba esa misma pulsación como «seleccionar texto» sobre
   la opción que quedaba debajo (la marcaba en azul con sus asas; lo vio Jore,
   2026-10-10). */
.ctx-capa, .menu-pop { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
/* En pantallas táctiles, mantener presionada una fila abre su menú: que no
   seleccione además el nombre como texto. */
@media (pointer: coarse) {
    .toque-largo { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
}

/* ── Etiquetas de correo (§25.10) ────────────────────────────────────────
   El punto de color en la lista y el árbol; el chip con nombre en el lector;
   la paleta y las filas del modal. */
/* Los puntitos Thunderbird (2026-08-26): verde = sin leer, gris = leído, en
   cada fila; y el de carpeta, entre el icono y el nombre, cuando tiene no
   leídos. La carpeta pequeñita va encima del remitente en las vistas que
   mezclan carpetas (inteligentes y búsqueda). */
.buzon-punto {
    /* La caja es el blanco del clic; el círculo de color va en el ::before. */
    flex: none; width: 1.1rem; height: 1.1rem; display: inline-flex;
    align-items: center; justify-content: center;
    margin: -0.3rem -0.15rem -0.3rem -0.3rem;
    align-self: center; cursor: pointer;
}
.buzon-punto::before { content: ''; width: 0.5rem; height: 0.5rem; border-radius: 50%; }
.buzon-punto.nuevo::before { background: #22c55e; }
/* Gris de texto, no de borde: el borde en el tema oscuro casi no se ve. */
.buzon-punto.pendiente::before { background: var(--color-text-2); }
.buzon-punto.leido::before { background: transparent; border: 1px solid var(--color-text-2); }
.buzon-punto.leido:hover::before { background: var(--color-text-2); }
.buzon-carpeta-mini {
    display: block; font-size: var(--t-2xs); color: var(--color-text-2);
    text-transform: uppercase; letter-spacing: 0.03em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    margin-bottom: 0.1rem;
}

.buzon-tag-dot {
    display: inline-block; width: 0.62rem; height: 0.62rem; border-radius: 50%;
    flex: none; vertical-align: middle;
}
.buzon-tags-lector {
    display: flex; flex-wrap: wrap; gap: 0.35rem;
    padding: 0.4rem 0.9rem; border-bottom: 1px solid var(--color-border);
    background: var(--color-surface);
}
.buzon-tag-chip {
    display: inline-flex; align-items: center; gap: 0.35rem;
    font-size: var(--t-sm); padding: 0.15rem 0.55rem; border-radius: 999px;
    background: color-mix(in srgb, var(--tag-color) 18%, transparent);
    border: 1px solid color-mix(in srgb, var(--tag-color) 45%, transparent);
}
.buzon-tag-chip::before {
    content: ''; width: 0.5rem; height: 0.5rem; border-radius: 50%;
    background: var(--tag-color);
}
.etq-lista { display: flex; flex-direction: column; gap: 0.15rem; max-height: 40vh; overflow-y: auto; }
.etq-fila { display: flex; align-items: center; gap: 0.3rem; }
.etq-editar, .etq-nueva { margin-top: 0.6rem; border-top: 1px solid var(--color-border); padding-top: 0.6rem; }
.etq-color {
    width: 1.4rem; height: 1.4rem; border-radius: 50%; border: 2px solid transparent;
    cursor: pointer; padding: 0;
}
.etq-color.activo { border-color: var(--color-text); }

/* ── Pestaña del redactor (estilo Roundcube, opt-in) ─────────────────────
   La pestaña ES el redactor: sin navegación ni tabbar, y el redactor desde
   el borde de arriba. Lo demás del correo queda debajo y no estorba. */
.redactor-solo .navbar, .redactor-solo .tabbar-movil { display: none !important; }
.redactor-solo .buzon-redactar { top: 0 !important; }
/* El salvavidas del redactor: en escritorio solo donde NO hay barra principal. */
@media (min-width: 769px) {
    body:not(.redactor-solo) .redactar-soporte { display: none !important; }
}
/* NADA de la app se ve mientras el redactor carga — solo fondo. `visibility`
   y no `display`: así el redactor, los diálogos que abre (programar,
   adjuntar) y los toasts pueden re-mostrarse por encima de un ancestro
   escondido, cosa que display no permite. */
.redactor-solo > *:not(script) { visibility: hidden; }
.redactor-solo .buzon-redactar,
.redactor-solo .modal-fondo,
.redactor-solo .toast-cont,
/* La barra de «Enviando… Deshacer»: sin ella, en la pestaña del redactor el
   envío parecía tragarse el contador y la pestaña «se cerraba sola» — se
   cerraba BIEN, al terminar una cuenta atrás que nadie veía (2026-08-26). */
.redactor-solo .vaciado-banner,
.redactor-solo .ctx-capa { visibility: visible; }
/* ⚠️ `.menu-wrap` es un CONTEXTO DE APILADO (position + z-index), así que el
   z-index del desplegable de dentro NO compite con el de fuera: compite el de
   la envoltura, y entre envolturas iguales gana la ÚLTIMA del documento. Por
   eso los iconos de la barra de una nota se pintaban ENCIMA del desplegable de
   etiquetas, que está más arriba en el HTML. Se sube la envoltura mientras el
   menú está abierto —solo mientras—: dejarla subida haría que su botón tapara
   los desplegables de las otras. */
.menu-wrap.menu-arriba { z-index: 50; }
.chevron-abajo { display: inline-flex; transition: transform 0.15s ease; }
.chevron-abajo svg { width: 1rem; height: 1rem; }
.chevron-abajo.abierto { transform: rotate(180deg); }
.menu-pop {
    position: absolute; top: calc(100% + 0.35rem); left: 0; z-index: 50;
    min-width: 12.5rem; max-width: calc(100vw - 1.5rem); padding: 0.35rem;
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-md); box-shadow: 0 10px 28px rgba(0,0,0,0.28);
    display: flex; flex-direction: column; gap: 0.1rem;
}
.menu-pop-item {
    display: flex; align-items: center; gap: 0.65rem; width: 100%;
    padding: 0.6rem 0.7rem; border-radius: var(--radius-sm); border: 0;
    background: transparent; color: var(--color-text); cursor: pointer;
    font-size: var(--t-lg); text-align: left; white-space: nowrap; margin: 0;
}
.menu-pop-item:hover { background: var(--color-surface-2); }
/* Acción destructiva dentro de un menú (p. ej. «Borrar» en una nota), igual que
   `.btn-icono.peligro` y `.accion-sel.peligro`. */
.menu-pop-item.peligro:hover { color: var(--color-danger); }
.menu-pop-item.activo { background: var(--color-primary); color: #fff; }
.menu-pop-item svg { width: 1.2rem; height: 1.2rem; flex: none; }
/* «Nuevo» dentro de «Agregar»: se despliega en el propio menú (sangrado), con
   su flechita al final del renglón. */
.menu-pop-item.menu-pop-sub { padding-left: 1.6rem; }
.menu-pop-flecha { margin-left: auto; display: inline-flex; transition: transform 0.15s; }
.menu-pop-flecha svg { width: 1rem; height: 1rem; }
.menu-pop-flecha.abierta { transform: rotate(180deg); }
/* Menú «Compartir» de la barra de selección (app/correo/enlace). En escritorio la
   acción va al final de la barra: el desplegable se ancla a la DERECHA para no
   desbordar. (En móvil, ver la media query: abre hacia arriba y ocupa la barra.) */
.accion-compartir .menu-pop { left: auto; right: 0; }
.menu-pop-der { left: auto; right: 0; }
/* Texto de ayuda dentro de un menú (p. ej. «todavía no tiene modelos»). */
.menu-pop-vacio { margin: 0.2rem 0.6rem; padding: 0.15rem 0; font-size: var(--t-md); color: var(--color-text-muted); }
/* Última opción del menú, separada de la lista: es una acción, no un elemento más. */
.menu-pop-sep { border-top: 1px solid var(--color-border); margin-top: 0.25rem; padding-top: 0.5rem; }

/* Fila de modelo: el nombre ocupa todo y las acciones aparecen al pasar por encima,
   para que la lista se lea limpia y el clic principal (aplicar) sea el fácil de acertar. */
.modelo-fila { display: flex; align-items: center; }
.modelo-aplicar { flex: 1; min-width: 0; }
.modelo-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* «de la empresa» / «de MexCloud» a UN espacio normal del nombre (Jore, 2026-10-26: el
   hueco del menú entre sus piezas, 0.65rem, se veía como un espacio de más). */
.modelo-aplicar > .modelo-nombre + .texto-muted, .modelo-aplicar > .texto-muted + .texto-muted { margin-left: calc(0.28em - 0.65rem); flex: none; white-space: nowrap; }
.modelo-accs { display: flex; gap: 0.1rem; padding-right: 0.4rem; opacity: 0; transition: opacity 0.12s; }
.modelo-fila:hover .modelo-accs, .modelo-fila:focus-within .modelo-accs { opacity: 1; }
.modelo-accs svg { width: 1rem; height: 1rem; }
/* En táctil no hay «pasar por encima»: siempre visibles. */
@media (hover: none) { .modelo-accs { opacity: 1; } }

/* ---- Selector de tema ---- */
.tema-selector { display: inline-flex; align-items: center; gap: 0.4rem; }

/* ---- Gestor de archivos ---- */
.files-layout { display: grid; grid-template-columns: 260px 1fr; gap: 1rem; min-height: 60vh; }
.file-tree { border-right: 1px solid var(--color-border); padding-right: 0.75rem; overflow-y: auto; }
.file-tree ul { list-style: none; margin: 0; padding-left: 0.75rem; }
.file-tree .nodo { display: flex; align-items: center; gap: 0.3rem; padding: 0.3rem 0.4rem; border-radius: var(--radius-sm); }
.file-tree .nodo:hover { background: var(--color-surface-2); }
.file-tree .nodo.activo { background: color-mix(in srgb, var(--color-primary) 12%, transparent); color: var(--color-primary); font-weight: 600; }
.file-tree .nodo.activo .tipo-icono svg { stroke: var(--color-primary); }
/* Línea divisoria entre la carpeta personal y las compartidas. */
.file-tree .nodo.primera-compartida { margin-top: 0.5rem; padding-top: 0.6rem; border-top: 1px solid var(--color-border); }
.file-tree .nodo-etq { display: flex; align-items: center; gap: 0.35rem; flex: 1; min-width: 0; cursor: pointer; }
.file-tree .nodo-etq > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El nombre es lo que se recorta, no lo que venga detrás: el candado de carpeta
   segura va DESPUÉS y sin él la elipsis se la habría llevado el icono (dejando
   al nombre empujar la fila hasta desbordar el árbol). */
.file-tree .nodo-etq > .nodo-nombre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-tree .nodo-etq > .candado-seguro { flex: none; }
/* Expandir/contraer del árbol (archivos Y carpetas de correo: ambos paneles llevan
   `.file-tree`). Era un icono de 0.7rem en una caja de 1rem: se veía apenas y era difícil
   de acertar, sobre todo con el dedo.
   El ÁREA de pulsación crece más que el dibujo —es lo que de verdad cuesta acertar—, y el
   margen negativo se la come del relleno de la fila para que el árbol no se estire: objetivo
   más grande, misma densidad. El color pasa de `muted` a `text-2` porque el problema era
   también de contraste. */
.file-tree .twisty { flex: none; width: 1.5rem; height: 1.5rem; margin: -0.15rem 0; display: inline-flex; align-items: center; justify-content: center; color: var(--color-text-2); cursor: pointer; user-select: none; border-radius: var(--radius-sm); }
.file-tree .twisty svg { width: 0.95rem; height: 0.95rem; transition: transform var(--transition); }
.file-tree .twisty.abierto svg { transform: rotate(90deg); }
.file-tree .twisty:hover { color: var(--color-text); background: var(--color-surface-2); }
.file-tree .twisty-esp { cursor: default; visibility: hidden; }
/* En táctil no hay puntero fino: el objetivo se acerca a los 32 px recomendados. */
@media (hover: none) {
    .file-tree .twisty { width: 2rem; height: 2rem; margin: -0.3rem 0; }
    .file-tree .twisty svg { width: 1.1rem; height: 1.1rem; }
}

/* Cabecera FIJA del gestor: envuelve el breadcrumb y (en escritorio) la barra de
   selección, para tenerlos siempre a mano aunque estés varias páginas abajo.
   top negativo = al padding de .contenido, para que con el margen negativo la
   caja quede FLUSH arriba al pegarse; los márgenes negativos cancelan el padding
   de .contenido para que el fondo llegue de borde a borde. */
.cabecera-gestor {
    position: sticky; z-index: 30;
    top: -1.5rem;
    margin: -1.5rem -1.5rem 1rem;
    padding: 0.7rem 1.5rem;
    background: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
}
.breadcrumb {
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem;
    color: var(--color-text-muted);
}
/* Barra de acciones (Agregar/Ver/vista) dentro de la cabecera sticky. */
.barra-acciones-gestor { margin-top: 0.6rem; }
/* «Por persona»: sin migas, este es el único renglón; el buscador toma lo que sobra. */
.barra-acciones-gestor.cab-personas { margin-top: 0; flex-wrap: nowrap; }
.cab-personas .personas-buscar { flex: 1 1 6rem; min-width: 0; max-width: 22rem; }
/* En el teléfono la barra va JUSTA: con el gap de fábrica (0.75rem) y el
   padding ancho de los botones, el grupo vista+Aa se caía al segundo
   renglón por unos píxeles. Apretado, cabe todo en uno. */
@media (max-width: 480px) {
    .barra-acciones-gestor { gap: 0.4rem; }
    .barra-acciones-gestor .btn:not(.btn-sm) { padding-left: 0.6rem; padding-right: 0.6rem; }
}
.breadcrumb .btn-atras { margin-right: 0.4rem; }
.breadcrumb .miga { display: inline-flex; align-items: center; gap: 0.15rem; }
.breadcrumb .miga-enlace {
    display: inline-flex; align-items: center; gap: 0.35rem;
    padding: 0.25rem 0.5rem; border-radius: var(--radius-sm);
    color: var(--color-text-2); text-decoration: none; font-weight: 500;
    transition: background var(--transition), color var(--transition);
}
.breadcrumb .miga-enlace:hover { background: var(--color-surface-2); color: var(--color-text); }
.breadcrumb .miga-actual {
    color: var(--color-text); font-weight: 600;
    background: color-mix(in srgb, var(--color-primary) 10%, transparent);
}
.breadcrumb .miga-inicio svg { width: 1rem; height: 1rem; display: block; }
.breadcrumb .sep { display: inline-flex; align-items: center; color: var(--color-text-muted); opacity: 0.55; }
.breadcrumb .sep svg { width: 0.9rem; height: 0.9rem; display: block; }

.file-list-table { width: 100%; border-collapse: collapse; }
.file-list-table th, .file-list-table td { padding: 0.55rem 0.6rem; text-align: left; border-bottom: 1px solid var(--color-border); }
.file-list-table th { font-size: var(--t-sm); text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); font-weight: 600; }
.file-list-table tbody tr:hover { background: var(--color-surface-2); }
.file-list-table tbody tr.sel { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }

/* Casilla de selección: checkbox grande y área clicable amplia (toda la celda),
   para que sea fácil de atinar con el mouse o el dedo. */
.file-list-table th.celda-sel, .file-list-table td.celda-sel { width: 3rem; padding: 0; text-align: center; }
.check-sel { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 2.7rem; cursor: pointer; }
.check-sel input[type="checkbox"] { width: 1.3rem; height: 1.3rem; cursor: pointer; accent-color: var(--color-primary); }
.file-list-table .col-acc { text-align: right; white-space: nowrap; width: 1%; }

/* ---- Nombre con icono de tipo y subtítulo ---- */
.tipo-icono { flex: none; display: inline-flex; }
.tipo-icono svg { width: 1.6rem; height: 1.6rem; display: block; }
.tipo-icono .miniatura {
    width: 1.9rem; height: 1.9rem; display: block; object-fit: cover;
    border-radius: var(--radius-sm); background: var(--color-surface-2);
}

/* ---- Visor de PDF (PDF.js) ---- */
.pdf-vista {
    height: 72vh; overflow-y: auto; background: var(--color-surface-2);
    border-radius: var(--radius-md); padding: 0.75rem;
    display: flex; flex-direction: column; align-items: center; gap: 0.75rem;
}
.pdf-vista .pdf-pagina {
    max-width: 100%; height: auto; background: #fff;
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25); border-radius: 2px;
}
/* Acercado con «+» (pdfZoom): la página es más ancha que el visor y se recorre
   también de lado; centrada «safe» para que no se corte la orilla izquierda. */
.pdf-vista.pdf-zoom { overflow-x: auto; align-items: safe center; }
.pdf-vista.pdf-zoom .pdf-pagina { max-width: none; flex: none; }
/* La barrita «− 100 % +» bajo la foto o el PDF del visor. */
.preview-zoom { display: flex; justify-content: center; align-items: center; gap: .35rem; margin-top: .5rem; position: relative; z-index: 2; }
.preview-zoom .btn svg { display: block; width: 1rem; height: 1rem; }
.preview-zoom-pct { min-width: 4.2rem; font-variant-numeric: tabular-nums; }
/* En el teléfono, la foto cabe con la barra de arriba y la del zoom a la vista. */
@media (max-width: 768px) {
    .preview-modal .preview-img { display: block; margin: 0 auto; max-height: calc(100dvh - 11rem); object-fit: contain; }
}

/* ---- Indicador de cuota ---- */
.cuota-widget { font-size: var(--t-sm); }
.cuota-sidebar { margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--color-border); }
.cuota-movil { display: none; margin-bottom: 1rem; }
.cuota-cab { display: flex; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.35rem; color: var(--color-text-muted); flex-wrap: wrap; }
.cuota-barra { height: 0.4rem; background: var(--color-surface-2); border-radius: 999px; overflow: hidden; }
.cuota-barra > span { display: block; height: 100%; width: 0; background: var(--color-primary); transition: width var(--transition); }
.cuota-alerta .cuota-barra > span { background: #f59e0b; }
.cuota-peligro .cuota-barra > span { background: var(--color-danger); }
.cuota-alerta .cuota-cab, .cuota-peligro .cuota-cab { color: var(--color-text-2); }
@media (max-width: 768px) { .cuota-movil { display: block; } }

/* ---- Reproductor de audio ---- */
.audio-vista { display: flex; flex-direction: column; align-items: center; gap: 1rem; padding: 1.5rem 0.5rem; }
.audio-icono svg { width: 4rem; height: 4rem; display: block; }
.audio-nombre { font-weight: 600; text-align: center; overflow-wrap: anywhere; }
.audio-vista audio { max-width: 32rem; }

/* ---- Reproductor de vídeo ---- */
.video-vista { display: flex; justify-content: center; }
/* Transcripción al pie del vídeo: una lista de momentos en los que se hizo clic
   para saltar. Alta fija y con su propio desplazamiento para que el vídeo no se
   vaya de la pantalla en cuanto la charla es larga. */
.transcripcion-panel { width: 100%; margin-top: 0.75rem; border-top: 1px solid var(--color-border); padding-top: 0.6rem; }
.transcripcion-lista { max-height: 14rem; overflow-y: auto; margin-top: 0.5rem; }
.transcripcion-linea { display: flex; gap: 0.6rem; width: 100%; text-align: left; padding: 0.3rem 0.4rem;
    background: none; border: 0; border-radius: var(--radius-sm); color: inherit; cursor: pointer; font: inherit; }
.transcripcion-linea:hover { background: var(--color-bg); }
.transcripcion-linea.activa { background: var(--color-bg); }
.transcripcion-min { color: var(--color-text-muted); font-variant-numeric: tabular-nums; flex: none; }
.video-vista video { width: 100%; max-height: 72vh; background: #000; border-radius: var(--radius-md); }

/* ---- Vista de CSV/TSV como tabla ---- */
.csv-vista { max-height: 72vh; overflow: auto; border: 1px solid var(--color-border); border-radius: var(--radius-md); }
.csv-tabla { border-collapse: collapse; width: max-content; min-width: 100%; font-size: var(--t-md); }
.csv-tabla th, .csv-tabla td {
    border: 1px solid var(--color-border); padding: 0.35rem 0.6rem;
    text-align: left; white-space: nowrap; max-width: 24rem;
    overflow: hidden; text-overflow: ellipsis;
}
.csv-tabla th { position: sticky; top: 0; background: var(--color-surface-2); font-weight: 600; z-index: 1; }
.csv-tabla tr:nth-child(even) td { background: color-mix(in srgb, var(--color-surface-2) 40%, transparent); }
.enlace-nombre { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.nombre-txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.nombre-linea { overflow-wrap: anywhere; }
.subtitulo { display: none; font-size: var(--t-sm); color: var(--color-text-muted); }
.file-tree .tipo-icono svg { width: 1.2rem; height: 1.2rem; }

/* ---- Botones de icono ---- */
.btn-icono {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.25rem; height: 2.25rem; flex: none; padding: 0;
    border: 1px solid transparent; border-radius: var(--radius-sm);
    background: transparent; color: var(--color-text-2); cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.btn-icono:hover { background: var(--color-surface-2); color: var(--color-text); }
.btn-icono:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }
.btn-icono svg { width: 1.2rem; height: 1.2rem; display: block; }
.btn-icono.peligro:hover { color: var(--color-danger); background: color-mix(in srgb, var(--color-danger) 14%, transparent); }
.acciones-iconos { display: inline-flex; align-items: center; gap: 0.15rem; justify-content: flex-end; }

/* ---- «Versiones» cuando el archivo TIENE historia ----
   Lo pidió Jore (2026-09-24): saber qué documentos tienen versiones sin
   abrirlos uno por uno. El botón toma el color de acento y lleva en la esquina
   cuántas anteriores guarda; sin versiones se queda gris como los demás, y es
   ese contraste —no el icono en sí— lo que salta a la vista en una lista larga.
   Donde el botón no se ve (lista en el móvil y cuadrícula), va una marca junto
   al nombre, igual que la de las firmas. */
.btn-versiones { position: relative; }
.btn-icono.con-versiones { color: var(--color-primary); }
.btn-icono.con-versiones:hover { color: var(--color-primary-h); }
.btn-icono .versiones-num {
    position: absolute; top: 0; right: 0;
    min-width: 1rem; height: 1rem; padding: 0 0.22rem; border-radius: 999px;
    background: var(--color-primary); color: var(--color-primary-fg);
    font-size: var(--t-2xs); font-weight: 700; line-height: 1rem; text-align: center;
    font-variant-numeric: tabular-nums; pointer-events: none;
}
.accion-sel.con-versiones { color: var(--color-primary); border-color: color-mix(in srgb, var(--color-primary) 55%, var(--color-border)); }
.accion-sel .versiones-num {
    min-width: 1.1rem; padding: 0 0.3rem; border-radius: 999px;
    background: var(--color-primary); color: var(--color-primary-fg);
    font-size: var(--t-2xs); font-weight: 700; line-height: 1.1rem; text-align: center;
}
.versiones-marca {
    display: inline-flex; align-items: center; gap: 0.15rem; margin-left: 0.35rem;
    color: var(--color-primary); font-size: var(--t-xs); font-weight: 600;
    vertical-align: middle; cursor: pointer; font-variant-numeric: tabular-nums;
}
.versiones-marca svg { width: 0.95em; height: 0.95em; }

/* ---- «Compartir» cuando el archivo YA se compartió ----
   Mismo lenguaje que el de versiones, con dos estados:
     · comp-compartido → color de acento y un punto: salió (enlace vigente,
       correo u otra aplicación) y no consta que lo hayan bajado.
     · comp-descargado → verde con cuántas veces se bajó.
   ⚠️ La cifra verde usa `--color-success-fg`, que cada tema define: ningún
   color único se lee sobre los siete verdes (el blanco da 2.3:1 en Oscuro y el
   negro 2.9:1 en Alto contraste). Mismo caso que `--color-primary-fg`. */
.btn-compartir { position: relative; }
.btn-icono.comp-compartido,
.accion-sel.comp-compartido { color: var(--color-primary); }
.btn-icono.comp-descargado,
.accion-sel.comp-descargado { color: var(--color-success); }
.btn-icono.comp-compartido:hover { color: var(--color-primary-h); }
.accion-sel.comp-compartido { border-color: color-mix(in srgb, var(--color-primary) 55%, var(--color-border)); }
.accion-sel.comp-descargado { border-color: color-mix(in srgb, var(--color-success) 55%, var(--color-border)); }
.btn-icono .compartido-num {
    position: absolute; top: 0; right: 0;
    min-width: 1rem; height: 1rem; padding: 0 0.22rem; border-radius: 999px;
    background: var(--color-success); color: var(--color-success-fg);
    font-size: var(--t-2xs); font-weight: 700; line-height: 1rem; text-align: center;
    font-variant-numeric: tabular-nums; pointer-events: none;
}
.accion-sel .compartido-num {
    min-width: 1.1rem; padding: 0 0.3rem; border-radius: 999px;
    background: var(--color-success); color: var(--color-success-fg);
    font-size: var(--t-2xs); font-weight: 700; line-height: 1.1rem; text-align: center;
}
.btn-icono .compartido-punto {
    position: absolute; top: 0.2rem; right: 0.2rem;
    width: 0.5rem; height: 0.5rem; border-radius: 50%;
    background: var(--color-primary); box-shadow: 0 0 0 2px var(--color-surface);
    pointer-events: none;
}
.compartido-marca {
    display: inline-flex; align-items: center; gap: 0.15rem; margin-left: 0.35rem;
    font-size: var(--t-xs); font-weight: 600; vertical-align: middle; cursor: pointer;
    font-variant-numeric: tabular-nums;
}
.compartido-marca.comp-compartido { color: var(--color-primary); }
.compartido-marca.comp-descargado { color: var(--color-success); }
.compartido-marca svg { width: 0.95em; height: 0.95em; }
.btn-con-icono { display: inline-flex; align-items: center; gap: 0.45rem; }

/* ---- Barra de acciones sobre la selección ---- */
.barra-seleccion {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
    background: var(--color-surface-2); padding: 0.5rem 0.75rem;
    border-radius: var(--radius-md); margin-top: 0.6rem;
}
.barra-conteo { font-weight: 600; }
.barra-acciones { display: flex; align-items: center; gap: 0.4rem; margin-left: auto; flex-wrap: wrap; }
.accion-sel {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.4rem 0.7rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); background: var(--color-surface);
    color: var(--color-text-2); cursor: pointer; font: inherit; font-size: var(--t-md);
    transition: background var(--transition), color var(--transition);
}
.accion-sel:hover { background: var(--color-surface-2); color: var(--color-text); }
.accion-sel svg { width: 1.1rem; height: 1.1rem; }
.accion-sel.peligro:hover { color: var(--color-danger); border-color: var(--color-danger); }
.btn-con-icono svg { width: 1.05rem; height: 1.05rem; }
.salir-icono { display: none; }
.file-list-table th.col-orden { cursor: pointer; user-select: none; }
.file-list-table th.col-orden:hover { color: var(--color-text-2); }
.file-list-table tbody tr[draggable="true"] { cursor: grab; }

/* Destino de arrastre (mover a carpeta): fila, carpeta de barra lateral o miga. */
.file-list-table tbody tr.drop-activo,
.file-tree .nodo.drop-activo,
.breadcrumb a.drop-activo {
    outline: 2px dashed var(--color-primary); outline-offset: -2px;
    background: color-mix(in srgb, var(--color-primary) 15%, transparent);
    border-radius: var(--radius-sm);
}

.drop-zone {
    border: 2px dashed var(--color-border); border-radius: var(--radius-lg);
    padding: 1.5rem; text-align: center; color: var(--color-text-muted);
    transition: border-color var(--transition), background var(--transition);
}
.drop-zone.activa { border-color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 8%, transparent); }

/* Selector de carpeta (mover/copiar). Reusa las migas del breadcrumb pero
   neutraliza su comportamiento fijo (dentro del modal es estático). */
.picker-migas { position: static; margin: 0 0 0.75rem; padding: 0; border: 0; background: none; }
.picker-nueva { margin: 0 0 0.6rem; }
.picker-nueva-form { display: flex; align-items: center; gap: 0.4rem; }
.picker-nueva-form .input { flex: 1; min-width: 0; }
.picker-lista { max-height: 45vh; overflow-y: auto; border: 1px solid var(--color-border); border-radius: var(--radius-md); margin-bottom: 1rem; }
.picker-vacio { padding: 0.9rem; margin: 0; }
.picker-item {
    display: flex; align-items: center; gap: 0.6rem; width: 100%;
    padding: 0.6rem 0.7rem; background: none; border: 0;
    border-bottom: 1px solid var(--color-border); color: var(--color-text);
    cursor: pointer; text-align: left; font: inherit;
}
.picker-item:last-child { border-bottom: 0; }
.picker-item:hover { background: var(--color-surface-2); }
.picker-nombre { flex: 1; }
.picker-item .tipo-icono svg { width: 1.3rem; height: 1.3rem; display: block; }
.picker-chevron { color: var(--color-text-muted); display: inline-flex; }
.picker-chevron svg { width: 1rem; height: 1rem; display: block; }

/* Fantasma de conteo al arrastrar varios elementos (imagen de arrastre). Se
   posiciona fuera de vista: solo se usa como setDragImage y se elimina. */
.drag-conteo {
    position: fixed; top: -1000px; left: -1000px;
    padding: 0.3rem 0.6rem; border-radius: var(--radius-md);
    background: var(--color-primary); color: var(--color-primary-fg);
    font-size: var(--t-md); font-weight: 600; white-space: nowrap;
    box-shadow: var(--shadow-md);
}

.upload-progress { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 1rem; }
.upload-progress .fila { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem; align-items: center; }

/* ---- Modal ---- */
.modal-fondo {
    position: fixed; inset: 0; background: var(--color-overlay);
    display: flex; align-items: center; justify-content: center; padding: 1rem; z-index: 70;
}
/* Diálogo que se abre SOBRE otro diálogo (p. ej. confirmar algo desde el perfil).
   Con el mismo z-index que el de abajo decidiría el orden del marcado, y salía
   DETRÁS. Por encima de los diálogos (70), por debajo de los avisos (100). */
.modal-fondo.modal-encima { z-index: 80; }
/* La vista previa es una CAPA DE FONDO, no un diálogo: lo que se abra desde ella
   —el aviso de salir de una carpeta segura, por ejemplo— tiene que quedar
   ENCIMA. Compartiendo el 70 de `.modal-fondo` decidía el orden del marcado, y
   como la vista previa va después en el documento, ganaba ella: el diálogo salía
   detrás y había que cerrar la vista para poder contestarlo (2026-08-20, lo
   reportó Jore). Por debajo de los diálogos (70) y por encima de los paneles y
   desplegables (60-63). */
.preview-capa { z-index: 64; }
.modal {
    background: var(--color-surface); color: var(--color-text);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
    width: 100%; max-width: 32rem; max-height: 90vh; overflow: auto; padding: 1.5rem;
}
.modal-titulo { margin-top: 0; font-family: var(--font-title); }

/* «Mi perfil»: los ajustes agrupados en bloques colapsables. Se usa `<details>`
   nativo (teclado y lector de pantalla salen gratis); el estado abierto lo lleva
   Alpine para que solo haya UNO abierto y se recuerde entre visitas — por eso el
   summary hace `@click.prevent`, si no la apertura nativa pelearía con `:open`. */
/* Revisar lo que se le manda a la IA: plegado de fábrica.
   La revisión sigue estando a un clic y el resumen de lo que se ocultó se ve
   siempre; lo que se pliega es la pared de texto, que en un manual de cien
   páginas nadie va a leer y solo estorba para llegar al botón de enviar. */
.ia-revisar { border: 1px solid var(--color-border); border-radius: var(--radius-md); margin: 0.6rem 0; }
.ia-revisar[open] { background: var(--color-surface-2); }
.ia-revisar-cab {
    display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
    padding: 0.55rem 0.75rem; cursor: pointer; list-style: none; user-select: none;
    border-radius: var(--radius-md); font-weight: 600;
}
.ia-revisar-cab::-webkit-details-marker { display: none; }
.ia-revisar-cab:hover { background: var(--color-surface-2); }
.ia-revisar-chev { display: inline-flex; color: var(--color-text-2); transition: transform var(--transition); }
.ia-revisar[open] .ia-revisar-chev { transform: rotate(180deg); }
.ia-revisar-cuerpo { padding: 0 0.75rem 0.75rem; }

/* ── Chat de IA ─────────────────────────────────────────────────────────
   Dos columnas: historial y conversación. El hilo desplaza por dentro y el
   redactor se queda abajo fijo, que es lo que espera uno de un chat. */
.chat-cuerpo { grid-template-columns: var(--chat-width, 280px) 5px 1fr; }
/* La capa del cajón NO existe en escritorio: `contents` la borra del árbol de
   cajas y el lateral sigue siendo, él mismo, la columna de la rejilla. */
.chat-lateral-fondo { display: contents; }
.chat-lateral-cab, .chat-abrir-historial { display: none; }
.chat-lateral { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.75rem; border-right: 1px solid var(--color-border); min-height: 0; }
.chat-nuevo { width: 100%; justify-content: center; }
/* El nivel es una elección ocasional: ocupa lo justo y no compite con el
   asistente, que es lo que se cambia a diario. */
.chat-nivel { max-width: 9rem; font-size: var(--t-md); }
.chat-erp { max-width: 12rem; font-size: var(--t-md); }
.chat-erp.activo { border-color: var(--color-primary); color: var(--color-primary); }
.chat-buscar { font-size: var(--t-md); padding: 0.35rem 0.5rem; }
.chat-lista { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 0.15rem; min-height: 0; }
.chat-vacio { font-size: var(--t-md); text-align: center; margin-top: 1rem; }
.chat-item { display: flex; align-items: center; gap: 0.15rem; border-radius: var(--radius-sm); }
.chat-item:hover { background: var(--color-surface-2); }
/* Una conversación fijada tiene que NOTARSE: van primero en la lista, pero sin
   esto los dos pines se veían idénticos y no había forma de saber cuál era
   cuál. (No existía ninguna regla `.activo` para .btn-icono: el `:class` del
   marcado no pintaba nada.) */
.chat-item .btn-icono.activo { color: var(--color-primary); opacity: 1; }
.chat-item .btn-icono.activo svg { fill: currentColor; }
.chat-item.activo { background: color-mix(in srgb, var(--color-primary) 14%, transparent); }
.chat-item-abrir { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; padding: 0.45rem 0.5rem; background: none; border: 0; color: inherit; text-align: left; cursor: pointer; font: inherit; }
/* DOS líneas, no una. El título se genera de la pregunta, y en una sola línea
   el corte cae siempre antes de lo que distingue una conversación de otra
   («Cuáles son los 10 países c…»). Con dos, ya se lee el asunto. */
.chat-item-tit {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
    overflow: hidden; font-size: var(--t-base); line-height: 1.3;
}
/* Con el título a dos líneas los botones ya no deben centrarse: quedaban
   flotando a media altura de una fila alta. */
.chat-item { align-items: flex-start; }
.chat-item .btn-icono { margin-top: 0.3rem; }
/* En escritorio hay sitio para los tres botones; el menú sobra. */
.chat-item-menu { display: none; }
.chat-item-sub { font-size: var(--t-xs); color: var(--color-text-muted); }

/* `min-height: 0` es imprescindible en los dos: sin él, un hijo que desplaza
   dentro de una rejilla estira al padre y el redactor se sale de la pantalla. */
.chat-panel { display: flex; flex-direction: column; padding: 0; min-height: 0; min-width: 0; }
.chat-hilo { flex: 1; overflow-y: auto; padding: 1rem 1.25rem; display: flex; flex-direction: column; gap: 0.75rem; min-height: 0; min-width: 0; }
.chat-bienvenida { margin: auto; text-align: center; color: var(--color-text-muted); max-width: 26rem; }
.chat-bienvenida-ic { display: inline-flex; opacity: 0.35; }
.chat-bienvenida-ic svg { width: 2.5rem; height: 2.5rem; }
.chat-msg { max-width: 100%; min-width: 0; }   /* todo el ancho del chat (Jore, 2026-10-22: las tablas se partían) */
.chat-msg-usuario { align-self: flex-end; background: color-mix(in srgb, var(--color-primary) 16%, transparent); border-radius: var(--radius-lg); padding: 0.6rem 0.9rem; }
/* Los saltos de línea que escribió la persona se respetan, pero SOLO en su
   texto: puesto en todo el globo, también contaban como renglones en blanco los
   saltos y la sangría de la plantilla (la parte de imágenes, oculta) y una
   pregunta de una línea medía 300 px (lo vio Jore, 2026-10-06). */
.chat-msg-usuario .chat-msg-cuerpo { white-space: pre-wrap; }
.chat-msg-asistente { align-self: flex-start; width: 100%; }
.chat-msg-cuerpo { line-height: 1.6; overflow-wrap: anywhere; }
.chat-msg-cuerpo > :first-child { margin-top: 0; }
.chat-msg-cuerpo > :last-child { margin-bottom: 0; }
.chat-msg-cuerpo h2 { font-size: var(--t-xl); margin: 1rem 0 0.4rem; }
.chat-msg-cuerpo h3 { font-size: var(--t-lg); margin: 0.8rem 0 0.3rem; }
.chat-msg-cuerpo ol, .chat-msg-cuerpo ul { padding-left: 1.4rem; margin: 0.5rem 0; }
.chat-msg-cuerpo blockquote { margin: 0.6rem 0; padding: 0.4rem 0.8rem; border-left: 3px solid var(--color-primary); background: var(--color-surface-2); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.chat-msg-cuerpo pre { background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.7rem 0.85rem; overflow-x: auto; font-size: var(--t-md); }
.chat-msg-cuerpo code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.88em; }
.chat-msg-cuerpo :not(pre) > code { background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: 0.3rem; padding: 0.1rem 0.35rem; }
/* La tabla, a su ancho natural (las cifras y las fechas no se parten); si no
   cabe, se desplaza de lado DENTRO de su caja (`.chat-tabla`, la pone
   chatRender) en vez de ensanchar la página. Un texto
   largo dentro de una celda sí se acomoda en renglones. */
.chat-tabla { max-width: 100%; overflow-x: auto; margin: 0.7rem 0; }
.chat-msg-cuerpo table { border-collapse: collapse; margin: 0.7rem 0; width: max-content; max-width: none; }
.chat-tabla > table { margin: 0; }
.chat-msg-cuerpo th, .chat-msg-cuerpo td { border: 1px solid var(--color-border); padding: 0.35rem 0.55rem; text-align: left; max-width: 28rem; }
.chat-msg-cuerpo th { background: var(--color-surface-2); }
.chat-msg-cuerpo img { max-width: 100%; border-radius: var(--radius-md); }
.chat-pensando, .chat-error { align-self: flex-start; font-size: var(--t-md); }

/* Imagen generada. El ancho lo manda el contenedor: en el móvil una de 1024px
   se saldría de la pantalla. */
.chat-imagen {
    margin: 0;
    /* NADA de `width: fit-content` aquí: el ancho preferido de la figura pasa a
       ser el de la imagen (1024px), y en una rejilla cuyo mínimo automático es
       `auto` eso ensancha la columna entera y saca la pantalla del móvil. */
    max-width: 100%;
    min-width: 0;
}
.chat-imagen img {
    display: block;
    max-width: 100%;
    height: auto;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
}
.chat-imagen figcaption {
    margin-top: 0.4rem;
    font-size: var(--t-sm);
    color: var(--color-text-2);
    line-height: 1.35;
}
/* Pulsar la imagen no la descarga: despliega dónde quedó guardada, porque
   saber que está en sus archivos es lo que hace útil guardarla ahí. */
.chat-imagen img { cursor: pointer; }
/* El aviso se ciñe al ancho de la IMAGEN, no del mensaje: así se lee como parte
   de ella. Se hace sobre el propio aviso —no sobre la figura— porque poner un
   ancho intrínseco en la figura desborda la rejilla en pantallas estrechas. */
.chat-imagen-ubic {
    width: fit-content;
    max-width: 100%;
    margin-top: 0.45rem;
    padding: 0.6rem 0.75rem;
    background: var(--color-surface-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: var(--t-sm);
    line-height: 1.4;
}
.chat-imagen-ubic p { margin: 0 0 0.45rem; }
.chat-imagen-nombre {
    color: var(--color-text-2);
    word-break: break-word;
}
.chat-imagen-ubic .btn svg { width: 0.95rem; height: 0.95rem; }
/* En el móvil los dos botones no caben de lado a lado: se envuelven. */
.chat-imagen-acc { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.chat-imagen-acc .btn { text-decoration: none; }
.chat-imagen-ida {
    margin: 0;
    font-size: var(--t-sm);
    color: var(--color-text-2);
    font-style: italic;
}

/* Documentos adjuntos a la conversación, encima de la barra de escribir: se ve
   sobre qué está respondiendo la IA sin tener que recordarlo. */
.chat-adjuntos {
    display: flex; flex-wrap: wrap; gap: 0.35rem;
    padding: 0.5rem 1.25rem 0;
    min-width: 0;
}
.chat-adjunto {
    display: inline-flex; align-items: center; gap: 0.3rem;
    max-width: 100%;
    padding: 0.2rem 0.3rem 0.2rem 0.45rem;
    border: 1px solid var(--color-border); border-radius: 999px;
    background: var(--color-surface-2);
    font-size: var(--t-sm);
}
.chat-adjunto svg { width: 0.85rem; height: 0.85rem; flex: none; }
.chat-adjunto-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.chat-adjunto-x {
    border: 0; background: none; color: var(--color-text-2);
    font-size: var(--t-lg); line-height: 1; padding: 0 0.15rem; cursor: pointer; flex: none;
}
.chat-adjunto-x:hover { color: var(--color-danger); }
.chat-aviso { align-self: flex-start; font-size: var(--t-sm); color: var(--color-text-2); font-style: italic; }
.chat-clip { flex: none; }
/* Aviso del selector cuando adjunta al chat: sin él, que falte una carpeta
   segura parece un fallo. */
.picker-nota {
    margin: 0 0 0.5rem; font-size: var(--t-sm); line-height: 1.35;
    color: var(--color-text-2);
}
.chat-redactar { display: flex; align-items: flex-end; gap: 0.4rem; padding: 0.7rem 1.25rem; border-top: 1px solid var(--color-border); background: var(--color-surface); }
.chat-asistente { flex: 0 0 auto; max-width: 12rem; }
.chat-entrada { flex: 1; resize: none; max-height: 8rem; }
.chat-enviar { flex: none; }
/* Dictar la pregunta (2026-10-20): el mismo gesto que el micrófono de Mensajes. */
.chat-mic { touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; transition: transform 0.15s; }
.chat-mic.grabando { transform: scale(1.25); background: var(--color-danger) !important; border-color: var(--color-danger) !important; color: #fff; }
.chat-entrada.dictando { border-color: var(--color-danger); }
.chat-dictar-x { flex: none; }
/* Escuchar una respuesta: discreto, debajo de ella. */
.chat-escuchar {
    display: inline-flex; align-items: center; gap: 0.35rem; margin-top: 0.35rem; padding: 0.2rem 0.45rem;
    font-size: var(--t-sm); color: var(--color-text-muted); background: none; border: 0; border-radius: var(--radius-sm); cursor: pointer;
}
.chat-escuchar svg { width: 1rem; height: 1rem; }
.chat-escuchar:hover, .chat-escuchar.activo { color: var(--color-primary); background: var(--color-surface-2); }
.chat-escuchar:disabled { opacity: 0.6; cursor: progress; }

/* Bloque de código de una respuesta: cabecera con el lenguaje y «Copiar». */
.chat-codigo { border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; margin: 0.7rem 0; }
.chat-codigo-cab { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.25rem 0.5rem 0.25rem 0.7rem; background: var(--color-surface-2); border-bottom: 1px solid var(--color-border); }
.chat-codigo-lang { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); }
.chat-copiar { border: 0; background: none; color: var(--color-text-2); font: inherit; font-size: var(--t-sm); padding: 0.2rem 0.45rem; border-radius: var(--radius-sm); cursor: pointer; }
.chat-copiar:hover { background: var(--color-surface); color: var(--color-text); }
.chat-copiar.copiado { color: var(--color-success); }
.chat-codigo pre { margin: 0; border: 0; border-radius: 0; }

/* Colores del código. Se mapean las clases de highlight.js a la paleta del
   sistema en vez de traer su hoja de estilos: así el resaltado cambia con el
   tema (día/noche/los demás) en lugar de quedarse con los colores de otro. */
.hljs-comment, .hljs-quote { color: var(--color-text-muted); font-style: italic; }
.hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-section, .hljs-doctag, .hljs-type { color: #c792ea; }
.hljs-string, .hljs-regexp, .hljs-addition, .hljs-attribute, .hljs-meta .hljs-string { color: #a5d6a7; }
.hljs-number, .hljs-symbol, .hljs-bullet, .hljs-link { color: #f78c6c; }
.hljs-title, .hljs-name, .hljs-selector-id, .hljs-selector-class, .hljs-title.function_ { color: #82aaff; }
.hljs-variable, .hljs-template-variable, .hljs-attr, .hljs-property { color: #ffcb6b; }
.hljs-built_in, .hljs-class .hljs-title { color: #89ddff; }
.hljs-deletion { color: var(--color-danger); }
.hljs-emphasis { font-style: italic; }
.hljs-strong { font-weight: 600; }

/* Chat: temas en el lateral, cabecera de la conversación y editor de asistentes. */
.chat-temas { display: flex; flex-direction: column; gap: 0.1rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--color-border); }
.chat-temas-cab { display: flex; align-items: center; justify-content: space-between; font-size: var(--t-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); }
.chat-tema-nuevo { margin: 0.2rem 0; }
.chat-tema-fila { display: flex; align-items: center; gap: 0.1rem; }
.chat-tema { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; padding: 0.3rem 0.45rem; border: 0; border-radius: var(--radius-sm); background: none; color: inherit; font: inherit; font-size: var(--t-md); text-align: left; cursor: pointer; }
.chat-tema:hover { background: var(--color-surface-2); }
.chat-tema.activo { background: color-mix(in srgb, var(--color-primary) 14%, transparent); color: var(--color-primary); font-weight: 600; }
.chat-tema-n { flex: none; font-size: var(--t-xs); color: var(--color-text-muted); }
.chat-tema-fila .btn-icono { opacity: 0; }
.chat-tema-fila:hover .btn-icono, .chat-tema-fila .btn-icono:focus-visible { opacity: 1; }
/* Sin «hover» (teléfono, tableta) el botón de borrar se ve siempre, discreto. */
@media (hover: none) { .chat-tema-fila .btn-icono { opacity: 0.6; } }

.chat-cabecera { display: flex; align-items: center; gap: 0.5rem; padding: 0.55rem 1.25rem; border-bottom: 1px solid var(--color-border); }
/* El título ES el botón de renombrar: un lápiz aparte sería un icono más que
   adivinar, y aquí el gesto natural es tocar el título. */
.chat-titulo { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; background: none; border: 0; color: inherit; font: inherit; font-weight: 600; cursor: text; padding: 0.2rem 0.3rem; border-radius: var(--radius-sm); }
.chat-titulo:hover { background: var(--color-surface-2); }
.chat-titulo-in { flex: 1; font-weight: 600; }
.chat-tema-sel, .chat-cabecera .chat-asistente { max-width: 11rem; font-size: var(--t-md); min-width: 0; }
.chat-titulo-nueva { color: var(--color-text-muted); cursor: default; }
.chat-asistente-cfg { flex: none; }

.chat-asist-lista { display: flex; flex-direction: column; gap: 0.15rem; margin-top: 1.25rem; padding-top: 0.75rem; border-top: 1px solid var(--color-border); }
.chat-asist-item { display: flex; align-items: center; gap: 0.4rem; padding: 0.35rem 0.4rem; border-radius: var(--radius-sm); }
.chat-asist-item:hover { background: var(--color-surface-2); }
.chat-asist-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Admin de empresa: el selector de sección en móvil. El desplegable ocupa todo
   el ancho para que se lea de un vistazo en qué sección estás — el nombre es el
   rótulo del botón, no algo que haya que abrir para averiguar. */
.admin-secciones { display: none; width: 100%; }
.admin-secciones-btn { width: 100%; justify-content: flex-start; }
.admin-secciones .menu-pop { left: 0; right: 0; min-width: 0; }

.perfil-grupo { border: 1px solid var(--color-border); border-radius: var(--radius-md); margin-bottom: 0.6rem; background: var(--color-surface); }
.perfil-grupo[open] { background: var(--color-surface-2); }
.perfil-grupo-cab {
    display: grid; grid-template-columns: 1fr auto; align-items: center;
    gap: 0.15rem 0.6rem; padding: 0.7rem 0.85rem; cursor: pointer;
    list-style: none; user-select: none; border-radius: var(--radius-md);
}
.perfil-grupo-cab::-webkit-details-marker { display: none; } /* el triángulo de serie */
.perfil-grupo-cab:hover { background: var(--color-surface-2); }
.perfil-grupo-tit { font-weight: 600; }
/* El subtítulo dice qué hay DENTRO: cerrado, un bloque sin pistas obliga a
   abrirlos todos para encontrar algo. */
.perfil-grupo-sub { grid-column: 1; font-size: var(--t-sm); color: var(--color-text-muted); line-height: 1.35; }
.perfil-grupo-chev { grid-column: 2; grid-row: 1 / span 2; display: inline-flex; color: var(--color-text-2); transition: transform var(--transition); }
.perfil-grupo-chev svg { width: 1.1rem; height: 1.1rem; }
.perfil-grupo[open] .perfil-grupo-chev { transform: rotate(180deg); }
.perfil-grupo-cuerpo { padding: 0.2rem 0.85rem 0.85rem; }
.perfil-grupo-cuerpo > h3:first-child { margin-top: 0.3rem; }
.modal-acciones { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1.5rem; }

/* ── IA de correo: panel de revisión previa ──
   El texto que se enviará se muestra en monoespaciada y con los saltos respetados: es un
   PAYLOAD que el usuario debe poder auditar, no prosa. Se limita la altura para que el
   botón de enviar quede siempre visible y nadie acepte sin haber podido mirar. */
.ia-modal { max-width: 44rem; }
.ia-sub { margin: 1rem 0 0.25rem; font-size: var(--t-lg); }
.ia-envio {
    max-height: 15rem; overflow: auto; margin: 0.5rem 0 0.75rem; padding: 0.7rem;
    background: var(--color-surface-2); border: 1px solid var(--color-border);
    border-radius: var(--radius-md); font-family: var(--font-mono); font-size: var(--t-sm);
    white-space: pre-wrap; word-break: break-word;
}
.ia-resultado { font-family: var(--font-sans); font-size: var(--t-base); max-height: 22rem; }
/* La instrucción se muestra aparte del texto: son las DOS mitades de la petición. */
.ia-instruccion { max-height: 8rem; font-family: var(--font-sans); border-left: 3px solid var(--color-primary); }
.ia-etiquetas { display: inline-flex; flex-wrap: wrap; gap: 0.3rem; margin-left: 0.4rem; }
/* Nombres propuestos. Los MARCADOS se ven distintos de los meramente sugeridos: el usuario
   tiene que poder saber de un vistazo qué está protegido y qué no, sin releer el texto. */
.ia-nombres { margin-top: 0.75rem; }
.ia-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.4rem; }
.ia-chip { display: inline-flex; align-items: stretch; border: 1px solid var(--color-border);
    border-radius: var(--radius-full); overflow: hidden; font-size: var(--t-md); }
.ia-chip button { border: none; background: transparent; color: var(--color-text-2);
    padding: 0.15rem 0.6rem; cursor: pointer; display: inline-flex; align-items: center; gap: 0.3rem; }
.ia-chip button:hover { background: var(--color-surface-2); }
.ia-chip.activo { border-color: var(--color-success); }
.ia-chip.activo > button:first-child { background: var(--color-success); color: #fff; }
.ia-chip.activo svg { width: 0.85rem; height: 0.85rem; }
.ia-chip-mas { font-size: var(--t-sm); border-left: 1px solid var(--color-border) !important; }

/* El aviso de alcance NO es decorativo: dice qué NO protege el enmascarado. */
.ia-aviso {
    margin: 0.75rem 0 0; padding: 0.6rem 0.7rem; font-size: var(--t-md);
    border-left: 3px solid var(--color-warning); background: var(--color-surface-2);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0; color: var(--color-text-2);
}
/* Editor de texto en la web. */
.modal-ancho { max-width: 60rem; }
/* Editor Office (Collabora): ocupa casi toda la ventana. */
.modal-office { max-width: 98vw; width: 98vw; height: 95vh; max-height: 95vh; padding: 0.75rem; overflow: hidden; }
.office-caja { display: flex; flex-direction: column; height: 100%; }
.office-frame { flex: 1 1 auto; width: 100%; border: 0; border-radius: var(--radius-md); background: #fff; }

/* ── Mis Notas (tipo Keep) ─────────────────────────────────────────────── */
/* Colores post-it: pastel con texto oscuro (legible en tema día y noche,
   como un post-it físico). «default» sí sigue el tema de la app. */
.nota-color-default  { --nota-bg: var(--color-surface); --nota-fg: var(--color-text); --nota-bd: var(--color-border); }
.nota-color-rojo     { --nota-bg: #f28b82; --nota-fg: #202124; --nota-bd: #e06055; }
.nota-color-naranja  { --nota-bg: #fbbc04; --nota-fg: #202124; --nota-bd: #e0a800; }
.nota-color-amarillo { --nota-bg: #fff475; --nota-fg: #202124; --nota-bd: #e6d84f; }
.nota-color-verde    { --nota-bg: #ccff90; --nota-fg: #202124; --nota-bd: #a5e673; }
.nota-color-azul     { --nota-bg: #cbf0f8; --nota-fg: #202124; --nota-bd: #a0dbe8; }
.nota-color-morado   { --nota-bg: #d7aefb; --nota-fg: #202124; --nota-bd: #bd8ef0; }
.nota-color-rosa     { --nota-bg: #fdcfe8; --nota-fg: #202124; --nota-bd: #f0a9d0; }
.nota-color-gris     { --nota-bg: #e8eaed; --nota-fg: #202124; --nota-bd: #c8ccd0; }

/* Una nota de color es SIEMPRE papel claro, también con el tema oscuro. Los
   campos de dentro tienen que saberlo: si toman el fondo del tema, plantan una
   barra negra en mitad del papel (así se veía la fecha del recordatorio). Solo
   «default» sigue al tema, porque esa nota SÍ es del color de la aplicación. */
.nota-color-rojo, .nota-color-naranja, .nota-color-amarillo, .nota-color-verde,
.nota-color-azul, .nota-color-morado, .nota-color-rosa, .nota-color-gris {
    --nota-esquema: light;
    --nota-campo-bg: rgba(255, 255, 255, 0.6);
}
.nota-color-default { --nota-esquema: normal; --nota-campo-bg: var(--color-surface); }

/* `color-scheme` NO sobra: las partes NATIVAS del campo de fecha —el
   «dd/mm/aaaa», los dos puntos, el icono del calendario— las pinta el navegador
   con su propia paleta y no hay `color` que las alcance. */
.nota-editor .input, .nota-editor .select, .nota-editor .textarea {
    color-scheme: var(--nota-esquema, normal);
    color: var(--nota-fg);
    background: var(--nota-campo-bg);
    border-color: var(--nota-bd);
}
.nota-editor .input::placeholder, .nota-editor .textarea::placeholder { color: var(--nota-fg); opacity: 0.55; }

.notas-cuerpo { display: grid; grid-template-columns: var(--notas-width, 220px) 5px 1fr; min-height: 0; }
.notas-filtros { padding: 1rem 0.5rem; border-right: 1px solid var(--color-border); display: flex; flex-direction: column; gap: 0.15rem; overflow-y: auto; }
.notas-filtro { display: flex; align-items: center; gap: 0.6rem; padding: 0.55rem 0.9rem; border: 0; background: transparent; color: var(--color-text); border-radius: 2rem; cursor: pointer; text-align: left; width: 100%; font-size: var(--t-base); }
.notas-filtro:hover { background: var(--color-bg); }
.notas-filtro.activo { background: color-mix(in srgb, var(--color-primary) 16%, transparent); color: var(--color-primary); font-weight: 600; }
.notas-filtro svg { width: 1.15rem; height: 1.15rem; flex: 0 0 auto; }
.notas-filtro-n { font-size: var(--t-xs); opacity: 0.6; }
/* Cada etiqueta del panel lleva sus acciones (renombrar y borrar) al lado. Se
   revelan al pasar por encima —o siempre, en pantallas táctiles, donde no hay
   «pasar por encima»— para que la lista no parezca un panel de mandos. */
.notas-filtro-fila { display: flex; align-items: center; gap: 0.15rem; }
.notas-filtro-fila .notas-filtro { flex: 1 1 auto; min-width: 0; }
.notas-filtro-fila .notas-filtro span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notas-filtro-accs { display: flex; gap: 0.1rem; opacity: 0; transition: opacity 0.12s; flex: none; }
.notas-filtro-fila:hover .notas-filtro-accs,
.notas-filtro-fila:focus-within .notas-filtro-accs { opacity: 1; }
@media (hover: none) { .notas-filtro-accs { opacity: 1; } }

.notas-nueva { max-width: 36rem; margin: 0 auto 1.5rem; }
.notas-nueva-ph { width: 100%; padding: 0.7rem 0.9rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text); box-shadow: var(--shadow-sm); cursor: text; box-sizing: border-box; }
/* Barrita para cerrar la nota abierta: se toca o se arrastra hacia abajo. Zona
   de toque alta (la barra visible es fina, pero el área sensible no) porque en
   el teléfono es la forma principal de cerrar. */
.nota-tirador { display: flex; align-items: center; justify-content: center; height: 1.6rem; margin: -0.35rem -0.35rem 0.1rem; cursor: grab; touch-action: none; }
.nota-tirador:active { cursor: grabbing; }
.nota-tirador > span { display: block; width: 2.5rem; height: 4px; border-radius: 999px; background: currentColor; opacity: 0.3; transition: opacity var(--transition), width var(--transition); }
.nota-tirador:hover > span, .nota-tirador:focus-visible > span { opacity: 0.55; width: 3.2rem; }
.nota-tirador:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: var(--radius-sm); }

.nota-editor { background: var(--nota-bg); color: var(--nota-fg); border: 1px solid var(--nota-bd); border-radius: var(--radius-md); padding: 0.6rem 0.75rem; box-shadow: var(--shadow-md); }
.nota-titulo-in, .nota-cont-in { width: 100%; background: transparent; border: 0; color: inherit; font-family: inherit; outline: none; box-sizing: border-box; }
.nota-titulo-in { font-weight: 600; font-size: var(--t-lg); margin-bottom: 0.3rem; }
.nota-cont-in { resize: vertical; min-height: 3.5rem; font-size: var(--t-lg); white-space: pre-wrap; line-height: 1.4; }
/* Nota con formato: el editor es un contenteditable que hereda el color del
   post-it (no el blanco del correo), y la barra de Redactar va encima, sin marco. */
.nota-rt-editor { min-height: 26vh; max-height: 52vh; overflow-y: auto; cursor: text; overflow-wrap: anywhere; }
.nota-rt-editor[contenteditable="false"] { cursor: default; }
.nota-rt-editor:empty::before { content: attr(data-ph); color: currentColor; opacity: 0.55; }
.nota-rt-editor ul, .nota-rt-editor ol, .nota-card-html ul, .nota-card-html ol { margin: 0.2rem 0; padding-left: 1.4rem; }
.nota-rt-editor blockquote, .nota-card-html blockquote { margin: 0.2rem 0 0.2rem 0.4rem; padding-left: 0.6rem; border-left: 2px solid currentColor; opacity: 0.8; }
.nota-rt-editor a, .nota-card-html a { color: inherit; text-decoration: underline; }
.buzon-rt-barra.nota-rt-barra { border: 0; border-bottom: 1px solid color-mix(in srgb, currentColor 18%, transparent); border-radius: 0; background: transparent; padding: 0.15rem 0; margin-bottom: 0.3rem; }
/* ⚠️ TODO lo de la barra hereda el color DEL POST-IT, no el del tema: en tema
   oscuro `--color-text` es claro, y sobre una nota amarilla los iconos de «Tipo
   de letra» y «Tamaño» —que lo traían fijo— desaparecían (lo reportó Jore,
   2026-09-20). Lo mismo los separadores y el sombreado al pasar el cursor. */
.nota-rt-barra .buzon-rt-btn, .nota-rt-barra .buzon-rt-icosel { color: inherit; }
.nota-rt-barra .buzon-rt-sep { background: currentColor; opacity: 0.25; }
.nota-rt-barra .buzon-rt-btn:hover, .nota-rt-barra .buzon-rt-icosel:hover,
.nota-rt-barra .buzon-rt-btn.buzon-rt-mas.activo { background: color-mix(in srgb, currentColor 14%, transparent); }
.nota-rt-barra .buzon-rt-btn.buzon-rt-mas { background: transparent; }
.nota-titulo-in::placeholder, .nota-cont-in::placeholder { color: currentColor; opacity: 0.55; }
.nota-barra { display: flex; align-items: center; gap: 0.35rem; margin-top: 0.5rem; flex-wrap: wrap; }
.nota-colores { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.nota-color-pt { width: 1.35rem; height: 1.35rem; border-radius: 50%; border: 2px solid rgba(0,0,0,0.18); background: var(--nota-bg); cursor: pointer; padding: 0; }
.nota-color-pt.sel { border-color: #202124; box-shadow: 0 0 0 2px #fff inset; }
/* Selector de color como menú (ahorra espacio en la barra, sobre todo en móvil) */
.nota-color-trigger { padding: 0; opacity: 1; }
/* Anillo arcoíris fijo: el color actual coincide con el fondo del editor y se
   camuflaría; este disco siempre es visible y se lee como «colores». */
.nota-color-actual { display: block; width: 1.4rem; height: 1.4rem; border-radius: 50%; border: 1px solid rgba(0,0,0,0.3); background: conic-gradient(#f28b82, #fbbc04, #fff475, #ccff90, #cbf0f8, #d7aefb, #fdcfe8, #f28b82); }
.nota-color-pop { flex-direction: row; flex-wrap: wrap; gap: 0.45rem; width: max-content; min-width: 0; max-width: 14rem; top: auto; bottom: calc(100% + 0.35rem); }
.nota-color-pop .nota-color-pt { width: 1.6rem; height: 1.6rem; }
/* El menú de acciones se abre HACIA ARRIBA, como el de color: la barra vive al
   pie del editor, que es un modal con `overflow: auto`, así que hacia abajo el
   menú queda cortado por el propio modal (comprobado renderizándolo). Con tope
   de alto y desplazamiento por si algún día crece o la pantalla es muy baja. */
.nota-acciones-pop { top: auto; bottom: calc(100% + 0.35rem); max-height: 60vh; overflow-y: auto; }

.notas-grid { columns: 240px; column-gap: 0.9rem; }
/* Mientras se arrastra el tirador la cuadrícula conserva su ancho (ver panelResizeIniciar): si
   el panel de etiquetas crece, lo que no cabe se corta en vez de sacar una barra de lado. */
.notas-cuerpo.redimensionando > .contenido { overflow-x: hidden; }
/* Papelera de Notas: el aviso y «Vaciar papelera», arriba de la cuadrícula. */
.notas-papelera-barra { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.6rem; margin: 0 0 0.9rem; font-size: var(--t-base); }
.nota-card { break-inside: avoid; width: 100%; margin: 0 0 0.9rem; background: var(--nota-bg); color: var(--nota-fg); border: 1px solid var(--nota-bd); border-radius: var(--radius-md); padding: 0.75rem 0.85rem; cursor: pointer; position: relative; box-shadow: var(--shadow-sm); transition: box-shadow 0.15s; }
.nota-card:hover { box-shadow: var(--shadow-md); }
.nota-card-titulo { font-weight: 600; margin-bottom: 0.25rem; word-break: break-word; padding-right: 1.2rem; }
.nota-card-cont { white-space: pre-wrap; word-break: break-word; font-size: var(--t-base); line-height: 1.4; max-height: 14rem; overflow: hidden; }
.nota-pin { position: absolute; top: 0.5rem; right: 0.5rem; width: 1rem; height: 1rem; opacity: 0.75; display: inline-flex; }
.nota-card-etqs { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.5rem; }
.nota-etq { font-size: var(--t-xs); background: rgba(0,0,0,0.09); border-radius: 1rem; padding: 0.12rem 0.55rem; }
.nota-etq-quita { cursor: pointer; }
.nota-etq-quita:hover { background: rgba(0,0,0,0.18); }
.nota-acciones { display: flex; gap: 0.15rem; margin-top: 0.5rem; opacity: 0; transition: opacity 0.15s; }
.nota-card:hover .nota-acciones, .nota-acciones:focus-within { opacity: 1; }
.nota-acc { background: transparent; border: 0; cursor: pointer; color: inherit; opacity: 0.7; width: 1.9rem; height: 1.9rem; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; padding: 0; }
.nota-acc:hover { background: rgba(0,0,0,0.1); opacity: 1; }
.nota-acc.activo { opacity: 1; }
/* El reproductor del audio QUE PREPARA EL SERVIDOR (leer la nota en voz alta).
   Se llama `.nota-voz` y no `.nota-audio` a propósito: `.nota-audio` ya existe
   más abajo y es otra cosa —los audios GRABADOS que la persona adjunta—. */
.nota-voz { margin: 0.5rem 0 0; }
.nota-voz audio { height: 2.2rem; }
/* La bocina de la tarjeta cerrada (solo cuando su audio ya está hecho). */
.nota-card-audio { margin: 0.4rem 0 0; cursor: default; }
.nota-card-audio audio { height: 2rem; }
/* El reproductor lo pinta el navegador entero, con su propia paleta: sobre un
   papel de color hay que decirle que la de aquí es clara, o planta una pastilla
   negra en la nota (lo mismo que pasaba con la fecha). */
.nota-card-audio audio, .nota-voz audio { color-scheme: var(--nota-esquema, normal); max-width: 100%; }

/* Entrar en el teléfono con un QR. */
.vinc-caja { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 1rem; max-width: 22rem; text-align: center; }
/* El QR llega como SVG del servidor. Fondo blanco SIEMPRE: con el tema oscuro
   un código sobre fondo negro no lo lee ninguna cámara. */
.vinc-qr { background: #fff; padding: 0.6rem; border-radius: 8px; display: inline-block; line-height: 0; }
.vinc-qr svg { width: 200px; height: 200px; display: block; }
.vinc-nums { display: flex; gap: 0.5rem; justify-content: center; }
.vinc-num { flex: 1; font-size: var(--t-3xl); font-weight: 700; padding: 0.7rem 0; font-variant-numeric: tabular-nums; }
.vinc-ok { color: var(--color-success); }
.vinc-mal { color: var(--color-danger); }

/* «No escucho nada»: la ayuda de la muestra de voz, plegada hasta que hace
   falta. Se abre sola cuando el navegador no dejó sonar el ejemplo. */
.voz-ayuda { margin: 0.6rem 0 0; font-size: var(--t-md); color: var(--color-text-muted); }
.voz-ayuda summary { cursor: pointer; width: fit-content; }
.voz-ayuda p { margin: 0.5rem 0; }
.voz-ayuda ul { margin: 0.4rem 0; padding-left: 1.1rem; }
.voz-ayuda li { margin: 0.25rem 0; }
.nota-acc svg { width: 1.05rem; height: 1.05rem; }
.nota-etq-menu { margin: 0.5rem 0; font-size: var(--t-base); }
.nota-etq-menu summary { cursor: pointer; opacity: 0.85; }
/* El mismo selector, pero como menú de Alpine (el <details> nativo se quedaba
   abierto). El desplegable flota sobre el editor para no empujar la barra de
   acciones hacia abajo mientras se elige. */
.nota-etq-menu-wrap { position: relative; margin: 0.5rem 0; font-size: var(--t-base); }
.nota-etq-boton { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.3rem 0.5rem; background: none; border: 0; color: var(--color-text); opacity: 0.85; cursor: pointer; font: inherit; border-radius: var(--radius-sm); }
.nota-etq-boton:hover { background: var(--color-surface-2); opacity: 1; }
.nota-etq-chevron { display: inline-flex; width: 0.9rem; height: 0.9rem; transition: transform 0.12s; }
.nota-etq-chevron.abierto { transform: rotate(90deg); }
/* La posición real la calcula anclarMenuFlotante (fixed, con la altura que
   quepa); esto es el aspecto y el punto de partida. `min-width` con `max-width`
   para que en el teléfono no se salga por el lado. */
.nota-etq-menu-wrap .nota-etq-lista { position: absolute; z-index: 60; left: 0; top: 100%; min-width: 14rem; max-width: calc(100vw - 2rem); max-height: 15rem; overflow-y: auto; overscroll-behavior: contain; padding: 0.5rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); }
.nota-etq-listo { width: 100%; margin-top: 0.5rem; }
/* Miniatura del archivo adjuntado ANTES de guardar la nota. */
.nota-arch-mini { width: 2rem; height: 2rem; object-fit: cover; border-radius: var(--radius-sm); flex: none; }
.nota-etq-lista { padding: 0.4rem 0; display: flex; flex-direction: column; gap: 0.2rem; max-height: 12rem; overflow: auto; }
.nota-etq-op { display: flex; align-items: center; gap: 0.5rem; }
.nota-etq-check { flex: 1; min-width: 0; display: flex; align-items: center; gap: 0.5rem; cursor: pointer; }
.nota-etq-acc { display: inline-flex; align-items: center; justify-content: center; width: 1.7rem; height: 1.7rem; padding: 0; background: none; border: none; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-sm); flex: none; }
.nota-etq-acc svg { width: 0.95rem; height: 0.95rem; }
.nota-etq-acc:hover { background: var(--color-surface-2); color: var(--color-text); }
.nota-etq-acc-del:hover { color: #ef4444; }
/* Archivos de «Mis archivos» adjuntos por referencia. */
.nota-archivos { display: flex; flex-direction: column; gap: 0.35rem; margin: 0.4rem 0; }
.nota-arch { display: flex; align-items: center; gap: 0.3rem; }
.nota-arch-abrir { flex: 1; min-width: 0; display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.5rem; background: rgba(0,0,0,0.05); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; color: inherit; font: inherit; text-align: left; }
.nota-arch-abrir:hover:not(:disabled) { border-color: var(--color-primary); }
.nota-arch-abrir:disabled { cursor: default; opacity: 0.7; }
.nota-arch-mini { width: 2rem; height: 2rem; object-fit: cover; border-radius: var(--radius-sm); flex: none; }
.nota-arch-ic { display: inline-flex; width: 1.1rem; height: 1.1rem; color: var(--color-text-muted); flex: none; }
.nota-arch-ic svg { width: 100%; height: 100%; }
.nota-arch-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-base); }
.nota-arch-no-etq { font-size: var(--t-2xs); color: #ef4444; flex: none; }
.nota-arch-no .nota-arch-nom { text-decoration: line-through; color: var(--color-text-muted); }
/* Chips de archivos en la tarjeta (solo lectura). */
.nota-card-arch { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.35rem; }
.nota-arch-chip { display: inline-flex; align-items: center; gap: 0.3rem; max-width: 100%; font-size: var(--t-xs); background: rgba(0,0,0,0.09); border-radius: 0.5rem; padding: 0.12rem 0.5rem; }
.nota-arch-chip-ic { display: inline-flex; width: 0.85rem; height: 0.85rem; flex: none; }
.nota-arch-chip-ic svg { width: 100%; height: 100%; }
.nota-arch-chip-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nota-arch-chip.nota-arch-no .nota-arch-chip-nom { text-decoration: line-through; opacity: 0.7; }
/* Archivo seleccionable en el picker de adjuntar. */
.picker-archivo .picker-adj { margin-left: auto; font-size: var(--t-sm); color: var(--color-primary); flex: none; }
.picker-archivo:disabled { opacity: 0.55; cursor: default; }
.picker-archivo:disabled .picker-adj { color: var(--color-text-muted); }

/* ── Buzón: cliente de correo light (Fase 1) ── */
.buzon { max-width: 900px; margin: 0 auto; }
/* `position: relative` + z-index: sin esto, los desplegables de esta cabecera
   (el de «Ver») quedaban DEBAJO del panel del lector, que se dibuja después y
   les pasaba por encima. */
.buzon-cab { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.9rem; position: relative; z-index: 45; }
.buzon-cuenta { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-md); }
.buzon-lista { display: flex; flex-direction: column; border: 1px solid var(--color-border); border-radius: var(--radius-lg); overflow: hidden; background: var(--color-surface); }
/* ── Vista de conversación (§25.9) ────────────────────────────────────────
   La PILA detrás del avatar dice «aquí hay más de uno» antes de leer la cifra;
   con dos bordes basta, tres ya es ruido. */
.buzon-avatar-pila { position: relative; }
.buzon-avatar-pila::before,
.buzon-avatar-pila::after {
    content: ''; position: absolute; inset: 0; border-radius: 50%;
    border: 1px solid var(--color-border); background: var(--color-surface-2); z-index: -1;
}
.buzon-avatar-pila::before { transform: translate(3px, 3px); }
.buzon-avatar-pila::after { transform: translate(6px, 6px); opacity: 0.55; }
.buzon-hilo-n {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 1.35rem; height: 1.1rem; padding: 0 0.3rem; flex: none;
    border: 1px solid var(--color-border); border-radius: 999px;
    font-size: var(--t-xs); font-weight: 700; color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}
.buzon-hilo-n.con-nuevos { border-color: var(--color-primary); color: var(--color-primary); }

.buzon-hilo { flex: 1; min-height: 0; overflow-y: auto; }
.buzon-hilo-msg { border-bottom: 1px solid var(--color-border); }
.buzon-hilo-cab {
    display: flex; align-items: center; gap: 0.6rem; width: 100%;
    padding: 0.5rem 0.9rem; background: var(--color-surface-2);
    border: 0; cursor: pointer; color: inherit; font: inherit; text-align: left;
}
.buzon-hilo-msg.abierto .buzon-hilo-cab { background: var(--color-surface); }
.buzon-hilo-cab .buzon-avatar { width: 1.7rem; height: 1.7rem; font-size: var(--t-xs); }
.buzon-hilo-de { font-weight: 600; font-size: var(--t-md); flex: none; }
.buzon-hilo-prev {
    font-size: var(--t-sm); color: var(--color-text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.buzon-hilo-cuerpo { padding: 0.2rem 0.9rem 1rem 3.2rem; }

/* Deslizar un correo para marcarlo leído/no leído (ver app.js).
   El renglón va dentro de `.buzon-fila`, que recorta y aloja el fondo que
   asoma. Por eso el borde de separación pasa a la ENVOLTURA: en el botón se
   movería con él y la lista parecería descoserse. Y por eso el botón lleva
   fondo OPACO: sin él, el aviso de debajo se transparentaría en todo el ancho
   y no se entendería nada. */
.buzon-fila { position: relative; overflow: hidden; border-bottom: 1px solid var(--color-border); }
.buzon-fila:last-child { border-bottom: none; }
.buzon-desliz {
    position: absolute; inset: 0; display: flex; align-items: center; gap: 0.45rem;
    padding: 0 1.1rem; background: var(--color-primary); color: #fff;
    font-size: var(--t-md); font-weight: 600;
}
.buzon-desliz.der { justify-content: flex-start; }
.buzon-desliz.izq { justify-content: flex-end; }
.buzon-desliz-ic { width: 1.15rem; height: 1.15rem; flex: none; }
.buzon-desliz-ic svg { width: 100%; height: 100%; display: block; }
.buzon-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.7rem 0.85rem; background: var(--color-surface); border: none; cursor: pointer; text-align: left; color: inherit; font: inherit; width: 100%; position: relative; touch-action: pan-y; }
/* La vuelta se anima; el arrastre NO (seguiría al dedo con retraso). */
.buzon-item.volviendo { transition: transform 0.18s ease-out; }
.buzon-item:hover { background: var(--color-surface-2); }
.buzon-avatar { flex: none; width: 2.3rem; height: 2.3rem; border-radius: 50%; background: var(--color-primary); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 600; }
.buzon-item-cuerpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.buzon-item-top { display: flex; align-items: baseline; gap: 0.5rem; }
.buzon-de { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-fecha { flex: none; font-size: var(--t-sm); color: var(--color-text-muted); }
.buzon-item-meta { flex: none; display: flex; flex-direction: row; align-items: center; gap: 0.3rem; white-space: nowrap; }
.buzon-clip { width: 0.85rem; height: 0.85rem; color: var(--color-text-muted); }
.buzon-clip svg { width: 100%; height: 100%; display: block; }
/* Selección múltiple + barra de acciones en lote */
.buzon-avatar { cursor: pointer; user-select: none; }
.buzon-avatar-sel { background: var(--color-success); }
.buzon-item.marcado { background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface)); }
/* Un adjunto que va a viajar como ENLACE se marca antes de enviar: el cambio no
   puede ser una sorpresa ni para quien manda ni para quien recibe. */
.buzon-adj-chip.como-enlace { border-color: var(--color-primary); }
.buzon-adj-chip.como-enlace .buzon-adj-ic { color: var(--color-primary); }
.buzon-adj-modo { gap: 0.4rem; margin: 0.35rem 0 0; font-size: var(--t-md); }
.buzon-adj-nota { font-size: var(--t-sm); margin: 0.15rem 0 0; }

/* Aviso de «puede darse de baja de esta lista». Discreto a propósito: es una
   ayuda, no una alarma — y aparece en muchos correos legítimos. */
.buzon-baja-barra {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.45rem 0.9rem; font-size: var(--t-md);
    color: var(--color-text-muted);
    border-bottom: 1px solid var(--color-border);
    background: var(--color-surface-2);
}
.buzon-baja-ic { width: 0.95rem; height: 0.95rem; flex: none; }
.buzon-baja-ic svg { width: 100%; height: 100%; display: block; }

/* La cuenta atrás de «Deshacer»: un número, no una barra. Lo que importa es
   «me quedan seis segundos», y una barra que se vacía no dice cuántos. */
.saliente-cuenta {
    flex: none; min-width: 1.6rem; text-align: center;
    font-variant-numeric: tabular-nums; font-weight: 700;
    color: var(--color-text-muted);
}

/* El cartel de «está usted viendo solo …», con su ✕ para quitarlo. Va en la
   barra fija, que tiene altura fija: por eso es pequeño y de una línea. */
.buzon-filtro-chip {
    display: inline-flex; align-items: center; gap: 0.3rem; cursor: pointer;
    padding: 0.15rem 0.5rem; border-radius: 999px; white-space: nowrap;
    font-size: var(--t-sm); font-weight: 600;
    background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
    color: var(--color-text); border: 1px solid var(--color-primary);
}
/* ⚠️ LOS CHIPS SÍ SE ENCOGEN. La barra es `nowrap` y sus hijos llevan
   `flex-shrink: 0`; con eso, un chip de texto fijo empujaba el botón de
   actualizar FUERA de la pantalla en el móvil (pasó con «Programados (1)»). No
   se puede arreglar con `overflow` en la barra —recortaría los desplegables—,
   así que se arregla dejando que el chip ceda espacio. */
/* ⚠️ SOLO EL CHIP CON ETIQUETA SE ENCOGE. Los de programados y seguimiento son
   un icono y una cifra: encogerlos los recorta hasta dejar el icono partido, que
   es lo que se veía en escritorio con los dos a la vez. Ceder espacio solo tiene
   sentido cuando hay texto que recortar. */
/* La cinta del buzón de equipo TAMBIÉN se encoge. Sin esto empujaba fuera de la
   barra lo que venía detrás —las insignias y el botón de actualizar— en cuanto
   el nombre era largo, que es justo lo que pasa cuando lleva el dominio pegado
   para distinguir dos buzones con el mismo usuario. */
.buzon-sel-barra .buzon-equipo-cinta { flex-shrink: 1; min-width: 7rem; }
.buzon-sel-barra .buzon-filtro-chip { flex-shrink: 1; min-width: 0; overflow: hidden; }
.buzon-sel-barra .chip-prog,
.buzon-sel-barra .chip-seguir { flex: none; overflow: visible; }
/* Columna estrecha (la ajusta el usuario, así que se mira SU ancho y no el de
   la ventana): los botones se quedan en iconos, igual que en el móvil, y así
   caben las insignias enteras y el botón de actualizar. */
/* ── La barra se aprieta POR ESCALONES, y solo cuando hace falta ──────────
   Antes se apretaba entera de golpe, por debajo de un ancho fijo (530 px)
   medido a mano. Ese número no aguantaba que apareciera nada nuevo —la píldora
   de «programado», por ejemplo— y apretaba de más en cuanto la columna era
   estrecha, aunque cupiera todo.
   Ahora el ancho se MIDE (`medirBarraSel`) y se quita lo justo:
     nivel 1 → se va la etiqueta de ordenar («Lo más reciente»);
     nivel 2 → se va también la de «Seleccionar».
   En ese orden porque ordenar se reconoce por su icono y su estado se ve en el
   propio chip; «Seleccionar» es la acción, y es la última que se queda muda.
   Los dos conservan su `title`, así que el nombre sigue estando. */
/* Último recurso: con la columna en su mínimo (240 px) no cabe ni con todo en
   iconos. Antes eso RECORTABA —el botón de actualizar dejaba de existir—; así
   al menos se alcanza deslizando. La barra de desplazamiento no se pinta: el
   gesto está, el adorno sobra.
   ⚠️ `min-width: 0` es lo que hace que desplace en vez de crecer y salirse
   (ya mordió antes en las tiras del móvil). */
.buzon-sel-barra.nivel-2 { overflow-x: auto; min-width: 0; scrollbar-width: none; }
.buzon-sel-barra.nivel-2::-webkit-scrollbar { display: none; }
.buzon-sel-barra.nivel-1 .buzon-btn-orden > span:not(:first-child),
.buzon-sel-barra.nivel-2 .buzon-btn-orden > span:not(:first-child),
.buzon-sel-barra.nivel-2 .buzon-btn-sel > span:not(:first-child),
.buzon-sel-barra.nivel-2 .buzon-btn-vaciar > span:not(:first-child) { display: none; }
.buzon-filtro-chip .chip-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El de SIN RESPUESTA llama más: es un recordatorio que la persona pidió, y si
   pasa desapercibido no sirve de nada. */
/* La insignia aparece con CUALQUIER seguimiento vivo —para poder consultarlos y
   quitarlos antes de que venzan— y solo se enciende cuando alguno ya venció. */
.chip-seguir { color: var(--color-text); }
.chip-seguir.vencidos { border-color: var(--color-warning); }
.chip-seguir.vencidos .buzon-filtro-x { opacity: 1; color: var(--color-warning); }
.select-sm { height: 1.7rem; padding: 0 0.4rem; font-size: var(--t-sm); width: auto; }

/* ⚠️ El de PROGRAMADOS va sin texto SIEMPRE, no solo en el móvil: en la barra
   del escritorio no le cabía entero y salía como «P… (1)», que es peor que no
   poner nada. El calendario y la cifra ya lo dicen todo, y el nombre completo
   está en el `title`. */
.chip-prog .chip-txt { display: none; }
.buzon-filtro-x { width: 0.8rem; height: 0.8rem; display: inline-flex; flex: none; opacity: 0.75; }
.buzon-filtro-x svg { width: 100%; height: 100%; display: block; }

/* La barra de selección se queda A LA VISTA al desplazar la lista: si se va
   hacia arriba al buscar otro correo, uno acaba seleccionando a ciegas y
   subiendo cada vez para actuar. `sticky` + fondo opaco, y por encima de los
   renglones (que llevan su propio apilado). */
.buzon-sel-barra {
    display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--color-border); background: var(--color-surface);
    position: sticky; top: 0; z-index: 40;
    box-shadow: 0 2px 6px rgb(0 0 0 / 18%);
}
/* La de SELECCIÓN va al pie del panel, pegada abajo: arriba empujaba la lista
   al marcar un correo y el siguiente clic caía en el botón que acababa de
   ocupar ese punto —archivando sin querer—. Abajo no mueve nada. */
/* LAS DOS BARRAS COMPARTEN SITIO Y ALTURA: la fija (seleccionar, actualizar)
   y la de acciones sobre lo marcado. Al marcar, una sustituye a la otra y la
   lista NO se mueve — que era lo que hacía que un clic de más archivara el
   correo o cerrara la selección recién hecha. */
/* ALTURA EXACTA, no mínima: con `min-height` una barra acababa unos píxeles
   más alta que la otra según sus botones, y la lista seguía dando un saltito
   al marcar. */
.buzon-sel-barra { height: 3rem; box-sizing: border-box; }
/* Sin envolver: dos renglones serían otra vez altura variable.
   ⚠️ NADA DE `overflow` AQUÍ: recorta el desplegable de «Seleccionar», que sale
   por debajo de la barra. Lo que no cabe se recorta con `min-width: 0` en los
   hijos y, en estrecho, quitando las etiquetas. */
.buzon-sel-barra { flex-wrap: nowrap; }
.buzon-sel-barra > * { min-width: 0; flex-shrink: 0; }
.buzon-sel-barra .btn svg { width: 1.1rem; height: 1.1rem; display: block; }
.buzon-sel-barra .crece { flex: 1; }
/* «Solo no leídos» de la barra fija (escritorio). Encendido se rellena de
   acento, IGUAL que el circulito del móvil (`.buzon-filtro-fab.activo`): es el
   mismo mando y tiene que verse el mismo.
   Va SIN etiqueta, solo icono y `title`: en esta barra cada píxel cuenta.
   ⚠️ NO existe ninguna regla `.activo` genérica, ni para `.btn` ni para
   `.btn-icono` —lo avisa el comentario de `.chat-item .btn-icono.activo`—, así
   que sin esto el `:class="… && 'activo'"` de la plantilla no pintaría NADA: el
   filtro se pondría y el botón seguiría igual. Un interruptor que no se ve
   encendido deja al usuario sin saber por qué le faltan correos.
   Por eso el botón «Ver» de la cabecera lleva TAMBIÉN esta clase: tenía el
   mismo `:class="buzonFiltro && 'activo'"` y tampoco se encendía. La diferencia
   está en cuándo: el de la barra solo con «no leídos» —es su interruptor—, el
   de «Ver» con cualquier filtro, porque es el menú donde se eligen todos. */
.buzon-btn-filtro.activo {
    background: var(--color-primary); border-color: var(--color-primary);
    color: var(--color-primary-fg);
}
.buzon-btn-filtro.activo svg { stroke: currentColor; }
/* Los iconos de la barra superior, encendidos.
   ⚠️ Hacía falta escribirlo: como avisa el comentario de arriba, NO hay regla
   `.activo` genérica para `.btn-icono`, así que el `:class="… && 'activo'"` de
   la plantilla no pintaba nada. El del asistente lo llevaba desde siempre y
   nunca se encendió; ahora lo hace, igual que el de Administración cuando se
   está dentro. Un botón que lleva a una pantalla debe verse distinto cuando ya
   se está en ella. */
.nav-usuario .btn-icono.activo { color: var(--color-primary); }
.nav-usuario .btn-icono.activo svg { stroke: currentColor; }
.buzon-sel-n { font-weight: 600; min-width: 1.4rem; text-align: center; }
/* ── Barra de acciones sobre lo marcado: qué cabe, por ancho del PANEL ──────
   El modo lo decide `buzonBarraModo` midiendo la columna, no una media query:
   el usuario ajusta este panel con el separador y el viewport no se entera.

   ⚠️ LA ALTURA NO CAMBIA EN NINGÚN MODO (3rem, arriba). Quitar una etiqueta
   estrecha el botón, no lo encoge de alto; si algún día un modo cambiara el
   alto, la lista volvería a dar el saltito al marcar y el clic siguiente
   caería en otro botón. Es lo que se prueba en `bin/probar-barra-seleccion.php`.

   `media`: lo de mover (posponer, mover, archivar) se queda en iconos; spam y
   eliminar se van a «Más», donde conservan su nombre. */
.buzon-barra-sel.ancho-media .btn-con-icono > span:last-child { display: none; }
/* `estrecha`: además, posponer y mover salen de la barra (los oculta el
   marcado); queda lo frecuente y reversible, más «Más». */
.buzon-barra-sel.ancho-estrecha .btn-con-icono > span:last-child { display: none; }
/* El menú «Más» no se recorta: la barra no lleva `overflow` a propósito. */
.buzon-barra-sel .menu-wrap { flex: none; }
/* En el teléfono más estrecho de verdad (320px) los botones caben por tres
   píxeles, y con el contador en cuatro dígitos («1234 marcados») dejarían de
   caber. Se aprieta el hueco y el relleno —que no tocan la ALTURA— para tener
   margen. Medido, no supuesto: `bin/probar-barra-seleccion.php` exige holgura. */
.buzon-barra-sel.ancho-estrecha { gap: 0.3rem; padding-left: 0.4rem; padding-right: 0.4rem; }

@media (max-width: 640px) {
    /* Solo iconos: con las etiquetas no caben en un renglón, y dos renglones
       serían otra vez altura variable. El nombre queda en el `title`. */
    .buzon-sel-barra .btn-con-icono > span:last-child { display: none; }
    .buzon-barra-fija .btn-con-icono > span:not(:first-child) { display: inline-flex; }
    /* (El de programados ya va sin texto en TODAS las anchuras; ver más abajo.)
       ⚠️ El del FILTRO sí conserva su etiqueta: es lo único que dice CUÁL está
       puesto, y sin ella el chip sería un aspa sin sentido. Ese se encoge con
       puntos suspensivos, que es lo que hace la regla de arriba. */
}
.buzon-del:hover:not(:disabled) { color: var(--color-danger); border-color: var(--color-danger); }
.buzon-mover-arbol { max-height: 22rem; overflow-y: auto; margin: 0.5rem 0; border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 0.3rem; }
/* Arrastrar mensajes a una carpeta (escritorio): resalta el destino. */
.buzon-pane-tree .nodo.drop-activo { background: color-mix(in srgb, var(--color-primary) 22%, transparent); outline: 2px dashed var(--color-primary); outline-offset: -2px; border-radius: var(--radius-sm); }
.buzon-asunto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-muted); font-size: var(--t-base); }
.buzon-item.no-leido .buzon-de { font-weight: 700; }
.buzon-item.no-leido .buzon-asunto { color: var(--color-text); font-weight: 500; }
.buzon-item.no-leido .buzon-avatar { box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-primary); }
/* Lector: en escritorio va en el 3er panel (en flujo); en móvil, overlay a pantalla completa (ver media query). */
/* Los dos «a pantalla completa» del correo tapan la tabbar a propósito (z 60/62 >
   40), pero el banner de vaciado va por encima de ellos (z 90). Como son columnas
   flex cuyo último hijo desplaza (el iframe/texto del mensaje, el cuerpo del
   redactor), el padding inferior encoge esa zona y el final del contenido queda
   por ARRIBA del banner; sin él, las últimas líneas se quedaban debajo sin manera
   de sacarlas (ya no queda nada que desplazar). Ver --alto-vaciado en app.js. */
/* EL LECTOR TAMPOCO TAPA LA NAVEGACIÓN (mismo trato que el redactor): en
   escritorio respeta la barra de arriba y en el teléfono deja libre la
   tabbar de abajo — si no, abrir un correo encerraba a la persona. */
.buzon-lector { position: fixed; inset: 0; top: var(--navbar-real, var(--navbar-height)); z-index: 60; background: var(--color-bg); display: flex; flex-direction: column; height: auto; padding-bottom: var(--alto-vaciado, 0px); }
@media (max-width: 768px) {
    .buzon-lector { top: 0; bottom: calc(3.9rem + env(safe-area-inset-bottom)); }
}
.buzon-lector-cab { display: flex; align-items: flex-start; gap: 0.6rem; padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface); }
/* ▲▼: el correo anterior y el siguiente de la lista (también ↑/↓). */
.buzon-lector-nav { display: flex; flex-direction: column; gap: 0.1rem; margin-left: auto; flex-shrink: 0; }
.buzon-lector-nav .btn-icono { width: 1.9rem; height: 1.6rem; }
.buzon-lector-nav .btn-icono:disabled { opacity: 0.35; cursor: default; }
/* Al recorrerla con ↑/↓, el correo abierto no queda debajo de la barra fija de
   arriba de la lista ni del paginador de abajo. */
.buzon-main .buzon-lista .buzon-item { scroll-margin-top: 3.8rem; scroll-margin-bottom: 3.8rem; }
.buzon-lector-meta { flex: 1; min-width: 0; }
.buzon-lector-asunto { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-lector-de { font-size: var(--t-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A quién va el correo, bajo el remitente. Una sola línea: si no cabe, se
   recorta con puntos suspensivos y el «+N» —que nunca se encoge— sigue a la
   vista, porque es justo el que lleva a la lista completa. */
.buzon-lector-para { display: flex; align-items: baseline; gap: 0.3rem; font-size: var(--t-sm); min-width: 0; }
.buzon-para-nombres { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-para-mas { flex: none; background: none; border: 0; padding: 0; font: inherit; cursor: pointer; color: var(--color-primary); }
.buzon-para-mas:hover { text-decoration: underline; }
.buzon-lector-fecha { flex: none; font-size: var(--t-sm); }
.buzon-cargando-msg { padding: 1rem; }
.buzon-adjuntos { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0.5rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface); }
.buzon-adj { display: inline-flex; align-items: center; gap: 0.3rem; font-size: var(--t-sm); background: var(--color-surface-2); border-radius: 0.5rem; padding: 0.15rem 0.5rem; }
.buzon-adj-desc { max-width: 100%; border: 1px solid var(--color-border); cursor: pointer; color: inherit; font: inherit; padding: 0.25rem 0.55rem; }
.buzon-adj-desc:hover { border-color: var(--color-primary); color: var(--color-primary); }
.buzon-adj-desc .buzon-adj-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 16rem; }
.buzon-adj-desc .buzon-adj-tam { flex: none; }
.buzon-adj-ic { display: inline-flex; width: 0.85rem; height: 0.85rem; }
.buzon-adj-ic svg { width: 100%; height: 100%; }
/* Cada adjunto: chip de descarga + botón «Guardar en Mis archivos». */
.buzon-adj-item { display: inline-flex; align-items: center; gap: 0.15rem; }
.buzon-adj-guardar { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.25rem 0.5rem; border: none; background: none; color: var(--color-text-2); cursor: pointer; font: inherit; font-size: var(--t-sm); border-radius: 0.5rem; }
.buzon-adj-guardar:hover { color: var(--color-primary); background: var(--color-surface-2); }
.buzon-adj-guardar svg { width: 1.05rem; height: 1.05rem; flex: none; }
/* ── Invitación de calendario (iMIP) dentro del lector ──
   Tarjeta destacada sobre el cuerpo del correo, con la barra de acento a la izquierda
   para que se lea como «esto no es texto del mensaje, es un evento». */
.buzon-invitacion { margin: 0.6rem 0.9rem; padding: 0.7rem 0.9rem; border: 1px solid var(--color-border); border-left: 3px solid var(--color-primary); border-radius: 0.6rem; background: var(--color-surface-2); }
.buzon-invitacion.cancelada { border-left-color: var(--color-danger); }
.buzon-inv-cab { display: flex; align-items: center; gap: 0.4rem; color: var(--color-primary); font-size: var(--t-sm); text-transform: uppercase; letter-spacing: 0.03em; }
.buzon-invitacion.cancelada .buzon-inv-cab { color: var(--color-danger); }
.buzon-inv-ic { display: inline-flex; width: 0.95rem; height: 0.95rem; }
.buzon-inv-ic svg { width: 100%; height: 100%; }
.buzon-inv-titulo { margin: 0.25rem 0 0.4rem; font-size: var(--t-xl); font-weight: 600; color: var(--color-text); overflow-wrap: anywhere; }
.buzon-inv-datos { display: flex; flex-direction: column; gap: 0.2rem; font-size: var(--t-md); color: var(--color-text-2); }
.buzon-inv-fila { display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; }
.buzon-inv-etq { flex: none; min-width: 4.5rem; color: var(--color-text-muted); font-size: var(--t-sm); }
.buzon-inv-col { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; flex: 1; }
.buzon-inv-resumen { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.5rem; font-size: var(--t-sm); color: var(--color-text-2); }
/* Botón que se lee como enlace: es un cambio de vista, no una acción sobre el evento;
   con aspecto de botón competiría con «Aceptar»/«Rechazar», que sí lo son. */
.buzon-inv-mas { background: none; border: 0; padding: 0; font: inherit; color: var(--color-primary); cursor: pointer; text-decoration: underline; }
.buzon-inv-mas:hover { text-decoration: none; }
.buzon-inv-gente { display: flex; flex-wrap: wrap; gap: 0.3rem; min-width: 0; }
/* Desplegada, ACOTADA y con scroll propio: sin el tope, desplegar 50 invitados
   volvería a empujar el correo fuera de la pantalla, que es el fallo original. */
.buzon-inv-gente.desplegada { max-height: 8.5rem; overflow-y: auto; align-content: flex-start; }
/* Cada invitado con su estado (PARTSTAT): el color dice si aceptó sin tener que leerlo. */
.buzon-inv-persona { font-size: var(--t-sm); padding: 0.1rem 0.45rem; border-radius: 0.5rem; background: var(--color-surface); border: 1px solid var(--color-border); }
.buzon-inv-persona.est-accepted { border-color: var(--color-success); color: var(--color-success); }
.buzon-inv-persona.est-declined { border-color: var(--color-danger); color: var(--color-danger); text-decoration: line-through; }
.buzon-inv-persona.est-tentative { border-color: var(--color-warning); color: var(--color-warning); }
.buzon-inv-acc { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.7rem; margin-top: 0.7rem; padding-top: 0.6rem; border-top: 1px solid var(--color-border); }
.buzon-inv-pregunta { font-size: var(--t-md); color: var(--color-text-2); }
.buzon-inv-botones { display: flex; gap: 0.35rem; flex-wrap: wrap; }
/* La tarjeta ya usa surface-2, que es el fondo por defecto de .btn: sin esto los
   botones secundarios se confunden con el fondo y no se leen como botones. */
.buzon-inv-botones .btn { background: var(--color-surface); border-color: var(--color-border); }
.buzon-inv-botones .btn:hover { background: var(--color-border); }
.buzon-inv-botones .btn-primary { background: var(--color-primary); color: var(--color-primary-fg); border-color: var(--color-primary); }
.buzon-inv-botones .btn-primary:hover { background: var(--color-primary-h); }
/* La respuesta vigente queda marcada, para poder cambiarla sin perder cuál eligió. */
.buzon-inv-botones .elegida { outline: 2px solid var(--color-primary); outline-offset: 1px; }
.buzon-inv-espera { font-size: var(--t-sm); }
.buzon-inv-nota { margin-top: 0.6rem; padding-top: 0.6rem; border-top: 1px solid var(--color-border); font-size: var(--t-md); color: var(--color-text-2); display: flex; flex-direction: column; gap: 0.15rem; }
@media (max-width: 640px) {
    /* La barra de acciones del lector, en UN renglón. Con las siete acciones
       nombradas ocupaba tres, y el correo empezaba fuera de la pantalla. Las
       secundarias se van al menú de los tres puntos (ver app.html) y lo que
       queda se aprieta, igual que en `.col-acc`. */
    .buzon-lector-acc { gap: 0.35rem; padding: 0.45rem 0.6rem; }
    .buzon-lector-acc .btn-con-icono { padding: 0.35rem 0.5rem; }

    .buzon-invitacion { margin: 0.5rem 0.6rem; padding: 0.6rem 0.7rem; }
    /*
     * Etiqueta y valor EN EL MISMO RENGLÓN, en dos columnas.
     *
     * Antes la etiqueta llevaba `min-width: 100%`, que la mandaba a su propio
     * renglón: con «Cuándo», «Dónde», «Organiza» e «Invitados» eran ocho
     * renglones donde caben cuatro, y en un teléfono la tarjeta se comía la
     * pantalla antes de empezar el correo. Las etiquetas son cortas y los
     * valores caben de sobra al lado.
     *
     * Con grid y no con flex porque es lo que mantiene alineados los valores
     * entre filas; con flex, cada renglón colocaba el suyo donde le tocara.
     */
    .buzon-inv-fila { display: grid; grid-template-columns: 4.3rem 1fr; gap: 0.1rem 0.5rem; }
    .buzon-inv-etq { min-width: 0; }
    /* Sin esto, un valor largo sin espacios (un enlace de la sala) ensancha su
       columna y saca de cuadro la tarjeta entera. */
    .buzon-inv-fila > :not(.buzon-inv-etq) { min-width: 0; overflow-wrap: anywhere; }
    .buzon-inv-titulo { font-size: var(--t-lg); margin: 0.2rem 0 0.35rem; }
    .buzon-inv-datos { gap: 0.3rem; }
}
/* Opciones de envío en el redactor (solo con transporte SMTP). */
/* El interruptor del plegable de opciones del redactor. Discreto: es una fila
   de servicio, no una acción. */
.buzon-opc-toggle { display: flex; align-items: center; gap: 0.45rem; width: 100%; padding: 0.45rem 0.1rem; background: none; border: 0; color: var(--color-text-muted); font: inherit; font-size: var(--t-base); cursor: pointer; text-align: left; }
.buzon-opc-toggle:hover { color: var(--color-text); }
/* La fila de «Opciones del correo» lleva, a la derecha, el botón de plegar el encabezado. */
.buzon-opc-fila { display: flex; align-items: center; gap: 0.3rem; }
.buzon-opc-fila .buzon-opc-toggle { flex: 1; min-width: 0; }
.buzon-campos { display: flex; flex-direction: column; gap: 0.6rem; }
/* El encabezado plegado: un renglón con destinatario y asunto. */
.buzon-campos-resumen {
    display: flex; align-items: center; gap: 0.6rem; width: 100%; min-width: 0;
    padding: 0.5rem 0.7rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    background: var(--color-surface); color: var(--color-text); font: inherit; font-size: var(--t-base); cursor: pointer; text-align: left;
}
.buzon-campos-resumen:hover { border-color: var(--color-primary); }
.buzon-campos-resumen-para { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-campos-resumen-asunto { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.buzon-campos-resumen-asunto::before { content: '·'; margin-right: 0.6rem; font-weight: 400; color: var(--color-text-muted); }
.buzon-campos-resumen svg { width: 1rem; height: 1rem; }
.buzon-opc-toggle svg { width: 1rem; height: 1rem; }
/* La flecha gira al abrir, como en el resto de la aplicación. */
.buzon-opc-toggle .chevron-abajo { margin-left: auto; transition: transform .15s; }
.buzon-opc-toggle .chevron-abajo.abierto { transform: rotate(180deg); }

.buzon-opc-envio { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; padding: 0.35rem 0; }
.buzon-opc-prio { display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--t-md); color: var(--color-text-2); }
.buzon-opc-prio .select { width: auto; }
.buzon-opc-acuse { display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--t-md); color: var(--color-text-2); cursor: pointer; }
/* Prioridad declarada por el remitente: marca en la lista y aviso en el lector. */
/* El «!» solo ocupa la franja central de su caja, así que se ve más pequeño de lo que
   mide: se le da más caja y más grosor de trazo para que se lea de un vistazo. */
.buzon-prio { display: inline-flex; width: 1.15rem; height: 1.15rem; flex: none; }
.buzon-prio svg { width: 100%; height: 100%; stroke-width: 3; }
.buzon-prio.prio-alta { color: var(--color-danger); }
.buzon-prio.prio-baja { color: var(--color-text-muted); }
.buzon-prio-barra { display: flex; align-items: center; gap: 0.4rem; padding: 0.4rem 0.9rem; font-size: var(--t-sm); border-bottom: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text-2); }
.buzon-prio-barra svg { width: 1.05rem; height: 1.05rem; flex: none; stroke-width: 3; }
.buzon-prio-barra.prio-alta { color: var(--color-danger); }
/* Petición de acuse de lectura: barra discreta, no un modal — no debe estorbar al leer. */
.acuse-tit { margin: 1rem 0 0.25rem; font-size: var(--t-lg); }
.acuse-ayuda { font-size: var(--t-sm); margin: 0 0 0.5rem; }
.buzon-acuse { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.7rem; padding: 0.5rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface-2); font-size: var(--t-md); }
.buzon-acuse-txt { flex: 1; min-width: 12rem; color: var(--color-text-2); }
.buzon-acuse-acc { display: flex; gap: 0.35rem; }
/*
 * De «Detalles» hacia abajo scrollea TODO junto: detalles, tarjetas, adjuntos y
 * el mensaje. Antes solo scrolleaba el cuerpo y lo demás se quedaba fijo, así
 * que una invitación con diez adjuntos empujaba el mensaje fuera de la pantalla
 * y no había forma de llegar a él.
 */
.buzon-lector-scroll { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
/*
 * `flex: 1 0 auto` y no `flex: 1`: dentro de una zona con scroll, `grow` solo
 * reparte el espacio SOBRANTE, así que cuando el contenido pasa de la pantalla
 * el elemento se queda con su altura real y scrollea el contenedor, que es justo
 * lo que se busca.
 */
.buzon-iframe { flex: 1 0 auto; min-height: 60vh; width: 100%; max-width: 100%; border: none; background: #fff; }
.buzon-iframe-caja { display: contents; }   /* solo envuelve el x-for: el marco sigue siendo hijo del flex */
/* Ya dijo cuánto mide: se le pone esa altura exacta (en línea) y deja de tener
   scroll propio. Sin medir se queda como estaba, con su 60vh y scroll interno. */
.buzon-iframe.medido { flex: none; min-height: 0; }
/* ---- Fondo «papel» al leer y redactar (Jore, 2026-09-24) ----
   El blanco puro deslumbra, sobre todo con un tema oscuro alrededor. Se atenúa con un
   `filter` sobre el MARCO —no se toca el HTML del correo—, así que el mensaje conserva
   su diseño y sus colores, solo más apagados, y se envía y se recibe igual.
   Valores MEDIDOS en el navegador, no a ojo (texto #111 sobre blanco, como el lector):
     · papel → el blanco queda en #dbdbda; texto 13.8:1, enlace azul 4.7:1
     · tenue → #c2c2c1; texto 10.9:1 (para leer de noche o con tema oscuro)
   La pizca de sepia es la calidez del papel; con más, los colores del correo viran. */
:root[data-fondo-correo="papel"] :is(.buzon-iframe, .buzon-rt-editor, .firma-previa-caja) { filter: sepia(0.1) brightness(0.86); }
:root[data-fondo-correo="tenue"] :is(.buzon-iframe, .buzon-rt-editor, .firma-previa-caja) { filter: sepia(0.1) brightness(0.76); }
/* Cuerpo del correo como texto plano (toggle «Sólo texto»). */
.buzon-texto-plano { flex: 1 0 auto; margin: 0; overflow: visible; padding: 0.9rem; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: var(--t-md); line-height: 1.5; background: var(--color-surface); color: var(--color-text); }
/* Con recuadros de caracteres de caja (│ ─ ┌): interlineado natural y sin partir
   renglones, o las líneas verticales quedan cortadas y las columnas se descuadran. */
.buzon-texto-plano.con-cajas { line-height: normal; }
/* Fila «Detalles · Sólo texto» + panel de detalles (destinatarios). */
.buzon-lector-vista { display: flex; gap: 1rem; padding: 0.35rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface); }
.buzon-vista-link { display: inline-flex; align-items: center; gap: 0.35rem; border: none; background: none; color: var(--color-text-2); cursor: pointer; font: inherit; font-size: var(--t-sm); padding: 0.15rem 0; }
.buzon-vista-link:hover, .buzon-vista-link.activo { color: var(--color-primary); }
.buzon-vista-link svg { width: 0.95rem; height: 0.95rem; flex: none; }
/* El «Quitar el filtro» del aviso de lista vacía: subrayado para que se lea
   como lo que es —algo en lo que se puede pulsar— en medio de una frase. */
.buzon-vacio-quitar { color: var(--color-primary); text-decoration: underline; font-size: inherit; }
.buzon-detalles { padding: 0.5rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface-2); font-size: var(--t-md); display: flex; flex-direction: column; gap: 0.25rem; }
.buzon-detalle-fila { display: flex; gap: 0.5rem; }
.buzon-detalle-etq { flex: none; min-width: 6rem; color: var(--color-text-2); font-weight: 600; }
.buzon-detalle-val { min-width: 0; overflow-wrap: anywhere; }
/* Carpetas IMAP en ÁRBOL colapsable (como el de Mis archivos). */
/* La fila de carpetas del teléfono lleva el chip a la izquierda y, en el hueco
   que le sobraba a la derecha, el menú que antes era una barra entera de iconos
   (`.buzon-cab`, ver abajo). Con `min-width: 0` el nombre largo de una carpeta
   se recorta con puntos suspensivos en vez de empujar al menú fuera. */
.buzon-carpetas { margin-bottom: 0.7rem; display: flex; align-items: center; gap: 0.5rem; }
.buzon-carpetas .buzon-carpeta-toggle { min-width: 0; }
.buzon-cab-menu { margin-left: auto; flex: none; }
.buzon-carpeta-toggle { max-width: 100%; }
/* El chip cuando lo que se ve NO es una carpeta sino un buzón inteligente. Se
   pinta como la píldora del filtro —mismo acento, mismo borde— porque es lo
   mismo que decía ella, y así se lee «estoy en una vista», no «estoy en una
   carpeta que se llama Hoy». El icono también cambia, en la plantilla. */
.buzon-carpeta-toggle.es-vista {
    background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
    border-color: var(--color-primary);
}
.buzon-carpeta-toggle span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-carpeta-chev { display: inline-flex; width: 1.15rem; height: 1.15rem; transition: transform var(--transition); }
.buzon-carpeta-chev.abierto { transform: rotate(180deg); }
.buzon-arbol { margin-top: 0.4rem; max-height: 22rem; overflow-y: auto; border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); padding: 0.3rem; }
.buzon-nodo { display: flex; align-items: center; gap: 0.1rem; border-radius: var(--radius-sm); }
.buzon-nodo.activa { background: var(--color-surface-2); }
.buzon-nodo-tog { flex: none; width: 1.5rem; height: 1.7rem; display: inline-flex; align-items: center; justify-content: center; background: none; border: none; color: var(--color-text-muted); cursor: pointer; padding: 0; }
.buzon-nodo-tog svg { width: 0.85rem; height: 0.85rem; }
.buzon-nodo-vacio { cursor: default; }
.buzon-nodo-lbl { flex: 1; min-width: 0; display: flex; align-items: center; gap: 0.4rem; text-align: left; background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: 0.35rem 0.3rem; }
.buzon-nodo-lbl > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-nodo-ic { flex: none; }
.buzon-nodo-ic svg { width: 1.1rem; height: 1.1rem; }
/* Contador de no-leídos por carpeta (LIST-STATUS). */
.buzon-folder-n { flex: none; font-size: var(--t-2xs); font-weight: 600; background: var(--color-primary); color: #fff; border-radius: 0.7rem; padding: 0.03rem 0.4rem; min-width: 1.15rem; text-align: center; line-height: 1.45; }
.nodo.con-nuevos .nodo-etq, .buzon-nodo.con-nuevos .buzon-nodo-lbl { font-weight: 700; }
/* Papelera de carpeta (aparece al pasar el cursor sobre la carpeta, escritorio). */
.buzon-folder-del { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; padding: 0; background: none; border: none; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-sm); opacity: 0; }
.buzon-folder-del svg { width: 0.85rem; height: 0.85rem; }
.file-tree .nodo:hover .buzon-folder-del { opacity: 1; }
.buzon-folder-del:hover { color: var(--color-danger); }
/* Pantalla táctil grande (tableta): sin «hover», los iconos se ven siempre. */
@media (hover: none) { .buzon-folder-del { opacity: 0.6; } }
/* «Cargar más» al final de la lista. */
/* Pulsación larga = clic derecho en táctil (2026-09-13): sin el menú nativo de
   iOS («copiar», «abrir enlace») ni la selección de texto encima del nuestro. */
@media (pointer: coarse) {
    .file-list-table tbody tr, .galeria-item, .file-tree .nodo { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
}

/* Paginador de la lista de correo (2026-09-13). FIJO y visible siempre (lo pidió
   Jore): con la lista larga quedaba al final del scroll y había que bajar hasta
   el fondo para cambiar de página. */
.buzon-paginador { display: flex; align-items: center; gap: 0.3rem; padding: 0.35rem 0.5rem; border-top: 1px solid var(--color-border); font-size: var(--t-md); background: var(--color-surface); }
/* Escritorio: el panel de la lista es quien hace scroll, así que basta pegarlo
   al fondo de ese panel. */
@media (min-width: 769px) {
    .buzon-pane-list .buzon-paginador { position: sticky; bottom: 0; z-index: 3; }
}
/* Teléfono: hace scroll la página entera; se fija justo ENCIMA de la tabbar
   (3.9rem). z 38: debajo de los botones flotantes (39), de la tabbar (40) y del
   lector y el redactor (60+), que lo tapan como tapan todo lo demás. */
@media (max-width: 768px) {
    .buzon-paginador {
        position: fixed; left: 0; right: 0; z-index: 38;
        bottom: calc(3.9rem + env(safe-area-inset-bottom));
        box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.12);
    }
    /* Que el último correo no quede debajo de la barra. */
    .buzon-main.con-paginador .buzon-lista { margin-bottom: 3rem; }
    /* Y los dos botones redondos suben lo que mide la barra, para no encimarse. */
    body:has(.buzon-main.con-paginador) .buzon-filtro-fab,
    body:has(.buzon-main.con-paginador) .buzon-redactar-fab { bottom: calc(3.9rem + env(safe-area-inset-bottom) + 3.4rem); }
    body:has(.buzon-main.con-paginador) .buzon-fab-menu { bottom: calc(3.9rem + env(safe-area-inset-bottom) + 6.9rem); }
}
.buzon-paginador .btn-icono { font-size: var(--t-xl); line-height: 1; min-width: 2rem; }
.buzon-paginador .btn-icono:disabled { opacity: 0.35; }
.buzon-paginador-rango { flex: 1; min-width: 0; text-align: center; opacity: 0.85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.buzon-paginador-num { width: 4.2rem; padding: 0.2rem 0.35rem; text-align: center; }
/* Indicador de búsqueda dentro de la carpeta de correo. */
.buzon-busq-info { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.6rem; background: var(--color-surface-2); border-bottom: 1px solid var(--color-border); font-size: var(--t-md); }
.buzon-busq-info .crece { flex: 1; }
.buzon-busq-ic { flex: none; width: 0.9rem; height: 0.9rem; color: var(--color-text-muted); }
.buzon-busq-ic svg { width: 100%; height: 100%; }
.buzon-busq-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Sección «Correos» en la búsqueda global. */
.busq-correos-ic { display: inline-flex; width: 1.1rem; height: 1.1rem; vertical-align: -2px; }
.busq-correos-ic svg { width: 100%; height: 100%; }

/* Tira de progreso de la búsqueda global: una pastilla por categoría, con lo
   que lleva encontrado o «buscando…» si aún no ha contestado. Envuelve en vez
   de desplazarse: en el móvil son cuatro y caben en dos renglones, y una tira
   que se desplaza esconde justo lo que se quiere mirar de un vistazo. */
.busq-estado { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: 0 0 .8rem; }
.busq-estado-tit { font-size: var(--t-sm); }
.busq-cat {
    display: inline-flex; align-items: baseline; gap: .35rem;
    padding: .2rem .55rem; border-radius: var(--radius-full);
    background: var(--color-surface-2); font-size: var(--t-sm);
}
.busq-cat-etq { color: var(--color-text-2); }
.busq-cat-n { font-weight: 600; }
/* Mientras espera, la pastilla late despacio: se ve que sigue trabajando sin
   meter otro spinner girando en pantalla. */
.busq-cat.busca, .busq-cat.espera { animation: busq-late 1.4s ease-in-out infinite; }
/* 'parcial': ya hay resultados y siguen llegando. La pastilla NO se atenúa
   —lo que muestra ya es bueno— pero late el puntito de continuación. */
.busq-cat-mas { color: var(--color-text-2); animation: busq-late 1.4s ease-in-out infinite; }
.busq-cat.busca .busq-cat-n, .busq-cat.espera .busq-cat-n { font-weight: 400; font-style: italic; }
.busq-cat.error .busq-cat-n { color: var(--color-danger); font-weight: 400; }
@keyframes busq-late { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .busq-cat.busca, .busq-cat.espera, .busq-cat-mas { animation: none; } }
.buzon-nodo.activa .buzon-nodo-lbl { font-weight: 600; color: var(--color-primary); }
.buzon-nodo-lbl:hover { color: var(--color-primary); }
/* Panel izquierdo de carpetas (escritorio). En móvil, .file-tree ya lo oculta y se
   usa el árbol colapsable de arriba (.buzon-carpetas-movil). */
.buzon-sidebar { padding-top: 0.5rem; }
@media (min-width: 769px) { .buzon-carpetas-movil { display: none; } }
/* Acciones del lector (Responder / Reenviar). */
.buzon-lector-acc { display: flex; gap: 0.35rem; padding: 0.45rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface); flex-wrap: wrap; }
/* UNA fila: en escritorio los botones van compactos (texto chico, menos
   relleno); en el teléfono son iconos puros —los nombres viven en el menú de
   los tres puntos, donde ya estaba lo delicado— y caben todos juntos. */
.buzon-lector-acc .btn-sm { padding: 0.35rem 0.55rem; font-size: var(--t-sm); }
/* Las acciones del lector, sin nombre (2026-09-17): cuadradas y con el icono
   centrado, para que se lean como grupo de iconos y no como botones de texto a
   los que les falta el texto. Van así en las DOS vistas; eliminar, no deseado
   y archivar se repiten en el menú de los tres puntos, que es donde llevan su
   nombre escrito (ver el marcado). */
.buzon-lector-acc .btn-icono-solo { display: inline-flex; align-items: center; justify-content: center; padding: 0.4rem; line-height: 0; }
.buzon-lector-acc .btn-icono-solo svg { width: 1.15rem; height: 1.15rem; }
/* El botón de IA es el mismo en los dos tamaños; en el teléfono pierde el
   rótulo «IA» pero CONSERVA el chevrón, que es lo que avisa de que abre un menú
   en vez de disparar una acción. Sin esto se quedaba con el relleno de un botón
   CON texto y descuadraba la fila de iconos; y como aquí van dos dibujos
   —icono y chevrón— lleva algo de aire a la derecha y un hueco entre ambos. */
@media (max-width: 768px) {
    .buzon-lector-acc .ia-lectura-boton { display: inline-flex; align-items: center; justify-content: center; gap: 0.1rem; padding: 0.4rem 0.3rem 0.4rem 0.4rem; line-height: 0; }
    .buzon-lector-acc .ia-lectura-boton > span:first-child svg { width: 1.15rem; height: 1.15rem; }
    .buzon-lector-acc .ia-lectura-boton .chevron-abajo svg { width: 0.85rem; height: 0.85rem; }
}
@media (max-width: 768px) {
    .buzon-lector-acc { gap: 0.3rem; padding: 0.4rem 0.6rem; }
    .buzon-lector-acc .btn-sm { padding: 0.4rem 0.5rem; }
}
/* Redactar (overlay a pantalla completa). */
/* Vista segura del .eml adjunto: capa completa encima del lector (60) y del
   redactor (62); el correo sospechoso se lee en un iframe sandbox SIN permisos. */
.buzon-eml-vista { position: fixed; inset: 0; z-index: 63; background: var(--color-bg); display: flex; flex-direction: column; }
.buzon-eml-cab { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.8rem; border-bottom: 1px solid var(--color-border); }
.buzon-eml-tit { margin: 0; font-size: var(--t-lg); }
.buzon-eml-cuerpo { display: flex; flex-direction: column; flex: 1; min-height: 0; padding: 0.8rem; gap: 0.6rem; }
.buzon-eml-nota { margin: 0; padding: 0.5rem 0.8rem; border-radius: var(--radius-md); background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface)); font-size: var(--t-base); }
.buzon-eml-meta { display: flex; flex-direction: column; gap: 0.15rem; font-size: var(--t-base); overflow-wrap: anywhere; }
/* Texto plano en la propia página: sin iframe no hay estilos del spam, ni
   colisiones de tema, ni navegadores que lo dejen en blanco. */
.buzon-eml-texto { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin: 0; padding: 0.8rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text); font: 0.92rem/1.55 var(--font-sans); white-space: pre-wrap; overflow-wrap: anywhere; }
.buzon-eml-cargando { padding: 2rem; text-align: center; }
@media (max-width: 768px) {
    .buzon-eml-vista { padding-bottom: env(safe-area-inset-bottom); }
}

.buzon-redactar { position: fixed; inset: 0; z-index: 62; background: var(--color-bg); display: flex; flex-direction: column; padding-bottom: var(--alto-vaciado, 0px); }
/* EL REDACTOR NO TAPA LA NAVEGACIÓN, EN NINGÚN TAMAÑO. Antes ocupaba la
   pantalla entera (`inset: 0`) y no había forma de ir a Notas o a Archivos a
   media redacción: el único camino era el botón de apartar, que hay que
   descubrir. Dejando la navegación a la vista se toca la sección de siempre y
   el correo se aparta solo.
     · en PC     queda debajo de la barra de arriba (que lleva las secciones)
     · en móvil  queda encima de la barra de abajo */
.buzon-redactar { top: var(--navbar-real, var(--navbar-height)); }
@media (max-width: 768px) {
    .buzon-redactar { top: 0; bottom: calc(3.9rem + env(safe-area-inset-bottom)); }
}
/* Al arrastrar archivos encima: marco y letrero. `pointer-events: none` para que
   el letrero no robe el dragleave/drop del redactor. */
.buzon-redactar.soltar-aqui { outline: 3px dashed var(--color-primary); outline-offset: -6px; }
.buzon-soltar-aviso { position: absolute; inset: 0; z-index: 5; display: flex; align-items: center; justify-content: center; pointer-events: none; font-size: var(--t-xl); font-weight: 600; color: var(--color-primary); background: color-mix(in srgb, var(--color-bg) 82%, transparent); }
.buzon-redactar-cab { display: flex; align-items: center; gap: 0.6rem; padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface); }
.buzon-redactar-tit { flex: 1; margin: 0; font-size: var(--t-xl); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* TOPE DE 1200 px, centrado (Jore, 2026-09-26; 1000 quedó corto). Con 800 sobraba medio panel
   vacío; sin tope, los renglones se hacían demasiado largos para leer. En
   la PC lleva además margen a los lados aunque el panel sea más angosto. */
.buzon-redactar-cuerpo { flex: 1; display: flex; flex-direction: column; gap: 0.6rem; padding: 0.9rem; width: 100%; max-width: 1200px; margin: 0 auto; overflow-y: auto; }
@media (min-width: 769px) { .buzon-redactar-cuerpo { padding-left: 1.5rem; padding-right: 1.5rem; } }
.buzon-campo { display: flex; align-items: center; gap: 0.6rem; }
.buzon-campo > span:first-child { flex: none; width: 3.2rem; color: var(--color-text-muted); font-size: var(--t-base); }
.buzon-campo .input { flex: 1; min-width: 0; }
.buzon-cc { display: flex; flex-direction: column; gap: 0.6rem; }
.buzon-cc-toggle { align-self: flex-start; background: none; border: none; color: var(--color-primary); cursor: pointer; font: inherit; font-size: var(--t-md); padding: 0; }
/* Los tres puntos que sacan Cc/Cco en el teléfono, pegados a «Para». La fila es
   `align-items: flex-start`, así que queda a la altura del primer renglón del
   campo aunque el autocompletado lo crezca. Encendido se pinta, como cualquier
   interruptor: ⚠️ `.btn-icono` NO tiene regla `.activo` propia —lo avisa
   `.buzon-btn-filtro`—, así que sin esto el `:class` no pintaría nada. */
.buzon-cc-mas { flex: none; margin-top: 0.1rem; }
.buzon-cc-mas.activo { background: var(--color-primary); color: var(--color-primary-fg); }
/* Apagado cuando ya hay direcciones escritas: entonces solo abre, nunca pliega. */
.buzon-cc-mas:disabled { opacity: 0.45; cursor: default; }
.buzon-textarea { flex: 1; min-height: 12rem; resize: vertical; font-family: inherit; line-height: 1.5; }
/* Autocompletado de destinatarios (CardDAV). */
.buzon-campo-ac { align-items: flex-start; }
.buzon-campo-etq { flex: none; width: 3.2rem; color: var(--color-text-muted); font-size: var(--t-base); padding-top: 0.5rem; }
.buzon-ac-wrap { flex: 1; min-width: 0; position: relative; }
.buzon-ac-wrap .input { width: 100%; }
.buzon-ac-pop { position: absolute; top: calc(100% + 0.2rem); left: 0; right: 0; z-index: 5; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); max-height: 16rem; overflow-y: auto; padding: 0.25rem; }
.buzon-ac-item { display: flex; align-items: center; gap: 0.6rem; width: 100%; padding: 0.4rem 0.5rem; background: none; border: none; border-radius: var(--radius-sm); cursor: pointer; text-align: left; color: inherit; font: inherit; }
.buzon-ac-item.activo, .buzon-ac-item:hover { background: var(--color-surface-2); }
.buzon-ac-avatar { flex: none; width: 1.9rem; height: 1.9rem; border-radius: 50%; background: var(--color-primary); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: var(--t-md); }
.buzon-ac-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.buzon-ac-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.buzon-ac-mail { overflow: hidden; font-size: var(--t-sm); color: var(--color-text-muted); display: flex; gap: 0.35rem; align-items: center; }
/* El corte con «…» va en el correo, no en el contenedor: la etiqueta nunca se recorta. */
.buzon-ac-mail > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Etiqueta del correo (trabajo/casa) cuando el contacto tiene varios: distingue cuál es cuál. */
.buzon-ac-etq { flex: none; font-size: var(--t-2xs); padding: 0 0.3rem; border-radius: 0.4rem; background: var(--color-surface-2); border: 1px solid var(--color-border); }
/* Adjuntos en redacción */
.buzon-adj-acc { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.buzon-adj-lista { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.buzon-adj-chip { display: inline-flex; align-items: center; gap: 0.35rem; max-width: 100%; font-size: var(--t-sm); background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: 0.5rem; padding: 0.2rem 0.25rem 0.2rem 0.5rem; }
.buzon-adj-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 14rem; }
.buzon-adj-tam { flex: none; font-size: var(--t-xs); }
.buzon-adj-x { display: inline-flex; align-items: center; justify-content: center; width: 1.3rem; height: 1.3rem; padding: 0; background: none; border: none; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-sm); flex: none; }
.buzon-adj-x:hover { color: var(--color-danger); }
.buzon-adj-x svg { width: 0.8rem; height: 0.8rem; }

/* ── Correo: layout de 3 paneles (árbol · lista · vista previa) en escritorio ── */
.buzon-sep { display: none; }
/* Solo a ≥769 px (ver el bloque de abajo): en el teléfono las carpetas van en su panel aparte. */
.buzon-arbol-plegar, .buzon-arbol-plegar-cab { display: none; }
.buzon-preview-vacio { display: none; }
@media (min-width: 769px) {
    .buzon-main { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
    .buzon-main .buzon-cab { padding: 0.7rem 1rem; margin: 0; border-bottom: 1px solid var(--color-border); }
    .buzon-main .buzon-aviso-card { margin: 1rem; }
    .buzon-panes { flex: 1; min-height: 0; display: grid; grid-template-columns: var(--w-tree, 210px) 5px var(--w-list, 330px) 5px 1fr; }
    .buzon-pane { min-height: 0; overflow-y: auto; }
    .buzon-pane-tree { padding: 0.5rem 0.3rem; }
    .buzon-pane-tree.file-tree { border-right: none; }
    .buzon-pane-list { border-right: 1px solid var(--color-border); }
    .buzon-pane-list .buzon-lista { border: none; border-radius: 0; }
    .buzon-pane-preview { overflow: hidden; min-width: 0; }
    .buzon-sep { display: block; background: var(--color-border); cursor: col-resize; }
    .buzon-sep:hover, .buzon-sep:active { background: var(--color-primary); }
    /* Columna de carpetas plegable (2026-09-13): plegada es una franja de 2.2rem
       con el botón para volver a abrirla; el separador de su ancho desaparece. */
    .buzon-arbol-plegar {
        display: flex; align-items: center; justify-content: center;
        width: 1.8rem; height: 1.8rem; margin: 0 0 0.3rem auto; padding: 0;
        border: 1px solid var(--color-border); border-radius: var(--radius-sm);
        background: var(--color-surface); color: var(--color-text-2);
        font-size: var(--t-xl); line-height: 1; cursor: pointer;
    }
    .buzon-arbol-plegar:hover { color: var(--color-primary); border-color: var(--color-primary); }
    /* Abierta: el de plegar va en el renglón de «Buzones inteligentes», tras el «+». */
    .buzon-arbol-plegar-cab { display: inline-flex; align-items: center; justify-content: center; font-size: var(--t-lg); line-height: 1; }
    .buzon-panes.arbol-oculto { grid-template-columns: 2.2rem 0 var(--w-list, 330px) 5px 1fr; }
    .buzon-panes.arbol-oculto > .buzon-pane-tree { padding: 0.5rem 0.2rem; overflow: hidden; }
    .buzon-panes.arbol-oculto > .buzon-pane-tree > :not(.buzon-arbol-plegar) { display: none !important; }
    .buzon-panes.arbol-oculto > .buzon-pane-tree > .buzon-arbol-plegar { margin: 0 auto; }
    .buzon-panes.arbol-oculto > .buzon-sep:first-of-type { visibility: hidden; pointer-events: none; }
    /* Lector en flujo dentro del panel de vista previa (no overlay en escritorio) */
    .buzon-lector { position: static; inset: auto; z-index: auto; height: 100%; }
    .buzon-lector-atras { display: none; }
    .buzon-preview-vacio { display: flex; height: 100%; flex-direction: column; align-items: center; justify-content: center; gap: 0.6rem; color: var(--color-text-muted); padding: 1rem; text-align: center; }
    .buzon-preview-ic { width: 2.6rem; height: 2.6rem; opacity: 0.35; }
    .buzon-preview-ic svg { width: 100%; height: 100%; }
    .buzon-preview-logo { width: clamp(90px, 38%, 180px); height: auto; opacity: 0.9; }
    .buzon-item.sel { background: var(--color-surface-2); box-shadow: inset 3px 0 0 var(--color-primary); }
    .buzon-cargando { padding: 1rem; }
}
/* Aviso de imágenes remotas bloqueadas (con botón para mostrarlas). */
/* Informe de entrega de un rebote. Monoespaciado y con desplazamiento propio:
   son líneas `Clave: valor` que no se deben partir, y el `Diagnostic-Code` del
   servidor remoto puede ser larguísimo. */
.buzon-informe { margin: 0.6rem 0.9rem; border: 1px solid var(--color-border); border-left: 3px solid var(--color-danger); border-radius: var(--radius-md); background: var(--color-surface); }
.buzon-informe-cab { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.7rem 0; font-size: var(--t-sm); font-weight: 600; color: var(--color-text-2); }
.buzon-informe-cab svg { width: 1rem; height: 1rem; }
.buzon-informe-txt { margin: 0.35rem 0 0; padding: 0 0.7rem 0.6rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--t-sm); line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 14rem; overflow: auto; }

.buzon-imgs-barra { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; padding: 0.5rem 0.9rem; background: var(--color-surface-2); border-bottom: 1px solid var(--color-border); font-size: var(--t-md); color: var(--color-text-muted); }
.buzon-imgs-barra .btn { flex: none; }
.buzon-lector { overflow: hidden; }
.nota-enlaces { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.5rem; }
.nota-enlace { display: flex; flex-direction: column; border: 1px solid var(--nota-bd); border-radius: 0.5rem; background: color-mix(in srgb, var(--nota-fg) 8%, transparent); color: inherit; text-decoration: none; overflow: hidden; }
.nota-enlace:hover { background: color-mix(in srgb, var(--nota-fg) 15%, transparent); }
.nota-enlace-img { width: 100%; height: 120px; object-fit: cover; display: block; background: rgba(0,0,0,0.06); }
.nota-enlace-pie { display: flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.55rem; min-width: 0; }
.nota-favicon { width: 1rem; height: 1rem; flex: 0 0 auto; border-radius: 3px; object-fit: contain; }
.nota-enlace-ic { flex: 0 0 auto; display: inline-flex; opacity: 0.7; }
.nota-enlace-ic svg { width: 1rem; height: 1rem; }
.nota-enlace-txt { min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.nota-enlace-titulo { font-size: var(--t-md); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nota-enlace-dom { font-size: var(--t-xs); opacity: 0.65; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nota-chip-recordatorio { display: inline-flex; align-items: center; gap: 0.35rem; margin-top: 0.5rem; font-size: var(--t-xs); padding: 0.15rem 0.55rem; border-radius: 1rem; background: color-mix(in srgb, var(--nota-fg) 10%, transparent); }
.nota-chip-recordatorio svg { width: 0.85rem; height: 0.85rem; }
.nota-recordatorio-ctrl { display: flex; align-items: center; gap: 0.5rem; margin: 0.6rem 0; color: var(--nota-fg); }
.nota-recordatorio-ic { display: inline-flex; flex: 0 0 auto; opacity: 0.75; }
.nota-recordatorio-ic svg { width: 1.1rem; height: 1.1rem; }
.nota-fecha-in { flex: 1 1 auto; height: 2rem; }
/* Checklists */
.nota-items { display: flex; flex-direction: column; gap: 0.1rem; min-height: 26vh; }
.nota-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.15rem 0; }
.nota-item input[type=checkbox] { flex: 0 0 auto; width: 1.05rem; height: 1.05rem; accent-color: var(--nota-fg); }
.nota-item-txt { flex: 1 1 auto; min-width: 0; background: transparent; border: 0; border-bottom: 1px solid transparent; color: inherit; font-family: inherit; font-size: var(--t-lg); padding: 0.15rem 0; outline: none; }
.nota-item-txt:focus { border-bottom-color: var(--nota-bd); }
.nota-item.hecho .nota-item-txt { text-decoration: line-through; opacity: 0.55; }
.nota-item-mas { display: inline-flex; opacity: 0.6; }
.nota-item-mas svg { width: 1.05rem; height: 1.05rem; }
.nota-items-card { display: flex; flex-direction: column; gap: 0.15rem; margin-top: 0.4rem; }
.nota-item-card { display: flex; align-items: center; gap: 0.4rem; font-size: var(--t-base); }
.nota-item-card .nota-check { display: inline-flex; flex: 0 0 auto; opacity: 0.75; }
.nota-item-card .nota-check svg { width: 0.95rem; height: 0.95rem; }
.nota-item-card.hecho { text-decoration: line-through; opacity: 0.5; }
.nota-mas-items { font-size: var(--t-sm); opacity: 0.65; margin-top: 0.15rem; }
/* Imágenes adjuntas */
.nota-imgs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.4rem 0; }
.nota-img { position: relative; width: 6.5rem; height: 6.5rem; border-radius: 0.5rem; overflow: hidden; border: 1px solid var(--nota-bd); }
.nota-img img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.nota-img-x { position: absolute; top: 2px; right: 2px; display: inline-flex; align-items: center; justify-content: center; width: 1.4rem; height: 1.4rem; padding: 0; border: 0; border-radius: 50%; background: rgba(0, 0, 0, 0.55); color: #fff; cursor: pointer; }
.nota-img-x svg { width: 0.9rem; height: 0.9rem; }
.nota-imgs-card { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin-top: 0.4rem; }
.nota-img-card { width: 3.25rem; height: 3.25rem; object-fit: cover; border-radius: 0.4rem; border: 1px solid var(--nota-bd); }
/* Audios (grabaciones) */
.nota-audios { display: flex; flex-direction: column; gap: 0.35rem; margin: 0.4rem 0; }
.nota-audio { display: flex; align-items: center; gap: 0.4rem; }
.nota-audio audio { flex: 1; min-width: 0; height: 2.2rem; }
.nota-audio-dur { font-size: var(--t-sm); opacity: 0.7; flex: none; }
.nota-chip-audio { display: inline-flex; align-items: center; gap: 0.3rem; margin-top: 0.4rem; font-size: var(--t-sm); opacity: 0.75; }
.nota-chip-audio svg { width: 0.95rem; height: 0.95rem; }
/* Botón de grabación + cronómetro */
.nota-acc.grabando { color: #e0392b; opacity: 1; background: rgba(224, 57, 43, 0.12); }
.nota-acc.grabando svg { width: 1.3rem; height: 1.3rem; }
.nota-grab-timer { display: inline-flex; align-items: center; gap: 0.35rem; font-size: var(--t-md); font-variant-numeric: tabular-nums; color: #e0392b; }
.nota-grab-dot { width: 0.6rem; height: 0.6rem; border-radius: 50%; background: #e0392b; animation: nota-grab-pulso 1s ease-in-out infinite; }
@keyframes nota-grab-pulso { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } }
/* Visor a pantalla completa */
.nota-img-visor { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.9); padding: 1rem; }
.nota-img-visor img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 0.4rem; cursor: zoom-out; }
.nota-img-visor-x { position: absolute; top: max(0.75rem, env(safe-area-inset-top)); right: 0.75rem; display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; padding: 0; border: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.15); color: #fff; cursor: pointer; }
.nota-img-visor-x svg { width: 1.4rem; height: 1.4rem; }
/* Arrastrar para reordenar */
.nota-grip { position: absolute; top: 1px; left: 50%; transform: translateX(-50%); display: inline-flex; opacity: 0; cursor: grab; touch-action: none; color: inherit; }
.nota-card:hover .nota-grip { opacity: 0.4; }
.nota-grip:active { cursor: grabbing; }
.nota-grip svg { width: 1.15rem; height: 1.15rem; }
.nota-grip-item { position: static; transform: none; opacity: 0.4; flex: 0 0 auto; }
.nota-grip-item svg { width: 1rem; height: 1rem; }
@media (hover: none) { .nota-grip { opacity: 0.35; } }
body.arrastrando-notas, body.arrastrando-notas * { cursor: grabbing !important; user-select: none !important; }

@media (hover: none) { .nota-acciones { opacity: 1; } }
/* 768 y no 720: es el corte de `.solo-movil`, y el botón de filtros del móvil
   es un `.solo-movil` — con cortes distintos quedaba una franja (721–768) con
   el botón muerto y la columna de filtros vacía. */
@media (max-width: 768px) {
    /* ⚠️ Filas EXPLÍCITAS: el botón de filtros mide lo suyo y el resto es de
       las notas. Sin esto, con una vista VACÍA («Compartidas conmigo» sin
       notas, la papelera limpia) el sobrante de la rejilla se repartía entre
       las filas y el botón se inflaba hasta un cuadro gigante. Los demás hijos
       (telón, panel, tirador) van display:none o position:fixed y no generan
       fila. */
    .notas-cuerpo { grid-template-columns: 1fr; grid-template-rows: auto 1fr; align-content: start; }
    .panel-sep { display: none; }
    /* Los filtros ya NO se apilan encima de las notas: van en panel lateral
       (como las carpetas del correo). Cerrado no existe; abierto es una capa
       fija a toda altura sobre su telón. La transición hace que al soltar un
       arrastre a medias vuelva suave a su sitio. */
    .notas-filtros { display: none; }
    .notas-filtros.abierto {
        display: flex; flex-direction: column;
        position: fixed; top: 0; bottom: 0; left: 0; right: 22%;
        max-width: 22rem; z-index: 60;
        background: var(--color-surface);
        border-right: 1px solid var(--color-border); border-bottom: 0;
        padding: 0.8rem 0.6rem;
        padding-top: calc(0.8rem + env(safe-area-inset-top));
        padding-bottom: calc(0.8rem + env(safe-area-inset-bottom));
        overflow-y: auto; overscroll-behavior: contain;
        box-shadow: var(--shadow-lg, 0 8px 32px rgba(0,0,0,.35));
        transition: transform 0.15s ease-out;
    }
    .notas-grid { columns: 160px; }
}
.notas-filtro-toggle-caja { padding: 0.6rem 0.85rem 0; }
@media (max-width: 768px) {
    .notas-filtros-fondo {
        position: fixed; inset: 0; z-index: 59;
        background: color-mix(in srgb, #000 45%, transparent);
    }
}
@media (min-width: 769px) { .notas-filtros-fondo, .notas-filtro-toggle-caja { display: none; } }
.editor-area {
    width: 100%; min-height: 58vh; resize: vertical; box-sizing: border-box;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--t-base); line-height: 1.5; tab-size: 4;
    /* Ajuste de línea: las líneas largas se envuelven en vez de exigir scroll
       horizontal (se preservan saltos y espacios; se parten tokens muy largos). */
    white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
    padding: 0.75rem; border: 1px solid var(--color-border); border-radius: var(--radius-md);
    background: var(--color-bg); color: var(--color-text);
}

/* Pestañas del editor (varios archivos). En el teléfono se desplazan de lado. */
.editor-pestanas { display: flex; align-items: stretch; gap: 0.2rem; overflow-x: auto; margin-bottom: 0.5rem; border-bottom: 1px solid var(--color-border); scrollbar-width: thin; }
.editor-pestana {
    display: inline-flex; align-items: center; gap: 0.3rem; flex: 0 0 auto; max-width: 14rem;
    padding: 0.35rem 0.3rem 0.35rem 0.65rem; border: 1px solid transparent; border-bottom: 0;
    border-radius: var(--radius-md) var(--radius-md) 0 0; cursor: pointer; font-size: var(--t-md);
    color: var(--color-text-muted); user-select: none;
}
.editor-pestana:hover { background: var(--color-surface-2, var(--color-surface)); }
.editor-pestana.activa { color: var(--color-text); background: var(--color-bg); border-color: var(--color-border); margin-bottom: -1px; font-weight: 600; }
.editor-pestana-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.editor-pestana-sucia { color: var(--color-primary); font-size: var(--t-2xs); }
.editor-pestana-x { display: inline-flex; border: 0; background: none; color: inherit; padding: 0.15rem; border-radius: 4px; cursor: pointer; opacity: 0.6; }
.editor-pestana-x:hover { opacity: 1; background: color-mix(in srgb, var(--color-text) 12%, transparent); }
.editor-pestana-x svg, .editor-pestana-mas svg { width: 0.85rem; height: 0.85rem; }
.editor-pestana-mas { flex: 0 0 auto; display: inline-flex; align-items: center; padding: 0 0.6rem; border: 0; background: none; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-md); }
.editor-pestana-mas:hover, .editor-pestana-mas.activo { color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.editor-minimizar { flex: 0 0 auto; margin-left: auto; display: inline-flex; align-items: center; padding: 0 0.6rem; border: 0; background: none; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-md); }
.editor-minimizar:hover { color: var(--color-text); background: color-mix(in srgb, var(--color-text) 8%, transparent); }
.editor-minimizar svg { width: 1rem; height: 1rem; }
/* El editor minimizado: una pastilla abajo a la izquierda (a la derecha están los
   botones flotantes de Correo); en el teléfono, encima de la barra de módulos. */
.editor-pastilla {
    position: fixed; left: 1rem; bottom: 1rem; z-index: 65;
    display: inline-flex; align-items: center; gap: 0.45rem; max-width: min(22rem, calc(100vw - 2rem));
    padding: 0.55rem 0.9rem; border: 1px solid var(--color-border); border-radius: 999px;
    background: var(--color-surface); color: var(--color-text); box-shadow: 0 6px 20px rgb(0 0 0 / 0.18);
    cursor: pointer; font-size: var(--t-base);
}
.editor-pastilla:hover { border-color: var(--color-primary); }
.editor-pastilla svg { width: 1rem; height: 1rem; flex: 0 0 auto; }
.editor-pastilla-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 768px) { .editor-pastilla { bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px)); } }
body.esc-activo .editor-pastilla { bottom: calc(48px + 0.75rem); } /* sobre la barra de tareas del modo escritorio */
/* En su propia ventana del modo escritorio: el editor ocupa toda la ventana. */
html.en-ventana-editor .editor-fondo { background: var(--color-bg); padding: 0; align-items: stretch; }
html.en-ventana-editor .editor-fondo > .modal {
    max-width: none; width: 100%; height: 100%; max-height: none; border-radius: 0; box-shadow: none;
    padding: 0.4rem 0.75rem 0.6rem; overflow: hidden;
}
html.en-ventana-editor .editor .modal-acciones { margin-top: 0.5rem; }
/* «Abrir otro archivo» */
.editor-explorador { display: flex; flex-direction: column; gap: 0.5rem; }
.editor-explorador-ruta { font-size: var(--t-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 24rem; }
.editor-explorador-filtro { margin-left: auto; min-width: 10rem; flex: 0 1 16rem; }
.editor-explorador-lista { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; border: 1px solid var(--color-border); border-radius: var(--radius-md); }
.editor-explorador-lista li > button { display: flex; align-items: center; gap: 0.5rem; width: 100%; padding: 0.45rem 0.7rem; border: 0; background: none; color: var(--color-text); text-align: left; cursor: pointer; font-size: var(--t-base); }
.editor-explorador-lista li > button:hover { background: var(--color-surface-2, var(--color-surface)); }
.editor-explorador-lista li > button.abierto { font-weight: 600; }
.editor-explorador-lista li > button svg { width: 1rem; height: 1rem; flex: 0 0 auto; opacity: 0.75; }
.editor-explorador-lista li.texto-muted { padding: 0.6rem 0.7rem; }
@media (max-width: 640px) {
    .editor-explorador-filtro { margin-left: 0; flex: 1 1 100%; }
}
/* ⚠️ EL EDITOR VA EN COLUMNA Y SOLO CRECE O SE ENCOGE EL ÁREA DE TEXTO. Lo
   demás (pestañas, botones, barra de estado, acciones) mide lo suyo y no cede:
   la barra de pestañas tiene desplazamiento lateral, y con eso el navegador la
   dejaba encoger hasta 11 px —las pestañas «quedaban atrás del editor» al abrir
   un segundo archivo (Jore, 2026-10-22)—. Y el diálogo tiene alto fijo, así que
   no se desplaza: antes, al enfocar el editor, las pestañas se iban por arriba. */
.editor-fondo > .modal { display: flex; flex-direction: column; height: 90vh; height: 90dvh; overflow: hidden; }
.editor { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.editor > * { flex: 0 0 auto; }
.editor > .editor-cm, .editor > .editor-explorador, .editor > .editor-area { flex: 1 1 auto; min-height: 9rem; }
/* El editor de código (CodeMirror): su propio desplazamiento. */
.editor-cm {
    overflow: hidden;
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
}
.editor-cm .cm-editor { height: 100%; }
/* En el teléfono los números de línea se comían un sexto del ancho (Jore, 2026-10-28):
   fuera. Las flechas de plegar se quedan, son angostas. */
@media (max-width: 768px) { .editor-cm .cm-lineNumbers { display: none; } }
.editor-barra { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.45rem; }
.editor-barra .btn.activo { background: color-mix(in srgb, var(--color-primary) 14%, transparent); border-color: var(--color-primary); }
@media (max-width: 640px) {
    .editor-barra .btn-con-icono span + span { display: none; } /* en el teléfono, solo el ícono */
}
/* Barra de estado del editor: en qué codificación y con qué saltos se guarda. */
.editor-estado { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; margin-top: 0.45rem; font-size: var(--t-sm); color: var(--color-text-muted); }
.editor-estado label { display: inline-flex; align-items: center; gap: 0.35rem; }
.editor-estado select { font-size: var(--t-sm); padding: 0.15rem 0.3rem; }
.editor-conflicto {
    margin-top: 0.6rem; padding: 0.6rem 0.75rem; border-radius: var(--radius-md);
    border: 1px solid var(--color-danger); background: color-mix(in srgb, var(--color-danger) 8%, transparent);
    font-size: var(--t-base);
}
.editor-conflicto p { margin: 0 0 0.5rem; }

/* ---- Toasts ---- */
.toast-cont { position: fixed; top: 1rem; right: 1rem; display: flex; flex-direction: column; gap: 0.5rem; z-index: 100; max-width: min(90vw, 24rem); }
.toast {
    display: flex; align-items: flex-start; gap: 0.5rem;
    padding: 0.75rem 1rem; border-radius: var(--radius-md);
    background: var(--color-surface); color: var(--color-text);
    border: 1px solid var(--color-border); border-left: 4px solid var(--color-info);
    box-shadow: var(--shadow-md); animation: toast-in var(--transition);
}
.toast > span { flex: 1; }

/* Buscar duplicados ----------------------------------------------------- */
.dup-actual { font-size: var(--t-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-height: 1.2em; }
.dup-lista { max-height: min(60vh, 34rem); overflow-y: auto; display: flex; flex-direction: column; gap: 0.75rem; margin: 0.75rem 0; }
/* `flex: none` NO sobra: la lista es una columna flex con alto máximo, y sin
   él, con muchos grupos, el navegador los encogía hasta dejarlos en una raya
   (su `overflow: hidden` escondía el contenido). Con dos grupos no se notaba. */
.dup-grupo { flex: none; border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.dup-grupo-tit { padding: 0.4rem 0.75rem; font-size: var(--t-sm); font-weight: 600; background: var(--color-surface-2); color: var(--color-text-2); }
.dup-fila { display: flex; align-items: center; gap: 0.6rem; padding: 0.45rem 0.75rem; border-top: 1px solid var(--color-border); cursor: pointer; }
.dup-grupo-tit + template + .dup-fila, .dup-grupo-tit + .dup-fila { border-top: 0; }
.dup-fila.se-queda { background: color-mix(in srgb, var(--color-success) 8%, transparent); }
.dup-mini { width: 2.6rem; height: 2.6rem; flex: none; border-radius: 4px; object-fit: cover; background: var(--color-surface-2); }
.dup-icono { display: inline-flex; align-items: center; justify-content: center; }
.dup-icono svg { width: 1.4rem; height: 1.4rem; }
.dup-datos { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.dup-nombre { overflow-wrap: anywhere; }
.dup-ruta { font-size: var(--t-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dup-queda { flex: none; }
@media (max-width: 640px) { .dup-queda { font-size: var(--t-2xs); padding: 0.1rem 0.4rem; } .dup-fila { gap: 0.45rem; padding-inline: 0.5rem; } }

/* Carpetas grandes (VIRT_UMBRAL en app.js): huecos, riel y letrero ---------- */
.virt-hueco td { padding: 0; border: 0; }
.virt-hueco-g { grid-column: 1 / -1; }
.riel {
    position: fixed; z-index: 35; width: 2.75rem; pointer-events: none;
    opacity: 0; transition: opacity 0.25s;
}
.riel.visible { opacity: 1; }
/* Solo el asa recibe el puntero, y solo cuando se ve: la pista invisible
   taparía los botones del extremo derecho de cada renglón. */
.riel-asa {
    position: absolute; right: 0; width: 2.1rem; height: 44px;
    display: flex; align-items: center; justify-content: center;
    background: var(--color-surface); color: var(--color-text-2);
    border: 1px solid var(--color-border); border-radius: 22px 6px 6px 22px;
    box-shadow: var(--shadow-md); cursor: grab; touch-action: none; user-select: none;
}
.riel.visible .riel-asa { pointer-events: auto; }
.riel-asa.arrastrando { cursor: grabbing; background: var(--color-primary); color: #fff; border-color: var(--color-primary); }
.riel-asa svg { width: 1.1rem; height: 1.1rem; }
/* El asa del editor de texto (editor-codigo.js, montarAsa): la del riel, dentro del editor. */
.cm-asa-riel { position: absolute; right: 0; width: 2.6rem; z-index: 6; pointer-events: none; opacity: 0; transition: opacity 0.25s; }
.cm-asa-riel.visible { opacity: 1; }
.cm-asa {
    position: absolute; right: 2px; width: 2.1rem; height: 44px;
    display: flex; align-items: center; justify-content: center;
    background: var(--color-surface); color: var(--color-text-2);
    border: 1px solid var(--color-border); border-radius: 22px 6px 6px 22px;
    box-shadow: var(--shadow-md); cursor: grab; touch-action: none; user-select: none;
}
.cm-asa-riel.visible .cm-asa { pointer-events: auto; }
.cm-asa-riel.arrastrando .cm-asa { cursor: grabbing; background: var(--color-primary); color: #fff; border-color: var(--color-primary); }
.cm-asa svg { width: 1.1rem; height: 1.1rem; }
.cm-asa-burbuja {
    position: absolute; right: 2.9rem; margin-top: 6px; white-space: nowrap; display: none;
    padding: 0.35rem 0.8rem; border-radius: var(--radius-full);
    background: var(--color-primary); color: #fff; font-weight: 600; font-size: var(--t-lg); box-shadow: var(--shadow-md);
}
.cm-asa-riel.arrastrando .cm-asa-burbuja { display: block; }
.riel-burbuja {
    position: absolute; right: 3rem; margin-top: 2px; white-space: nowrap;
    padding: 0.4rem 0.85rem; border-radius: var(--radius-full);
    background: var(--color-primary); color: #fff; font-weight: 600; font-size: var(--t-lg);
    box-shadow: var(--shadow-md);
}
.virt-letrero {
    position: fixed; z-index: 35; transform: translateX(-50%); pointer-events: none;
    padding: 0.25rem 0.8rem; border-radius: var(--radius-full); font-size: var(--t-sm); font-weight: 600;
    background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); box-shadow: var(--shadow-md);
}

/* Avance de mover/copiar (ejecutarMoverCopiar): abajo a la derecha, lejos de
   los toasts de arriba; en el teléfono, encima de la barra de módulos. */
.copia-avance {
    position: fixed; right: 1rem; bottom: 1rem; z-index: 95; width: min(22rem, calc(100vw - 2rem));
    display: flex; flex-direction: column; gap: 0.4rem; padding: 0.75rem 1rem;
    background: var(--color-surface); color: var(--color-text);
    border: 1px solid var(--color-border); border-left: 4px solid var(--color-primary);
    border-radius: var(--radius-md); box-shadow: var(--shadow-md); animation: toast-in var(--transition);
}
.copia-avance-cab { display: flex; align-items: center; gap: 0.5rem; font-size: var(--t-base); }
.copia-avance-cab > span { display: inline-flex; flex: none; color: var(--color-primary); }
.copia-avance-cab svg { width: 1.1rem; height: 1.1rem; }
.copia-avance-nombre { font-size: var(--t-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.copia-avance-pie { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; font-size: var(--t-sm); }
@media (max-width: 768px) {
    .copia-avance { left: 1rem; right: 1rem; width: auto; bottom: calc(4.5rem + env(safe-area-inset-bottom)); }
}
/* Separador de la barra de selección: marca dónde empieza lo que saca el correo
   de en medio. Sin él, «marcar leído» y «eliminar» parecen lo mismo. */
.buzon-sel-sep { width: 1px; align-self: stretch; margin: 0.15rem 0.35rem; background: var(--color-border); flex: none; }

.toast-accion {
    flex: none; background: none; border: 0; padding: 0; cursor: pointer;
    color: var(--color-primary); font: inherit; font-weight: 600; white-space: nowrap;
}
.toast-accion:hover { text-decoration: underline; }
.toast-exito { border-left-color: var(--color-success); }
.toast-alerta { border-left-color: var(--color-warning); }
.toast-peligro { border-left-color: var(--color-danger); }
@keyframes toast-in { from { opacity: 0; transform: translateX(1rem); } to { opacity: 1; transform: none; } }

/* ---- Utilidades ---- */
.pila { display: flex; flex-direction: column; gap: 1rem; }
.fila { display: flex; align-items: center; gap: 0.75rem; }
.fila-fin { justify-content: flex-end; }
.oculto { display: none !important; }
.centrado { display: grid; place-items: center; min-height: 100vh; padding: 1rem; }
.panel-login { width: 100%; max-width: 22rem; }

/* ---- Responsive: en móvil, el árbol se oculta y se navega por breadcrumb ---- */
/* ── Aviso de versión nueva ───────────────────────────────────────────────
   Abajo y a un lado: informa sin interrumpir, y no tapa la barra de acciones
   del móvil (que vive abajo del todo, de ahí el hueco). Por encima de los
   modales a propósito —el caso que más importa es justo cuando hay una capa
   abierta, porque es cuando la recarga automática se aplaza—. */
.version-nueva { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(env(safe-area-inset-bottom, 0px) + 4.5rem); z-index: 90; display: flex; align-items: center; gap: 0.6rem; max-width: min(30rem, calc(100vw - 2rem)); padding: 0.55rem 0.6rem 0.55rem 0.9rem; border-radius: var(--radius-lg); background: var(--color-surface); border: 1px solid var(--color-border); box-shadow: 0 6px 24px rgba(0,0,0,.18); font-size: var(--t-base); }
.version-nueva .btn { flex: 0 0 auto; }
.version-nueva-cerrar { flex: 0 0 auto; opacity: 0.6; }
.version-nueva-cerrar:hover { opacity: 1; }
@media (min-width: 769px) { .version-nueva { bottom: 1.25rem; } }

/* ── LA FRANJA DE LAS TABLETAS (769–1500 px) ──────────────────────────────
   Entre el móvil y un escritorio ancho no había nada, y ahí la barra no cabe:
   hamburguesa + marca + módulo + seis pestañas con texto + buscador + usuario
   suman ~1550 px. El `flex-wrap` las repartía en dos o tres renglones, con el
   usuario suelto debajo del logo — que es lo que se vio en la tablet, y se
   notaba más en «Administración» porque ese rótulo es de los largos.

   Se hace lo MISMO que ya hace el móvil: las pestañas se quedan en iconos. Son
   ~360 px menos y la barra vuelve a un renglón. No se pierde nada: cada botón
   ya lleva su `title` y su `aria-label`, y la sección abierta se sigue diciendo
   con letra al lado del logo.

   El tope se fijó midiendo, no estimando: ver la tabla de anchos del commit. */
@media (min-width: 769px) and (max-width: 1500px) {
    /* Icono ARRIBA y su nombre en letra chica DEBAJO, como la barra inferior
       del teléfono (Jore, 2026-10-01: en la tablet, un icono solo y chico
       obligaba a adivinar). Apilado ocupa mucho menos ancho que el texto al
       lado, así que sigue cabiendo en un renglón. */
    .navbar .nav-tabs .btn-con-icono {
        flex-direction: column; gap: 0.15rem; padding: 0.25rem 0.3rem; min-width: 3.2rem;
    }
    .navbar .nav-tabs .btn-con-icono svg { width: 1.35rem; height: 1.35rem; }
    .navbar .nav-tabs .nav-tab-txt {
        display: block; font-size: var(--t-2xs); line-height: 1; font-weight: 500;
        max-width: 4.6rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* El nombre de la persona, recortado: con los nombres de las pestañas, la
       tablet en horizontal (1180 px) se iba a dos renglones. Sigue diciendo
       quién es, completo en el `title`, y el menú de cuentas sigue al lado. */
    .navbar .usuario-nombre { max-width: 6rem; }
    /* La búsqueda con ancho FIJO y el espacio libre todo para el título de la
       sección (que se corta con «…»): así las pestañas, la búsqueda y los iconos
       quedan pegados a la derecha y NO se recorren al cambiar de «Correo» a
       «Configuración» (Jore, 2026-10-01: en la tablet bailaban). */
    .navbar .busqueda-barra { flex: 0 1 13.5rem; }
    .navbar .nav-seccion-desk { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
/* Medido: con 13.5 rem la barra se va a dos renglones entre 1150 y 1199 px (la
   tablet en horizontal de 1180), donde 11 rem sí cabe en uno. Solo ahí, 11. */
@media (min-width: 1150px) and (max-width: 1199px) {
    .navbar .busqueda-barra { flex-basis: 11rem; }
}
/* Lo mismo ARRIBA de 1500 px cuando no cabe: `navbar-compacta` (y los dos escalones siguientes) la pone app.js
   al ver que algo cayó al segundo renglón (con Administración, Red y Clientes
   la barra pide más de lo que se midió para el tope de arriba). */
@media (min-width: 769px) {
    .navbar.navbar-compacta .nav-tabs .btn-con-icono {
        flex-direction: column; gap: 0.15rem; padding: 0.25rem 0.3rem; min-width: 3.2rem;
    }
    .navbar.navbar-compacta .nav-tabs .btn-con-icono svg { width: 1.35rem; height: 1.35rem; }
    .navbar.navbar-compacta .nav-tabs .nav-tab-txt {
        display: block; font-size: var(--t-2xs); line-height: 1; font-weight: 500;
        max-width: 4.6rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .navbar.navbar-compacta .usuario-nombre { max-width: 6rem; }
    .navbar.navbar-compacta .busqueda-barra { flex: 0 1 13.5rem; }
    .navbar.navbar-sin-nombre .usuario-nombre { display: none !important; }
    .navbar.navbar-solo-iconos .nav-tabs .nav-tab-txt { display: none; }
    .navbar.navbar-solo-iconos .nav-tabs .btn-con-icono { min-width: 0; }
    .navbar.navbar-solo-iconos { gap: 0.5rem; }
    .navbar.navbar-solo-iconos .nav-usuario { gap: 0.15rem; margin-left: 0.25rem; }
    .navbar.navbar-busqueda-abajo { padding-bottom: 0.4rem; }
    .navbar.navbar-busqueda-abajo .busqueda-barra { order: 5; flex: 1 1 100%; max-width: none; }
}

@media (max-width: 768px) {
    /* Barras de botones (nav, herramientas, subtabs) envuelven en vez de
       desbordar la pantalla en celulares. */
    .fila { flex-wrap: wrap; }
    /* Botones de acción de las tablas: solo icono en móvil (la tabla queda
       mucho más angosta y casi no hay que deslizar). */
    .col-acc .btn-con-icono > span:last-child { display: none; }
    .col-acc .btn-con-icono { padding: 0.35rem 0.45rem; }
    .app-cuerpo { grid-template-columns: 1fr; }
    /* El historial se va a un CAJÓN. Antes era una tira horizontal arriba, y
       con cuatro conversaciones ya era inservible: títulos cortados y a
       deslizar de lado a ciegas. En un cajón cabe la lista vertical entera y
       la conversación se queda con toda la pantalla.
       (De paso desaparece el desbordamiento de la tira, que estiraba la
       rejilla: medido, 597px de ancho en una pantalla de 390.) */
    .chat-cuerpo { grid-template-columns: 1fr; grid-template-rows: 1fr; }
    .panel-sep { display: none; }
    .chat-lateral-fondo {
        display: none;                     /* .abierto lo enciende */
        position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, 0.45);
    }
    .chat-lateral-fondo.abierto { display: flex; }
    .chat-lateral {
        width: min(86vw, 21rem); height: 100%;
        border-right: 0; padding: 0.75rem;
        background: var(--color-surface);
        box-shadow: 2px 0 16px rgba(0, 0, 0, 0.3);
        min-width: 0;
    }
    .chat-lateral-cab {
        display: flex; align-items: center; justify-content: space-between;
        gap: 0.5rem; font-weight: 600; padding-bottom: 0.25rem;
    }
    .chat-abrir-historial { display: inline-flex; }
    /* La lista y los temas se quedan VERTICALES: es un cajón, hay altura. */
    .chat-item { max-width: none; }
    /* Los tres botones se llevaban 120 px de los 311 útiles —el 39% del
       renglón— para acciones ocasionales, mientras al título le faltaban. Se
       van a un menú: un toque más para renombrar, fijar o borrar, y el ancho
       de vuelta donde se lee. */
    .chat-item-renombrar, .chat-item .btn-icono.chat-item-fijar,
    .chat-item .btn-icono.chat-item-borrar { display: none; }
    .chat-item-menu { display: block; position: relative; }
    .chat-item-menu .menu-pop { right: 0; left: auto; }
    /* La cabecera ENVUELVE: en un teléfono no caben en un renglón el título,
       el asistente y el tema, y como los <select> no encogen por debajo de su
       contenido, el título se quedaba en una letra y el último se salía del
       borde. Mejor dos renglones que un recorte. */
    .chat-cabecera { padding: 0.5rem 0.7rem; flex-wrap: wrap; row-gap: 0.4rem; }
    .chat-cabecera .crece { display: none; }   /* con envoltura solo abre huecos */
    /* El título se va: en un teléfono se quedaba en dos letras y no se leía,
       y el ancho que ocupaba es justo el que les hacía falta a los nombres de
       los asistentes. Renombrar sigue estando en el historial. */
    .chat-titulo, .chat-titulo-nueva { display: none; }
    .chat-titulo-in { flex: 1 1 100%; }        /* al renombrar sí ocupa su renglón */
    /* Con «MasAdmin» son tres listas en el renglón (Jore, 2026-10-22: la última
       bajaba a otro renglón). Las bases suman lo que cabe en 360 px y TODAS
       pueden encoger (`min-width: 0`): el texto se recorta, el renglón no se parte. */
    .chat-cabecera .chat-asistente { flex: 1 1 5.5rem; max-width: none; min-width: 0; }
    .chat-cabecera .chat-nivel { flex: 0 1 5rem; max-width: 6.5rem; min-width: 0; }
    .chat-cabecera .chat-erp { flex: 0 1 6rem; max-width: 8.5rem; min-width: 0; }
    .chat-tema-sel { flex: 1 1 5.5rem; max-width: none; min-width: 0; }
    .chat-cabecera .select { padding-left: 0.4rem; padding-right: 0.2rem; font-size: var(--t-sm); }
    .chat-abrir-historial { flex: none; }
    .chat-redactar { padding: 0.6rem 0.7rem; }
    .chat-asistente { max-width: 7rem; }
    .sidebar { display: none; }
    .files-layout { grid-template-columns: 1fr; }
    .file-tree { display: none; }
    .navbar { gap: 0.35rem; padding: 0.4rem 0.55rem; }
    /* Wordmark un pelín menor en móvil para que quepan logo + «Mis archivos»
       (con texto en el dashboard) + salir en un solo renglón hasta ~360px. */
    /* En móvil ya cabe la marca junto al logo (las pestañas se fueron a la barra
       inferior): se muestra «MexMail/MexCloud · Módulo», un pelín más chica. */
    .navbar .marca .wordmark { display: inline; font-size: var(--t-xl); }
    /* En móvil las pestañas quedan solo con Mis archivos (dashboard) o vacías;
       el resto vive en la hamburguesa. Va INLINE junto a la marca (no en un
       renglón propio); el usuario se empuja a la derecha. Si no cabe, el
       flex-wrap del navbar lo baja solo. */
    .navbar .nav-tabs { order: 1; flex-basis: auto; margin-left: 0; }
    /* Solo iconos en móvil: caben las 3 secciones (Archivos/Notas/Correo) en un renglón.
       Iconos un poco más grandes (tap-target) con padding justo para no saltar de renglón. */
    .navbar .nav-tabs .nav-tab-txt { display: none; }
    .navbar .nav-tabs .btn-con-icono { padding: 0.3rem 0.45rem; }
    .navbar .nav-tabs .btn-con-icono svg { width: 1.3rem; height: 1.3rem; }
    /* El nombre del módulo ahora también en móvil (antes se ocultaba y se usaba
       .nav-seccion-movil). Elipsis + tope de ancho por si el módulo es largo. */
    /* UN SOLO RENGLÓN SIEMPRE (Jore, 2026-09-22): con «Configuración» o
       «Administración» los iconos de la derecha bajaban a un segundo renglón y
       la cabecera cambiaba de alto entre secciones. Lo que cede es el nombre de
       la sección (se recorta con puntos suspensivos); marca e iconos, nunca. */
    /* ⚠️ Se SIGUE envolviendo: el buscador es hijo de la barra y vive en su
       propio renglón (flex-basis 100%). Con `nowrap` se quedaba en el primero
       y la barra medía 546 px: la página se volvía más ancha que la pantalla y
       el teléfono dejaba alejar con los dedos (2026-09-22, un despliegue). Lo
       que evita el segundo renglón de iconos es que el nombre de la sección
       pueda encogerse hasta cero; marca e iconos no se encogen. */
    .navbar .marca, .navbar .hamburguesa, .navbar .nav-usuario { flex-shrink: 0; }
    /* `flex-basis: 0`: el nombre no «pide» sitio al repartir el renglón, así
       nunca es él quien manda los iconos abajo; después crece hasta lo que
       sobre y se recorta con puntos suspensivos. */
    .navbar .nav-seccion-desk { font-size: var(--t-lg); flex: 1 1 0; min-width: 0; max-width: max-content; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .navbar .nav-usuario { order: 2; margin-left: auto; gap: 0.15rem; }
    .navbar .usuario-nombre { max-width: 6rem; }
    .solo-movil { display: inline-flex !important; }
    .admin-secciones.solo-movil { display: block !important; } /* ocupa el ancho */
    /* Dentro de un menú desplegable, un elemento solo-móvil es un RENGLÓN como
       sus hermanos, no un botón suelto: `inline-flex` lo dejaba a media anchura
       y desalineado. Ya estaba resuelto así para la barra de selección; esto lo
       generaliza a cualquier menú. */
    .menu-pop .solo-movil { display: flex !important; }
    .tema-selector .texto-muted { display: none; }
    .salir-texto { display: none; }
    .salir-icono { display: inline-flex; }
    .contenido { --contenido-pad: 1rem; padding: var(--contenido-pad) 0.85rem; }
    /* ⚠️ EL HUECO ENTRE EL NAVBAR Y LA BARRA DE ACCIONES.
       En el teléfono quien desplaza es `.contenido`, y `sticky top: 0` pega a su
       caja de RELLENO —no a su borde—, así que el `padding-top` queda por encima
       y por esa franja se veía pasar la lista (2026-09-09, lo reportó Jore con
       una captura). Con el `top` negativo del mismo tamaño queda a ras: medido,
       de 16 px de hueco a 0.
       VA SOLO AQUÍ: en escritorio `.contenido` está en `overflow: hidden` y no
       desplaza, así que allá el negativo no arreglaría nada y sí podría meter
       parte de la barra debajo del navbar. */
    .buzon-sel-barra { top: calc(-1 * var(--contenido-pad, 0px)); }
    /* z-index 45 (no 30) porque la cabecera es `sticky` y por tanto CREA UN
       CONTEXTO DE APILADO: la barra de selección vive DENTRO de ella y en móvil
       se fija al pie, así que su `z-index:50` se compara solo entre hermanas,
       no contra la tabbar (40). Con 30 la tabbar tapaba la segunda fila de
       acciones (Compartir/Borrar/Limpiar). Queda por debajo del drawer (60) y
       de los diálogos (70). */
    .cabecera-gestor { top: -1rem; margin: -1rem -0.85rem 0.85rem; padding: 0.55rem 0.85rem; z-index: 45; }

    /* Solo en el GESTOR se ocultan las acciones por fila en móvil (pasan a la
       barra inferior de selección). En Papelera/Enlaces/Admin se mantienen. */
    .tabla-gestor .col-acc { display: none; }
    /* La barra de selección crece a 2-3 filas según cuántas acciones apliquen,
       así que el hueco al pie NO puede ser fijo: se mide la barra de verdad
       (--alto-barra-sel, ver app.js) o si no, se supone una fila. */
    .con-barra { padding-bottom: calc(max(var(--alto-barra-sel, 5.5rem), var(--alto-vaciado, 0px)) + 0.5rem); }

    /* En móvil no hay arrastrar-y-soltar: se sube con el botón «Subir» o por
       «Compartir con». Se oculta la zona de soltar y «Subir carpeta»
       (webkitdirectory apenas funciona en móvil). */
    .drop-zone { display: none; }
    .solo-escritorio { display: none !important; }

    .barra-seleccion {
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
        margin: 0; border-radius: 0; border-top: 1px solid var(--color-border);
        background: var(--color-surface); flex-direction: column; align-items: stretch;
        gap: 0.15rem; padding: 0.3rem 0.4rem;
        padding-bottom: calc(0.3rem + env(safe-area-inset-bottom));
        box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.18);
    }
    .barra-conteo { text-align: center; font-size: var(--t-sm); color: var(--color-text-muted); font-weight: 600; }
    /* Con varias acciones (incl. IA) no caben en una fila: se acomodan en
       varias (wrap) a 4 por fila, para que TODAS se vean sin desplazar. */
    .barra-acciones {
        margin-left: 0; gap: 0.1rem 0; justify-content: center; flex-wrap: wrap;
        min-width: 0; max-width: 100%;
    }
    .accion-sel {
        flex: 0 0 25%; flex-direction: column; gap: 0.15rem;
        border: none; background: transparent; padding: 0.35rem 0.2rem;
        font-size: var(--t-2xs); color: var(--color-text-2); min-width: 0;
    }
    .accion-sel:hover { background: transparent; }
    .accion-sel:active { background: var(--color-surface-2); }
    .accion-sel svg { width: 1.5rem; height: 1.5rem; }
    .accion-sel .accion-etq { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
    /* «Compartir» como una celda más de la rejilla (4 por fila); su disparador
       llena la celda. `position:static` hace que el desplegable se posicione
       respecto de la barra fija (no del wrap), para abrir ARRIBA y a lo ancho. */
    .barra-acciones .menu-wrap.accion-compartir { position: static; flex: 0 0 25%; display: flex; }
    /* El disparador llena la celda (si no, hereda `flex:0 0 25%` de .accion-sel y
       queda al 25% del wrap → la etiqueta «Compartir» se trunca a «C…»). */
    .barra-acciones .menu-wrap.accion-compartir .accion-sel { flex: 1 1 auto; width: 100%; }
    .barra-seleccion .accion-compartir .menu-pop {
        top: auto; bottom: calc(100% + 0.4rem); left: 0.5rem; right: 0.5rem;
        min-width: 0; max-width: none;
    }
    .barra-seleccion .accion-compartir .menu-pop .menu-pop-item { font-size: var(--t-lg); }
    .barra-seleccion .menu-pop .solo-movil { display: flex !important; }
}

/* En pantallas estrechas se ocultan «Tamaño» y «Modificado»: el tamaño pasa a
   subtítulo bajo el nombre (estilo Cx File Explorer). */
@media (max-width: 640px) {
    .file-list-table .col-mod, .file-list-table .col-tam { display: none; }
    .file-list-table th, .file-list-table td { padding: 0.6rem 0.4rem; }
    .subtitulo { display: block; }
    .tipo-icono svg { width: 2rem; height: 2rem; }
    .tipo-icono .miniatura { width: 2.5rem; height: 2.5rem; }
    .enlace-nombre { gap: 0.7rem; }
}

/* Comparativo de tarifas: resalta la columna del modo vigente. */
.col-vigente { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.file-list-table th.col-vigente { color: var(--color-primary); }
.tabla-scroll { overflow-x: auto; }


/* ---- Panel de inicio (dashboard personal) ---- */
/* Encabezado de sección del panel de Inicio (Notas / Archivos / Correo) */
/* El «Ver» va PEGADO al título, no al otro extremo de la pantalla: con el
   título estirado (flex:1) el botón acababa a un palmo de aquello que abre, y
   en una pantalla ancha ni se relacionaban. `wrap` para que en el teléfono el
   botón baje en vez de apretar el título. */
.panel-seccion-cab { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.6rem; flex-wrap: wrap; }
.panel-seccion-tit { display: flex; align-items: center; gap: 0.5rem; margin: 0; flex: 0 1 auto; min-width: 0; font-size: var(--t-xl); font-weight: 600; }
.panel-seccion-cab > .btn { flex: none; }
.panel-seccion-ic { display: inline-flex; width: 1.2rem; height: 1.2rem; color: var(--color-primary); }
.panel-seccion-ic svg { width: 100%; height: 100%; }
/* MasAdmin en el Resumen (2026-10-24): Cobranza y Ventas, una al lado de la otra (apiladas en el teléfono). */
.res-erp { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: 0.8rem; }
/* Sin el margen de `.card + .card`: en la rejilla bajaba la segunda. */
.res-erp .card + .card { margin-top: 0; }
.res-erp-card { padding: 0.8rem 0.9rem; display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
.res-erp-cab { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; justify-content: space-between; }
.res-erp-logo { width: 1.2rem; height: 1.2rem; object-fit: contain; border-radius: 3px; }
.res-erp-sel { font-size: var(--t-md); padding: 0.2rem 0.4rem; max-width: 12rem; }
.res-erp-cifras { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.3rem; }
.res-erp-cifra { flex: 1 1 8rem; display: flex; flex-direction: column; align-items: flex-start; gap: 0.1rem; padding: 0.45rem 0.6rem; border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-surface-2, var(--color-surface)); color: inherit; cursor: pointer; text-align: left; }
.res-erp-cifra strong { font-size: var(--t-xl); font-variant-numeric: tabular-nums; }
.res-erp-cifra span { font-size: var(--t-sm); color: var(--color-text-muted); }
.res-erp-cifra.alerta strong { color: var(--color-danger); }
.res-erp-delta { margin: 0 0 0.3rem; font-size: var(--t-sm); color: var(--color-text-muted); }
.res-erp-delta.sube { color: var(--color-success); }
.res-erp-delta.baja { color: var(--color-danger); }
/* Los cuadros del Reporteador en el Resumen (2026-10-25). El Panorama, a todo lo ancho. */
.res-erp-ancha { grid-column: 1 / -1; }
.res-erp-pano { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: 0.5rem; }
.res-erp-pano-tile { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-surface-2, var(--color-surface)); color: inherit; cursor: pointer; text-align: left; }
.res-erp-pano-lbl { font-size: var(--t-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res-erp-pano-tile strong { font-size: var(--t-xl); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res-erp-pano-tile.warn strong { color: var(--color-warning); }
.res-erp-pano-tile.bad strong { color: var(--color-danger); }
.res-erp-pano-sub { font-size: var(--t-xs); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res-erp-pano-sub b.sube { color: var(--color-success); }
.res-erp-pano-sub b.baja { color: var(--color-danger); }
.res-erp-cli small { display: block; font-size: var(--t-xs); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.res-erp-buscar { display: flex; align-items: center; gap: 0.4rem; padding: 0 0.6rem; height: 34px; border: 1px solid var(--color-border); border-radius: 17px; background: var(--color-bg); margin-bottom: 0.4rem; }
.res-erp-buscar svg { width: 15px; height: 15px; opacity: 0.6; flex: none; }
.res-erp-buscar input { flex: 1; min-width: 0; border: 0; background: transparent; color: inherit; font: inherit; outline: none; }
.res-erp-exist { padding: 0.35rem 0.5rem; border-radius: 6px; background: var(--color-surface-2, var(--color-surface)); font-size: var(--t-md); }
.res-erp-exist + .res-erp-exist { margin-top: 0.3rem; }
.res-erp-exist-cab { display: flex; justify-content: space-between; gap: 0.5rem; }
.res-erp-exist-cab span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.res-erp-exist-alm { display: flex; flex-wrap: wrap; gap: 0.1rem 0.8rem; font-size: var(--t-xs); color: var(--color-text-muted); }
.res-erp-exist-alm .cero { opacity: 0.6; }
.res-erp-fila { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 0.6rem; align-items: baseline; width: 100%; padding: 0.3rem 0.2rem; border: 0; border-top: 1px solid var(--color-border); background: none; color: inherit; cursor: pointer; text-align: left; font-size: var(--t-md); }
.res-erp-fila:hover { background: var(--color-surface-2, var(--color-surface)); }
.res-erp-cli { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.res-erp-imp { font-variant-numeric: tabular-nums; }
.res-erp-dias { font-size: var(--t-sm); color: var(--color-text-muted); white-space: nowrap; }
.res-erp-dias.atraso { color: var(--color-danger); font-weight: 600; }
.res-erp-tabs { display: inline-flex; background: var(--color-surface-2, var(--color-surface)); border: 1px solid var(--color-border); border-radius: 999px; padding: 2px; }
.res-erp-tabs button { padding: 2px 10px; border: 0; border-radius: 999px; background: none; color: var(--color-text-muted); font-size: var(--t-xs); cursor: pointer; }
.res-erp-tabs button.activo { background: var(--color-primary); color: var(--color-primary-fg); }
/* Mini-estadísticas (resumen de notas) */
.panel-mini { display: grid; grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr)); gap: 0.75rem; }
.mini-stat { text-align: center; padding: 0.4rem 0.25rem; }
.mini-num { font-size: var(--t-4xl); font-weight: 700; line-height: 1.1; }
.mini-lbl { font-size: var(--t-sm); color: var(--color-text-muted); margin-top: 0.15rem; }
.mini-stat.mini-alerta .mini-num { color: var(--color-primary); }
/* Resumen de correo MexMail (3 donuts) */
.correo-donuts { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: 1.25rem; }
.correo-donut { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.5rem; }
.correo-donut-tit { font-size: var(--t-base); color: var(--color-text-muted); }
.correo-donut-tit b { color: var(--color-text); }
.donut-sm { width: 8.5rem; height: 8.5rem; }
.leyenda-mini { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.3rem 0.75rem; font-size: var(--t-sm); }
.leyenda-mini .lm { display: inline-flex; align-items: center; gap: 0.35rem; }
.panel-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 1rem; }
/* En móvil, cada recuadro de espacio a lo ancho (va DESPUÉS de la base para ganar). */
@media (max-width: 640px) { .panel-stats { grid-template-columns: 1fr; } }
.stat-card { padding: 1.1rem 1.25rem; }
.stat-label { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); font-weight: 600; }
.stat-valor { font-size: var(--t-4xl); font-weight: 700; line-height: 1.1; margin: 0.3rem 0 0.15rem; }
.stat-sub { font-size: var(--t-sm); color: var(--color-text-muted); }
/* Dos donuts (Espacio + Tipos) lado a lado; en móvil se apilan solos. */
.panel-donuts { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 1rem; align-items: stretch; }
@media (max-width: 640px) { .panel-donuts { grid-template-columns: 1fr; } }
/* Gráfico centrado y leyenda centrada dentro de cada tarjeta (escritorio y móvil). */
.panel-donuts .card { display: flex; flex-direction: column; margin: 0; }
.panel-donuts .donut-wrap { flex-direction: column; align-items: center; justify-content: center; gap: 1rem; flex: 1; }
.panel-donuts .donut { width: 9.5rem; height: 9.5rem; }
.panel-donuts .leyenda { align-items: center; text-align: center; width: 100%; }
/* Aviso accionable (recordatorios de notas): tarjeta-botón en una fila. */
.panel-aviso { display: flex; align-items: center; gap: 0.7rem; width: 100%; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.panel-aviso:hover { border-color: var(--color-primary); }
.panel-aviso-ic { display: inline-flex; width: 1.3rem; height: 1.3rem; color: var(--color-primary); flex: none; }
.panel-aviso-ic svg { width: 100%; height: 100%; }
.panel-aviso-txt { flex: 1; min-width: 0; }
.panel-aviso-chev { display: inline-flex; width: 1.1rem; height: 1.1rem; color: var(--color-text-muted); flex: none; }
.panel-aviso-chev svg { width: 100%; height: 100%; }
.donut-wrap { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; }
.donut { width: 11rem; height: 11rem; flex: none; max-width: 100%; }
.donut svg { width: 100%; height: 100%; display: block; }
.leyenda { display: flex; flex-direction: column; gap: 0.45rem; min-width: 0; }
.leyenda-item { display: flex; align-items: center; gap: 0.5rem; font-size: var(--t-base); }
.leyenda-punto { width: 0.8rem; height: 0.8rem; border-radius: 50%; flex: none; }
.barras { display: flex; align-items: flex-end; gap: 0.4rem; height: 10rem; padding-top: 0.5rem; }
.barra-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; min-width: 0; }
.barra-valor { font-size: var(--t-xs); color: var(--color-text-muted); margin-bottom: 0.2rem; height: 1rem; line-height: 1; }
.barra { width: 62%; max-width: 2.5rem; background: var(--color-primary); border-radius: var(--radius-sm) var(--radius-sm) 0 0; transition: height var(--transition); }
.barra-cero { background: var(--color-surface-2); }
.barra-dia { font-size: var(--t-2xs); color: var(--color-text-muted); margin-top: 0.35rem; white-space: nowrap; }
/* Barras agrupadas por día (enviados/recibidos) para «Correos en la semana». */
.barras-sem { height: 9rem; }
.barras-sem .barra-par { flex: 1; width: 100%; display: flex; align-items: flex-end; justify-content: center; gap: 0.25rem; }
.barra-uni { flex: 1; min-width: 0; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; }
.barras-sem .barra-valor { font-size: var(--t-2xs); height: 0.9rem; }
.barras-sem .barra { width: 60%; max-width: 1rem; }
.barra-env { background: #a855f7; }
.barra-rec { background: #3b82f6; }
@keyframes girar { to { transform: rotate(360deg); } }
.girando svg { animation: girar 0.8s linear infinite; }


/* ---- Vista de galería ---- */
.vista-toggle { display: inline-flex; gap: 0.25rem; }
.vista-toggle svg { width: 1.15rem; height: 1.15rem; display: block; }
/* El «Aa» en galería escala el TAMAÑO DE CELDA, no un zoom del lienzo: las
   miniaturas se re-acomodan nítidas (más fotos por renglón), sin el borroso
   de escalar píxeles. */
.galeria { display: grid; grid-template-columns: repeat(auto-fill, minmax(calc(8.5rem * var(--gestor-zoom, 1)), 1fr)); gap: 0.75rem; }
.galeria-item { position: relative; border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; background: var(--color-surface); }
.galeria-item.sel { border-color: var(--color-primary); box-shadow: 0 0 0 1px var(--color-primary); }
.galeria-thumb { aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center; background: var(--color-surface-2); cursor: pointer; overflow: hidden; }
.galeria-img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--transition); }
.galeria-thumb:hover .galeria-img { transform: scale(1.04); }
.galeria-icono svg { width: 3rem; height: 3rem; }
/* Distintivo de «esto se reproduce» sobre el fotograma de un vídeo. Un fotograma
   se parece a una foto, y en una galería mezclada no había forma de distinguirlos
   sin leer la extensión. El contenedor ya recorta (`overflow: hidden`), así que
   basta con posicionarlo dentro; se le da `position: relative` para anclarlo.
   Va con el triángulo dibujado en CSS —bordes— y no un icono: es decoración,
   no información que haya que leer (de ahí el aria-hidden en el marcado). */
.galeria-thumb { position: relative; }
.mini-play {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: 2.4rem; height: 2.4rem; border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    display: flex; align-items: center; justify-content: center;
    pointer-events: none;   /* el clic es del fotograma, no del adorno */
}
.mini-play::after {
    content: ''; display: block;
    border-style: solid; border-width: .42rem 0 .42rem .68rem;
    border-color: transparent transparent transparent #fff;
    margin-left: .16rem;    /* el triángulo pesa a la izquierda: se centra a ojo */
}
/* Preview apilado de carpeta con fotos (vista galería): pila inclinada estilo polaroid */
.galeria-pila { position: relative; width: 100%; aspect-ratio: 1 / 1; }
.galeria-pila-foto {
    position: absolute; width: 50%; height: 50%; object-fit: cover;
    border: 3px solid #fff; border-radius: 2px;
    box-shadow: 0 1px 5px rgba(0, 0, 0, 0.35);
    background: var(--color-surface);
}
.galeria-pila-foto:nth-child(1) { top: 6%;  left: 7%;  transform: rotate(-7deg); z-index: 1; }
.galeria-pila-foto:nth-child(2) { top: 4%;  left: 43%; transform: rotate(6deg);  z-index: 2; }
.galeria-pila-foto:nth-child(3) { top: 45%; left: 5%;  transform: rotate(5deg);  z-index: 3; }
.galeria-pila-foto:nth-child(4) { top: 43%; left: 45%; transform: rotate(-6deg); z-index: 4; }
.galeria-thumb:hover .galeria-pila-foto { box-shadow: 0 2px 9px rgba(0, 0, 0, 0.45); }
.galeria-nombre { font-size: var(--t-sm); padding: 0.4rem 0.5rem 0.15rem; display: flex; align-items: center; gap: 0.3rem; color: var(--color-text-2); }
.galeria-sub { font-size: var(--t-xs); padding: 0 0.5rem 0.4rem; color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.galeria-check {
    position: absolute; top: 0.35rem; left: 0.35rem; z-index: 6;
    display: flex; align-items: center; justify-content: center;
    width: 2.1rem; height: 2.1rem; border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--color-surface) 72%, transparent); cursor: pointer;
}
.galeria-check input[type="checkbox"] { width: 1.35rem; height: 1.35rem; cursor: pointer; accent-color: var(--color-primary); }
/* Botón «No es esta persona» por foto (lente Por persona). */
.galeria-separar {
    position: absolute; top: 0.35rem; right: 0.35rem; z-index: 6;
    background: color-mix(in srgb, var(--color-surface) 82%, transparent);
}
.galeria-separar svg { width: 1.2rem; height: 1.2rem; }
/* Estrella de Favoritos (lista + galería) */
.btn-fav.activo { color: #f5b301; }
.galeria-fav { position: absolute; top: 0.35rem; right: 0.35rem; z-index: 6; width: 1.9rem; height: 1.9rem; border-radius: 50%; background: rgba(0, 0, 0, 0.4); color: #fff; }
.galeria-fav svg { width: 1.15rem; height: 1.15rem; }
.galeria-fav.activo { color: #f5b301; }
/* Descargar desde la miniatura: debajo de la estrella, mismo tamaño y color.
   Aparece al pasar por encima para no ensuciar la cuadrícula; en pantallas
   táctiles no hay «pasar por encima», así que ahí se queda visible. */
.galeria-bajar { position: absolute; top: 2.5rem; right: 0.35rem; z-index: 6; width: 1.9rem; height: 1.9rem; border-radius: 50%; background: rgba(0, 0, 0, 0.4); color: #fff; opacity: 0; transition: opacity 0.12s; }
.galeria-bajar svg { width: 1.05rem; height: 1.05rem; }
.galeria-item:hover .galeria-bajar,
.galeria-item:focus-within .galeria-bajar { opacity: 1; }
@media (hover: none) { .galeria-bajar { opacity: 1; } }
/* Distintivo de espacio (personal/compartida): icono pequeño a la izquierda del nombre */
.galeria-nombre-esp { flex: none; display: inline-flex; line-height: 0; }
.galeria-nombre-esp svg { width: 0.95rem; height: 0.95rem; }
.galeria-nombre-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.galeria-nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; width: 2.75rem; height: 2.75rem; border: none; border-radius: 50%; background: rgba(0, 0, 0, 0.45); color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.galeria-nav:hover { background: rgba(0, 0, 0, 0.65); }
.galeria-nav svg { width: 1.5rem; height: 1.5rem; }
.galeria-nav-prev { left: 0.75rem; }
.galeria-nav-next { right: 0.75rem; }
@media (max-width: 640px) {
    .galeria { grid-template-columns: repeat(auto-fill, minmax(calc(6.5rem * var(--gestor-zoom, 1)), 1fr)); gap: 0.5rem; }
    .galeria-nav { width: 2.25rem; height: 2.25rem; }
}

/* Modo "Por fecha": carpetas virtuales de año / mes ---------------------- */
.fecha-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: 0.75rem; margin-top: 0.5rem; }
.fecha-card {
    display: flex; flex-direction: column; align-items: flex-start; gap: 0.3rem;
    padding: 1rem 1.1rem; border: 1px solid var(--color-border); border-radius: var(--radius-md);
    background: var(--color-surface); color: var(--color-text); cursor: pointer; text-align: left;
    transition: border-color 0.12s, background 0.12s, transform 0.12s;
}
.fecha-card:hover { border-color: var(--color-primary); background: var(--color-surface-2); transform: translateY(-1px); }
.fecha-card-icono svg { width: 1.6rem; height: 1.6rem; display: block; color: var(--color-primary); }
.fecha-card-num { font-size: var(--t-2xl); font-weight: 600; line-height: 1.1; }
.fecha-card-sub { font-size: var(--t-md); color: var(--color-text-muted); }
@media (max-width: 640px) {
    .fecha-cards { grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); gap: 0.5rem; }
    .fecha-card { padding: 0.8rem 0.9rem; }
    .fecha-card-num { font-size: var(--t-xl); }
}

/* Lente «Por persona»: mosaicos con carita circular ---------------------- */
.persona-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); gap: 0.9rem; margin-top: 0.5rem; }
.persona-card { position: relative; }
.persona-card-btn {
    width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0.35rem;
    padding: 0.9rem 0.6rem; border: 1px solid var(--color-border); border-radius: 0.7rem;
    background: var(--color-surface); color: var(--color-text); cursor: pointer; text-align: center;
}
.persona-card-btn:hover { border-color: var(--color-primary); background: var(--color-surface-2); transform: translateY(-1px); }
.persona-cara {
    width: 5rem; height: 5rem; border-radius: 50%; overflow: hidden; display: flex;
    align-items: center; justify-content: center; background: var(--color-surface-2); flex: 0 0 auto;
}
.persona-cara img { width: 100%; height: 100%; object-fit: cover; }
.persona-cara svg { width: 2.2rem; height: 2.2rem; color: var(--color-text-muted); }
.persona-nombre { font-size: var(--t-lg); font-weight: 600; line-height: 1.15; word-break: break-word; }
.persona-nombre.sin-nombre { font-weight: 500; color: var(--color-text-muted); font-style: italic; }
.persona-sub { font-size: var(--t-sm); color: var(--color-text-muted); }
.persona-editar { position: absolute; top: 0.35rem; right: 0.35rem; opacity: 0; transition: opacity 0.15s; }
.persona-fusionar { position: absolute; bottom: 0.35rem; left: 0.35rem; opacity: 0; transition: opacity 0.15s; }
.persona-eliminar { position: absolute; bottom: 0.35rem; right: 0.35rem; opacity: 0; transition: opacity 0.15s; }
.persona-card:hover .persona-editar, .persona-editar:focus,
.persona-card:hover .persona-fusionar, .persona-fusionar:focus,
.persona-card:hover .persona-eliminar, .persona-eliminar:focus { opacity: 1; }
/* Selección múltiple de personas (quitar falsos positivos en lote) */
.persona-check { position: absolute; top: 0.35rem; left: 0.35rem; z-index: 2; opacity: 0; transition: opacity 0.15s; line-height: 0; cursor: pointer; }
.persona-check input[type="checkbox"] { width: 1.15rem; height: 1.15rem; cursor: pointer; accent-color: var(--color-primary); }
.persona-card:hover .persona-check, .persona-check:focus-within, .persona-card.sel .persona-check { opacity: 1; }
.persona-card.sel .persona-card-btn { border-color: var(--color-primary); box-shadow: 0 0 0 1px var(--color-primary); }
.personas-sel-barra { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; min-height: 2.6rem; margin: 0.3rem 0 0; padding: 0.4rem 0.6rem; background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: var(--radius-md); font-size: var(--t-md); }
/* Por páginas (2026-10-31): buscador, filtros con su cuenta y el paginador. */
.personas-arriba { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.8rem; margin-top: 0.3rem; min-height: 2.6rem; scroll-margin-top: 0.5rem; }
/* Nombre en un renglón: todas las tarjetas del mismo alto. */
.personas-vista .persona-card-btn { min-width: 0; }
.personas-vista .persona-nombre { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.personas-buscar { flex: 1 1 12rem; max-width: 18rem; }
.personas-filtros { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.personas-filtro { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.35rem 0.8rem; border: 1px solid var(--color-border); border-radius: 2rem; background: var(--color-surface); color: var(--color-text); cursor: pointer; font-size: var(--t-md); }
.personas-filtro:hover { border-color: var(--color-primary); }
.personas-filtro.activo { background: color-mix(in srgb, var(--color-primary) 16%, transparent); border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; }
.personas-filtro-n { font-size: var(--t-xs); opacity: 0.7; font-variant-numeric: tabular-nums; }
.persona-cards.cargando { opacity: 0.55; transition: opacity 0.15s; }
/* FIJO a la base de la pantalla (Jore, 2026-10-31: «ajustar a la base»), encima
   de la barra de módulos en el teléfono. personasMedir pone --pie-abajo/izq/ancho
   con lo medido; la vista deja abajo su alto para que nada quede tapado. */
.personas-paginador { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.6rem; position: fixed; z-index: 39; bottom: var(--pie-abajo, 0.5rem); left: var(--pie-izq, 1rem); width: var(--pie-ancho, calc(100% - 2rem)); box-sizing: border-box; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: 0 -3px 12px rgba(0, 0, 0, 0.1); }
.personas-vista { padding-bottom: calc(var(--pie-alto, 3.2rem) + 1.2rem); }
.modal .personas-paginador { position: static; width: auto; margin-top: 0.8rem; box-shadow: none; }
.personas-paginador .btn svg { width: 1rem; height: 1rem; }
.personas-deslizador { flex: 1 1 auto; min-width: 0; accent-color: var(--color-primary); }
.personas-pag-txt { font-size: var(--t-md); color: var(--color-text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.personas-fusionar-lista { max-height: 52vh; overflow: auto; padding: 2px; }
.modal .personas-buscar { max-width: none; width: 100%; margin-bottom: 0.4rem; }
@media (max-width: 640px) {
    .personas-buscar { max-width: none; }
    /* Teléfono (Jore, 2026-10-31: «hay demasiado espacio ocupado»): los filtros en
       una sola tira que se desliza de lado, y tarjetas compactas. */
    .personas-filtros { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; width: 100%; }
    .personas-filtro { flex: 0 0 auto; padding: 0.3rem 0.7rem; }
    .personas-vista .persona-card-btn { padding: 0.55rem 0.3rem 0.5rem; gap: 0.2rem; }
    .personas-vista .persona-nombre { font-size: var(--t-md); }
    .personas-vista .persona-sub { font-size: var(--t-xs); }
    .personas-vista :is(.persona-editar, .persona-fusionar, .persona-eliminar) { width: 1.8rem; height: 1.8rem; padding: 0.25rem; }
    .personas-vista :is(.persona-editar, .persona-fusionar, .persona-eliminar) svg { width: 1rem; height: 1rem; }
    .personas-vista .persona-editar { top: 0.2rem; right: 0.2rem; }
    .personas-vista .persona-fusionar { bottom: 0.2rem; left: 0.2rem; }
    .personas-vista .persona-eliminar { bottom: 0.2rem; right: 0.2rem; }
    .personas-vista .persona-check { top: 0.3rem; left: 0.3rem; }
    .personas-paginador { padding: 0.35rem 0.5rem; gap: 0.4rem; }
    .persona-cards { grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr)); gap: 0.6rem; }
    .persona-cara { width: 4rem; height: 4rem; }
    .persona-editar, .persona-fusionar, .persona-eliminar { opacity: 1; }
}
/* Táctil de cualquier tamaño (también tabletas): las acciones y la casilla de
   selección se ven siempre; con el dedo no hay «hover» que las descubra. */
@media (hover: none) {
    .persona-editar, .persona-fusionar, .persona-eliminar { opacity: 1; }
    .persona-check { opacity: 0.85; }
}

/* Buscador (cabecera) + resultados --------------------------------------- */
.busqueda-barra { order: 2; display: inline-flex; align-items: center; gap: 0.4rem; flex: 1 1 12rem; max-width: 24rem; min-width: 8rem; padding: 0.3rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); }
.busqueda-barra:focus-within { border-color: var(--color-primary); }
/* Buscador propio del picker (el navbar se oculta en modo picker). */
.picker-buscar { display: flex; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface-2); }
.picker-buscar .busqueda-barra { flex: 1 1 auto; max-width: none; }
/* Indicador de carpeta segura (candado) junto al nombre. */
.candado-seguro { display: inline-flex; align-items: center; width: 0.85em; height: 0.85em; margin-left: 0.35rem; color: var(--color-primary); vertical-align: middle; }
.candado-seguro svg { width: 100%; height: 100%; }
/* Distintivo de firma, hermano del candado de las carpetas seguras: ámbar
   mientras faltan firmas, verde cuando ya están todas. */
.firma-marca { display: inline-flex; align-items: center; width: 0.85em; height: 0.85em; margin-left: 0.35rem; color: var(--color-warning); vertical-align: middle; cursor: pointer; }
.firma-marca.firmada { color: var(--color-success); }
.firma-marca svg { width: 100%; height: 100%; }
/* «Transcribiendo…» de una grabación recién llegada. Es un estado que dura
   minutos: se pinta discreto —no es un error ni pide nada— y late despacio para
   que se lea como «esto sigue en marcha» y no como una etiqueta fija. */
.chip-transcribiendo { display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.4rem; border-radius: var(--radius-sm); background: var(--color-surface-2); color: var(--color-text-muted); font-size: 0.72em; font-weight: 500; white-space: nowrap; vertical-align: middle; animation: latir-transcribiendo 1.8s ease-in-out infinite; }
@keyframes latir-transcribiendo { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) { .chip-transcribiendo { animation: none; } }
/* Contraseñas de aplicación del buzón. La recién creada se destaca porque es
   lo único de la pantalla que hay que copiar AHORA; el resto es una lista. */
.clave-app-nueva { margin: 0.8rem 0; padding: 0.7rem 0.85rem; border: 1px solid var(--color-primary); border-radius: var(--radius-md); background: var(--color-surface-2); }
.clave-app-valor { display: block; margin-bottom: 0.5rem; font-family: var(--font-mono); font-size: var(--t-xl); letter-spacing: 0.04em; word-break: break-all; color: var(--color-text); }
/* Fila de «escriba algo y pulse Agregar». ⚠️ ENVUELVE: con tres piezas —un
   desplegable, el cuadro y el botón— en una ventana estrecha no caben, y un
   flex que no envuelve NO se desplaza: crece y saca barra horizontal al diálogo
   entero, dejando el botón cortado por la derecha. El cuadro se lleva el sitio
   sobrante pero no baja de 10rem; por debajo de eso, el botón salta de renglón. */
.clave-app-alta { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.9rem 0; }
.clave-app-alta .input { flex: 1 1 10rem; min-width: 0; }
/* ⚠️ `width: auto` NO SOBRA: el `.select` del sistema es `width: 100%`, así que
   dentro del flex se llevaba la fila entera (602 de 602 px, medido) y empujaba
   fuera el cuadro y el botón. Aquí se le devuelve su ancho natural. */
.clave-app-alta .select { flex: 0 0 auto; width: auto; max-width: 100%; }
.clave-app-alta .btn { flex: 0 0 auto; }
.clave-app-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.clave-app-fila { display: flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.2rem; border-bottom: 1px solid var(--color-border); }
.clave-app-nombre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Apagada: se ve que sigue ahí, pero que no abre nada. */
.clave-app-nombre.apagada { color: var(--color-text-muted); text-decoration: line-through; }
.clave-app-estado { font-size: var(--t-sm); color: var(--color-text-muted); white-space: nowrap; }
.clave-app-acciones { display: flex; gap: 0.15rem; flex-shrink: 0; }
/* La copia local de los reenvíos. Se enmarca porque no es una casilla más: es
   la que decide si el buzón sigue recibiendo. Cuando está quitada Y hay
   reenvíos, se pinta de aviso — ese es el estado que puede doler. */
.reenvio-copia { margin-top: 1rem; padding: 0.7rem 0.85rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); }
.reenvio-copia.aviso { border-color: var(--color-warning); }
/* El ajuste fino del antispam. La barra solo aparece en «Personalizado», así que
   se enmarca para que se lea como «esto es lo que estoy tocando». */
.antispam-fino { margin-top: 0.7rem; padding: 0.7rem 0.85rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); }
.antispam-fino-fila { display: flex; align-items: center; gap: 0.9rem; }
.antispam-rango { flex: 1; min-width: 0; accent-color: var(--color-primary); }
/* Cifras tabulares: sin ellas el número baila al arrastrar y parece que salta. */
.antispam-fino-valor { min-width: 3ch; font-size: var(--t-2xl); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; color: var(--color-text); }
.antispam-fino-escala { display: flex; justify-content: space-between; gap: 0.5rem; margin-top: 0.35rem; font-size: var(--t-xs); color: var(--color-text-muted); }
.antispam-fino-escala span:nth-child(2) { text-align: center; }
/* El umbral de TODA la empresa: separado por una línea porque no es «más de
   lo mismo» —se le aplica a otras personas— y tiene su propio botón. */
.antispam-dominio { margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--color-border); }
.antispam-dominio h3 { margin: 0 0 0.2rem; font-size: var(--t-lg); }
.antispam-dominio .radio-fila { margin: 0.5rem 0; }
.antispam-dominio > .btn { margin-top: 0.7rem; }
.antispam-fino-escala span:last-child { text-align: right; }
.busqueda-icono svg { width: 1.05rem; height: 1.05rem; display: block; color: var(--color-text-muted); }
.busqueda-input { flex: 1; min-width: 0; border: none; background: transparent; color: var(--color-text); font-size: var(--t-base); outline: none; }
.resultados { display: flex; flex-direction: column; gap: 0.6rem; }
.resultado { padding: 0.7rem 0.9rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
.resultado-acciones { display: flex; flex-wrap: wrap; gap: 0.2rem; margin-top: 0.5rem; }
.resultado-nombre { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 600; color: var(--color-text); }
.resultado-nombre:hover { color: var(--color-primary); }
.resultado-nombre .tipo-icono svg { width: 1.15rem; height: 1.15rem; }
.resultado-ruta { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.25rem; font-size: var(--t-sm); }
.resultado-carpeta { display: inline-flex; align-items: center; gap: 0.3rem; color: var(--color-text-muted); }
.resultado-carpeta svg { width: 0.9rem; height: 0.9rem; }
.resultado-carpeta:hover { color: var(--color-primary); }
.resultado-frag { margin: 0.4rem 0 0; font-size: var(--t-md); color: var(--color-text-muted); line-height: 1.4; }
@media (max-width: 640px) {
    .busqueda-barra { order: 4; flex-basis: 100%; max-width: none; }
}

/* Resumen con IA (modal) ------------------------------------------------- */
.resumen-caja { white-space: pre-wrap; word-break: break-word; max-height: 50vh; overflow-y: auto; padding: 0.9rem 1rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); font-size: var(--t-base); line-height: 1.5; margin: 0.5rem 0; }
.resumen-nota { font-size: var(--t-sm); }

/* Q&A con IA (modal) ----------------------------------------------------- */
.qa-hilo { display: flex; flex-direction: column; gap: 0.75rem; max-height: 42vh; overflow-y: auto; margin: 0.5rem 0; }
.qa-turno { display: flex; flex-direction: column; gap: 0.35rem; }
.qa-pregunta { display: flex; align-items: flex-start; gap: 0.4rem; font-weight: 600; }
.qa-pregunta svg { width: 1rem; height: 1rem; flex: none; margin-top: 0.2rem; color: var(--color-primary); }
.qa-respuesta { white-space: pre-wrap; word-break: break-word; padding: 0.6rem 0.8rem; border-radius: var(--radius-md); background: var(--color-surface-2); border: 1px solid var(--color-border); font-size: var(--t-base); line-height: 1.5; }
.qa-error { color: var(--color-danger); }
.qa-form { display: flex; gap: 0.5rem; margin: 0.5rem 0; }
.qa-form .input { flex: 1; }

/* Fichita de datos clave (IA) -------------------------------------------- */
.ficha-tipo { margin: 0.3rem 0 0.6rem; }
.ficha { display: flex; flex-direction: column; gap: 0.4rem; max-height: 46vh; overflow-y: auto; margin: 0.5rem 0; }
.ficha-fila { display: grid; grid-template-columns: minmax(7rem, 34%) 1fr; gap: 0.75rem; padding: 0.45rem 0.7rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); }
.ficha-campo { font-weight: 600; margin: 0; }
.ficha-valor { margin: 0; word-break: break-word; }
@media (max-width: 640px) { .ficha-fila { grid-template-columns: 1fr; gap: 0.15rem; } }

/* Menú de acciones de IA (modal) ----------------------------------------- */
.ia-opciones { display: flex; flex-direction: column; gap: 0.4rem; margin: 0.6rem 0; }
.ia-opciones button { display: flex; align-items: center; gap: 0.6rem; width: 100%; text-align: left; padding: 0.7rem 0.9rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); color: var(--color-text); cursor: pointer; font-size: var(--t-lg); font-weight: 600; transition: border-color 0.12s, background 0.12s; }
.ia-opciones button:hover { border-color: var(--color-primary); background: var(--color-surface); }
.ia-opciones button svg { width: 1.2rem; height: 1.2rem; flex: none; color: var(--color-primary); }

/* Contraseñas de aplicación (WebDAV) — perfil */
.app-token-box { background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.6rem 0.7rem; margin-bottom: 0.6rem; }
.app-token-fila { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.app-token { flex: 1; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--t-lg); letter-spacing: 0.03em; word-break: break-all; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 0.4rem; padding: 0.35rem 0.5rem; }
.app-pwd-lista { display: flex; flex-direction: column; gap: 0.35rem; margin: 0.2rem 0 0.2rem; }
.app-pwd-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.55rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); }
.app-pwd-etq { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Modal de notificaciones de correo nuevo (modo + reglas de filtrado). */
.avisos-modos { display: flex; flex-direction: column; gap: .45rem; margin: .6rem 0; }
.radio-fila { display: flex; align-items: center; gap: .5rem; cursor: pointer; }
.radio-fila input { margin: 0; }
.avisos-reglas { border-top: 1px solid var(--color-border); margin-top: .6rem; padding-top: .6rem; display: flex; flex-direction: column; gap: .5rem; }
.avisos-regla { display: flex; align-items: center; gap: .4rem; }
.avisos-regla select.input { width: auto; flex: 0 0 auto; }
.avisos-regla-op { flex: 0 0 auto; }
.avisos-regla input.input { flex: 1 1 auto; min-width: 0; }
.avisos-ayuda { font-size: .82em; line-height: 1.35; margin: .1rem 0 0; }

/* Configuración → Notificaciones: una fila por origen de aviso. La casilla
   arriba y no centrada, para que no baile según lo larga que sea la
   explicación de cada uno. */
.avisos-origenes { display: flex; flex-direction: column; gap: .1rem; }
.aviso-origen { display: flex; align-items: flex-start; gap: .6rem; padding: .55rem .5rem; border-radius: 8px; cursor: pointer; }
.aviso-origen:hover { background: var(--color-surface-2); }
/* Tarjeta de IA en Administración (0215): qué se enmascara, y qué no. */
.ia-privacidad { display: flex; gap: .65rem; align-items: flex-start; margin-top: .75rem; padding: .7rem .8rem; border-radius: 10px; background: var(--color-surface-2); font-size: var(--t-base); line-height: 1.45; }
.ia-privacidad-ico { flex: none; width: 1.25rem; height: 1.25rem; margin-top: .1rem; color: var(--color-primary); }
.ia-privacidad-ico svg { width: 100%; height: 100%; }
.ia-privacidad p { margin: .25rem 0 0; }
.aviso-origen input { margin: .2rem 0 0; flex: 0 0 auto; }
.aviso-origen-txt { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.aviso-origen-etq { font-size: var(--t-base); display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; }
.aviso-origen-desc { font-size: var(--t-sm); line-height: 1.35; }
/* El de seguridad no se pulsa: sin cursor de mano ni resalte, para que se lea
   como lo que es —información— y no como un interruptor que no responde. El
   hueco ocupa lo mismo que una casilla para que su texto empiece donde el de
   las demás filas; si no, el badge lo empujaba y la columna quedaba en zigzag. */
.aviso-origen-fijo { cursor: default; }
.aviso-origen-fijo:hover { background: none; }
.aviso-origen-hueco { flex: 0 0 auto; width: 13px; }

/* Editor de correo con formato (contenteditable + barra de execCommand). */
.buzon-rt { flex: 1; display: flex; flex-direction: column; min-height: 12rem; min-width: 0; }
/* BARRA DE FORMATO EN DOS FILAS: lo de diario y el resto tras un «…».
   Antes era UNA fila que se desplazaba a lo ancho. Funcionaba, pero en el
   teléfono nadie adivina que arrastrando a la izquierda hay más botones: lo que
   no se ve, no existe (lo reportó Jore, 2026-09-10, pidiendo lo de Roundcube).
   ⚠️ EL «…» ES SOLO DE PANTALLAS ESTRECHAS. En la computadora caben las dos
   filas —de corrido, o partidas por el `flex-wrap` si la ventana es angosta— y
   esconder botones a quien tiene sitio para ellos sería un paso de más. Por eso
   `.buzon-rt-extra` se despliega con una CLASE y no con `x-show`: `x-show`
   pondría `display:none` también aquí.
   ⚠️ `flex: 0 0 auto` en las filas no es opcional: si se las deja encoger,
   `flex-wrap` no llega a actuar nunca —se comprimen hasta caber las dos en un
   renglón— y volvemos al desplazamiento escondido de antes. */
.buzon-rt-barra { display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem; min-width: 0; padding: 0.25rem; border: 1px solid var(--color-border); border-bottom: none; border-radius: 8px 8px 0 0; background: var(--color-surface-2); }
.buzon-rt-fila { flex: 0 0 auto; display: flex; align-items: center; gap: 0.15rem; flex-wrap: nowrap; }
.buzon-rt-btn.buzon-rt-mas { display: none; }   /* clase doblada: `.buzon-rt-btn` se declara debajo y ganaba el `display` */

@media (max-width: 768px) {
    /* Una fila debajo de la otra, cada una a todo el ancho. */
    .buzon-rt-barra { flex-direction: column; align-items: stretch; }
    /* Red de seguridad: en un teléfono muy angosto la primera fila todavía
       podría no caber. Que se desplace es mejor que que se rompa —y ahora lo
       que se esconde ahí son duplicados del desplegable, no botones únicos—. */
    .buzon-rt-fila { min-width: 0; overflow-x: auto; }
    /* Pegado al borde derecho, que es donde se corta la fila y donde uno busca
       lo que falta. `sticky` para que siga a la vista aunque la fila se
       desplace; con fondo propio, o los botones se le verían por debajo. */
    .buzon-rt-btn.buzon-rt-mas { display: inline-flex; margin-left: auto; position: sticky; right: 0; background: var(--color-surface-2); }
    .buzon-rt-btn.buzon-rt-mas.activo { background: var(--color-border); }
    .buzon-rt-extra { display: none; flex-wrap: wrap; }
    /* Aquí SÍ se deja partir en varios renglones: es un panel que se abre a
       propósito y se cierra al momento, no el alto que se paga siempre. */
    .buzon-rt-extra.abierto { display: flex; }
}

/* Con dedo no hay barra de desplazamiento que valga: se arrastra y ya. Con
   ratón sí se deja la del sistema, que si no, en una ventana estrecha, los
   botones de la derecha quedarían escondidos sin ninguna pista. */
@media (hover: none) {
    .buzon-rt-fila { scrollbar-width: none; }
    .buzon-rt-fila::-webkit-scrollbar { display: none; }
}
/* Que no se encojan al no caber: encogidos se vuelven inpulsables. */
.buzon-rt-btn { flex: none; min-width: 2rem; height: 2rem; padding: 0 0.4rem; border: none; background: transparent; border-radius: 6px; cursor: pointer; color: var(--color-text); font-size: var(--t-lg); display: inline-flex; align-items: center; justify-content: center; }
.buzon-rt-btn:hover { background: var(--color-border); }
.buzon-rt-btn svg { width: 18px; height: 18px; }
.buzon-rt-color { width: 2rem; height: 2rem; padding: 2px; border: none; background: transparent; cursor: pointer; }
.buzon-rt-sep { flex: none; width: 1px; align-self: stretch; margin: 0.2rem 0.25rem; background: var(--color-border); }

/* APRETAR EL PASO EN EL TELÉFONO, para que la fila desplegable quepa en UN
   renglón. Con los 2rem de la computadora, de 375 px para abajo el último
   botón se caía a un tercer renglón (lo reportó Jore, 2026-09-10, con la
   captura de su teléfono). Aquí el botón baja a 1.9rem —sigue siendo un blanco
   de 30x32, y el alto no se toca— y los separadores se retiran SOLO de la fila
   desplegable: son adorno, y los grupos se siguen leyendo por el dibujo de los
   iconos. Con eso entra a 360 px. Por debajo de 340 vuelve a partirse, y no hay
   arreglo que no sea encoger los botones hasta no poder pulsarlos.
   ⚠️ ESTE BLOQUE VA DESPUÉS de `.buzon-rt-btn` y compañía A PROPÓSITO: misma
   especificidad, gana el último. Puesto arriba, con el resto de lo del móvil,
   no tenía ningún efecto. */
@media (max-width: 768px) {
    .buzon-rt-fila { gap: 0.1rem; }
    .buzon-rt-btn { min-width: 1.9rem; padding: 0 0.25rem; }
    .buzon-rt-icosel, .buzon-rt-color { width: 1.9rem; }
    .buzon-rt-extra .buzon-rt-sep { display: none; }
}


/* ⚠️ EL INPUT DE COLOR NO PUEDE IR EN `display:none`.
   El navegador ancla el selector nativo en la CAJA del input; sin caja la
   toma en 0,0 y lo abre en la esquina superior izquierda de la pantalla,
   encima del menú de hamburguesa (2026-09-09, lo reportó Jore).
   Aquí el input conserva su caja —del tamaño del botón y justo encima—, pero
   es invisible y no recibe el ratón: el clic lo hace el botón por código. */
.buzon-rt-color { position: relative; display: inline-flex; flex: none; }
.buzon-rt-color > input[type="color"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: none;
    opacity: 0;
    pointer-events: none;
}

/* ── Tipo y tamaño de letra: icono visible, select invisible encima ──────
   Un `<select>` no admite iconos dentro. Rotularlos «Predeterminada» y
   «Normal» se comía media barra —en el móvil, más— para decir algo que además
   nunca cambia: al elegir se vuelve siempre a la primera opción, así que ese
   texto era una etiqueta fija, no un estado.
   El select conserva su CAJA (igual que el input de color, y por lo mismo: el
   desplegable se ancla en ella) pero va transparente encima del icono. Y sí
   recibe el ratón —al revés que el color, que lo dispara un botón— porque un
   select se abre solo al pulsarlo, que es justo lo que se quiere, y en el
   móvil abre el selector del sistema. */
.buzon-rt-icosel {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    /* Mismas medidas y mismo hover que `.buzon-rt-btn`: en la barra tienen que
       leerse como un botón más, no como un control aparte. */
    width: 2rem;
    height: 2rem;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--color-text);
    cursor: pointer;
}
.buzon-rt-icosel:hover { background: var(--color-border); }
.buzon-rt-icosel > span { display: inline-flex; pointer-events: none; }
.buzon-rt-icosel svg { width: 1.05rem; height: 1.05rem; }
.buzon-rt-icosel > select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: none;
    opacity: 0;
    cursor: pointer;
    /* Safari en iOS ignora `opacity` en un select para el fondo: sin esto se
       ve un rectángulo gris encima del icono. */
    -webkit-appearance: none;
    appearance: none;
}

/* El botón de quitar formato. Antes llevaba un icono de «x» —dos líneas
   cruzadas— que se lee como «cerrar», no como «limpiar el formato». Una «A»
   tachada dice de qué va sin leer el rótulo. */
.buzon-rt-quitar { position: relative; font-style: italic; }
.buzon-rt-quitar::after {
    content: '';
    position: absolute;
    left: -0.15rem;
    right: -0.15rem;
    top: 50%;
    height: 1.5px;
    background: currentColor;
    transform: rotate(-12deg);
}
/* El editor con formato es una HOJA DE PAPEL, no una superficie de la aplicación: va
   siempre en blanco, aunque el tema sea oscuro. Razón: el contenido lleva sus colores EN
   LÍNEA (la firma trae `color:#333` porque el correo se lee sobre blanco en el cliente del
   destinatario), así que pintarlo sobre fondo oscuro lo volvía ilegible —texto gris
   oscuro sobre azul oscuro—. Es además lo que ya hacían el panel de lectura
   (`.buzon-iframe`, #fff) y la vista previa de la firma: el editor era el único fuera de
   norma. Y es lo honesto: lo que se ve aquí es lo que le llega al destinatario.
   Los colores se fijan a los MISMOS del panel de lectura para que redactar y leer se vean
   igual; no se usan variables de tema a propósito. */
.buzon-rt-editor { flex: 1; min-height: 10rem; overflow-y: auto; padding: 0.6rem 0.7rem; border: 1px solid var(--color-border); border-radius: 0 0 8px 8px; background: #fff; color: #111; caret-color: #111; line-height: 1.5; outline: none; }
.buzon-rt-editor:focus { border-color: var(--color-primary); }
.buzon-rt-editor:empty::before { content: attr(data-ph); color: #6b7280; }
.buzon-rt-editor blockquote { margin: 0.2rem 0 0 0.4rem; padding-left: 0.6rem; border-left: 2px solid #d1d5db; color: #6b7280; }
.buzon-rt-editor a { color: var(--color-primary); }
.buzon-rt-editor img { max-width: 100%; height: auto; }
/* Selección: la del sistema sobre papel blanco en tema oscuro puede quedar ilegible. */
.buzon-rt-editor ::selection { background: #b3d4fc; color: #111; }
.buzon-modo-sel { display: inline-flex; border: 1px solid var(--color-border); border-radius: 6px; overflow: hidden; }
.buzon-modo-sel button { border: none; background: transparent; color: var(--color-text-2); padding: 0.2rem 0.6rem; font-size: var(--t-sm); cursor: pointer; }
.buzon-modo-sel button.activo { background: var(--color-primary); color: var(--color-primary-fg); }

/* Carpetas de correo especiales: color del ícono por tipo (temático claro/oscuro). */
.buzon-fic-inbox   { color: var(--color-primary); }
.buzon-fic-sent    { color: var(--color-success); }
.buzon-fic-drafts  { color: var(--color-warning); }
.buzon-fic-spam    { color: var(--color-danger); }
.buzon-fic-trash   { color: var(--color-text-muted); }
.buzon-fic-archive { color: var(--color-info); }

/* Globo de no leídos sobre el ícono de Correo (header y hamburguesa). */
.nav-tab-correo { position: relative; overflow: visible; }
.nav-badge { position: absolute; top: -5px; right: -5px; min-width: 1.05rem; height: 1.05rem; padding: 0 0.25rem; box-sizing: border-box; border-radius: 999px; background: var(--color-danger); color: #fff; font-size: var(--t-2xs); font-weight: 700; line-height: 1.05rem; text-align: center; box-shadow: 0 0 0 2px var(--color-bg); pointer-events: none; }
.drawer-badge { margin-left: auto; min-width: 1.2rem; height: 1.2rem; padding: 0 0.3rem; box-sizing: border-box; border-radius: 999px; background: var(--color-danger); color: #fff; font-size: var(--t-2xs); font-weight: 700; line-height: 1.2rem; text-align: center; }

/* Nombre de la sección abierta junto a la marca (escritorio). */
.nav-seccion-desk { color: var(--color-text-muted); font-weight: 600; font-size: var(--t-xl); white-space: nowrap; letter-spacing: -0.01em; }
/* También en escritorio cede el nombre y no el usuario: con una ventana
   mediana, «Configuración» o «Administración» mandaban el bloque del usuario a
   un segundo renglón (Jore, 2026-09-22). Base 0 y tope en su propio ancho. */
.navbar .nav-seccion-desk { flex: 1 1 0; min-width: 0; max-width: max-content; overflow: hidden; text-overflow: ellipsis; }
.nav-seccion-desk::before { content: '· '; opacity: 0.65; }
.nav-seccion-movil { display: none; } /* solo en móvil (ver media query) */

/* Gestor de filtros (Sieve). */
.reglas-modal { max-width: 560px; }
.reglas-lista { display: flex; flex-direction: column; gap: 0.4rem; margin: 0.6rem 0; max-height: 45vh; overflow-y: auto; }
/* El pie que explica que los filtros solo corren en la entrega. Separado de los
   botones para que no se lea como la leyenda de uno de ellos. */
.regla-aplicar-pie { margin: 0.9rem 0 0.4rem; font-size: var(--t-sm); line-height: 1.4; }
.regla-fila { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-surface-2); }
.regla-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.regla-nombre { font-weight: 600; }
.regla-resumen { font-size: var(--t-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.regla-acc { flex: 0 0 auto; display: flex; gap: 0.15rem; }
.regla-comb { display: flex; gap: 1rem; margin-bottom: 0.45rem; flex-wrap: wrap; }
.regla-cond { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.4rem; flex-wrap: wrap; }
.regla-cond select.input { width: auto; flex: 0 0 auto; }
.regla-cond input.input { flex: 1 1 8rem; min-width: 0; }

/* Módulo de Contactos. */
.contactos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.6rem; margin-top: 0.8rem; }
.contacto-card { display: flex; align-items: center; gap: 0.7rem; padding: 0.6rem 0.7rem; border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-surface); cursor: pointer; text-align: left; color: inherit; width: 100%; }
.contacto-card:hover { border-color: var(--color-primary); }
.contacto-foto { flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%; overflow: hidden; display: inline-flex; align-items: center; justify-content: center; background: var(--color-surface-2); }
.contacto-foto img { width: 100%; height: 100%; object-fit: cover; }
.contacto-inicial { font-weight: 700; color: var(--color-primary); font-size: var(--t-xl); }
.contacto-datos { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.contacto-nombre { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contacto-mail { font-size: var(--t-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contacto-foto-edit { display: flex; align-items: center; gap: 0.9rem; margin: 0.4rem 0 0.8rem; }
.contacto-foto.grande { width: 72px; height: 72px; }
.contacto-foto.grande .contacto-inicial { font-size: var(--t-4xl); }
.contacto-foto-btns { display: flex; flex-direction: column; gap: 0.35rem; align-items: flex-start; }

/* Selector de archivos: cabecera con toggle lista/galería + vista galería + Favoritos. */
.picker-cab { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem; }
.picker-vista { display: inline-flex; gap: 0.2rem; flex: 0 0 auto; }
.picker-vista svg { width: 1.15rem; height: 1.15rem; display: block; }
.picker-galeria { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 0.5rem; max-height: 55vh; overflow-y: auto; padding: 0.2rem; }
.picker-gal-item { display: flex; flex-direction: column; gap: 0.3rem; align-items: center; padding: 0.5rem; border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-surface); cursor: pointer; color: inherit; }
.picker-gal-item:hover:not(:disabled) { border-color: var(--color-primary); }
.picker-gal-item:disabled { opacity: 0.55; cursor: default; }
/* Ya adjunto: es un estado ELEGIDO, no «no disponible». Por eso recupera la opacidad y se
   marca con una palomita sobre la miniatura — atenuarlo sin más se confundía con un archivo
   inutilizable y, en galería, apenas se notaba. */
.picker-gal-item.usado { opacity: 1; border-color: var(--color-success); position: relative; }
/* La palomita cuelga del ELEMENTO, no de la miniatura: esta lleva `overflow: hidden` y
   recortaría el distintivo. */
.picker-gal-item.usado::after {
    content: '✓';
    position: absolute; top: 0.25rem; right: 0.25rem;
    width: 1.25rem; height: 1.25rem; border-radius: 50%;
    background: var(--color-success); color: #fff;
    font-size: var(--t-md); line-height: 1.25rem; text-align: center; font-weight: 700;
    box-shadow: 0 0 0 2px var(--color-surface);
}
.picker-gal-thumb { width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden; display: flex; align-items: center; justify-content: center; background: var(--color-surface-2); }
.picker-gal-thumb img { width: 100%; height: 100%; object-fit: cover; }
.picker-gal-thumb .tipo-icono svg { width: 2.2rem; height: 2.2rem; }
.picker-gal-nom { font-size: var(--t-sm); text-align: center; width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.picker-fav .tipo-icono svg, .picker-gal-item .tipo-icono svg { }
.picker-fav .tipo-icono svg { color: var(--color-warning); }

/* Contacto: teléfono en la tarjeta. */
.contacto-tel { font-size: var(--t-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Ver fuente del correo. */
.fuente-modal { max-width: 760px; }
.fuente-pre { max-height: 60vh; overflow: auto; white-space: pre-wrap; word-break: break-all; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: var(--t-xs); line-height: 1.4; background: var(--color-surface-2); color: var(--color-text); border: 1px solid var(--color-border); border-radius: 8px; padding: 0.6rem; margin: 0.4rem 0; }

/* Bandera (\Flagged) en la lista de correos (estilo Roundcube). */
.buzon-bandera { cursor: pointer; color: var(--color-text-muted); display: inline-flex; align-items: center; opacity: 0.55; transition: opacity 0.12s, color 0.12s; }
.buzon-bandera svg { width: 0.95rem; height: 0.95rem; display: block; }
.buzon-bandera:hover { opacity: 1; color: var(--color-danger); }
.buzon-bandera.activa { opacity: 1; color: var(--color-danger); }
.buzon-bandera.activa svg { fill: currentColor; }

/* Estrella de «destacado» en la tarjeta de Inicio (coincide con filtros de aviso). */
.destacado-star { display: inline-flex; align-items: center; color: var(--color-warning); margin-right: 0.3rem; }
.destacado-star svg { width: 0.85rem; height: 0.85rem; fill: currentColor; }

/* Móvil: el email de la cuenta se recorta en la cabecera de Correo → ocultarlo (va al final para ganar por orden). */
@media (max-width: 768px) { .buzon-cuenta { display: none; } }
/* ⚠️ EN EL TELÉFONO LA BARRA DEL CORREO NO EXISTE: sus cinco controles viven en
   el menú «⋮» del final de la fila de carpetas. Gastaba un renglón entero de una
   pantalla pequeña en cosas que se tocan una vez al mes —crear una carpeta,
   ajustes, reglas, elegir qué se ve y el tamaño de letra— (lo pidió Jore,
   2026-09-11). Se esconde la fila ENTERA y no sus botones uno a uno: vacía
   seguiría cobrando su `margin-bottom`, que es justo lo que se quería ahorrar.
   Nada más vive aquí: `.buzon-cuenta` ya estaba oculta en el móvil (arriba) y
   el «Redactar» es el circulito de abajo a la derecha. */
@media (max-width: 768px) { .buzon-cab { display: none; } }

/* Progreso de vaciar papelera (banner flotante; sigue aunque ocultes/navegues). */
.vaciado-banner { position: fixed; left: 50%; transform: translateX(-50%); bottom: 1rem; z-index: 90; display: flex; align-items: center; gap: 0.8rem; max-width: min(560px, calc(100vw - 1.5rem)); padding: 0.6rem 0.9rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 12px; box-shadow: 0 10px 30px var(--color-shadow); }
.vaciado-cuerpo { display: flex; flex-direction: column; gap: 0.35rem; min-width: 11rem; flex: 1 1 auto; }
.vaciado-txt { font-size: var(--t-md); font-weight: 600; }
.vaciado-barra { height: 6px; border-radius: 999px; background: var(--color-surface-2); overflow: hidden; }
.vaciado-fill { height: 100%; background: var(--color-primary); transition: width 0.2s ease; }

/* Imágenes adjuntas: miniaturas + lightbox (estilo Roundcube). */
.buzon-adj-imgs { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.6rem; }
/* La miniatura y sus acciones van juntas: descargar y guardar en Mis archivos,
   lo mismo que tiene cualquier otro adjunto. */
.buzon-adj-img-caja { display: inline-flex; flex-direction: column; gap: 0.15rem; width: 190px; }
.buzon-adj-img-caja .buzon-adj-img { width: 100%; }
/* Una acción por renglón, con su etiqueta. */
.buzon-adj-img-acc { display: flex; flex-direction: column; gap: 0.1rem; }
.buzon-adj-img-acc .btn-icono {
    /* `.btn-icono` es un CUADRADO de 2.25rem: con la etiqueta dentro la recortaba
       —y ni se veía que estaba ahí—. Aquí manda el contenido. */
    width: auto; height: auto;
    padding: 0.3rem 0.4rem; justify-content: flex-start; font-size: var(--t-xs); gap: 0.35rem;
    /* Una etiqueta por renglón: partida en tres se lee peor que el icono solo. */
    white-space: nowrap;
}
.buzon-adj-img-acc svg { width: 1rem; height: 1rem; flex: none; }
@media (max-width: 768px) {
    /* Teléfono: miniatura más estrecha, y la etiqueta es la versión corta. */
    .buzon-adj-img-caja { width: 130px; }
    .buzon-adj-img-acc .btn-icono { font-size: var(--t-xs); padding: 0.25rem 0.3rem; }
}
.buzon-adj-img { display: flex; flex-direction: column; width: 130px; border: 1px solid var(--color-border); border-radius: 8px; overflow: hidden; background: var(--color-surface); cursor: pointer; padding: 0; color: inherit; }
.buzon-adj-img:hover { border-color: var(--color-primary); }
.buzon-adj-img img { width: 100%; height: 95px; object-fit: cover; display: block; background: var(--color-surface-2); }
.buzon-adj-img-nom { font-size: var(--t-xs); padding: 0.25rem 0.4rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--color-text-muted); }
.img-correo-modal { max-width: 92vw; }
.img-correo-nom { margin: 0.6rem 0 0; font-size: var(--t-md); word-break: break-word; }
/* Tres botones CON etiqueta: en escritorio caben en un renglón; en el teléfono
   envuelven y ocupan el ancho, en vez de encogerse hasta ser ilegibles. */
.img-correo-acc { flex-wrap: wrap; }
@media (max-width: 768px) {
    .img-correo-acc { flex-direction: column; align-items: stretch; }
    .img-correo-acc .btn { justify-content: center; }
}
.img-correo-full { max-width: 100%; max-height: 74vh; border-radius: 8px; display: block; margin: 0 auto; background: var(--color-surface-2); }

/* Botón «marcar todo como leído» en el árbol de carpetas (hover en escritorio, visible en móvil). */
.buzon-folder-leer { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; padding: 0; background: none; border: none; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-sm); opacity: 0; }
.buzon-folder-leer svg { width: 0.9rem; height: 0.9rem; }
.file-tree .nodo:hover .buzon-folder-leer { opacity: 1; }
.buzon-folder-leer:hover { color: var(--color-primary); }
.buzon-nodo .buzon-folder-leer { opacity: 0.6; }

/* 2FA: «confiar en este dispositivo» — caja con buen área de toque, separada del botón. */
.dosfa-recordar { gap: 0.6rem; align-items: center; justify-content: center; width: 100%; margin: 0.7rem 0 0.4rem; padding: 0.7rem 0.85rem; border: 1px solid var(--color-border); border-radius: 10px; cursor: pointer; font-size: var(--t-base); box-sizing: border-box; }
.dosfa-recordar:hover { border-color: var(--color-primary); }
.dosfa-recordar input { width: 1.2rem; height: 1.2rem; flex: none; margin: 0; }

/* Foto del remitente (contacto CardDAV) en el avatar de la lista y el lector. */
.buzon-avatar { overflow: hidden; }
.buzon-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.buzon-avatar-foto { background: none; }
.buzon-lector-avatar { width: 2.3rem; height: 2.3rem; font-size: var(--t-lg); }

/* Vista previa de texto: mismos colores del editor (temático en todos los temas). */
.preview-texto-wrap { max-height: 74vh; overflow: auto; }
.preview-texto {
    margin: 0; box-sizing: border-box; min-height: 40vh;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--t-base); line-height: 1.5; tab-size: 4;
    white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
    padding: 0.75rem; border: 1px solid var(--color-border); border-radius: var(--radius-md);
    background: var(--color-bg); color: var(--color-text);
}

/* «Ver como página» (§44): el iframe del dominio aislado, a todo lo que da.
   Fondo blanco fijo: es la página de otro, con sus colores, no la del tema. */
.preview-pagina-wrap { display: flex; flex-direction: column; gap: 0.4rem; }
.preview-pagina { display: block; width: 100%; height: 72vh; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: #fff; }
.preview-pagina-nota { font-size: var(--t-sm); margin: 0; }

/* ── Próximos eventos (tarjeta de Inicio) ────────────────────────── */
.panel-ev-lista { display: flex; flex-direction: column; }
.panel-ev { display: flex; align-items: center; gap: 0.7rem; width: 100%; text-align: left; background: none; border: none; border-left: 3px solid var(--c); padding: 0.5rem 0.6rem; border-radius: 6px; cursor: pointer; color: var(--color-text); }
.panel-ev:hover { background: var(--color-surface-2); }
.panel-ev-fecha { display: flex; flex-direction: column; flex: none; min-width: 6.4rem; }
.panel-ev-dia { font-weight: 600; font-size: var(--t-md); text-transform: capitalize; }
.panel-ev-hora { font-size: var(--t-xs); color: var(--color-text-2); font-variant-numeric: tabular-nums; }
.panel-ev-tit { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.panel-ev-rep { flex: none; font-size: var(--t-sm); color: var(--color-text-muted); white-space: nowrap; }
.panel-ev-ic { flex: none; opacity: 0.55; }
.panel-ev-ic svg { width: 15px; height: 15px; }

/* ── Calendario (CalDAV) ─────────────────────────────────────────── */
.cal-cab { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.cal-nav { display: flex; align-items: center; gap: 0.35rem; }
.cal-titulo { margin: 0; font-size: var(--t-xl); min-width: 9.5rem; text-align: center; text-transform: capitalize; }
.cal-wrap { display: grid; grid-template-columns: 1fr 20rem; gap: 1rem; align-items: start; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--color-border); border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.cal-dow { background: var(--color-surface-2); color: var(--color-text-2); font-size: var(--t-xs); font-weight: 600; text-align: center; padding: 0.4rem 0; text-transform: uppercase; letter-spacing: 0.03em; }
.cal-cell { background: var(--color-surface); min-height: 5.5rem; padding: 0.25rem; cursor: pointer; display: flex; flex-direction: column; gap: 0.15rem; transition: background 0.12s; }
.cal-cell:hover { background: var(--color-surface-2); }
.cal-cell.fuera { background: var(--color-bg); }
.cal-cell.fuera .cal-cell-num { opacity: 0.45; }
.cal-cell.sel { outline: 2px solid var(--color-primary); outline-offset: -2px; }
.cal-cell-num { font-size: var(--t-sm); font-weight: 600; color: var(--color-text-2); align-self: flex-end; width: 1.55rem; height: 1.55rem; display: flex; align-items: center; justify-content: center; }
.cal-cell.hoy .cal-cell-num { background: var(--color-primary); color: var(--color-primary-fg); border-radius: 50%; }
.cal-cell-evs { display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.cal-chip { display: flex; align-items: center; gap: 0.25rem; width: 100%; text-align: left; border: none; border-left: 3px solid var(--c); border-radius: 4px; padding: 1px 4px; font-size: var(--t-xs); line-height: 1.35; cursor: pointer; background: color-mix(in srgb, var(--c) 16%, transparent); color: var(--color-text); overflow: hidden; }
.cal-chip.todo-dia { background: var(--c); color: #fff; border-left: none; }
.cal-chip-h { font-variant-numeric: tabular-nums; opacity: 0.85; flex: none; }
.cal-chip-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-mas { border: none; background: none; color: var(--color-text-2); font-size: var(--t-2xs); text-align: left; padding: 0 4px; cursor: pointer; }
.cal-mas:hover { text-decoration: underline; }
.cal-dia { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.75rem; display: flex; flex-direction: column; gap: 0.4rem; }
/* La cabecera del panel del día: fecha con sus flechas a la izquierda, acciones
   a la derecha. `flex-wrap` porque en una columna estrecha —el panel del día en
   un portátil pequeño, o el teléfono— la fecha larga («viernes, 23 de agosto de
   2026») y dos botones no caben en un renglón, y sin envolver los botones se
   salían del panel. */
.cal-dia-cab { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.25rem; flex-wrap: wrap; }
.cal-dia-cab h3 { margin: 0; font-size: var(--t-lg); text-transform: capitalize; }
/* `min-width: 0` para que la fecha pueda encogerse en vez de empujar las flechas
   fuera: sin él un contenedor flex se niega a bajar del ancho de su contenido. */
.cal-dia-nav { display: flex; align-items: center; gap: 0.15rem; min-width: 0; flex: 1 1 auto; }
.cal-dia-nav h3 { flex: 1 1 auto; min-width: 0; text-align: center; }
/* La fecha ES el selector: el campo `date` va encima del texto, transparente y
   cubriéndolo entero, así que se lee el formato largo y se toca el calendario
   del sistema. El `opacity: 0` y no `visibility/display` es a propósito: los dos
   últimos harían que el campo dejara de recibir clics, que es justo lo que se
   busca de él. */
.cal-dia-fecha { position: relative; display: flex; align-items: center; justify-content: center; flex: 1 1 auto; min-width: 0; cursor: pointer; }
.cal-dia-fecha h3 { pointer-events: none; }
.cal-dia-fecha:hover h3 { text-decoration: underline dotted; text-underline-offset: 3px; }
.cal-dia-fecha-in { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; border: 0; padding: 0; }
/* Sin foco visible, tabular hasta aquí no se vería: el campo es transparente. */
.cal-dia-fecha:focus-within h3 { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: 4px; }
.cal-dia-accs { display: flex; align-items: center; gap: 0.4rem; flex: 0 0 auto; }
.cal-item { display: flex; align-items: flex-start; gap: 0.5rem; width: 100%; text-align: left; background: var(--color-surface-2); border: none; border-left: 3px solid var(--c); border-radius: 6px; padding: 0.45rem 0.6rem; cursor: pointer; }
.cal-item:hover { background: color-mix(in srgb, var(--c) 14%, var(--color-surface-2)); }
.cal-item-hora { font-size: var(--t-xs); color: var(--color-text-2); font-variant-numeric: tabular-nums; flex: none; min-width: 5.4rem; padding-top: 0.1rem; }
.cal-item-cuerpo { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.cal-item-tit { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.cal-item-lug { font-size: var(--t-sm); }
.cal-item-ic { flex: none; opacity: 0.6; }
.cal-item-ic svg { width: 15px; height: 15px; }
.cal-aviso { background: var(--color-surface-2); border-radius: var(--radius-md); padding: 0.5rem 0.7rem; font-size: var(--t-md); margin-bottom: 0.75rem; }
/* Sugerir horario (free/busy): botón + huecos propuestos como chips pulsables. */
.cal-hueco { margin: 0 0 0.75rem; }
.cal-hueco-res { margin-top: 0.5rem; }
.cal-hueco-nota { font-size: var(--t-sm); margin: 0 0 0.4rem; }
.cal-hueco-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.cal-hueco-chip { font-size: var(--t-sm); padding: 0.3rem 0.6rem; border-radius: 0.5rem; cursor: pointer; font: inherit; font-size: var(--t-sm); background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); }
.cal-hueco-chip:hover { border-color: var(--color-primary); color: var(--color-primary); }
/* Aviso de reprogramación: acento ámbar, es una advertencia, no un dato más. */
.cal-aviso-reprog { margin: -0.3rem 0 0.75rem; padding: 0.45rem 0.65rem; font-size: var(--t-sm); border-left: 3px solid var(--color-warning); background: var(--color-surface-2); border-radius: 0 var(--radius-md) var(--radius-md) 0; color: var(--color-text-2); }
.cal-fechas { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.cal-fila2 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.75rem; }
.cal-fh { display: flex; gap: 0.4rem; }
.cal-fh .input { min-width: 0; }
/* Invitados del evento (chips + autocompletado) */
.cal-inv-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.4rem; }
.cal-inv-chip { display: inline-flex; align-items: center; gap: 0.3rem; background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: 999px; padding: 0.15rem 0.5rem; font-size: var(--t-sm); max-width: 100%; }
.cal-inv-chip .cal-inv-ic { display: inline-flex; opacity: 0.6; }
.cal-inv-chip .cal-inv-ic svg { width: 0.85rem; height: 0.85rem; }
.cal-inv-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 13rem; }
.cal-inv-x { display: inline-flex; border: none; background: none; color: var(--color-text-2); cursor: pointer; padding: 0; }
.cal-inv-x:hover { color: var(--color-danger); }
.cal-inv-x svg { width: 0.85rem; height: 0.85rem; }
.cal-inv-input { position: relative; }
/* Input + «Agregar»: el botón sólo aparece cuando lo escrito ya es un correo válido. */
.cal-inv-fila { display: flex; gap: 0.4rem; align-items: center; }
.cal-inv-fila .input { flex: 1; min-width: 0; }
.cal-inv-add { flex: none; }
.cal-inv-chip.est-ok { border-color: var(--color-success); }
.cal-inv-chip.est-no { border-color: var(--color-danger); }
.cal-inv-chip.est-quiza { border-color: var(--color-warning); }
@media (max-width: 820px) {
    .cal-wrap { grid-template-columns: 1fr; }
    .cal-cell { min-height: 3.4rem; }
    .cal-cell-evs { flex-direction: row; flex-wrap: wrap; gap: 3px; align-content: flex-start; }
    /* Los eventos del día son PUNTOS, y un punto de 7px no es un botón: con el
       dedo se acertaba siempre al primero, y los demás eventos de ese día no
       había forma de abrirlos. Aquí solo indican «hay algo»; el toque lo recibe
       la celda, que selecciona el día y baja al panel con TODOS. */
    .cal-chip { width: 7px; height: 7px; padding: 0; border: none; border-radius: 50%; background: var(--c); overflow: visible; pointer-events: none; }
    .cal-mas { pointer-events: auto; }
    .cal-chip.todo-dia { width: 7px; height: 7px; }
    .cal-chip-h, .cal-chip-t { display: none; }
    .cal-titulo { min-width: 7.5rem; font-size: var(--t-xl); }
    .cal-fechas, .cal-fila2 { grid-template-columns: 1fr; }
    .cal-nuevo-txt { display: none; }
}

/* ── Navegación de módulos: pestañas FIJAS (PC arriba, móvil barra inferior) ── */
.nav-tab-activo { background: color-mix(in srgb, var(--color-primary) 15%, transparent); color: var(--color-primary); font-weight: 600; }
/* ── Buzones del equipo (carpetas prestadas) ──────────────────────────────
   Bloque aparte del árbol propio: en un árbol donde no se distingue de quién
   es cada carpeta, alguien acaba contestando en el buzón equivocado. */
.buzon-arbol-sep, .arbol-sep {
    margin: 0.7rem 0 0.15rem; padding: 0 0.3rem;
    font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--color-text-2);
}
.buzon-equipo-cab, .nodo-equipo-cab { font-weight: 600; }
/* La cinta que dice EN QUÉ BUZÓN se está: lo que evita el accidente de
   contestarle a un cliente desde el buzón que no era. */
.buzon-equipo-cinta {
    display: inline-flex; align-items: center; gap: 0.35rem;
    padding: 0.1rem 0.5rem; border-radius: 999px;
    background: color-mix(in srgb, var(--color-primary) 15%, var(--color-surface));
    border: 1px solid color-mix(in srgb, var(--color-primary) 35%, transparent);
    color: var(--color-text); font-size: var(--t-md); font-weight: 600;
}
.buzon-equipo-cinta svg { width: 0.95rem; height: 0.95rem; flex: 0 0 auto; }
/* Un tope y puntos suspensivos también en escritorio: el nombre de un buzón
   prestado puede llevar el dominio pegado —es lo que distingue dos con el mismo
   usuario— y sin tope empujaba fuera de la barra lo que venía detrás. */
.buzon-equipo-cinta { max-width: 16rem; }
.buzon-equipo-cinta > span:not([aria-hidden]) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* ⚠️ CON SUELO: dejarla encoger sin tope la reducía a 18 px —solo el icono, sin
   una letra— y entonces no dice EN QUÉ BUZÓN se está, que es justo para lo que
   existe. Con 7rem siempre se lee el principio del nombre. */

/* Filtro «no leídos» del correo: circulito fijo abajo a la izquierda, como el
   de Mail de iOS. Parece flotante pero está anclado sobre la tabbar (z 39 <
   40: la tabbar y los «pantalla completa» del correo lo tapan a propósito).
   Encendido se rellena de acento: una lista filtrada TIENE que notarse. */
.buzon-filtro-fab { display: none; }
@media (max-width: 768px) {
    .buzon-filtro-fab {
        display: inline-flex; align-items: center; justify-content: center;
        position: fixed; left: 0.9rem;
        bottom: calc(3.9rem + env(safe-area-inset-bottom) + 0.9rem);
        width: 3rem; height: 3rem; padding: 0; border-radius: 50%;
        border: 1px solid var(--color-border);
        background: var(--color-surface); color: var(--color-text-2);
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.22);
        z-index: 39; cursor: pointer;
    }
    /* El svg viene sin tamaño propio (solo viewBox): sin esto se colapsa
       y el botón sale como un círculo vacío. */
    .buzon-filtro-fab span { display: inline-flex; }
    .buzon-filtro-fab svg { width: 1.35rem; height: 1.35rem; }
    /* Presión larga: sin globo de selección ni menú del sistema. */
    .buzon-filtro-fab { -webkit-touch-callout: none; user-select: none; touch-action: manipulation; }
    /* El menucito de criterios, justo encima del botón. */
    .buzon-fab-menu {
        position: fixed; left: 0.9rem;
        bottom: calc(3.9rem + env(safe-area-inset-bottom) + 4.4rem);
        display: flex; flex-direction: column; padding: 0.3rem;
        background: var(--color-surface); border: 1px solid var(--color-border);
        border-radius: var(--radius-lg); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
        z-index: 39;
    }
    /* Apagado lleva la raya del color de acento, como el botón del buzón
       inteligente («Hoy») de arriba (Jore, 2026-09-30): con el borde gris se
       perdía sobre la lista en el tema oscuro. Encendido, relleno. */
    .buzon-filtro-fab { border-color: var(--color-primary); }
    .buzon-filtro-fab.activo {
        background: var(--color-primary); border-color: var(--color-primary);
        color: var(--color-primary-fg);
    }
}

/* Gemelo del de filtro, en la otra esquina: REDACTAR. Mismo tamaño, misma
   altura y el mismo z 39 —la tabbar y los «pantalla completa» del correo lo
   tapan igual—, pero relleno de acento desde el principio: aquel es un
   interruptor que a veces está encendido y este es LA acción de la pantalla.
   Sustituye al «+ Redactar» de la cabecera, que en el teléfono quedaba lejos
   del pulgar (lo pidió Jore, 2026-09-11). */
.buzon-redactar-fab { display: none; }
@media (max-width: 768px) {
    .buzon-redactar-fab {
        display: inline-flex; align-items: center; justify-content: center;
        position: fixed; right: 0.9rem;
        bottom: calc(3.9rem + env(safe-area-inset-bottom) + 0.9rem);
        width: 3rem; height: 3rem; padding: 0; border-radius: 50%;
        border: 1px solid var(--color-primary);
        background: var(--color-primary); color: var(--color-primary-fg);
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.22);
        z-index: 39; cursor: pointer;
        -webkit-touch-callout: none; user-select: none; touch-action: manipulation;
    }
    /* El svg viene sin tamaño propio (solo viewBox): sin esto el botón sale
       como un círculo vacío. Mismo cuidado que en el de filtro. */
    .buzon-redactar-fab span { display: inline-flex; }
    .buzon-redactar-fab svg { width: 1.35rem; height: 1.35rem; }
}

.tabbar-movil { display: none; } /* solo móvil (ver media query) */

@media (max-width: 768px) {
    .navbar .nav-tabs { display: none; } /* las pestañas de módulo viven en la barra inferior */
    .tabbar-movil {
        display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
        /* surface-2 (tono de «panel») para que la barra NO se confunda con el fondo de
           las listas (surface). El drawer es surface pero destaca por su sombra/overlay. */
        background: var(--color-surface-2); border-top: 1px solid var(--color-border);
        padding-bottom: env(safe-area-inset-bottom);
        box-shadow: 0 -3px 14px rgba(0, 0, 0, 0.16);
    }
    .tabbar-item {
        flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center;
        justify-content: center; gap: 3px; padding: 0.5rem 0.15rem 0.45rem;
        border: none; background: none; color: var(--color-text-2); cursor: pointer;
    }
    .tabbar-item.activo { color: var(--color-primary); }
    .tabbar-ic { display: inline-flex; position: relative; }
    .tabbar-ic svg { width: 1.75rem; height: 1.75rem; }
    .tabbar-lbl { font-size: var(--t-2xs); line-height: 1; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* Espacio para que el contenido no quede tapado por la barra inferior. Cuando está
       la barra de SELECCIÓN del gestor (.con-barra) ya se añade su propio espacio. */
    .contenido:not(.con-barra) { padding-bottom: calc(max(4.2rem + env(safe-area-inset-bottom), var(--alto-vaciado, 0px)) + 0.3rem); }
    .barra-seleccion { z-index: 50; } /* la barra de selección va por ENCIMA de la tabbar */

    /* Banner de «vaciando papelera». En escritorio es una píldora centrada de una
       fila; en móvil no cabía: `.vaciado-cuerpo` tiene `min-width:11rem` y los
       flex no encogen por debajo de su min-width, así que el conjunto desbordaba
       y «Detener» quedaba CORTADO fuera de la pantalla. Y a `bottom:1rem` se
       sentaba encima de la tabbar (z-index 90 > 40), tapando la navegación.
       Aquí: a lo ancho, en dos filas, y por encima de la barra inferior que
       toque — la tabbar, o la de selección si hay algo seleccionado. */
    .vaciado-banner {
        left: 0.5rem; right: 0.5rem; transform: none; max-width: none;
        bottom: calc(max(4.2rem + env(safe-area-inset-bottom), var(--alto-barra-sel, 0px)) + 0.4rem);
        flex-wrap: wrap; gap: 0.5rem 0.6rem;
    }
    .vaciado-cuerpo { min-width: 100%; } /* ocupa la primera fila; los botones bajan a la segunda */
    .vaciado-banner .btn { flex: 1 1 auto; justify-content: center; }
}

/* Total de no leídos junto al título de «Correo reciente» en Inicio. Es informativo: el
   globo del nav cuenta solo INBOX, esto suma todas las carpetas donde cae correo. */
.panel-sin-leer { font-weight: 400; font-size: var(--t-sm); color: var(--color-text-muted); margin-left: 0.35rem; }

/* Botón de firma del redactor: con etiqueta en PC (en móvil no cabe y queda icono solo,
   por `.solo-escritorio`). Necesita ancho automático, no la caja cuadrada de .btn-icono. */
.btn-firma { display: inline-flex; align-items: center; gap: 0.4rem; width: auto; padding: 0.4rem 0.6rem; font-size: var(--t-md); }

/* Editor de firma: elegir diseño, rellenar campos y ver el resultado. */
.firma-plantillas { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.8rem; }
.firma-plantilla { font: inherit; font-size: var(--t-md); padding: 0.35rem 0.7rem; border-radius: 0.5rem; cursor: pointer; background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); }
.firma-plantilla.activa { border-color: var(--color-primary); color: var(--color-primary); }
.firma-campos { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem 0.8rem; }
.firma-campo-ancho { grid-column: 1 / -1; }
.firma-nota { font-size: var(--t-sm); margin: 0.5rem 0 0; }
.firma-imagen-fila { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem; margin-top: 0.2rem; }
.firma-subir { cursor: pointer; }
.firma-imagen-estado { font-size: var(--t-sm); color: var(--color-text-muted); }
.firma-imagen-url { margin-top: 0.35rem; }
.firma-html { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: var(--t-sm); }
/* La previa se pinta con fondo claro fijo: es como se verá en el correo del destinatario,
   no como se ve en nuestra app (que puede estar en modo oscuro). */
.firma-previa { margin-top: 1rem; }
.firma-previa-tit { font-size: var(--t-sm); color: var(--color-text-muted); }
.firma-previa-caja { margin-top: 0.3rem; padding: 0.7rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: #fff; color: #333; overflow-x: auto; }
@media (max-width: 640px) { .firma-campos { grid-template-columns: 1fr; } }

/* Grupo «avanzado» de la consola: plegado, para que no se lea como una decisión pendiente
   en cada alta sino como algo que solo se toca con motivo. */
.avanzado-correo { margin: 0.6rem 0; padding: 0.5rem 0.7rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); }
.avanzado-correo > summary { cursor: pointer; font-size: var(--t-base); color: var(--color-text-2); }
.avanzado-correo[open] > summary { margin-bottom: 0.4rem; }

/* ── Redactar en móvil: los desplegables se anclan a la CABECERA, no a su botón ──
   Los botones de Modelos e IA son `solo-escritorio`, así que en móvil se ocultan y su
   contenedor colapsa a cero ancho. El menú, que se posiciona respecto a ese contenedor,
   aparecía desplazado. Se hace `static` el contenedor para que el desplegable se resuelva
   contra la cabecera y caiga alineado a su borde derecho, justo bajo la hamburguesa.
   Misma técnica que ya se usa con `.menu-wrap.accion-compartir` en la barra de selección.
   La especificidad (0,2,0) gana sobre `.menu-pop` y `.menu-pop-der`, así que no depende
   del orden dentro del archivo. */
@media (max-width: 768px) {
    .buzon-redactar-cab { position: relative; }
    .buzon-redactar-cab .menu-wrap { position: static; }
    .buzon-redactar-cab .menu-pop {
        left: auto;
        right: 0.6rem;
        top: calc(100% + 0.2rem);
        max-width: calc(100vw - 1.2rem);
        max-height: min(70vh, 26rem);
        overflow-y: auto;
    }
}

/* ---- Ayuda (manual de usuario) ---- */
/* Ancho de lectura acotado: una guía de 200 palabras a todo lo ancho de una
   pantalla de 27" no se lee, se escanea mal. */
.ayuda-panel { max-width: 46rem; }
/* Ver «LA BARRA A LA ORILLA»: el ancho de lectura, con el relleno de la derecha. */
.contenido.ayuda-panel { max-width: none; padding-right: max(var(--contenido-pad), calc(100% - 46rem + var(--contenido-pad))); }
.ayuda-buscar { width: 100%; margin: 0.75rem 0 1.25rem; }
.ayuda-tema { border: 1px solid var(--color-border); border-radius: var(--radius-md); margin-bottom: 0.5rem; background: var(--color-surface); }
.ayuda-tema > summary {
    display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
    padding: 0.7rem 0.9rem; cursor: pointer; font-weight: 600; list-style: none;
}
.ayuda-tema > summary::-webkit-details-marker { display: none; }
.ayuda-tema[open] > summary { border-bottom: 1px solid var(--color-border); }
.ayuda-tema-n { font-size: var(--t-sm); font-weight: 400; color: var(--color-text-2); }
.ayuda-lista { display: flex; flex-direction: column; }
.ayuda-item {
    display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
    width: 100%; text-align: left; padding: 0.6rem 0.9rem;
    background: none; border: 0; border-top: 1px solid var(--color-border);
    color: inherit; font: inherit; cursor: pointer;
}
.ayuda-lista > .ayuda-item:first-child { border-top: 0; }
.ayuda-item:hover { background: var(--color-surface-2); }
.ayuda-item-tit { flex: 1; min-width: 0; }
.ayuda-item-mod, .ayuda-item-rol { font-size: var(--t-xs); color: var(--color-text-2); }
.ayuda-vacio { padding: 1.5rem 0; }
.ayuda-volver { margin-bottom: 1rem; }
.ayuda-guia { line-height: 1.65; }
.ayuda-fecha { font-size: var(--t-sm); margin-top: 1.5rem; }
.ayuda-titulo { margin: 0 0 0.75rem; }
/* «Llévame ahí» (2026-10-04): debajo del título de la guía y bajo «Basado en». */
.ayuda-llevar { margin: -0.25rem 0 0.9rem; }
.soporte-llevar { margin-top: 0.5rem; }

/* ---- Soporte: el panel del agente de ayuda ---- */
/* Cuelga del icono de la cabecera, justo debajo. Antes era un globo flotante:
   había que arrastrarlo para que no tapara los botones del móvil, y bajo el
   redactor de correo (una capa a pantalla completa) desaparecía. Un icono fijo
   está siempre en el mismo sitio y no tapa nada.
   z-index 63 para quedar por encima de ese redactor (62); no hace falta
   esquivar los diálogos, porque el panel se cierra al abrir uno. */
.soporte {
    position: fixed; z-index: 63;
    top: calc(var(--navbar-height) + 0.4rem); right: 0.8rem;
}
.soporte-fondo, .soporte-tirador { display: none; }
.soporte-panel {
    display: flex; flex-direction: column;
    width: min(92vw, 24rem); height: min(72vh, 32rem);
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-md); box-shadow: 0 8px 32px var(--color-shadow);
    overflow: hidden;
}
.soporte-cab {
    display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
    padding: 0.5rem 0.5rem 0.5rem 0.9rem; font-weight: 600;
    background: var(--color-surface-2); border-bottom: 1px solid var(--color-border);
}
.soporte-hilo { flex: 1; min-height: 0; overflow-y: auto; padding: 0.75rem 0.9rem; display: flex; flex-direction: column; gap: 0.6rem; }
.soporte-saludo, .soporte-pensando { color: var(--color-text-2); font-size: var(--t-md); }
.soporte-msg { flex: none; max-width: 100%; min-width: 0; font-size: var(--t-base); }
.soporte-msg-usuario {
    align-self: flex-end; padding: 0.45rem 0.7rem; border-radius: var(--radius-lg);
    background: color-mix(in srgb, var(--color-primary) 16%, transparent);
}
/* `white-space: pre-wrap` va en el TEXTO, nunca en la burbuja: en la burbuja
   hay elementos hijos, y entonces los saltos de línea del propio HTML (la
   indentación de la plantilla) se pintan como renglones en blanco — la burbuja
   quedaba con 135px de hueco vacío dentro. */
.soporte-texto { white-space: pre-wrap; }
.soporte-fuentes { margin-top: 0.4rem; display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: baseline; font-size: var(--t-xs); color: var(--color-text-2); }
.soporte-fuente {
    border: 1px solid var(--color-border); border-radius: 999px;
    background: none; color: var(--color-primary); font: inherit; font-size: var(--t-xs);
    padding: 0.1rem 0.5rem; cursor: pointer;
}
.soporte-fuente:hover { background: var(--color-surface-2); }
.soporte-sugeridas { display: flex; flex-direction: column; align-items: flex-start; gap: 0.35rem; font-size: var(--t-sm); color: var(--color-text-2); }
.soporte-sugerida {
    border: 1px solid var(--color-border); border-radius: 1rem;
    background: none; color: var(--color-primary); font: inherit; font-size: var(--t-sm);
    padding: 0.3rem 0.7rem; cursor: pointer; text-align: left; max-width: 100%;
}
.soporte-sugerida:hover { background: var(--color-surface-2); }
.soporte-calif { display: flex; align-items: center; gap: 0.2rem; margin-top: 0.3rem; color: var(--color-text-2); }
.soporte-calif .btn-icono { width: 1.9rem; height: 1.9rem; }
.soporte-calif .btn-icono svg { width: 1rem; height: 1rem; }
.soporte-calif .btn-icono.activo { color: var(--color-primary); }
.soporte-gracias { font-size: var(--t-xs); margin-left: 0.3rem; }
.soporte-comentar { display: flex; gap: 0.4rem; margin-top: 0.3rem; }
.soporte-hablar-liga { background: none; border: 0; padding: 0; font: inherit; color: var(--color-primary); cursor: pointer; text-decoration: underline; }
.soporte-msg .soporte-hablar-liga { display: block; margin-top: 0.35rem; font-size: var(--t-sm); }
.soporte-hablar { display: flex; flex-direction: column; gap: 0.45rem; border: 1px solid var(--color-border); border-radius: 10px; padding: 0.7rem; font-size: var(--t-md); flex: none; }
.soporte-hablar p { margin: 0; color: var(--color-text-2); font-size: var(--t-sm); }
.soporte-hablar textarea { resize: vertical; min-height: 4.5rem; }
.soporte-comentar .input { flex: 1; min-width: 0; font-size: var(--t-sm); }
.soporte-redactar { display: flex; gap: 0.4rem; padding: 0.6rem; border-top: 1px solid var(--color-border); }
.soporte-redactar .input { flex: 1; min-width: 0; }
.soporte-aviso { margin: 0; padding: 0 0.7rem 0.6rem; font-size: var(--t-2xs); color: var(--color-text-2); line-height: 1.3; }
@media (max-width: 768px) {
    /* En el teléfono el panel es PANTALLA COMPLETA con dvh: cuando el teclado
       sale, el alto dinámico se encoge con él y quedan a la vista la cabecera,
       el hilo y la caja de escribir — colgado de la esquina, el teclado lo
       tapaba y scrolleaba la página de atrás (2026-08-25, lo vio Jore). */
    /* Hoja desde abajo: fondo atenuado y panel de dos tercios, o entero (.alta). */
    .soporte { inset: 0; top: 0; right: 0; }
    .soporte-fondo { position: absolute; inset: 0; background: color-mix(in srgb, #000 45%, transparent); }
    .soporte-panel {
        position: absolute; left: 0; right: 0; bottom: 0; width: 100%;
        height: 66vh; max-height: 100%; border-radius: var(--radius-lg) var(--radius-lg) 0 0; border: none;
        transition: height 0.18s ease-out, transform 0.12s ease-out;
        padding-bottom: env(safe-area-inset-bottom);
    }
    .soporte.alta .soporte-panel { height: 100%; border-radius: 0; }
    .soporte-tirador { display: flex; justify-content: center; padding: 0.5rem 0 0.25rem; cursor: grab; touch-action: none; }
    .soporte-tirador span { width: 2.6rem; height: 0.3rem; border-radius: 999px; background: var(--color-border); }
    .soporte-cab { background: transparent; border-bottom: 1px solid var(--color-border); }
}


/* ---- Resumen de correo del Inicio ----
   Se parece A PROPÓSITO poco a la bandeja. Antes este bloque reutilizaba
   `.buzon-item`, la misma pieza que la lista de verdad, y el resultado era que
   uno miraba el resumen, creía estar en Correo y volvía a pulsar «Correo». La
   cifra manda y los remitentes van como pastillas, no como renglones. */
.resumen-correo {
    display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
    width: 100%; text-align: left; cursor: pointer;
    font: inherit; color: inherit;
}
.resumen-correo:hover { border-color: var(--color-primary); }
.resumen-correo-cifra { display: flex; align-items: baseline; gap: .45rem; flex: 0 0 auto; }
.resumen-correo-cifra strong {
    font-size: var(--t-5xl); line-height: 1; font-weight: 700;
    color: var(--color-primary); font-family: var(--font-title);
}
.resumen-correo-cifra span { color: var(--color-text-2); font-size: var(--t-base); }
.resumen-correo-de { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; min-width: 0; font-size: var(--t-md); }
.resumen-correo-chip {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .2rem .6rem .2rem .2rem; border-radius: var(--radius-full);
    background: var(--color-surface-2); max-width: 13rem;
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.resumen-correo-ini {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.35rem; height: 1.35rem; border-radius: 50%; flex: none;
    background: var(--color-primary); color: var(--color-primary-fg);
    font-size: var(--t-2xs); font-weight: 700;
}
.resumen-correo-chip .destacado-star { width: .8rem; height: .8rem; flex: none; }
.resumen-correo-mas { color: var(--color-text-2); font-weight: 600; }
/* En móvil la cifra va sola arriba y los remitentes debajo: en una sola línea
   se comían el ancho y las pastillas quedaban cortadas a la mitad. */
/* ── Lo que uno dejó pendiente (Inicio) ────────────────────────────────
   Dos botones sueltos, no una tarjeta más: son un VISTAZO. Se enseñan solo
   cuando hay algo, porque una fila permanente que casi siempre dice cero es
   ruido y acaba sin mirarse — la misma razón por la que el chip de la barra
   del buzón tampoco es fijo. */
.resumen-pend { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .6rem; }
.resumen-pend button {
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .4rem .8rem; border-radius: var(--radius-full);
    border: 1px solid var(--color-border); background: var(--color-surface-2);
    font: inherit; font-size: var(--t-md); color: inherit; cursor: pointer;
    /* `min-width: 0` para que el texto pueda recortarse en el teléfono en vez
       de estirar la fila y sacar el botón de la pantalla. */
    min-width: 0;
}
.resumen-pend button:hover { border-color: var(--color-primary); }
.resumen-pend button strong { color: var(--color-primary); font-weight: 700; }
.resumen-pend .pend-ic { display: inline-flex; width: 1rem; height: 1rem; flex: 0 0 auto; }
.resumen-pend .pend-ic svg { width: 100%; height: 100%; }
/* Vencidos: los que ya pasaron su plazo piden algo, y se nota. */
.resumen-pend button.vencidos { border-color: var(--color-warning); }
.resumen-pend button.vencidos strong { color: var(--color-warning); }

@media (max-width: 560px) {
    .resumen-pend button { flex: 1 1 auto; justify-content: center; }
    .resumen-correo { gap: .6rem; }
    .resumen-correo-cifra { width: 100%; }
    .resumen-correo-chip { max-width: 100%; }
}

/* ── Mensajes (chat entre personas) ───────────────────────────────────
   Disposición de WhatsApp: la lista a un lado y la conversación al otro. En el
   teléfono son DOS pantallas, no dos columnas encogidas: entrar y volver, que
   es como se usa un chat con una mano. */
.msg-cuerpo { display: grid; grid-template-columns: var(--msg-width, 21rem) 5px 1fr; min-height: 0; }
.msg-lista { display: flex; flex-direction: column; border-right: 1px solid var(--color-border); min-height: 0; min-width: 0; }
.msg-lista-cab { padding: 0.75rem; display: flex; gap: 0.4rem; align-items: center; border-bottom: 1px solid var(--color-border); }
.msg-buscar { flex: 1; font-size: var(--t-md); padding: 0.35rem 0.5rem; }
.msg-items { flex: 1; overflow-y: auto; min-height: 0; }
.msg-item { display: flex; gap: 0.75rem; align-items: center; width: 100%; padding: 0.55rem 0.75rem; background: none; border: 0; color: inherit; text-align: left; cursor: pointer; font: inherit; }
/* La raya entre conversaciones empieza DESPUÉS del avatar, como en WhatsApp:
   así la columna de caras se lee de un vistazo. */
.msg-item .msg-item-txt { border-bottom: 1px solid var(--color-border); padding: 0.2rem 0 0.65rem; margin-bottom: -0.55rem; align-self: stretch; display: flex; flex-direction: column; justify-content: center; }
.msg-item-fila { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
.msg-item-fila .msg-item-nom { flex: 1; min-width: 0; }
.msg-item-hora { flex: none; font-size: var(--t-xs); color: var(--color-text-muted); }
.msg-item.sin-leer .msg-item-hora { color: var(--color-primary); font-weight: 600; }
.msg-item-fila .msg-item-sub { flex: 1; min-width: 0; font-size: var(--t-md); margin-top: 0.1rem; }
.msg-item-mudo { flex: none; color: var(--color-text-muted); line-height: 0; opacity: 0.7; }
.msg-item-mudo svg { width: 0.9rem; height: 0.9rem; }
.msg-item:hover { background: var(--color-surface-2); }
/* Canales (0286): una sección compacta arriba de la lista, por categoría, como
   en Discord. Sin número: lo nuevo va en negritas. */
.msg-canales { padding-bottom: 0.2rem; }
.msg-sec-tit { display: flex; align-items: center; gap: 0.2rem; margin: 0; padding: 0.55rem 0.75rem 0.15rem; font-size: var(--t-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-muted); }
.msg-sec-tit .btn-icono svg { width: 1rem; height: 1rem; }
.msg-sec-tit .crece { flex: 1; }
.msg-sec-tit-sola { padding-top: 0.8rem; border-top: 1px solid var(--color-border); margin-top: 0.4rem; }
.msg-cat { display: flex; align-items: center; gap: 0.25rem; width: 100%; padding: 0.4rem 0.75rem 0.1rem 0.5rem; background: none; border: 0; color: var(--color-text-muted); font: inherit; font-size: var(--t-sm); font-weight: 600; cursor: pointer; text-align: left; }
.msg-cat:hover { color: var(--color-text); }
.msg-cat-chev { line-height: 0; transition: transform 0.15s; }
.msg-cat-chev svg { width: 0.85rem; height: 0.85rem; }
.msg-cat.plegada .msg-cat-chev { transform: rotate(-90deg); }
.msg-canal { display: flex; align-items: center; gap: 0.45rem; width: calc(100% - 0.8rem); margin: 0 0.4rem; padding: 0.35rem 0.55rem; background: none; border: 0; border-radius: var(--radius-sm); color: var(--color-text-muted); font: inherit; font-size: var(--t-base); text-align: left; cursor: pointer; }
.msg-canal:hover { background: var(--color-surface-2); color: var(--color-text); }
.msg-canal.activo { background: color-mix(in srgb, var(--color-primary) 14%, transparent); color: var(--color-text); }
.msg-canal.sin-leer { color: var(--color-text); font-weight: 700; }
.msg-canal.archivado .msg-canal-nom, .msg-canal.silenciado .msg-canal-nom { opacity: 0.6; }
.msg-canal.archivado .msg-canal-nom { font-style: italic; }
.msg-canal-gato { flex: none; width: 1rem; text-align: center; font-weight: 600; opacity: 0.7; }
.msg-canal-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-avatar-gato { font-size: 1.2em; font-weight: 700; opacity: 0.85; }
.msg-archivado-nota { margin: 0; padding: 0.8rem 1rem; text-align: center; font-size: var(--t-md); color: var(--color-text-muted); border-top: 1px solid var(--color-border); background: var(--color-surface-2); }
.msg-canales-dlg { max-width: min(94vw, 34rem); width: 100%; }
.msg-canales-dlg-barra { gap: 0.5rem; margin-bottom: 0.6rem; flex-wrap: wrap; }
.msg-canales-dlg-lista { display: flex; flex-direction: column; max-height: 55vh; overflow-y: auto; }
.msg-canales-dlg-fila { display: flex; align-items: center; gap: 0.75rem; padding: 0.6rem 0.2rem; border-bottom: 1px solid var(--color-border); }
.msg-canales-dlg-fila.archivado { opacity: 0.7; }
.msg-canales-dlg-txt { flex: 1; min-width: 0; }
.msg-canales-dlg-nom { display: flex; align-items: baseline; gap: 0.3rem; font-weight: 600; flex-wrap: wrap; }
.msg-canales-dlg-cat { font-weight: 400; font-size: var(--t-sm); }
.msg-canales-dlg-desc { font-size: var(--t-md); overflow-wrap: anywhere; }
.msg-canal-previa { margin: 0.25rem 0 0; font-size: var(--t-sm); }
/* Menciones (0286). */
.msg-mencion { font-weight: 600; color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 12%, transparent); border-radius: 0.3em; padding: 0 0.15em; }
.msg-mencion-yo { background: color-mix(in srgb, var(--color-warning) 28%, transparent); color: inherit; }
.msg-redactor { position: relative; }
.msg-menc-pop { position: absolute; left: 0.5rem; right: 0.5rem; bottom: 100%; margin-bottom: 0.4rem; z-index: 20; max-height: 16rem; overflow-y: auto; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: 0.25rem; }
.msg-menc-op { display: flex; align-items: baseline; gap: 0.6rem; width: 100%; padding: 0.45rem 0.6rem; border: 0; border-radius: var(--radius-sm); background: none; color: var(--color-text); font: inherit; text-align: left; cursor: pointer; }
.msg-menc-op.activo { background: color-mix(in srgb, var(--color-primary) 14%, transparent); }
.msg-menc-nom { font-weight: 600; white-space: nowrap; }
.msg-menc-sub { font-size: var(--t-sm); color: var(--color-text-muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-globo-menc { background: var(--color-primary); color: var(--color-primary-fg); font-weight: 700; }
.msg-menc-boton { position: relative; }
.msg-menc-arroba { font-weight: 700; font-size: var(--t-xl); line-height: 1; }
.msg-menc-num { position: absolute; top: -0.1rem; right: -0.2rem; min-width: 1rem; height: 1rem; padding: 0 0.25rem; border-radius: 0.5rem; background: var(--color-primary); color: var(--color-primary-fg); font-size: var(--t-xs); font-weight: 700; line-height: 1rem; text-align: center; }
.msg-menc-fila { display: flex; flex-direction: column; gap: 0.15rem; width: 100%; padding: 0.6rem 0.4rem; border: 0; border-bottom: 1px solid var(--color-border); background: none; color: var(--color-text); font: inherit; text-align: left; cursor: pointer; }
.msg-menc-fila:hover { background: var(--color-surface-2); }
.msg-menc-fila.nueva { background: color-mix(in srgb, var(--color-warning) 10%, transparent); }
.msg-menc-fila-cab { display: flex; gap: 0.2rem; align-items: baseline; font-size: var(--t-md); min-width: 0; }
.msg-menc-fila-cab .crece { flex: 1; }
.msg-menc-hora { font-size: var(--t-xs); white-space: nowrap; }
.msg-menc-fila-txt { font-size: var(--t-md); overflow-wrap: anywhere; }
/* Mensajes fijados (0286). */
.msg-fijados-btn { display: inline-flex; align-items: center; gap: 0.2rem; font-size: var(--t-sm); font-weight: 600; width: auto; padding: 0 0.4rem; }
.msg-pie-chinche { line-height: 0; }
.msg-pie-chinche svg { width: 0.8rem; height: 0.8rem; }
.msg-fijado-fila { display: flex; align-items: center; gap: 0.3rem; border-bottom: 1px solid var(--color-border); }
.msg-fijado-fila .msg-menc-fila { border-bottom: 0; flex: 1; min-width: 0; }
.msg-fijado-por { font-size: var(--t-xs); }
/* Hilos (0286): el resumen bajo la raíz y el panel (a la derecha en la PC, a
   pantalla completa en el teléfono). */
.msg-hilo-res { display: inline-flex; align-items: center; gap: 0.35rem; margin-top: 0.35rem; padding: 0.2rem 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-primary); font: inherit; font-size: var(--t-sm); font-weight: 600; cursor: pointer; }
.msg-hilo-res svg { width: 0.95rem; height: 0.95rem; }
.msg-hilo-res:hover { background: var(--color-surface-2); }
.msg-hilo-res.nuevas { border-color: var(--color-primary); }
.msg-hilo-res-nuevas { color: var(--color-text); font-weight: 700; }
.msg-hilo-de { color: var(--color-text-muted); font-weight: 500; border-style: dashed; }
.msg-hilopanel { position: absolute; top: var(--msg-cab-alto, 0px); right: 0; bottom: 0; width: min(26rem, 100%); z-index: 30; display: flex; flex-direction: column; background: var(--color-bg); border-left: 1px solid var(--color-border); box-shadow: var(--shadow-md); }
.msg-hilopanel-cab { display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface); }
.msg-hilopanel-tit { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-hilopanel-lista { flex: 1; min-height: 0; overflow-y: auto; padding: 0.75rem; display: flex; flex-direction: column; gap: 0.6rem; }
.msg-hilopanel-msg { padding: 0.5rem 0.65rem; border-radius: var(--radius-md); background: var(--color-surface); border: 1px solid var(--color-border); }
.msg-hilopanel-msg.raiz { border-color: var(--color-primary); }
.msg-hilopanel-msg.fallo { border-color: var(--color-danger); }
.msg-hilopanel-msg.retirado .msg-hilopanel-txt { font-style: italic; color: var(--color-text-muted); }
.msg-hilopanel-autor { font-size: var(--t-sm); margin-bottom: 0.15rem; }
.msg-hilopanel-txt { white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--t-base); }
.msg-hilopanel-fallo { font-size: var(--t-sm); color: var(--color-danger); }
.msg-hilopanel-sep { margin: 0; font-size: var(--t-sm); text-align: center; }
.msg-hilopanel-redactor { position: relative; display: flex; flex-direction: column; gap: 0.4rem; padding: 0.6rem 0.75rem calc(0.6rem + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--color-border); background: var(--color-surface); }
.msg-hilopanel-entrada { resize: none; max-height: 10rem; }
.msg-hilopanel-pie { display: flex; align-items: center; gap: 0.5rem; justify-content: space-between; flex-wrap: wrap; }
.msg-hilopanel-alcanal { display: inline-flex; align-items: center; gap: 0.35rem; font-size: var(--t-sm); color: var(--color-text-muted); cursor: pointer; }
@media (max-width: 768px) {
    .msg-hilopanel { top: 0; width: 100%; border-left: 0; box-shadow: none; }
    /* Como la caja principal: por encima de la barra de módulos, y a ras con el teclado abierto. */
    .msg-hilopanel-redactor { padding-bottom: calc(0.7rem + 4.2rem + env(safe-area-inset-bottom)); }
    .teclado-mensajes .msg-hilopanel-redactor { padding-bottom: 0.55rem; }
}
.msg-item.activo { background: color-mix(in srgb, var(--color-primary) 14%, transparent); }
/* La inicial en un círculo: es lo que hace la propia app cuando un contacto no
   tiene foto, y evita pedir avatares que hoy no existen. */
.msg-avatar { flex: 0 0 auto; width: 2.4rem; height: 2.4rem; border-radius: 50%; display: grid; place-items: center; background: var(--color-surface-2); font-weight: 600; font-size: var(--t-lg); overflow: hidden; }
/* En la lista, más grandes: la cara es lo que se busca con la vista. */
.msg-item .msg-avatar { width: 3rem; height: 3rem; font-size: var(--t-xl); }
/* La inicial sobre el color de esa persona (el mismo en todas partes). */
.msg-avatar.inicial { color: #fff; }
.msg-avatar-ico { display: grid; place-items: center; line-height: 0; opacity: 0.8; }
.msg-avatar-ico svg { width: 55%; height: 55%; margin: auto; }
/* La foto llena el círculo: `cover` para que un retrato no salga deformado. */
.msg-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.msg-item.activo .msg-avatar, .msg-avatar.grupo { background: color-mix(in srgb, var(--color-primary) 30%, transparent); }
.msg-item-txt { flex: 1; min-width: 0; }
.msg-item-nom { display: block; font-size: var(--t-lg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-item.sin-leer .msg-item-nom { font-weight: 600; }
/* Recorta como el nombre: con la fecha larga («1 de agosto de 2025, 11:15
   a.m.») el renglón se partía en dos y la fila crecía. */
.msg-item-sub { display: block; font-size: var(--t-sm); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ── Presencia ────────────────────────────────────────────────────────────
   El puntito verde va PEGADO al avatar, no en una columna aparte: así no
   descuadra la fila cuando no hay nadie conectado, que es la mayor parte del
   tiempo. */
.msg-avatar { position: relative; }
/* ⚠️ EL AVATAR RECORTA (`overflow: hidden`), que es lo que mete la foto en el
   círculo — y se comía el punto: solo asomaba la esquina que caía dentro (lo
   reportó Jore con una captura). Se le quita el recorte SOLO a los que están en
   línea y la foto se redondea ella misma, que hace el mismo efecto sin cortar
   nada de fuera. La inicial no necesita recorte. */
.msg-avatar.en-linea { overflow: visible; }
.msg-avatar.en-linea img { border-radius: 50%; }
.msg-avatar.en-linea::after { content: ''; position: absolute; right: -1px; bottom: -1px; width: 0.7rem; height: 0.7rem; border-radius: 50%; background: var(--color-success); border: 2px solid var(--color-surface); }
.msg-cab-sub.presente { color: var(--color-success); }

/* ── Las palomitas (enviado / entregado / leído) ──────────────────────────
   Van en el pie de la burbuja, junto a la hora. Azul solo cuando TODOS lo
   leyeron; hasta entonces, del mismo gris tenue que la hora, para que no
   griten. */
.msg-palomas { display: inline-flex; align-items: center; padding: 0; background: none; border: 0; cursor: default; color: var(--color-text-muted); line-height: 0; }
.msg-palomas svg { width: 1rem; height: 1rem; }
.msg-palomas.leido { color: var(--color-primary); }
/* En grupo se puede pulsar para ver quién ha leído: ahí sí es un botón. */
.msg-burbuja.mio .msg-palomas { cursor: pointer; }
.msg-visto { font-size: var(--t-xs); color: var(--color-text-muted); padding: 0.2rem 0.1rem 0; text-align: right; }

/* ── Buscar dentro de los mensajes ────────────────────────────────────────
   Los aciertos por CONTENIDO, bajo su propio título. Sin avatar a propósito:
   lo que identifica un acierto es el trozo de texto, y un círculo por renglón
   empujaba el fragmento a una línea inútil de dos palabras. */
.msg-grupo-tit { margin: 0; padding: 0.55rem 0.75rem 0.35rem; font-size: var(--t-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); border-bottom: 1px solid var(--color-border); }
.msg-resultado { align-items: flex-start; }
/* Dos renglones y hasta ahí: los mensajes largos dejaban la lista ilegible.
   `min-width: 0` es lo que permite que el hijo se recorte en vez de crecer y
   sacar la columna entera de su sitio. */
/* ⚠️ `white-space: normal` a propósito: `.msg-item-sub` recorta a UNA línea sin
   ajustar, y el fragmento de un acierto quiere dos. Sin esto, la búsqueda
   pasaba a enseñar media frase seguida de puntos suspensivos. */
.msg-frag { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; white-space: normal; min-width: 0; color: var(--color-text); margin: 0.15rem 0; }
.msg-resultado .msg-item-txt { min-width: 0; }
/* El resaltado del mensaje al que se saltó: se apaga solo a los 4 s. Es para
   encontrarlo con la vista, no una marca que se quede puesta. */
.msg-burbuja.resaltado { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.msg-globo { flex: 0 0 auto; min-width: 1.35rem; height: 1.35rem; padding: 0 0.35rem; border-radius: 1rem; background: var(--color-primary); color: #fff; font-size: var(--t-xs); font-weight: 600; display: grid; place-items: center; }

.msg-panel { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.msg-cab { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface); }
/* `flex: 1`: el nombre ocupa el hueco y la cámara y el menú «⋮» quedan al
   extremo derecho (la clase `crece` solo vale dentro de la navbar). */
.msg-cab-txt { flex: 1; min-width: 0; line-height: 1.25; }
.msg-cab-txt.pulsable { cursor: pointer; }
.msg-cab-nom { font-weight: 600; }
.msg-cab-sub { font-size: var(--t-sm); color: var(--color-text-muted); }
.msg-volver { display: none; }

/* El menú de la conversación: `position: relative` para que el desplegable se
   ancle a él y no al panel, que desplaza. */
.msg-menu { position: relative; flex: 0 0 auto; }
.msg-menu .menu-pop { right: 0; left: auto; }
.msg-cargando-mas { align-self: center; font-size: var(--t-sm); color: var(--color-text-muted); padding: 0.4rem; margin: 0; }
/* ⚠️ `display: contents` Y NO UN DIV NORMAL. El bucle de Alpine necesita UNA
   sola raíz —los hermanos se descartan en silencio—, pero `.msg-hilo` es un
   flex en columna y las burbujas se colocan a izquierda o derecha con
   `align-self`: metidas dentro de un div de verdad, todas se irían a la
   izquierda y a lo ancho. Así el envoltorio no existe para la maquetación y
   burbuja y separador siguen siendo hijos del hilo.
   (El envoltorio NUNCA se esconde con x-show: eso es lo que rompe
   `display: contents`, y por eso el x-show vive en el separador de dentro.) */
.msg-fila { display: contents; }
/* El día, centrado y discreto: es un rótulo, no un mensaje. */
/* El día, centrado y discreto: es un rótulo, no un mensaje.
   (Sin `sticky`: los mensajes van en una sola lista plana, no en un bloque
   por día, así que los rótulos pegados se apilarían unos sobre otros.) */
.msg-dia { align-self: center; margin: 0.6rem 0 0.1rem; }
.msg-dia span { display: inline-block; padding: 0.25rem 0.75rem; border-radius: 0.5rem; background: var(--color-surface); color: var(--color-text-2); font-size: var(--t-xs); box-shadow: 0 1px 0.5px rgb(0 0 0 / 0.1); }

/* ⚠️ EL HILO VA «DE ABAJO ARRIBA»: column-reverse con UN solo hijo
   (`.msg-hilo-in`) que lleva los mensajes en su orden. Así el navegador mide el
   desplazamiento DESDE EL FINAL y el hilo se queda abajo solo, aunque una foto
   termine de llegar o el teclado encoja la vista (ver `msgAlFondo`). Y el
   fondo del chat, un tono por debajo de las burbujas, como el papel tapiz de
   WhatsApp: es lo que hace que cada burbuja se lea como una pieza. */
.msg-hilo-caja { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
.msg-hilo { flex: 1; overflow-y: auto; display: flex; flex-direction: column-reverse; min-height: 0;
    overscroll-behavior: contain;
    background: color-mix(in srgb, var(--color-primary) 5%, var(--color-bg)); }
/* Llena al menos el alto visible y empuja los mensajes ABAJO: con pocos, se
   leen junto a la caja de escribir, no colgados del techo. */
.msg-hilo-in { flex: 1 0 auto; display: flex; flex-direction: column; justify-content: flex-end; gap: 0.15rem; padding: 0.75rem 4% 0.9rem; }
.msg-panel > .msg-hilo { background: color-mix(in srgb, var(--color-primary) 5%, var(--color-bg)); }
.msg-vacio { margin: auto; color: var(--color-text-muted); font-size: var(--t-base); }
/* ── La burbuja, a la manera de WhatsApp ────────────────────────────────────
   Propio a la derecha y con color; ajeno a la izquierda, en blanco. Esquinas
   chicas, una sombra de un pixel y un PICO en la primera de cada racha del
   mismo autor; las siguientes van pegadas y sin pico. La hora y las palomitas
   van DENTRO, en la esquina de abajo, al final del texto. */
.msg-burbuja { --msg-fondo: var(--color-surface); max-width: 100%; border-radius: 0.55rem; padding: 0.3rem 0.5rem 0.35rem 0.6rem; position: relative;
    background: var(--msg-fondo); box-shadow: 0 1px 0.5px rgb(0 0 0 / 0.13); margin-top: 0.5rem; }
.msg-burbuja.seguido { margin-top: 0; }
.msg-burbuja.mio { --msg-fondo: color-mix(in srgb, var(--color-primary) 17%, var(--color-surface)); align-self: flex-end; border-top-right-radius: 0; }
.msg-burbuja.suyo { align-self: flex-start; border-top-left-radius: 0; }
.msg-burbuja.seguido.mio { border-top-right-radius: 0.55rem; }
.msg-burbuja.seguido.suyo { border-top-left-radius: 0.55rem; }
/* El pico: un triangulito del color de la burbuja, en la esquina de arriba. */
.msg-burbuja:not(.seguido)::before { content: ''; position: absolute; top: 0; width: 0.5rem; height: 0.8rem; background: var(--msg-fondo); }
.msg-burbuja.mio:not(.seguido)::before { right: -0.45rem; clip-path: polygon(0 0, 100% 0, 0 100%); }
.msg-burbuja.suyo:not(.seguido)::before { left: -0.45rem; clip-path: polygon(0 0, 100% 0, 100% 100%); }
.msg-autor { display: block; font-size: var(--t-sm); font-weight: 600; color: var(--color-primary); margin-bottom: 0.1rem; }
.msg-texto { white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--t-lg); line-height: 1.38; }
.msg-texto a { color: var(--color-primary); text-decoration: underline; overflow-wrap: anywhere; }
.msg-texto.retirado { font-style: italic; opacity: 0.6; }
/* Uno a tres emojis solos, grandes y sin burbuja que los encierre. */
.msg-burbuja.solo-emoji { background: transparent; box-shadow: none; }
.msg-burbuja.solo-emoji::before { display: none; }
.msg-burbuja.solo-emoji .msg-texto { font-size: var(--t-5xl); line-height: 1.15; }
/* La hora: en la esquina de abajo. Con texto, flota sobre el final de la
   última línea —el hueco invisible del final del texto le guarda el sitio—;
   sin texto (un archivo), va en su renglón. */
.msg-pie { display: flex; align-items: center; justify-content: flex-end; gap: 0.25rem; font-size: var(--t-2xs); color: var(--color-text-muted); white-space: nowrap; line-height: 1; }
.msg-burbuja.con-texto .msg-pie { position: absolute; right: 0.5rem; bottom: 0.3rem; }
.msg-pie-hueco { display: inline-block; width: 4.4rem; height: 0.6rem; }
.msg-burbuja.mio .msg-pie-hueco { width: 5.7rem; }
.msg-burbuja.editado .msg-pie-hueco { width: 8rem; }
.msg-burbuja.mio.editado .msg-pie-hueco { width: 9.3rem; }
/* El que no salió lleva debajo su renglón de «Reintentar»: ahí la hora va en
   su sitio normal y no encima de los botones. */
.msg-burbuja.fallo .msg-pie { position: static; margin-top: 0.2rem; }
.msg-burbuja.fallo .msg-pie-hueco { display: none; }
.msg-burbuja.sin-texto .msg-pie { margin-top: 0.2rem; }
/* Sobre una foto o un vídeo sin texto, la hora va ENCIMA de la imagen, en
   blanco con su sombra, como en WhatsApp. */
.msg-burbuja.solo-medio .msg-pie { position: absolute; right: 0.6rem; bottom: 0.55rem; margin: 0; color: #fff; padding: 0.15rem 0.35rem; border-radius: 0.6rem; background: rgb(0 0 0 / 0.38); }
.msg-burbuja.solo-medio .msg-pie .msg-palomas { color: #fff; }
.msg-burbuja.solo-medio .msg-pie .msg-palomas.leido { color: #7cc4ff; }
.msg-burbuja.solo-medio { padding: 0.2rem; }
/* La flechita del menú: solo al pasar el ratón, en la esquina de arriba. En el
   teléfono no hay ratón: ahí se mantiene pulsado el mensaje. */
.msg-mas { position: absolute; top: 0.15rem; right: 0.2rem; z-index: 1; display: none; padding: 0.1rem; border: 0; border-radius: 50%; cursor: pointer; line-height: 0;
    color: var(--color-text-muted); background: radial-gradient(circle, var(--msg-fondo) 55%, transparent 75%); }
.msg-mas svg { width: 1.1rem; height: 1.1rem; }
@media (hover: hover) {
    .msg-burbuja:hover .msg-mas, .msg-mas:focus-visible { display: block; }
}
.msg-burbuja.solo-medio .msg-mas { color: #fff; background: radial-gradient(circle, rgb(0 0 0 / 0.35) 50%, transparent 72%); }
/* En el teléfono, mantener pulsado abre el menú: que no salga encima el de
   seleccionar texto del sistema. Copiar está en el propio menú. */
@media (hover: none) {
    .msg-burbuja { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
}
/* Deslizar para responder: la flecha que asoma al pasar el tramo. */
.msg-burbuja.desliz-listo::after { content: '↩'; position: absolute; left: -2.2rem; top: 50%; transform: translateY(-50%); width: 1.8rem; height: 1.8rem; border-radius: 50%;
    display: grid; place-items: center; background: var(--color-surface); color: var(--color-text-2); box-shadow: 0 1px 2px rgb(0 0 0 / 0.2); font-size: var(--t-lg); }
/* Los avisos del chat («Ana añadió a Luis»): un rótulo en medio. */
.msg-sistema { align-self: center; margin: 0.6rem 0 0.2rem; max-width: 85%; text-align: center; }
.msg-sistema span { display: inline-block; padding: 0.3rem 0.75rem; border-radius: 0.5rem; background: var(--color-surface); color: var(--color-text-2); font-size: var(--t-sm); box-shadow: 0 1px 0.5px rgb(0 0 0 / 0.1); }
/* «3 mensajes no leídos»: una franja a lo ancho, donde empieza lo nuevo. */
.msg-sep-nuevos { align-self: stretch; text-align: center; margin: 0.6rem -5% 0.1rem; padding: 0.3rem 0; background: color-mix(in srgb, var(--color-surface) 70%, transparent); }
.msg-sep-nuevos span { font-size: var(--t-sm); font-weight: 600; color: var(--color-text-2); }
/* Lo que no pudo salir. */
.msg-fallo { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 0.3rem; font-size: var(--t-sm); color: var(--color-danger); }
.msg-fallo-btn { background: none; border: 0; padding: 0; font: inherit; font-weight: 600; color: var(--color-primary); cursor: pointer; }
.msg-palomas.pendiente svg { width: 0.85rem; height: 0.85rem; }
.msg-palomas.fallo { color: var(--color-danger); }
/* Ir al final: el circulito de abajo a la derecha, con lo que llegó. */
.msg-abajo { position: absolute; right: 1rem; bottom: 0.9rem; width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 0; cursor: pointer; display: grid; place-items: center;
    background: var(--color-surface); color: var(--color-text-2); box-shadow: 0 1px 4px rgb(0 0 0 / 0.25); z-index: 2; }
.msg-abajo svg { width: 1.3rem; height: 1.3rem; }
.msg-abajo-n { position: absolute; top: -0.4rem; right: -0.2rem; min-width: 1.3rem; height: 1.3rem; padding: 0 0.3rem; border-radius: 1rem; background: var(--color-primary); color: #fff; font-size: var(--t-xs); font-weight: 600; display: grid; place-items: center; }
/* El menú de un mensaje: flota donde se pidió. Se pinta invisible la primera
   vez —para medirlo— y aparece ya colocado. */
.msg-accion-fondo { position: fixed; inset: 0; z-index: 60; }
.msg-accion { position: fixed; display: block; min-width: 12rem; max-width: min(18rem, calc(100vw - 1rem)); visibility: hidden; }
.msg-accion.listo { visibility: visible; }
/* La fila de reacciones de arriba del menú: las de siempre, a un toque. */
.msg-accion-reac { display: flex; align-items: center; gap: 0.15rem; padding: 0.3rem 0.4rem 0.4rem; border-bottom: 1px solid var(--color-border); margin-bottom: 0.25rem; }
.msg-accion-reac button { border: 0; background: none; cursor: pointer; font-size: var(--t-2xl); line-height: 1; width: 2.2rem; height: 2.2rem; border-radius: 50%; display: grid; place-items: center; }
.msg-accion-reac button:hover { background: var(--color-surface-2); }
.msg-accion-reac button.mia { background: color-mix(in srgb, var(--color-primary) 20%, transparent); }
.msg-accion-reac-mas { color: var(--color-text-2); }
.msg-accion-reac-mas svg { width: 1.1rem; height: 1.1rem; }

/* ── Reacciones bajo la burbuja ─────────────────────────────────────────────
   Cuelgan del borde de abajo, montadas a medias sobre él, como en WhatsApp.
   La burbuja deja sitio debajo para que no pisen al mensaje siguiente. */
.msg-burbuja.con-reacciones { margin-bottom: 1.05rem; }
.msg-reacciones { position: absolute; bottom: -1.05rem; display: flex; gap: 0.2rem; z-index: 1; }
.msg-burbuja.suyo .msg-reacciones { left: 0.5rem; }
.msg-burbuja.mio .msg-reacciones { right: 0.5rem; }
.msg-reaccion { display: inline-flex; align-items: center; gap: 0.15rem; padding: 0.1rem 0.4rem; border-radius: 1rem; cursor: pointer; font: inherit; font-size: var(--t-md); line-height: 1.3;
    border: 1px solid var(--color-border); background: var(--color-surface); box-shadow: 0 1px 1px rgb(0 0 0 / 0.1); }
.msg-reaccion.mia { border-color: color-mix(in srgb, var(--color-primary) 55%, transparent); background: color-mix(in srgb, var(--color-primary) 14%, var(--color-surface)); }
.msg-reaccion-n { font-size: var(--t-xs); color: var(--color-text-2); }

/* «Reenviado», arriba del contenido, discreto como en WhatsApp. */
.msg-reenviado { display: flex; align-items: center; gap: 0.25rem; font-size: var(--t-xs); font-style: italic; color: var(--color-text-muted); margin-bottom: 0.1rem; }
.msg-reenviado svg { width: 0.85rem; height: 0.85rem; }

/* Álbum: cuatro fotos en cuadrícula, la cuarta con «+N» si hay más. */
.msg-album { display: grid; grid-template-columns: 1fr 1fr; gap: 0.2rem; width: min(17rem, 62vw); margin: 0.1rem 0 0.15rem; }
.msg-album-foto { position: relative; aspect-ratio: 1; border: 0; padding: 0; border-radius: 0.3rem; overflow: hidden; cursor: pointer; background: color-mix(in srgb, var(--color-text) 8%, transparent); }
.msg-album-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.msg-album-mas { position: absolute; inset: 0; display: grid; place-items: center; background: rgb(0 0 0 / 0.45); color: #fff; font-size: var(--t-3xl); font-weight: 600; }

/* Lo que se está subiendo: una barra fina de avance encima de la foto. */
.msg-subiendo { position: absolute; left: 0.5rem; right: 0.5rem; bottom: 0.5rem; height: 0.3rem; border-radius: 1rem; background: rgb(0 0 0 / 0.35); overflow: hidden; }
.msg-subiendo-barra { display: block; height: 100%; background: #fff; transition: width 0.2s; }
/* ⚠️ ANCHO FIJO, no en %: la burbuja mide lo que mide su contenido, y un
   reproductor «al 100 % de la burbuja» se quedaba en CERO — se veía la burbuja
   vacía y no había con qué darle play (lo reportó Jore, 2026-10-10). */
.msg-audio-caja { position: relative; width: min(17rem, 66vw); }
.msg-audio-caja .msg-audio { width: 100%; max-width: none; }
.msg-audio-caja .msg-subiendo { position: static; margin-top: 0.25rem; background: color-mix(in srgb, var(--color-text) 15%, transparent); }
.msg-audio-caja .msg-subiendo-barra { background: var(--color-primary); }

/* Soltar archivos sobre la conversación. */
.msg-panel { position: relative; }
.msg-soltar { position: absolute; inset: 0.5rem; z-index: 5; display: grid; place-items: center; border-radius: 0.8rem; pointer-events: none;
    border: 2px dashed var(--color-primary); background: color-mix(in srgb, var(--color-primary) 10%, color-mix(in srgb, var(--color-bg) 85%, transparent)); }
.msg-soltar span { font-weight: 600; color: var(--color-primary); }
/* En Notas cubre la pantalla; en la nota abierta, encima del cuadro (dentro de su fondo). */
.notas-soltar { position: fixed; inset: 0.75rem; z-index: 80; }

/* «Archivadas», arriba de la lista. */
.msg-archivadas .msg-archivadas-ico { flex: 0 0 auto; width: 3rem; display: grid; place-items: center; color: var(--color-text-2); line-height: 0; }
.msg-archivadas .msg-archivadas-ico svg { width: 1.3rem; height: 1.3rem; }
.msg-archivadas .msg-item-txt { padding-top: 0.55rem; }
.msg-globo-suave { background: var(--color-text-muted); }
.msg-elegido-ok { margin-left: auto; color: var(--color-primary); line-height: 0; }
.msg-elegido-ok svg { width: 1.1rem; height: 1.1rem; }

/* Grabando una nota de voz: el punto rojo que late y el tiempo. */
.msg-caja.msg-grabando { align-items: center; gap: 0.5rem; padding-right: 0.8rem; min-height: 2.75rem; }
.msg-grabando-punto { width: 0.7rem; height: 0.7rem; border-radius: 50%; background: #e5484d; animation: msg-latido 1s ease-in-out infinite; }
.msg-grabando-tiempo { font-variant-numeric: tabular-nums; font-weight: 600; }
.msg-grabando-txt { color: var(--color-text-muted); font-size: var(--t-md); }
@keyframes msg-latido { 50% { opacity: 0.25; } }
/* Al deslizar, el rótulo se mueve a la izquierda y pasa POR DEBAJO del punto
   y del contador, que se quedan quietos y tapan lo que les llega. */
.msg-caja.msg-grabando { overflow: hidden; }
.msg-grabando-punto, .msg-grabando-tiempo { position: relative; z-index: 1; }
.msg-grabando-tiempo { background: var(--color-surface); padding-right: 0.4rem; box-shadow: 0.6rem 0 0.5rem var(--color-surface); }
.msg-grabando-desliza { color: var(--color-text-muted); font-size: var(--t-md); margin-left: auto; white-space: nowrap; }
.msg-grabando-desliza.cancela { color: var(--color-danger); }
/* El micrófono: se sostiene, así que el navegador no debe tomar el gesto para
   desplazar ni para seleccionar. Mientras se graba crece, como en WhatsApp. */
.msg-mic-caja { position: relative; flex: none; }
.msg-mic { touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; transition: transform 0.15s; }
.msg-mic.grabando { transform: scale(1.35); background: #e5484d !important; }
.msg-mic-candado { position: absolute; bottom: calc(100% + 0.9rem); left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 0.1rem;
    padding: 0.45rem 0.35rem; border-radius: 1rem; background: var(--color-surface); color: var(--color-text-2); box-shadow: 0 1px 4px rgb(0 0 0 / 0.2); font-size: var(--t-2xs); }
.msg-mic-candado svg { width: 1rem; height: 1rem; }
.msg-fecha-sep { align-self: center; font-size: var(--t-xs); color: var(--color-text-muted); padding: 0.35rem 0.7rem; background: var(--color-surface-2); border-radius: 1rem; margin: 0.5rem 0; }
/* Enlace, no fila muerta: se pulsa para abrir o descargar. */
.msg-archivo { display: flex; align-items: center; gap: 0.6rem; padding: 0.45rem 0.55rem; margin: 0.1rem 0 0.15rem; color: inherit; text-decoration: none; border-radius: 0.4rem;
    background: color-mix(in srgb, var(--color-text) 6%, transparent); min-width: min(14rem, 60vw); }
.msg-archivo-ico { flex: none; line-height: 0; color: var(--color-text-2); }
.msg-archivo-datos { display: flex; flex-direction: column; min-width: 0; }
.msg-archivo:hover .msg-archivo-nom { text-decoration: underline; }
.msg-archivo-peso { font-size: var(--t-xs); color: var(--color-text-muted); flex: 0 0 auto; }
/* La foto manda en la burbuja: se ve, y al pulsarla se abre a tamaño completo. */
/* Fotos y vídeos: una caja con su sitio YA reservado (la proporción, si se
   conoce; si no, cuadrada) para que el hilo no salte cuando llega la imagen.
   La imagen la llena recortando lo que sobre. */
.msg-medio { --ar: 1; display: block; position: relative; width: min(17rem, 62vw); aspect-ratio: var(--ar); max-height: 22rem; margin: 0.1rem 0 0.15rem;
    border: 0; padding: 0; border-radius: 0.4rem; overflow: hidden; background: color-mix(in srgb, var(--color-text) 8%, transparent); cursor: pointer; }
.msg-medio img { display: block; width: 100%; height: 100%; object-fit: cover; }
.msg-video-portada { all: unset; display: block; width: 100%; height: 100%; cursor: pointer; position: relative; background: #000; }
.msg-play { position: absolute; inset: 0; margin: auto; width: 3.2rem; height: 3.2rem; border-radius: 50%; display: grid; place-items: center; background: rgb(0 0 0 / 0.5); color: #fff; }
.msg-play svg { width: 1.5rem; height: 1.5rem; margin-left: 0.15rem; }
.msg-video-vivo { width: 100%; height: 100%; background: #000; display: grid; place-items: center; }
.msg-video-vivo .msg-video { width: 100%; height: 100%; max-height: none; max-width: none; object-fit: contain; border-radius: 0; }
.msg-video-vivo .video-convertir { color: #fff; text-align: center; }
.msg-archivo-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El campo de corregir ocupa el sitio de la burbuja, sin moverla. */
.msg-editor { min-width: min(22rem, 60vw); }
.msg-editor textarea { width: 100%; box-sizing: border-box; }
.msg-retirar { background: none; border: 0; color: var(--color-text-muted); cursor: pointer; font: inherit; font-size: var(--t-2xs); padding: 0; }
.msg-retirar:hover, .msg-retirar.armado { color: var(--color-danger); }

/* Las mismas medidas que `.chat-redactar`: son dos chats y deben verse
   como la misma pieza. */
/* La barra de escribir de WhatsApp: una caja redonda con el emoji y el clip
   dentro, y el botón de enviar redondo al lado. Va sobre el mismo fondo que el
   chat, sin raya de separación. */
.msg-redactor { position: relative; display: flex; align-items: flex-end; gap: 0.45rem; padding: 0.45rem 0.75rem 0.55rem;
    background: color-mix(in srgb, var(--color-primary) 5%, var(--color-bg)); }
.msg-caja { flex: 1; min-width: 0; display: flex; align-items: flex-end; gap: 0.15rem; padding: 0.2rem 0.35rem; border-radius: 1.4rem; background: var(--color-surface); box-shadow: 0 1px 0.5px rgb(0 0 0 / 0.13); }
.msg-caja .btn-icono { flex: none; border-radius: 50%; }
.msg-entrada { flex: 1; resize: none; max-height: 10rem; min-height: 2.3rem; }
.msg-caja .msg-entrada { border: 0; outline: 0; background: transparent; color: inherit; font: inherit; font-size: var(--t-lg); line-height: 1.35; padding: 0.5rem 0.3rem; box-shadow: none; }
.msg-clip, .msg-enviar { flex: none; }
.msg-enviar { width: 2.75rem; height: 2.75rem; border-radius: 50%; }
/* Redondo y lleno, como el de WhatsApp, sea enviar o el micrófono. */
.msg-redactor .msg-enviar { background: var(--color-primary); color: #fff; border: 0; }
.msg-redactor .msg-enviar:hover { background: color-mix(in srgb, var(--color-primary) 85%, #000); }
.msg-redactor .msg-enviar svg { width: 1.25rem; height: 1.25rem; }
.msg-gente { max-height: 22rem; overflow-y: auto; display: flex; flex-direction: column; gap: 0.1rem; }
.msg-persona { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem; border: 0; background: none; color: inherit; cursor: pointer; font: inherit; text-align: left; border-radius: var(--radius-sm); width: 100%; }
.msg-persona:hover { background: var(--color-surface-2); }
.msg-persona.elegido { background: color-mix(in srgb, var(--color-primary) 16%, transparent); }

@media (max-width: 768px) {
    /* Dos pantallas, no dos columnas: se entra a la conversación y se vuelve. */
    /* `minmax(0, 1fr)` y no `1fr` a secas: la vista previa de cada
       conversación va en un renglón sin cortes, y con `1fr` la columna crecía
       hasta su largo —más ancha que la pantalla—, así que la hora y el número
       de no leídos se quedaban fuera, a la derecha. */
    .msg-cuerpo { grid-template-columns: minmax(0, 1fr); }
    /* La barra inferior es `position: fixed`, así que no empuja nada: hay que
       dejarle sitio a mano o tapa lo último de la pantalla — en el chat, justo
       el campo donde se escribe. Se usa la misma medida que el resto de la
       aplicación, con el hueco de la barra del sistema en los teléfonos que lo
       tienen. */
    .msg-redactor { padding-bottom: calc(0.7rem + 4.2rem + env(safe-area-inset-bottom)); }
    /* Escribiendo en Mensajes: la barra de módulos se va mientras el teclado
       está fuera (`vigilarTeclado`), y su hueco también. */
    .teclado-mensajes .tabbar-movil { display: none !important; }
    .teclado-mensajes .msg-redactor { padding-bottom: 0.55rem; }
    /* Y la aplicación entera cabe en el hueco visible sobre el teclado, con la
       cabecera de la conversación a la vista (ver `vigilarTeclado`). */
    /* Con el teclado, el hueco es chico: la barra general (logo y búsqueda)
       se va también y arriba queda solo con quién se habla, como en WhatsApp. */
    .teclado-mensajes .navbar { display: none !important; }
    .teclado-mensajes .app { grid-template-rows: 1fr; }
    .teclado-mensajes .app { position: fixed; left: 0; right: 0; top: var(--vv-top, 0px); height: var(--vv-alto, 100dvh); }
    .msg-items { padding-bottom: calc(4.2rem + env(safe-area-inset-bottom)); }
    .panel-sep { display: none; }
    .msg-lista { border-right: 0; }
    .msg-cuerpo.abierta .msg-lista { display: none; }
    .msg-cuerpo:not(.abierta) .msg-panel { display: none; }
    .msg-volver { display: inline-flex; }
    .msg-burbuja { max-width: 88%; }
}

/* Foto de la cuenta, en Mi perfil. */
.perfil-foto { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.4rem; flex-wrap: wrap; }
.perfil-foto-av {
    flex: 0 0 auto; width: 5rem; height: 5rem; border-radius: 50%; overflow: hidden;
    display: grid; place-items: center; background: var(--color-surface-2);
    font-weight: 600; font-size: var(--t-4xl); color: var(--color-text-muted);
}
.perfil-foto-av img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* De qué carpeta salió un resultado de búsqueda del correo. Discreto: es un
   dato de apoyo, no el asunto. */
.buzon-carpeta-res {
    display: inline-block; margin-top: 0.15rem; padding: 0.05rem 0.4rem;
    font-size: var(--t-xs); color: var(--color-text-2);
    background: var(--color-surface-2); border-radius: 999px;
}

/* Tira para encender y apagar calendarios en la vista. El apagado se ve
   apagado —punto hueco y texto atenuado— en vez de desaparecer: hay que poder
   volver a encenderlo. */
.cal-filtro { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0 0 0.7rem; }
.cal-filtro-item {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.25rem 0.6rem; border-radius: 999px; cursor: pointer;
    font: inherit; font-size: var(--t-md); color: var(--color-text);
    background: var(--color-surface-2); border: 1px solid var(--color-border);
}
.cal-filtro-punto { width: 0.65rem; height: 0.65rem; border-radius: 50%; flex: none; }
.cal-filtro-item.apagado { color: var(--color-text-2); opacity: 0.55; }
.cal-filtro-item.apagado .cal-filtro-punto { background: transparent !important; box-shadow: inset 0 0 0 2px currentColor; }

/* Lista de calendarios dentro de su menú. Sustituye a la tira de botones: con
   nombres largos —y los compartidos arrastran el nombre de su dueño— aquella
   ocupaba media pantalla. Aquí el nombre se recorta y se ve entero al pasar
   por encima. */
.cal-menu { min-width: 19rem; max-width: 24rem; }
.cal-menu-fila { display: flex; align-items: center; gap: 0.4rem; padding: 0.25rem 0.5rem; }
.cal-menu-ver { display: inline-flex; align-items: center; gap: 0.35rem; cursor: pointer; flex: none; }
.cal-menu-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-base); }
.cal-menu-tag {
    flex: none; font-size: var(--t-2xs); padding: 0.05rem 0.35rem; border-radius: 999px;
    background: color-mix(in srgb, var(--color-primary) 16%, transparent); color: var(--color-primary);
}
.cal-menu-tag.ajeno { background: var(--color-surface-2); color: var(--color-text-muted); }
.cal-menu-mini { flex: none; width: 1.5rem; height: 1.5rem; }
.cal-menu-mini:disabled { opacity: 0.3; cursor: default; }
.menu-pop-sep { height: 1px; background: var(--color-border); margin: 0.35rem 0; }

/* ── Buzones inteligentes ────────────────────────────────────────────────
   No son carpetas: van arriba del árbol, con su propia cabecera, para que se
   vea de un golpe que ese bloque no es el buzón real del servidor. */
.buzon-int-cab { display: flex; align-items: center; gap: 0.3rem; padding: 0.15rem 0.4rem 0.25rem; }
.buzon-int-tit { flex: 1; min-width: 0; font-size: var(--t-2xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.btn-icono-sm { width: 1.5rem; height: 1.5rem; padding: 0; }
.btn-icono-sm svg { width: 0.9rem; height: 0.9rem; }
.buzon-int-nodo .tipo-icono svg { width: 1rem; height: 1rem; }
/* Separador con las carpetas de verdad, que vienen justo debajo. */
.buzon-pane-tree .buzon-int-nodo:last-of-type { margin-bottom: 0.4rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--color-border); }
/* Modificar no es borrar: no se pinta de rojo al pasar por encima. */
.buzon-int-nodo .buzon-folder-del:first-of-type:hover { color: var(--color-primary); }
.buzon-nodo.buzon-int-nodo .buzon-folder-leer { opacity: 1; }
/* En el móvil no hay «pasar el cursor»: los botones se ven siempre. */
.buzon-arbol .buzon-int-nodo .buzon-folder-del { opacity: 1; }
/* Condiciones de estado en el editor: casillas con forma de botón. */
.buzon-int-estados { display: flex; flex-wrap: wrap; gap: 0.4rem; }
/* (La descripción del buzón activo tenía aquí su regla, para el renglón que
   había encima de la lista. Ese renglón se quitó: ahora el buzón abierto se
   dice con un chip en la barra fija y la descripción va en su `title`.) */

/* Aviso de que al guardar el evento cambia de calendario. */
.cal-mueve { font-size: var(--t-md); margin: 0.2rem 0 0; }

/* ── Asistente por voz ────────────────────────────────────────────────────
   Pantalla completa a propósito: se está hablando, no navegando, y cualquier
   otra cosa en la vista invita a tocarla en vez de a decir la frase. Heredado
   del asistente de don centavo, con la paleta y los radios de aquí. */
.busqueda-voz {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 1.9rem; height: 1.9rem; padding: 0; margin-left: 0.15rem;
    background: none; border: none; border-radius: var(--radius-full);
    color: var(--color-text-muted); cursor: pointer;
}
.busqueda-voz:hover { background: var(--color-surface-2); color: var(--color-primary); }
.busqueda-voz svg { width: 1.05rem; height: 1.05rem; display: block; }

.voz-capa {
    position: fixed; inset: 0; z-index: 1200;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0.4rem; padding: 1.5rem 1.1rem calc(1.5rem + env(safe-area-inset-bottom));
    background: var(--color-bg); text-align: center;
    animation: voz-entra 0.18s ease-out;
}
@keyframes voz-entra { from { opacity: 0; transform: scale(0.98); } to { opacity: 1; transform: none; } }

.voz-capa .voz-cerrar { position: absolute; top: 0.9rem; right: 0.9rem; }

.voz-circulo {
    display: flex; align-items: center; justify-content: center;
    width: 96px; height: 96px; margin-bottom: 0.6rem; border-radius: var(--radius-full);
    background: var(--color-primary); color: var(--color-primary-fg); position: relative;
}
.voz-circulo svg { width: 44px; height: 44px; }
/* El halo late solo mientras escucha: al pensar o al mostrar, quieto. */
.voz-circulo.voz-escuchando::after {
    content: ''; position: absolute; inset: 0; border-radius: inherit;
    background: var(--color-primary); animation: voz-halo 1.6s ease-out infinite;
}
@keyframes voz-halo { 0% { transform: scale(1); opacity: 0.55; } 100% { transform: scale(1.5); opacity: 0; } }
.voz-circulo.voz-pensando { animation: voz-respira 1.2s ease-in-out infinite; }
@keyframes voz-respira { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }

.voz-titulo { margin: 0; font-size: var(--t-2xl); font-weight: 600; color: var(--color-text); }
.voz-sub { margin: 0; font-size: var(--t-base); color: var(--color-text-muted); }

.voz-ondas { display: flex; gap: 7px; align-items: center; justify-content: center; height: 56px; margin: 0.5rem 0; }
.voz-onda {
    display: inline-block; width: 5px; height: 14px; border-radius: var(--radius-full);
    background: var(--color-primary); animation: voz-onda 1s ease-in-out infinite;
}
@keyframes voz-onda { 0%, 100% { height: 14px; opacity: 0.5; } 50% { height: 48px; opacity: 1; } }
.voz-ondas-quietas .voz-onda { animation-play-state: paused; opacity: 0.3; }

.voz-entendido { margin: 0 0 0.4rem; font-size: var(--t-base); color: var(--color-text-muted); font-style: italic; }
.voz-pregunta { margin: 0.2rem 0 0; font-size: var(--t-lg); color: var(--color-text); max-width: 34rem; }
.voz-vacio, .voz-error { margin: 0.4rem 0 0; font-size: var(--t-lg); color: var(--color-text-muted); }
.voz-error { color: var(--color-danger); }

/* Los resultados: tocables de sobra (se usan de pie, con una mano) y con
   scroll propio para que los botones de abajo no se vayan de la pantalla. */
.voz-resultado {
    display: flex; flex-direction: column; gap: 0.4rem;
    width: 100%; max-width: 34rem; margin-top: 0.6rem;
    max-height: 46vh; overflow-y: auto;
}
/* La respuesta del Chat IA (2026-10-20): texto corrido, alineado a la
   izquierda como en el chat, con scroll propio para no empujar los botones.
   ⚠️ «-panel» y no «.voz-ia»: esa clase ya la lleva el CÍRCULO en este estado
   (`'voz-' + agente.estado`) y lo estiraba a todo el ancho. */
.voz-ia-panel { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; width: 100%; max-width: 34rem; margin-top: 0.4rem; }
.voz-ia-respuesta {
    width: 100%; max-height: 42vh; overflow-y: auto; text-align: left;
    padding: 0.8rem 0.9rem; font-size: var(--t-lg);
    background: var(--color-surface); color: var(--color-text);
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
}
.voz-ia-escuchar svg { width: 1.05rem; height: 1.05rem; }
.voz-item {
    display: flex; align-items: center; width: 100%; min-height: 3rem;
    padding: 0.6rem 0.8rem; text-align: left; cursor: pointer;
    background: var(--color-surface); color: var(--color-text);
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
}
.voz-item:hover { border-color: var(--color-primary); }
.voz-item-txt { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.voz-item-txt strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voz-item-txt small { color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.voz-ayuda { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.8rem; color: var(--color-text-muted); font-size: var(--t-base); }
.voz-ayuda p { margin: 0 0 0.15rem; }

/* Envuelve: con tres botones —«Mejor no», «Sí, mándelo» y «Mejor guárdelo en
   Borradores»— la fila no cabe en un móvil y el tercero se salía de la
   pantalla. */
.voz-acciones { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; margin-top: 1.1rem; max-width: 34rem; }
.voz-acciones .btn { min-width: 7rem; min-height: 2.75rem; }
.voz-acciones .btn svg { width: 1.1rem; height: 1.1rem; }

@media (prefers-reduced-motion: reduce) {
    .voz-capa, .voz-circulo, .voz-circulo::after, .voz-onda { animation: none; }
}

/* La propuesta antes de aceptarla: grande y con pocas palabras. Es lo único
   que separa «me entendió» de «me llenó la agenda». */
.voz-propuesta {
    display: flex; flex-direction: column; gap: 0.3rem; align-items: center;
    width: 100%; max-width: 30rem; margin-top: 0.8rem; padding: 1rem;
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
}
.voz-propuesta-que { font-size: var(--t-md); color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.voz-propuesta-tit { font-size: var(--t-xl); color: var(--color-text); }
.voz-propuesta-cuando { font-size: var(--t-lg); color: var(--color-primary); font-weight: 600; }
/* Lo que el dictado va reconociendo, en vivo. */
.voz-oido { margin: 0.2rem 0 0; max-width: 30rem; font-size: var(--t-lg); color: var(--color-text); min-height: 1.4em; }
/* Diagnóstico del dictado: discreto, pero copiable. */
.voz-diag { margin-top: 0.9rem; max-width: 30rem; width: 100%; }
.voz-diag-abrir { background: none; border: none; color: var(--color-text-muted); font-size: var(--t-md); text-decoration: underline; cursor: pointer; }
.voz-diag-txt { margin: 0.4rem 0; padding: 0.5rem; max-height: 30vh; overflow: auto; white-space: pre-wrap; word-break: break-word; text-align: left; font-size: var(--t-sm); color: var(--color-text-2); background: var(--color-surface-2); border-radius: var(--radius-sm); }
/* Callar al asistente: junto a la equis, pero sin competir con ella. */
.voz-altavoz { position: absolute; top: 0.9rem; right: 3.4rem; color: var(--color-primary); }
.voz-altavoz-off { color: var(--color-text-muted); }
/* El correo antes de mandarlo: se lee, no se adivina. */
.voz-correo { width: 100%; margin-top: 0.5rem; text-align: left; }
.voz-correo-asunto { font-size: var(--t-md); color: var(--color-text-muted); margin-bottom: 0.35rem; }
.voz-correo-cuerpo {
    margin: 0; padding: 0.6rem 0.7rem; max-height: 30vh; overflow-y: auto;
    white-space: pre-wrap; word-break: break-word; color: var(--color-text);
    background: var(--color-surface-2); border-radius: var(--radius-sm);
}
/* Cada teléfono o correo en su renglón: se leen de un vistazo y se copian. */
.voz-item-txt .voz-dato { display: block; }
/* Avisos de Red en el asistente (2026-10-08): el mensaje y la recomendación se
   leen enteros, no cortados con «…» como el resto de renglones. */
.voz-item-txt .voz-red-msj, .voz-item-txt .voz-red-reco { white-space: normal; overflow: visible; }
.voz-item-txt .voz-red-reco { color: var(--color-text); }
.voz-red-sev { font-size: var(--t-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; }
.voz-red-alerta { color: var(--color-danger); }
.voz-red-aviso { color: var(--color-warning); }
.voz-red-info { color: var(--color-text-muted); }
.voz-red-caidos { margin: 0.2rem 0 0.4rem; padding: 0.5rem 0.75rem; border-radius: var(--radius-sm); color: var(--color-danger); background: var(--color-surface-2); }
.voz-propuesta-detalle { font-size: var(--t-base); color: var(--color-text-muted); }
/* Escribir la orden: el campo manda, el botón acompaña. */
.voz-escribir { display: flex; gap: 0.5rem; width: 100%; max-width: 30rem; margin-top: 1rem; }
.voz-escribir-campo { flex: 1; min-width: 0; min-height: 2.75rem; }

/* ── Ver fotos: gestos y pantalla completa ───────────────────────────────
   La imagen es lo que se toca, así que se le quita al navegador el gesto de
   desplazar horizontal: sin esto, deslizar para pasar de foto compite con el
   scroll de la página y a veces gana el scroll. */
/* IA en el visor de fotos ------------------------------------------------ */
.ia-foto { margin: 0 0 0.75rem; }
.ia-foto-opciones { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr)); gap: 0.5rem; }
.ia-foto-op {
    display: flex; flex-direction: column; gap: 0.2rem; text-align: left; padding: 0.65rem 0.8rem;
    border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); color: var(--color-text); cursor: pointer;
}
.ia-foto-op:hover:not(:disabled) { border-color: var(--color-primary); }
.ia-foto-op:disabled { opacity: 0.5; cursor: not-allowed; }
.ia-foto-op span { font-size: var(--t-sm); }
.ia-foto-nota { font-size: var(--t-sm); margin-top: 0.5rem; }
.ia-foto-etq { display: block; font-weight: 600; margin-bottom: 0.35rem; }
.ia-foto-espera { gap: 0.5rem; padding: 1.5rem 0; justify-content: center; }
.ia-foto-botones { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.ia-comparar { position: relative; line-height: 0; border-radius: var(--radius-md); overflow: hidden; background: var(--color-surface-2); }
.ia-comparar-antes { width: 100%; max-height: 65vh; object-fit: contain; display: block; }
/* El «después» se estira sobre el «antes» aunque mida otra cosa: la IA
   devuelve otra resolución, y para comparar tienen que coincidir. */
.ia-comparar-despues { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.ia-comparar-linea { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: #fff; box-shadow: 0 0 4px rgba(0, 0, 0, 0.6); pointer-events: none; }
.ia-comparar-etq { position: absolute; top: 0.5rem; padding: 0.15rem 0.5rem; border-radius: var(--radius-full); font-size: var(--t-xs); line-height: 1.4; background: rgba(0, 0, 0, 0.55); color: #fff; }
.ia-comparar-etq.izq { left: 0.5rem; }
.ia-comparar-etq.der { right: 0.5rem; }
.ia-comparar-rango { width: 100%; margin-top: 0.4rem; }

/* La barra de la vista previa (2026-10-10): Cerrar a la izquierda, el nombre
   se queda con lo que sobre y se RECORTA (antes empujaba los botones fuera en
   el teléfono), y los botones no se encogen nunca. Un toque en el nombre lo
   muestra entero, en varias líneas. */
/* El tamaño de la vista previa. En la PC, 30 % más grande que antes (52rem de
   ancho y 72vh de alto en los visores; lo pidió Jore, 2026-10-10): ancho hasta
   68rem y los visores de PDF, vídeo, CSV y texto hasta casi todo el alto. */
.preview-modal { max-width: min(90vw, 52rem); }
@media (min-width: 769px) {
    .preview-modal { max-width: min(94vw, 68rem); max-height: 96vh; padding: 1.25rem 1.5rem; }
    .preview-modal .pdf-vista,
    .preview-modal .csv-vista,
    .preview-modal .preview-texto-wrap { height: auto; max-height: calc(96vh - 7rem); }
    .preview-modal .pdf-vista { height: calc(96vh - 7rem); }
    .preview-modal .preview-pagina { height: calc(96vh - 9rem); }
    .preview-modal .video-vista video { max-height: calc(96vh - 7rem); }
    /* Una foto vertical cabe entera sin desplazar. */
    .preview-modal .preview-img { display: block; margin: 0 auto; max-height: calc(96vh - 10rem); object-fit: contain; }
}
/* Estirar el visor desde sus esquinas (2026-10-26; previewEstirar). Las asas son
   invisibles: solo el cursor dice que ahí se agarra. Con un tamaño puesto, los
   visores llenan el alto que hay (`--prev-h` lo pone previewTamEstilo). */
.preview-modal { position: relative; }
.preview-asa { position: absolute; width: 16px; height: 16px; z-index: 3; touch-action: none; }
.preview-asa-nw { top: 0; left: 0; cursor: nwse-resize; }
.preview-asa-ne { top: 0; right: 0; cursor: nesw-resize; }
.preview-asa-sw { bottom: 0; left: 0; cursor: nesw-resize; }
.preview-asa-se { bottom: 0; right: 0; cursor: nwse-resize; }
body.preview-estirando { cursor: nwse-resize; user-select: none; }
body.preview-estirando[data-estira=ne], body.preview-estirando[data-estira=sw] { cursor: nesw-resize; }
body.preview-estirando iframe { pointer-events: none; } /* una vista de página no se traga el arrastre */
.preview-modal.estirado .pdf-vista { height: calc(var(--prev-h) - 7rem); max-height: none; }
.preview-modal.estirado .preview-pagina { height: calc(var(--prev-h) - 9rem); max-height: none; }
.preview-modal.estirado .csv-vista,
.preview-modal.estirado .preview-texto-wrap { height: auto; max-height: calc(var(--prev-h) - 6.25rem); }
.preview-modal.estirado .preview-texto { min-height: calc(var(--prev-h) - 6.5rem); }
.preview-modal.estirado .video-vista video,
.preview-modal.estirado .preview-img { max-height: calc(var(--prev-h) - 10rem); }
.preview-modal.estirado .preview-img { display: block; margin: 0 auto; object-fit: contain; }
@media (max-width: 768px) { .preview-asa { display: none; } }
.preview-capa:fullscreen .preview-asa { display: none; }
/* `.fila` se parte en renglones en el teléfono (regla general); esta barra no. */
.fila.preview-barra { flex-wrap: nowrap; gap: 0.4rem; margin-bottom: 0.75rem; min-width: 0; }
.preview-barra > * { flex: none; }
.preview-barra .preview-nombre {
    flex: 1 1 auto; min-width: 0; cursor: default;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.preview-barra .preview-nombre.entero { white-space: normal; overflow-wrap: anywhere; }
.preview-barra .btn-icono { width: 2.1rem; height: 2.1rem; }
/* Los menús de la vista previa: el nombre completo arriba, y alto con tope. */
.preview-menu { min-width: 13rem; max-width: min(20rem, calc(100vw - 16px)); max-height: calc(100vh - 16px); overflow-y: auto; }
.preview-menu-nombre {
    padding: 0.35rem 0.6rem 0.5rem; margin-bottom: 0.25rem;
    border-bottom: 1px solid var(--color-border);
    font-size: var(--t-sm); color: var(--color-text-muted); overflow-wrap: anywhere;
}
/* Girar: la franja que abre «⋮ → Girar», bajo la barra. */
.preview-franja { display: flex; justify-content: center; align-items: center; gap: 0.4rem; margin-bottom: 0.6rem; }
@media (max-width: 768px) {
    /* En el teléfono: solo iconos; Descargar y pantalla completa pasan a «⋮». */
    .preview-barra .preview-etq { display: none; }
    .preview-barra .preview-boton { padding: 0; width: 2.1rem; height: 2.1rem; justify-content: center; }
    .preview-barra .preview-nombre { cursor: pointer; }
    .preview-solo-pc { display: none; }
}
.preview-img {
    max-width: 100%;
    border-radius: var(--radius-md);
    touch-action: pan-y pinch-zoom;
    transform-origin: center center;
    transition: transform 0.12s ease-out;
    will-change: transform;
}
/* En pantalla completa manda la foto: el marco del modal desaparece y la
   imagen ocupa todo, que es justo lo que se pidió al pulsar el botón. */
.preview-capa:fullscreen { background: #000; }
.preview-capa:fullscreen .modal {
    max-width: 100vw !important; width: 100vw; height: 100vh;
    margin: 0; padding: 0.5rem; background: transparent; border: none; box-shadow: none;
    display: flex; flex-direction: column; justify-content: safe center;
}
/* El visor estirado (previewTamEstilo) trae posición y medidas en línea: en
   pantalla completa se anulan, o el marco quedaba más alto que la pantalla y
   se cortaba arriba (Jore, 2026-10-30, en el modo escritorio). */
.preview-capa:fullscreen .modal.estirado {
    position: relative !important; left: auto !important; top: auto !important;
    width: 100vw !important; height: 100vh !important; max-height: 100vh !important; --prev-h: 100vh !important;
}
/* La foto ampliada se recorre con el dedo (previewPan), no con barras de
   desplazamiento del marco: lo que sobresale se recorta. */
.preview-capa:fullscreen .modal:has(> .preview-img) { overflow: hidden; }
.preview-capa:fullscreen .preview-img {
    object-fit: contain;
    border-radius: 0;
}
/* La foto toma solo lo que sobra entre la barra de arriba y la de «− 100 % +»
   de abajo (antes, con un alto calculado a ojo, la de abajo salía cortada). */
.preview-capa:fullscreen .modal:has(> .preview-img) { justify-content: flex-start; }
.preview-capa:fullscreen .modal:has(> .preview-img) > * { flex: none; }
.preview-capa:fullscreen .modal:has(> .preview-img) > .preview-img {
    flex: 1 1 0; min-height: 0; max-height: none; width: 100%; height: auto;
}
.preview-capa:fullscreen .preview-zoom { padding-bottom: .25rem; }
.preview-capa:fullscreen .fila strong { color: #fff; }
/* Documentos a pantalla completa: el visor crece hasta llenar el alto (la
   fila de botones se queda con su renglón). El PDF además se re-renderiza al
   ancho nuevo (reajustarPreview); estos solo son fluidos. */
.preview-capa:fullscreen .pdf-vista,
.preview-capa:fullscreen .csv-vista,
.preview-capa:fullscreen .preview-pagina,
.preview-capa:fullscreen .preview-texto {
    height: calc(100vh - 4rem);
    max-height: calc(100vh - 4rem);
    overflow-y: auto;
}
@media (prefers-reduced-motion: reduce) {
    .preview-img { transition: none; }
}

/* ── Ordenar: en la cabecera, no en la barra de arriba ───────────────────
   En el móvil, con el menú arriba, los botones no cabían en un renglón y la
   barra se partía en dos. Va al extremo derecho del renglón de «Nombre» — y NO
   en la columna de acciones, que en el móvil se oculta entera y se lo llevaba
   con ella. */
.file-list-table th.th-nombre-orden {
    display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
}
/* El título sigue ordenando por nombre al pulsarlo, como siempre. */
.file-list-table th.th-nombre-orden > span:first-child { cursor: pointer; }
.menu-orden { display: inline-block; vertical-align: middle; }
.menu-orden .btn { font-weight: 400; }
/* El desplegable se alinea a la DERECHA de su botón: pegado al borde de la
   pantalla, uno abierto a la izquierda se sale. */
.menu-pop-der { left: auto; right: 0; }

/* La galería no tiene cabecera donde colgarlo: un renglón fino propio. */
.barra-orden-galeria { display: flex; justify-content: flex-end; padding: 0.25rem 0 0.4rem; }

/* ── Saltar de mes y de año ──────────────────────────────────────────────
   Antes solo se avanzaba de mes en mes: un cumpleaños del año pasado eran
   doce toques. Se abre desde el propio título, que es donde se busca. */
.cal-salto-wrap { display: inline-flex; }
.cal-titulo-btn {
    display: inline-flex; align-items: center; gap: 0.3rem;
    background: none; border: none; padding: 0.1rem 0.3rem; border-radius: var(--radius-sm);
    color: inherit; font: inherit; cursor: pointer;
}
.cal-titulo-btn:hover { background: var(--color-surface-2); }
.cal-salto { min-width: 15rem; padding: 0.6rem; }
.cal-salto-anio {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.5rem; margin-bottom: 0.5rem; font-size: var(--t-xl);
}
.cal-salto-meses { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.3rem; }
.cal-salto-mes {
    padding: 0.5rem 0.2rem; min-height: 2.4rem; cursor: pointer;
    background: var(--color-surface-2); color: var(--color-text);
    border: 1px solid transparent; border-radius: var(--radius-sm);
    text-transform: capitalize; font-size: var(--t-md);
}
.cal-salto-mes:hover { border-color: var(--color-primary); color: var(--color-primary); }
.cal-salto-mes.activo { background: var(--color-primary); color: var(--color-primary-fg); }

/* ── Redactar sin quedarse encerrado ─────────────────────────────────────
   El redactor es `fixed; inset: 0`: tapa la pantalla entera, navegación
   incluida, así que no había forma de mirar un archivo o una nota a media
   redacción. Apartado, se esconde sin desmontarse —lo escrito vive en el DOM
   del editor— y deja una barra abajo para volver. */
.buzon-redactar.minimizado { display: none; }

.correo-apartado {
    position: fixed; z-index: 61;
    right: 1rem; bottom: calc(1rem + env(safe-area-inset-bottom));
    display: flex; align-items: center; gap: 0.6rem;
    max-width: min(22rem, calc(100vw - 2rem));
    padding: 0.6rem 0.75rem; cursor: pointer; text-align: left;
    background: var(--color-surface); color: var(--color-text);
    border: 1px solid var(--color-border); border-radius: var(--radius-lg);
    box-shadow: 0 4px 18px var(--color-shadow);
}
.correo-apartado:hover { border-color: var(--color-primary); }
.correo-apartado-ic { flex: none; display: flex; color: var(--color-primary); }
.correo-apartado-ic svg { width: 1.2rem; height: 1.2rem; }
.correo-apartado-txt { display: flex; flex-direction: column; min-width: 0; }
.correo-apartado-txt strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.correo-apartado-txt small { color: var(--color-text-muted); }
.correo-apartado-cerrar { flex: none; display: flex; color: var(--color-text-muted); border-radius: var(--radius-sm); }
.correo-apartado-cerrar:hover { color: var(--color-danger); }
.correo-apartado-cerrar svg { width: 1rem; height: 1rem; }

/* En el móvil, por encima de la barra de secciones de abajo. */
@media (max-width: 768px) {
    .correo-apartado { right: 0.75rem; left: 0.75rem; bottom: calc(4.5rem + env(safe-area-inset-bottom)); max-width: none; }
}

/* El tamaño del correo, solo al ordenar por tamaño: es entonces cuando sirve
   —y cuando hace falta para ver que la lista está bien ordenada—. */
.buzon-tam { font-size: var(--t-sm); color: var(--color-text-muted); white-space: nowrap; }

/* Choque de dos guardados: las dos versiones lado a lado. En el teléfono se
   apilan —a 44rem en una columna de 20rem no se lee ninguna de las dos— y el
   texto se recorta con scroll propio para que los botones de elegir no se vayan
   fuera de la pantalla con una nota larga. */
.nota-conflicto { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin: 0.75rem 0; }
.nota-conflicto-lado { min-width: 0; border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.5rem 0.6rem; }
.nota-conflicto-lado h3 { margin: 0 0 0.35rem; font-size: var(--t-sm); text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); }
.nota-conflicto-tit { margin: 0 0 0.25rem; font-weight: 600; }
.nota-conflicto-txt { margin: 0; max-height: 30vh; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; font-size: var(--t-base); }
@media (max-width: 640px) { .nota-conflicto { grid-template-columns: 1fr; } }

/* De quién es una nota compartida. Discreto: es un dato de contexto, no una
   alarma; compite con el texto de la nota y debe perder. */
.nota-compartida-pie,
.nota-compartida-aviso { display: flex; align-items: center; gap: 0.35rem; font-size: var(--t-sm); color: var(--color-text-muted); }
.nota-compartida-pie { margin-top: 0.35rem; }
.nota-compartida-aviso { margin: 0.1rem 0 0.5rem; }
.nota-compartida-pie svg,
.nota-compartida-aviso svg { width: 0.9em; height: 0.9em; }

/* Aviso de que los adjuntos de una nota no viajan con ella al compartirla.
   Se marca con la franja de advertencia y no con el rojo de error: no es un
   fallo, es algo que hay que saber ANTES de pulsar «Compartir». */
.nota-aviso-adjuntos {
    margin: 0.6rem 0 0; padding: 0.5rem 0.65rem; font-size: var(--t-sm); line-height: 1.4;
    border-left: 3px solid var(--color-warning);
    background: color-mix(in srgb, var(--color-warning) 10%, transparent);
    border-radius: var(--radius-sm, 4px);
}

/* Las dos horas de la franja de avisos, lado a lado. En el teléfono se apilan:
   dos campos de hora en una columna estrecha se quedan sin sitio para el
   selector nativo. */
.ventana-horas { display: flex; gap: 0.75rem; margin-top: 0.5rem; flex-wrap: wrap; }
.ventana-horas .campo { flex: 1 1 8rem; min-width: 0; margin: 0; }

/* ── Calendario: conmutador Mes / Agenda ──────────────────────────────────
   Un par de botones pegados que se leen como un solo control, con el activo
   marcado. En el teléfono el texto se va (`.cal-nuevo-txt`, como el resto de
   la barra) y quedan los iconos. */
.cal-vista-sw { display: inline-flex; border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.cal-vista-b { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.3rem 0.6rem; background: none; border: 0; color: var(--color-text-2); cursor: pointer; font: inherit; font-size: var(--t-md); }
.cal-vista-b + .cal-vista-b { border-left: 1px solid var(--color-border); }
.cal-vista-b:hover { background: var(--color-surface-2); }
.cal-vista-b.activo { background: var(--color-primary); color: #fff; }
.cal-vista-b svg { width: 1em; height: 1em; }

/* ── Calendario: la agenda ────────────────────────────────────────────── */
.cal-busq-cab { align-items: center; margin-bottom: 0.6rem; }
.cal-busq-cab h3 { margin: 0; font-size: var(--t-lg); }
.cal-busq-ayuda { font-size: var(--t-sm); margin-top: 0.6rem; }
.cal-agenda-cab { display: flex; align-items: flex-end; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.7rem; }
.cal-agenda-rango { max-width: 12rem; }
.cal-agenda-fechas { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.cal-agenda-fechas label { display: flex; flex-direction: column; gap: 0.15rem; font-size: var(--t-sm); color: var(--color-text-2); }
/* La tabla se desplaza DENTRO de su caja: sin esto, con un lugar largo el
   documento entero se iba de lado en el teléfono. */
.cal-agenda-caja { overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius-md); }
.cal-agenda { width: 100%; border-collapse: collapse; font-size: var(--t-base); }
.cal-agenda th { text-align: left; font-weight: 600; padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--color-border); white-space: nowrap; }
.cal-agenda td { padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--color-border); vertical-align: top; }
.cal-agenda tbody tr { cursor: pointer; border-left: 3px solid var(--c); }
.cal-agenda tbody tr:hover,
.cal-agenda tbody tr:focus-visible { background: color-mix(in srgb, var(--c) 12%, transparent); outline: none; }
.cal-agenda tbody tr:last-child td { border-bottom: 0; }
/* `tabular-nums` para que las fechas queden en columna y no bailen. */
.cal-ag-fecha { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--color-text-2); }
.cal-ag-tit { font-weight: 600; }
.cal-ag-sub { display: none; }
@media (max-width: 768px) {
    /* En el teléfono no caben cuatro columnas: se quitan las dos últimas y lo
       suyo baja bajo el título, que si no se perdería sin más. */
    .cal-agenda .col-lugar,
    .cal-agenda .col-cal { display: none; }
    .cal-ag-sub { display: block; font-weight: 400; font-size: var(--t-sm); color: var(--color-text-2); margin-top: 0.15rem; }
}

/* ── Correo: tamaño de letra en el menú «Ver» ─────────────────────────── */
.buzon-letra-fila { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; cursor: default; }
.buzon-letra-ctl { display: inline-flex; align-items: center; gap: 0.35rem; }
.buzon-letra-ctl .btn-icono { font-size: var(--t-sm); font-weight: 700; width: 1.9rem; }
/* Tabulares para que el 85% y el 130% midan lo mismo y los botones no bailen. */
.buzon-letra-pct { min-width: 2.9rem; text-align: center; font-variant-numeric: tabular-nums; font-size: var(--t-md); color: var(--color-text-muted); }

/* ── Correo: el árbol de carpetas del móvil, como panel lateral ──────────
   En escritorio no existe (.buzon-carpetas-movil se oculta a ≥769px), así que
   estas reglas solo actúan en el teléfono. El panel sale de la izquierda a
   toda altura; el telón oscurece la lista para que se lea como capa, no como
   un desplegable que empuja el contenido. */
@media (max-width: 768px) {
    .buzon-arbol-fondo {
        position: fixed; inset: 0; z-index: 59;
        background: color-mix(in srgb, #000 45%, transparent);
    }
    .buzon-carpetas-movil .buzon-arbol {
        position: fixed; top: 0; bottom: 0; left: 0; right: 22%;
        max-width: 22rem; max-height: none; z-index: 60;
        margin: 0; border: 0; border-right: 1px solid var(--color-border);
        border-radius: 0; padding: 0.8rem 0.6rem;
        padding-top: calc(0.8rem + env(safe-area-inset-top));
        padding-bottom: calc(0.8rem + env(safe-area-inset-bottom));
        overflow-y: auto; overscroll-behavior: contain;
        box-shadow: var(--shadow-lg, 0 8px 32px rgba(0,0,0,.35));
        transition: transform 0.15s ease-out;
        /* El arrastre de cierre pone transform en línea; esta transición hace
           que al soltar sin llegar al umbral, vuelva suave a su sitio. */
    }
}
@media (min-width: 769px) { .buzon-arbol-fondo { display: none; } }
/* «Empezar por las carpetas»: el panel pasa a PANTALLA, como en Aqua Mail. A
   todo lo ancho y, como el lector, dejando libre la tabbar de abajo. */
@media (max-width: 768px) {
    .buzon-carpetas-movil .buzon-arbol.buzon-arbol-pantalla {
        right: 0; max-width: none; box-shadow: none; border-right: 0;
        /* Debajo de la barra de arriba, como el lector y el resto de los módulos:
           tapándola no se veían sus opciones (Jore, 2026-10-29). */
        top: var(--navbar-real, var(--navbar-height)); padding-top: 0.8rem;
        bottom: calc(3.9rem + env(safe-area-inset-bottom));
        padding-bottom: 0.8rem; background: var(--color-bg);
        /* Fija: solo se desplaza hacia abajo, nunca de lado. */
        overflow-x: hidden; touch-action: pan-y; transform: none !important;
    }
}
.buzon-arbol-pantalla-cab { display: flex; align-items: baseline; gap: 0.6rem; padding: 0.2rem 0.4rem 0.8rem; flex-wrap: wrap; }
.buzon-arbol-pantalla-tit { font-size: var(--t-2xl); font-weight: 700; }
.buzon-arbol-pantalla-cuenta { font-size: var(--t-md); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-arbol-pantalla .buzon-nodo-lbl { padding-top: 0.55rem; padding-bottom: 0.55rem; }

/* El «Aa» de la barra del correo: texto y no icono —es exactamente lo que
   significa— con las mismas medidas que sus vecinos .btn-icono. Marcado
   `activo` cuando el tamaño no es el de fábrica, para que se vea de dónde
   viene una letra rara. */
.buzon-letra-aa { font-size: var(--t-md); font-weight: 700; letter-spacing: -0.02em; }
/* «Aa» fuera de su tamaño normal y el fondo «papel» puesto: se ven ENCENDIDOS.
   ⚠️ No hay regla `.activo` genérica para `.btn-icono` (lo avisan los comentarios de
   `.buzon-btn-filtro` y `.nav-usuario`): sin esto, el `:class="… && 'activo'"` de la
   plantilla no pintaba nada, y un ajuste puesto que no se ve deja sin saber por qué la
   letra está chica o el correo gris. */
.buzon-letra-aa.activo,
.buzon-fondo-btn.activo { color: var(--color-primary); }
.buzon-fondo-btn.activo svg { stroke: currentColor; }

/* Las tarjetas de los ajustes del correo: una por asunto dentro de su pestaña.
   Apiladas con aire, sin las rayas separadoras que hacían muro. */
.ajustes-tarjeta { margin-bottom: 0.8rem; }
.ajustes-tarjeta:last-child { margin-bottom: 0; }
.ajustes-tarjeta h3 { margin-top: 0; }

/* ── Importar filtros: la vista previa ─────────────────────────────────── */
.regla-imp-check { display: flex; align-items: center; padding-right: 0.5rem; }
.regla-imp-mala { opacity: 0.75; }
/* El motivo de lo intraducible, en el color de aviso: es información, no error. */
.regla-imp-motivo { font-size: var(--t-sm); color: var(--color-warning); }
.regla-imp-carpeta { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.3rem; }
.regla-imp-carpeta .select { max-width: 18rem; }

/* El «Aa» del correo: la variable la fija la raíz de la pantalla y aquí se
   consume. `zoom` y no font-size —encoge también avatares y márgenes, que es lo
   que hace caber más correos—, y por variable y no por :style en línea porque
   x-show y :style pelean por el mismo atributo (ver el comentario en el HTML). */
.buzon-lista,
.buzon-pane-tree.file-tree { zoom: var(--buzon-zoom, 1); }
/* ⚠️ El panel de carpetas del móvil es position:fixed, y `zoom` sobre una caja
   fija DESCOLOCA la caja (Chrome escala también sus coordenadas: el contenido
   se corría y los nombres quedaban fuera de pantalla — 2026-08-24). Se escala
   lo de DENTRO y la caja fija se queda quieta. */
.buzon-carpetas-movil .buzon-arbol > * { zoom: var(--buzon-zoom, 1); }

/* El «Aa» de Archivos: encoge la LISTA, la galería y el árbol — nunca la
   cabecera sticky ni la barra de selección (zoom en sticky/fixed los
   desplaza; la mina de siempre). */
.tabla-gestor { zoom: var(--gestor-zoom, 1); }
aside.sidebar.file-tree > * { zoom: var(--gestor-zoom, 1); }

/* «Mis carpetas» encabeza el bloque de las carpetas propias, y va alineado con
   los buzones inteligentes de arriba: la flecha ocupa el lugar del icono, así
   que se le da el ancho de un icono y no el de una flecha (2026-08-29). */
.file-tree .nodo-propio-cab .twisty { width: 1rem; }
.buzon-pane-tree .buzon-propio-cab .buzon-nodo-tog { width: 1.15rem; min-width: 0; }

/* En el teléfono la cinta va en la tira de botones que se desplaza, y con el
   correo completo empujaba la campanita fuera de la pantalla (2026-08-29, lo
   vio Jore). Ahí basta el nombre del buzón —«Ventas»—: la dirección entera se
   queda para la pantalla grande, donde sí cabe. */
@media (max-width: 768px) {
    /* La dirección ya no se pinta en ninguna parte (va en el título), así que
       aquí solo queda el tope de ancho, más apretado que en escritorio. */
    .buzon-equipo-cinta { max-width: 42vw; }
}

/* Lo que llega por Mensajes se mira en el propio hilo: vídeo y audio con su
   reproductor, y debajo el nombre y el menú del archivo (2026-08-29). */
.msg-video { display: block; max-width: min(22rem, 100%); max-height: 60vh; border-radius: var(--radius-sm); background: #000; }
.msg-audio { display: block; width: min(18rem, 100%); margin: 0.15rem 0; }
.msg-archivo-menu { display: flex; align-items: center; gap: 0.25rem; position: relative; margin-top: 0.15rem; }
.msg-archivo-nom-medio { font-size: var(--t-sm); color: var(--color-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
/* ⚠️ EL MENÚ ABRE HACIA EL LADO LIBRE, Y ESE LADO LO DICE DE QUIÉN ES EL
   MENSAJE. Se ancla a la BURBUJA, que es estrecha —lo ancho es el menú—, así
   que anclarlo siempre a la derecha lo mandaba 117 px fuera del hilo en los
   mensajes RECIBIDOS (medido en navegador, 2026-09-03: la burbuja de un
   recibido está pegada al borde izquierdo y el menú salía por detrás de él).
   `.msg-hilo` desplaza, o sea que RECORTA: lo que se sale no se ve, y no hay
   forma de llegar a esas opciones.
   Recibido → pegado a su izquierda, crece hacia la derecha. Propio → al revés.
   El `max-width` es el seguro para un hilo muy estrecho: antes de salirse,
   encoge. */
/* El ⋮ de un archivo que NO es medio va al final de su renglón, junto al
   nombre: debajo parecía un botón suelto sin dueño. Con una foto o un vídeo
   sigue en su propia línea —ahí abajo está el nombre— para no taparlos.
   El `~` distingue los dos casos sin tocar la plantilla: solo hay un
   `.msg-archivo` delante cuando el adjunto NO es medio. */
.msg-archivo { display: inline-flex; vertical-align: middle; }
.msg-archivo ~ .msg-archivo-menu {
    display: inline-flex; vertical-align: middle;
    margin-top: 0; margin-left: 0.15rem;
    /* ⚠️ SIN `position` PROPIA A PROPÓSITO: así el menú se ancla a la BURBUJA y
       no a este botón, que ahora mide dos dedos. Anclado al botón volvería a
       salirse del hilo, que es justo lo que se acaba de arreglar. */
    position: static;
}
.msg-burbuja.suyo .msg-archivo-menu .menu-pop { left: 0; right: auto; }
.msg-burbuja.mio .msg-archivo-menu .menu-pop { right: 0; left: auto; }
.msg-archivo-menu .menu-pop { max-width: min(16rem, 100vw - 2.5rem); }
/* Hacia arriba cuando abajo no cabe. Lo decide `msgMenuArchivo()` midiendo el
   hueco: en el CSS no se puede saber, depende de dónde esté el mensaje. */
.msg-archivo-menu .menu-pop.arriba { top: auto; bottom: calc(100% + 0.35rem); }
.video-convertir { display: flex; flex-direction: column; gap: 0.4rem; align-items: center; padding: 0.6rem; }
.video-convertir p { margin: 0; font-size: var(--t-md); }
/* «Subir de mi dispositivo» dentro del selector de archivos de Mensajes. */
.picker-subir { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; padding: 0.4rem 0 0.6rem; border-bottom: 1px solid var(--color-border); margin-bottom: 0.5rem; }
.picker-subir-pista { font-size: var(--t-sm); color: var(--color-text-2); }

/* En el árbol del correo el puntito de una etiqueta ocupa el lugar de un icono:
   si no, su nombre sale 6 px a la izquierda de «Hoy» o «Marcados» y el renglón
   parece descuadrado (2026-08-30). El puntito sigue igual de chico; lo que se
   iguala es el hueco. */
.buzon-pane-tree .buzon-tag-dot, .file-tree .buzon-tag-dot {
    width: 1rem; height: 1rem; background-clip: content-box; padding: 0.19rem;
}
/* Rótulo de sección con su botón a la derecha (administrar etiquetas). */
.buzon-sep-acc { display: flex; align-items: center; gap: 0.4rem; }
.buzon-sep-acc > span { flex: 1; min-width: 0; }
.buzon-sep-acc .btn-icono { opacity: .55; }
.buzon-sep-acc .btn-icono:hover { opacity: 1; }

/* En el teléfono, el lápiz de una etiqueta y el del rótulo son la ÚNICA manera
   de editarla: el menú del clic derecho no existe en pantallas táctiles. Se les
   da tamaño de dedo y se ven siempre (2026-08-30, lo topó Jore). */
@media (pointer: coarse) {
    .buzon-arbol .buzon-folder-leer,
    .buzon-pane-tree .buzon-folder-leer,
    .buzon-sep-acc .btn-icono { min-width: 2.25rem; min-height: 2.25rem; opacity: 0.85; }
    .buzon-arbol .buzon-folder-leer svg,
    .buzon-pane-tree .buzon-folder-leer svg,
    .buzon-sep-acc .btn-icono svg { width: 1.05rem; height: 1.05rem; }
}

/* ── Responder a un mensaje ───────────────────────────────────────────
   La cita va DENTRO de la burbuja y en tono menor: es contexto, no el
   mensaje. Con su barrita a la izquierda, como en cualquier mensajería. */
.msg-cita {
    display: block; width: 100%; text-align: left; margin: 0 0 0.3rem; padding: 0.25rem 0.5rem;
    background: color-mix(in srgb, var(--color-text) 8%, transparent);
    border-left: 3px solid color-mix(in srgb, var(--color-primary) 70%, transparent);
    border-radius: var(--radius-sm); border-top: 0; border-right: 0; border-bottom: 0;
    cursor: pointer; font-size: var(--t-sm); line-height: 1.25;
}
.msg-cita-autor { display: block; font-weight: 700; opacity: 0.85; }
.msg-cita-txt { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; opacity: 0.8; }
.msg-destacado { animation: msg-parpadeo 1.6s ease-out; }
@keyframes msg-parpadeo {
    0%, 40% { background: color-mix(in srgb, var(--color-primary) 35%, transparent); }
    100% { background: transparent; }
}
.msg-respondiendo {
    display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.75rem;
    border-top: 1px solid var(--color-border); background: var(--color-surface-2);
    font-size: var(--t-md);
}
.msg-resp-eti { font-weight: 600; flex: none; }
.msg-resp-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-2); }
/* La llamada dentro del hilo: un aviso con su botón, no un mensaje más. */
.msg-llamada { margin-top: 0.35rem; }

/* ── Soporte: la lista de expedientes y su detalle ─────────────────────
   Tres columnas en escritorio (vistas · lista · detalle) y una sola en el
   teléfono, donde el detalle tapa a la lista. */
/* La pantalla de tickets es UNA sola columna: la lista ocupa todo el ancho y,
   al abrir un expediente, la lista se aparta. Es como se lee un helpdesk —y
   como lo leían en el sistema anterior—: primero la tabla, luego el caso. */
/* `min-width: 0` no es adorno: como ítem de la rejilla de la aplicación, sin
   esto la tabla ancha ESTIRA la pantalla entera y saca la barra horizontal en
   el teléfono, en vez de deslizarse dentro de su caja. */
.tk-cuerpo { display: block; padding: 1rem; min-width: 0; }
.tk-barra { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-bottom: .8rem; }
.tk-fichas { display: flex; flex-wrap: wrap; gap: .4rem; }
.tk-ficha { display: inline-flex; align-items: center; gap: .45rem; padding: .4rem .75rem; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text); border-radius: var(--radius-sm); cursor: pointer; }
.tk-ficha:hover { border-color: var(--color-primary); }
.tk-ficha.activa { border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; box-shadow: inset 0 0 0 1px var(--color-primary); }
.tk-num { font-size: var(--t-sm); opacity: .75; font-variant-numeric: tabular-nums; }
.tk-buscar { max-width: 20rem; }
.tk-cola-filtro { max-width: 12rem; }
/* Red · Resumen: el nombre del router completo (Jore, 2026-10-07). */
.tk-cola-filtro.red-sel-router { max-width: 26rem; width: auto; }
.tk-lista { min-width: 0; }
.tk-tabla-caja { overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); }
.tk-tabla { width: 100%; border-collapse: collapse; font-size: var(--t-base); }
.tk-tabla th { text-align: left; background: var(--color-surface-2); border-bottom: 1px solid var(--color-border); white-space: nowrap; }
.tk-th { display: inline-flex; align-items: center; gap: .3rem; width: 100%; padding: .5rem .6rem; border: 0; background: none; color: var(--color-text-2); font: inherit; font-size: var(--t-xs); letter-spacing: .04em; text-transform: uppercase; cursor: pointer; }
.tk-th:hover { color: var(--color-primary); }
.tk-orden { font-size: var(--t-2xs); }
.tk-tr { border-bottom: 1px solid var(--color-border); cursor: pointer; }
.tk-tr:hover { background: color-mix(in srgb, var(--color-primary) 6%, transparent); }
.tk-tabla td { padding: .5rem .6rem; vertical-align: top; }
.tk-col-id { white-space: nowrap; }
.tk-col-fecha { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--color-text-2); }
.tk-col-asunto { min-width: 14rem; }
.tk-col-nombre, .tk-col-ultima, .tk-col-resp { min-width: 8rem; }
.tk-col-correo span, .tk-col-org span { display: inline-block; max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.tk-filtros { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; margin-bottom: .8rem; padding: .6rem .8rem; background: var(--color-surface-2); border-radius: var(--radius-sm); }
.tk-filtros-tit { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-2); }
.tk-check { display: inline-flex; align-items: center; gap: .35rem; cursor: pointer; }
.tk-check input { width: 1rem; height: 1rem; }
.tk-porpagina { display: inline-flex; align-items: center; gap: .4rem; font-size: var(--t-md); }
.tk-porpagina .input { width: 5rem; padding: .25rem .4rem; }
.tk-lote { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-bottom: .8rem; padding: .6rem .8rem; border: 1px solid var(--color-primary); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--color-primary) 8%, var(--color-surface)); }
.tk-lote .input { width: auto; min-width: 8rem; padding: .3rem .5rem; }
.tk-col-sel { width: 2.2rem; }
.tk-col-sel input { width: 1rem; height: 1rem; }
.tk-tr.marcada { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.tk-pie { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .6rem; font-size: var(--t-md); }
.tk-paginador { display: flex; align-items: center; gap: .2rem; }
.tk-pag { min-width: 2rem; padding: .3rem .5rem; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text); border-radius: var(--radius-sm); cursor: pointer; font-variant-numeric: tabular-nums; }
.tk-pag:hover:not(:disabled) { border-color: var(--color-primary); color: var(--color-primary); }
.tk-pag.activa { background: var(--color-primary); border-color: var(--color-primary); color: #fff; font-weight: 600; }
.tk-pag:disabled { opacity: .4; cursor: default; }
/* «IPs bloqueadas» (2026-10-30): el cuadrito para ir a una página. */
.red-ips-ir { display: inline-flex; margin: 0; }
.red-ips-ir .input { width: 4.5rem; padding: .3rem .4rem; text-align: center; font-variant-numeric: tabular-nums; }
.tk-hueco { padding: 0 .2rem; color: var(--color-text-2); }
.tk-folio { font-variant-numeric: tabular-nums; font-weight: 700; }
.tk-ref { display: block; font-size: var(--t-xs); color: var(--color-text-2); }
.tk-asunto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* EL ESTADO SE LEE POR COLOR ANTES QUE POR PALABRA. Cada uno tiene el suyo y
   siempre el mismo, aquí y en las gráficas: azul lo que acaba de entrar, verde
   lo que alguien está atendiendo, ámbar lo que espera al cliente —la pelota
   está fuera— y gris lo terminado. El relleno es tenue a propósito: son
   docenas de renglones, y un color pleno en cada uno cansa y deja de avisar. */
.tk-chip { font-size: var(--t-xs); padding: .1rem .5rem; border-radius: 999px; border: 1px solid var(--color-border); white-space: nowrap; font-weight: 600; }
.tk-nuevo { border-color: var(--color-primary); color: #1d4ed8; background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.tk-atendiendo { border-color: var(--color-success); color: #15803d; background: color-mix(in srgb, var(--color-success) 12%, transparent); }
.tk-esperando { border-color: var(--color-warning); color: #b45309; background: color-mix(in srgb, var(--color-warning) 14%, transparent); }
.tk-resuelto { border-color: #0d9488; color: #0f766e; background: color-mix(in srgb, #0d9488 12%, transparent); }
.tk-cerrado { border-color: #94a3b8; color: #475569; background: color-mix(in srgb, #94a3b8 16%, transparent); }
/* En oscuro el texto se aclara: el mismo tono sobre fondo oscuro no se lee. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .tk-nuevo { color: #93c5fd; }
    :root:not([data-theme="light"]) .tk-atendiendo { color: #86efac; }
    :root:not([data-theme="light"]) .tk-esperando { color: #fcd34d; }
    :root:not([data-theme="light"]) .tk-resuelto { color: #5eead4; }
    :root:not([data-theme="light"]) .tk-cerrado { color: #cbd5e1; }
}
:root[data-theme="dark"] .tk-nuevo { color: #93c5fd; }
:root[data-theme="dark"] .tk-atendiendo { color: #86efac; }
:root[data-theme="dark"] .tk-esperando { color: #fcd34d; }
:root[data-theme="dark"] .tk-resuelto { color: #5eead4; }
:root[data-theme="dark"] .tk-cerrado { color: #cbd5e1; }
/* La franja del renglón repite el color del estado: de un vistazo se ve el
   reparto de la lista sin leer una sola palabra. */
.tk-tr td:first-child { border-left: 3px solid transparent; }
.tk-fila-nuevo td:first-child { border-left-color: var(--color-primary); }
.tk-fila-atendiendo td:first-child { border-left-color: var(--color-success); }
.tk-fila-esperando td:first-child { border-left-color: var(--color-warning); }
.tk-fila-resuelto td:first-child { border-left-color: #0d9488; }
.tk-fila-cerrado td:first-child { border-left-color: #94a3b8; }
/* La prioridad se lee por color antes que por palabra, como en el sistema
   anterior: rojo lo que urge, ámbar lo alto, verde lo normal, gris lo que puede
   esperar. */
.tk-prio::before { content: ''; display: inline-block; width: .55rem; height: .55rem; border-radius: 2px; margin-right: .35rem; background: currentColor; vertical-align: baseline; }
.tk-p-urgente { border-color: var(--color-danger); color: var(--color-danger); font-weight: 600; }
.tk-p-alta { border-color: var(--color-warning); color: var(--color-warning); font-weight: 600; }
.tk-p-normal { border-color: var(--color-success); color: var(--color-success); }
.tk-p-baja { border-color: #94a3b8; color: #64748b; }
/* El expediente: hilo a la izquierda, lo que se cambia a la derecha. */
.tk-detalle { min-width: 0; }
.tk-exp-barra { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-bottom: .8rem; }
.tk-exp-barra strong { font-size: var(--t-xl); }
.tk-exp { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: 1rem; align-items: start; }
.tk-hilo { display: flex; flex-direction: column; gap: .7rem; min-width: 0; }
.tk-lado { display: flex; flex-direction: column; gap: .7rem; min-width: 0; }
.tk-tarjeta { border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); padding: .9rem 1rem; }
.tk-tarjeta-tit { margin: 0 0 .5rem; font-size: var(--t-lg); }
.tk-contacto { display: grid; grid-template-columns: auto 1fr; gap: .2rem .7rem; margin: 0 0 .6rem; }
.tk-contacto dt { font-size: var(--t-sm); color: var(--color-text-2); }
.tk-contacto dd { margin: 0; font-size: var(--t-base); overflow-wrap: anywhere; }
.tk-cuando { font-size: var(--t-sm); margin: .4rem 0 0; }
.tk-msg-cab { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem; margin-bottom: .35rem; font-size: var(--t-base); }
.tk-msg-cliente { background: var(--color-surface-2); }
.tk-msg-nota { border-left: 3px solid var(--color-warning); }
.tk-msg-cambio { padding: .4rem 1rem; font-size: var(--t-md); color: var(--color-text-2); background: transparent; border-style: dashed; }
.tk-etiq { font-size: var(--t-xs); padding: .05rem .4rem; border-radius: 999px; background: var(--color-warning); color: #fff; }
.tk-aviso { margin: 0 0 .7rem; padding: .5rem .7rem; border-left: 3px solid var(--color-warning); background: color-mix(in srgb, var(--color-warning) 10%, transparent); font-size: var(--t-base); }
.tk-opciones { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin-top: .5rem; }
.tk-opciones .input { width: auto; padding: .25rem .4rem; }
.tk-enlace { display: block; border: 0; background: none; padding: .1rem 0 .6rem; color: var(--color-primary); cursor: pointer; font: inherit; font-size: var(--t-md); text-align: left; text-decoration: underline; }
.tk-lado .campo { display: block; margin-bottom: .5rem; }
.tk-lado .campo > span { display: block; font-size: var(--t-sm); color: var(--color-text-2); margin-bottom: .15rem; }
.tk-detalles { display: grid; grid-template-columns: auto 1fr; gap: .3rem .7rem; margin: 0; }
.tk-detalles dt { font-size: var(--t-sm); color: var(--color-text-2); }
.tk-detalles dd { margin: 0; font-size: var(--t-md); overflow-wrap: anywhere; }
.tk-historial { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .25rem; }
.tk-historial button { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; width: 100%; padding: .3rem .4rem; border: 0; border-radius: var(--radius-sm); background: none; color: var(--color-text); text-align: left; font: inherit; font-size: var(--t-md); cursor: pointer; }
.tk-historial button:hover { background: var(--color-surface-2); }
/* El compromiso (Fase 3): lo vencido y lo que vence hoy se leen por color
   antes que por número, que es de lo que sirve una alarma. */
.tk-ficha-aviso { border-color: var(--color-warning); color: var(--color-warning); }
.tk-ficha-alarma { border-color: var(--color-danger); color: var(--color-danger); font-weight: 600; }
.tk-col-vence { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--color-text-2); }
.tk-vencido { color: var(--color-danger); font-weight: 600; }
.tk-porvencer { color: var(--color-warning); font-weight: 600; }
.tk-informes { min-width: 0; }
.tk-cifras { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: .7rem; margin-bottom: 1rem; }
.tk-cifra { display: flex; flex-direction: column; gap: .1rem; padding: .8rem .9rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); font-size: var(--t-sm); color: var(--color-text-2); }
.tk-cifra-n { font-size: var(--t-3xl); font-weight: 700; color: var(--color-text); font-variant-numeric: tabular-nums; }
.tk-graficas { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: .7rem; align-items: start; }
.tk-fila-barra { display: grid; grid-template-columns: 8rem minmax(0, 1fr) 2.5rem; gap: .5rem; align-items: center; margin-bottom: .3rem; font-size: var(--t-md); }
.tk-barra-etq { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-2); }
/* OJO: la pista de la barra NO puede llamarse `.tk-barra` — así se llama ya la
   barra de herramientas de la pantalla, y la regla la aplastaba (la
   herramienta quedaba de 11 px de alto, con sus botones fuera). */
.tk-barra-pista { display: block; height: .7rem; background: var(--color-surface-2); border-radius: 4px; overflow: hidden; }
.tk-barra-in { display: block; height: 100%; background: var(--color-primary); border-radius: 4px; }
.tk-barra-bien { background: var(--color-success); }
.tk-barra-regular { background: var(--color-warning); }
.tk-barra-mal { background: var(--color-danger); }
.tk-barra-n { text-align: right; font-variant-numeric: tabular-nums; }
.tk-opinion { margin: .2rem 0; font-size: var(--t-md); }
/* Por dónde va la respuesta, dicho junto al cuadro: no es lo mismo escribir en
   una conversación que mandar un correo, y quien contesta debe saber cuál. */
.tk-canal { font-size: var(--t-sm); color: var(--color-text-2); }
/* Los archivos del expediente: los del hilo se bajan, los sueltos se eligen
   para que salgan con la próxima respuesta. */
.tk-archivo { display: inline-flex; align-items: center; gap: .35rem; margin: .3rem .4rem 0 0; padding: .2rem .5rem; border: 1px solid var(--color-border); border-radius: 999px; font-size: var(--t-sm); color: var(--color-text); text-decoration: none; }
.tk-archivo:hover { border-color: var(--color-primary); color: var(--color-primary); }
.tk-archivo svg { width: 14px; height: 14px; }
.tk-archivos { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-top: .5rem; }
.tk-archivo-chip { display: inline-flex; align-items: center; gap: .35rem; padding: .2rem .5rem; border: 1px solid var(--color-border); border-radius: 999px; font-size: var(--t-sm); }
.tk-archivo-chip a { color: inherit; }
/* Lo que propone la IA se distingue de lo que dijeron las personas: mismo
   sitio, otro papel. Si se pareciera a un mensaje más, acabaría citándose como
   si lo hubiera dicho alguien. */
.tk-ia { border-left: 3px solid var(--color-primary); background: color-mix(in srgb, var(--color-primary) 6%, var(--color-surface)); }
.tk-ia-cambios { font-size: var(--t-md); margin: .5rem 0 0; }
.tk-ia-aviso { font-size: var(--t-sm); margin: .4rem 0 0; font-style: italic; }
.tk-ia-enviado { max-height: 14rem; overflow: auto; white-space: pre-wrap; font-size: var(--t-sm); background: var(--color-surface-2); padding: .5rem; border-radius: var(--radius-sm); }
/* El selector de cuentas de la barra. Cuelga del nombre, que es donde uno mira
   para saber con cuál está trabajando. */
.cuentas-sel { position: relative; display: inline-flex; }
/* `left: auto` NO es adorno: `.menu-pop` trae `left: 0`, y con los dos puestos
   el menú se estiraba desde el botón hacia la derecha y se salía de la
   pantalla. Anclado a la derecha, cabe siempre. */
.cuentas-pop { left: auto; right: 0; min-width: 15rem; z-index: 60; }
.cuentas-pop-fila { display: flex; align-items: center; gap: .15rem; }
.cuentas-pop-fila .menu-pop-item { flex: 1; min-width: 0; }
.cuentas-pop-x { display: inline-flex; align-items: center; padding: .35rem; border: 0; background: none; color: var(--color-text-2); cursor: pointer; border-radius: var(--radius-sm); }
.cuentas-pop-x:hover { background: var(--color-surface-2); color: var(--color-danger); }
.cuentas-pop-x svg { width: 16px; height: 16px; }
.cuentas-pop-txt { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; text-align: left; }
.cuentas-pop-txt small { font-size: var(--t-xs); }
.drawer-rotulo { margin: .6rem 0 .2rem; padding: 0 .9rem; font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-2); }
/* Las cuentas del navegador, en el cajón. La activa se marca; la X de quitar
   solo aparece cuando hay más de una —quitar la única es cerrar sesión, y para
   eso está el botón de abajo—. */
.drawer-cuenta { align-items: center; }
.drawer-cuenta-txt { display: flex; flex-direction: column; align-items: flex-start; text-align: left;
    line-height: 1.2; min-width: 0; flex: 1; }
/* Una línea cada uno: el nombre y el correo partidos en dos renglones y centrados
   convertían el renglón en un párrafo. */
.drawer-cuenta-txt > span, .drawer-cuenta-txt small { max-width: 100%; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; }
.drawer-cuenta-txt small { font-size: var(--t-xs); }
/* Sobre el azul de la cuenta activa, el gris de .texto-muted no se lee. */
.drawer-cuenta.activo .drawer-cuenta-txt small { color: inherit; opacity: .8; }
.drawer-cuenta-fila { display: flex; align-items: center; }
.drawer-cuenta-fila .drawer-cuenta { flex: 1; min-width: 0; }
/* Blanco de dedo: 44px de lado, que es lo que mide una yema. Con 15px se
   fallaba y se cambiaba de cuenta en vez de cerrarla. */
.drawer-cuenta-x { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin-right: .35rem; border: 0; background: none; cursor: pointer;
    color: var(--color-text-2); border-radius: var(--radius-sm); }
.drawer-cuenta-x:hover { background: var(--color-surface-2); color: var(--color-danger); }
.drawer-cuenta-x svg { width: 17px; height: 17px; }
.tk-th-simple { padding: .45rem .6rem; font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-2); }
.tk-etiq-rol { margin-left: .35rem; font-size: var(--t-2xs); padding: .05rem .35rem; border-radius: 999px; border: 1px solid var(--color-border); color: var(--color-text-2); }
.tk-col-carga { white-space: nowrap; font-variant-numeric: tabular-nums; }
.tk-archivo-ido { opacity: .6; cursor: default; }
.tk-archivo-ido:hover { border-color: var(--color-border); color: var(--color-text); }
.tk-controles { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: .6rem; margin-top: .8rem; }
.tk-historia { display: flex; flex-direction: column; gap: .4rem; max-height: 40vh; overflow-y: auto; }
.tk-ev { border-left: 3px solid var(--color-border); padding: .3rem .6rem; }
.tk-ev-nota { border-left-color: var(--color-primary); }
.tk-ev-cab { display: block; font-size: var(--t-xs); color: var(--color-text-2); }
.tk-ev-txt { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Lo que dijo el cliente contra lo que le contestamos: sin esta diferencia, un
   expediente de treinta mensajes se lee como un monólogo. */
.tk-ev-cliente { border-left-color: var(--color-primary); background: var(--color-surface-2); }
.tk-ev-historico { border-left-style: dashed; }
.tk-ev-adj { display: block; font-size: var(--t-xs); color: var(--color-text-2); margin-top: .2rem; }
/* En pantallas angostas se van cayendo columnas, de la menos necesaria a la
   más: nunca el folio, el asunto ni el estado. */
@media (max-width: 1400px) {
    .tk-col-correo, .tk-col-ultima { display: none; }
}
@media (max-width: 1100px) {
    .tk-col-org, .tk-col-resp { display: none; }
    /* Sin ancho para dos columnas, el hilo va arriba y lo demás debajo: en un
       teléfono se lee primero lo que pasó, no lo que se puede cambiar. */
    .tk-exp { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 768px) {
    .tk-col-nombre { display: none; }
    /* Las fichas se deslizan en un renglón: envolver sin ancho propio empuja la
       página entera y saca la barra horizontal (mordió antes en otras tiras). */
    .tk-fichas { flex-wrap: nowrap; overflow-x: auto; min-width: 0; width: 100%; -webkit-overflow-scrolling: touch; }
    .tk-ficha { white-space: nowrap; }
    .tk-buscar, .tk-cola-filtro { max-width: none; flex: 1 1 100%; }
    .tk-tabla { font-size: var(--t-sm); }
}


/* ── Gráficas del tablero ────────────────────────────────────────────────
   Portadas de MexMail (`graficas.js` ← `Graficas.php`) para que la nube y el
   correo enseñen la MISMA gráfica. Los colores llegan como `var(--graf-*)`, así
   que el tema claro y el oscuro se resuelven aquí y el SVG no sabe de temas. */
:root {
    --graf-recibidos: #2a78d6;
    --graf-enviados: #4a3aa7;
    --graf-spam: #eda100;
    --graf-virus: #d03b3b;
    --graf-bloqueos: #ec835a;
    --graf-espacio: #1baf7a;
    --graf-neutro: var(--color-surface-2);
    /* Las donas de Red (2026-10-03). Tres partes en anillo = TODOS los pares
       son vecinos: validados así (--pairs all) en claro y en oscuro. El azul y
       el morado de arriba fallaban en oscuro (ΔE 1.9 con protanopía). */
    --graf-dona-1: #2a78d6;
    --graf-dona-2: #eda100;
    --graf-dona-3: #1baf7a;
}
/* En oscuro se ACLARAN: los mismos tonos sobre fondo oscuro se apagan y dos
   series se vuelven la misma mancha.
   ⚠️ El atributo es `data-theme` (no `data-tema`) y HAY TRES TEMAS OSCUROS
   —oscuro, madrugada y carbón—, más el modo «sistema», que no pone atributo y
   sigue al del dispositivo. Escribir solo uno deja los otros con los colores
   del tema claro sobre fondo oscuro.
   ⚠️ **ESTA LISTA ES EL QUINTO PASO al añadir un tema oscuro**, y no estaba
   escrito en ningún sitio: los otros cuatro (tema.js, sistema-diseno.css,
   textos.js y PerfilControlador::TEMAS) se llevan toda la atención y este se
   queda atrás sin dar error — solo unas gráficas apagadas. */
[data-theme="oscuro"],
[data-theme="madrugada"],
[data-theme="carbon"],
[data-theme="aurora"],
[data-theme="obsidiana"],
[data-theme="commodore"] {
    --graf-recibidos: #3987e5;
    --graf-enviados: #9085e9;
    --graf-spam: #c98500;
    --graf-virus: #e66767;
    --graf-bloqueos: #d95926;
    --graf-espacio: #27c68c;
    --graf-dona-1: #3987e5;
    --graf-dona-2: #c98500;
    --graf-dona-3: #199e70;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) {
        --graf-recibidos: #3987e5;
        --graf-enviados: #9085e9;
        --graf-spam: #c98500;
        --graf-virus: #e66767;
        --graf-bloqueos: #d95926;
        --graf-espacio: #27c68c;
        --graf-dona-1: #3987e5;
        --graf-dona-2: #c98500;
        --graf-dona-3: #199e70;
    }
}

.grafica-caja { width: 100%; overflow-x: auto; }
.grafica-semana { width: 100%; height: auto; display: block; min-width: 22rem; }
.grafica-semana .rejilla { stroke: var(--color-border); stroke-width: 1; }
.grafica-semana .cifra { fill: var(--color-text-muted); font-size: 11px; }
/* El punto lleva el color del fondo alrededor: donde dos series se cruzan, se
   ve cuál va delante en vez de un borrón. */
.grafica-semana .punto { stroke: var(--color-surface); stroke-width: 2; }

.dona { width: 8.5rem; height: 8.5rem; margin: 0.25rem auto; display: block; }

/* ⚠️ EL TABLERO VA AL ANCHO DEL PANEL DE MEXMAIL (60rem), no al de la consola
   de empresa (78rem, que es ancho porque ahí lo que hay son tablas). Son la
   misma pantalla en los dos productos y se comparan de un vistazo; 18rem de
   diferencia se notan. De paso, el SVG de las gráficas escala con su caja: en
   78rem las cifras del eje salían más grandes que allá. Lo vio Jore. */
.contenido-tablero { max-width: min(60rem, 100%); }

/* Centrada bajo la gráfica, como el resto de leyendas del tablero: pegada a la
   izquierda quedaba descolgada del dibujo. */
.grafica-leyenda { list-style: none; margin: 0.5rem 0 0; padding: 0; font-size: var(--t-md); color: var(--color-text-2); text-align: center; }
.grafica-leyenda .grafica-leyenda-fila { justify-content: center; }
.grafica-leyenda li { margin-bottom: 0.2rem; }
.grafica-leyenda-fila { display: flex; flex-wrap: wrap; gap: 0.35rem 1.25rem; }
.chip { display: inline-block; width: 0.7em; height: 0.7em; border-radius: 2px; margin-right: 0.4em; vertical-align: baseline; }

/* ── Vistazo del correo al pasar el cursor ────────────────────────────────
   Solo con ratón de verdad: el propio JS no lo pide si no hay `pointer: fine`.

   ⚠️ `position: fixed` Y FUERA DE LA LISTA, colocado por coordenadas desde el
   JS. Dentro de la fila lo recortaban DOS `overflow: hidden` anidados —el de
   `.buzon-fila`, que tapa el panel de deslizar, y el de `.buzon-lista`, que
   redondea las esquinas—, así que solo asomaba una tira por debajo de su fila.
   Un recorte no lo arregla ningún `z-index`.

   ⚠️ `pointer-events: none` es imprescindible: el panel sale DEBAJO del
   cursor, y sin esto el ratón entraría en él, saldría de la fila y se
   dispararía el `mouseleave` — el vistazo parpadearía sin parar. */
.buzon-vistazo {
    position: fixed;
    z-index: 70;
    pointer-events: none;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: 0 0.6rem 1.6rem var(--color-shadow);
    font-size: var(--t-sm);
    line-height: 1.45;
    /* El texto viene con sus saltos; se respetan sin dejar que una línea
       larga ensanche el panel. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    /* Acotado: un vistazo, no el correo. Lo que sobre se desvanece. */
    max-height: 8.5rem;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
    animation: vistazo-entra 0.12s ease-out;
}

/* En la columna donde se lee el correo cabe mucho más: ahí el vistazo deja de
   ser un asomo apretado y se lee de verdad. */
.buzon-vistazo.en-panel {
    max-height: 16rem;
    font-size: var(--t-md);
    padding: 0.85rem 1rem;
    -webkit-mask-image: linear-gradient(to bottom, #000 86%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 86%, transparent 100%);
}

@keyframes vistazo-entra {
    from { opacity: 0; transform: translateY(-0.2rem); }
    to   { opacity: 1; transform: none; }
}

/* ── Selector de emojis (Mensajes) ────────────────────────────────────────
   Sale ENCIMA del redactor, dentro del panel de la conversación. No es un
   modal a propósito: se sigue viendo el hilo y lo que se lleva escrito, que es
   justo lo que uno mira para decidir qué emoji poner. */
.emoji-panel {
    /* ⚠️ `fixed` y colocado desde el JS: `.app` recorta con `overflow: hidden`
       y un panel absoluto se perdía entero en ventanas bajas.

       ⚠️ Y CON MEDIDAS POR OMISIÓN. El JS le pone `left/top/width/height`
       inline, pero si esa medición no llegara a hacerse el panel se quedaba
       SIN TAMAÑO —la rejilla es `flex: 1` dentro de un alto automático— y no
       se veía nada aunque estuviera en el documento. Esto garantiza que
       siempre haya algo visible; lo inline manda cuando existe. */
    position: fixed;
    z-index: 70;
    left: 1rem;
    bottom: 5.5rem;
    width: min(24rem, calc(100vw - 2rem));
    height: min(20rem, calc(100vh - 8rem));
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: 0 0.6rem 1.6rem var(--color-shadow);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.emoji-tabs { display: flex; gap: 0.1rem; padding: 0.35rem; border-bottom: 1px solid var(--color-border); overflow-x: auto; }
/* Sin esto la tira de pestañas CRECE en vez de desplazarse y se sale del panel. */
.emoji-tabs > * { flex: 0 0 auto; }
.emoji-tab {
    border: none; background: none; cursor: pointer; font-size: var(--t-xl);
    line-height: 1; padding: 0.3rem 0.45rem; border-radius: var(--radius-sm);
    opacity: 0.55;
}
.emoji-tab:hover { background: var(--color-bg); opacity: 1; }
.emoji-tab.activa { opacity: 1; background: var(--color-bg); box-shadow: inset 0 -2px 0 var(--color-primary); }

.emoji-busca { margin: 0.4rem; width: calc(100% - 0.8rem); font-size: var(--t-base); }

.emoji-rejilla {
    flex: 1;
    display: grid;
    /* Arriba y pegados: sin esto, con pocos emojis la única fila se estiraba a
       todo el alto y el emoji quedaba flotando en medio de un panel vacío. */
    align-content: start;
    grid-template-columns: repeat(auto-fill, minmax(2.1rem, 1fr));
    gap: 0.1rem;
    padding: 0 0.4rem 0.4rem;
    min-height: 0;
    overflow-y: auto;
}
.emoji-uno {
    border: none; background: none; cursor: pointer; padding: 0.25rem;
    font-size: var(--t-2xl); line-height: 1.2; border-radius: var(--radius-sm);
    /* La tipografía de emoji del sistema: sin esto, en algunos escritorios
       salen en blanco y negro. */
    font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
}
.emoji-uno:hover { background: var(--color-bg); }
.emoji-vacio { grid-column: 1 / -1; padding: 1rem 0.5rem; text-align: center; color: var(--color-text-muted); font-size: var(--t-md); }

.msg-emoji { font-size: var(--t-xl); line-height: 1; }
.msg-emoji.activo { background: var(--color-bg); }




/* ── Un correo archivado (.eml) abierto desde el gestor ──────────────────
   La cabecera va separada del cuerpo con una línea, como en el lector de
   Correo: quien abre esto viene de una carpeta de archivos y necesita saber
   de un vistazo que lo que tiene delante es un mensaje, no un documento. */
.preview-correo-cab {
    border-bottom: 1px solid var(--color-border);
    padding-bottom: .6rem;
    margin-bottom: .6rem;
    font-size: var(--t-base);
    line-height: 1.5;
}
.preview-correo-asunto { font-weight: 600; font-size: var(--t-lg); margin-bottom: .15rem; }
/* El aviso de que la vista es segura. Discreto pero presente: explica por qué
   no se ven las imágenes, que si no parece que el correo esté roto. */
.preview-correo-nota { font-size: var(--t-sm); margin: 0 0 .6rem; opacity: .85; }

/* ── Red: los routers de las oficinas (red.js) ──────────────────────────────
   Reutiliza las piezas de Soporte (tk-barra, tk-tabla, tk-chip, tk-pag) para
   que las dos listas se lean igual; aquí solo va lo propio. */
/* 22rem: con 18 la IP, la memoria y la versión se partían en dos renglones (Jore, 2026-09-29). */
.red-routers { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(22rem, 100%), 1fr)); gap: 1rem; }
.red-routers .card + .card { margin-top: 0; }
/* En «Red» y en «Red · Clientes» del socio la tarjeta del router va al ancho de
   la de 24 horas, con sus datos a la izquierda y tres donas a la derecha
   (2026-10-03). Va en un modificador: `.red-routers` sola sigue en mosaico. */
.red-routers-anchas { grid-template-columns: 1fr; container-type: inline-size; }
.red-routers-anchas .red-router { display: grid; grid-template-columns: minmax(15rem, 20rem) 1fr; column-gap: 2rem; align-items: start; }
.red-routers-anchas .red-router-cab, .red-routers-anchas .red-router-estado { grid-column: 1 / -1; }
/* La salud (0238): todo el ancho; los medidores en UNA fila y debajo las curvas,
   más altas. En columnas dejaba un hueco grande abajo a la derecha (Jore, 2026-10-12). */
.red-routers-anchas .red-salud { grid-column: 1 / -1; }
.red-routers-anchas .red-salud .red-medidores { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); column-gap: 1.25rem; }
.red-routers-anchas .red-salud .red-curvas { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); column-gap: 1.25rem; }
.red-routers-anchas .red-salud .red-curva { height: 4rem; }
.red-donas { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
.red-dona { margin: 0; text-align: center; min-width: 0; }
.red-dona figcaption { font-size: var(--t-sm); color: var(--color-text-2); margin-bottom: .2rem; }
.red-dona-caja { position: relative; width: 8.5rem; margin: 0 auto; }
.red-dona-caja .dona { margin: 0 auto; }
.red-dona-centro { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; line-height: 1.1; }
.red-dona-centro strong { font-size: var(--t-xl); font-variant-numeric: tabular-nums; color: var(--color-text); }
.red-dona-centro small { font-size: var(--t-xs); color: var(--color-text-muted); }
.red-dona-leyenda { list-style: none; margin: .4rem 0 0; padding: 0; font-size: var(--t-sm); color: var(--color-text-2); display: grid; gap: .15rem; }
.red-dona-leyenda li { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .1rem .35rem; text-align: left; }
.red-dona-leyenda .chip { margin: 0; }
.red-dona-leyenda strong { font-variant-numeric: tabular-nums; color: var(--color-text); font-weight: 600; }
.red-dona-nota { display: block; font-size: var(--t-xs); margin-top: .3rem; }
/* Por el ancho de la TARJETA, no de la ventana: la sección va junto al menú
   lateral y en una tableta la tarjeta es mucho más angosta que la pantalla. */
@container (max-width: 860px) {
    .red-routers-anchas .red-router { grid-template-columns: 1fr; }
    .red-routers-anchas .red-datos { max-width: 26rem; }
    .red-donas { margin-top: 1rem; }
}
@container (max-width: 520px) {
    .red-donas { grid-template-columns: 1fr; }
    .red-dona-leyenda { max-width: 16rem; margin-left: auto; margin-right: auto; }
}
.red-router-cab { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.red-router-cab h3 { margin: 0; font-size: var(--t-lg); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El escudo de EnlacesPYME (iconos.js, `enlacespyme`): trae sus colores de marca. */
.ico-epyme { stroke: none; }
.red-router-epyme { display: inline-flex; flex: none; }
.red-router-epyme svg { width: 1.15rem; height: 1.25rem; }
/* El logotipo de EnlacesPYME arriba de las pestañas de Seguridad. */
.seg-marca { color: var(--color-text); }
.seg-logotipo { display: block; height: 2.4rem; width: auto; max-width: 100%; margin-inline: auto; }
@media (max-width: 640px) { .seg-logotipo { height: 2rem; } }
.red-router-estado { font-size: var(--t-sm); margin: .2rem 0 .7rem; }
/* EL SEMÁFORO SE LEE POR COLOR, pero nunca SOLO por color: al lado va siempre
   la palabra («Reportando», «Sin contacto»), que es lo que lee quien no
   distingue el rojo del verde. */
.red-sem { display: inline-block; width: .75rem; height: .75rem; border-radius: 50%; flex: none; background: var(--color-border); vertical-align: middle; margin-right: .3rem; }
.red-sem-verde { background: var(--color-success); }
.red-sem-amarillo { background: var(--color-warning); }
.red-sem-rojo { background: var(--color-danger); }
.red-sem-gris { background: var(--color-border); }
/* La salud de un Servidor EnlacesPYME en su tarjeta (0238). */
.red-salud { border-top: 1px solid var(--color-border); margin-top: .75rem; padding-top: .6rem; display: grid; gap: .6rem; }
.red-salud-cab { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; border: 0; background: none; padding: 0; font: inherit; color: var(--color-text); cursor: pointer; text-align: left; }
.red-salud-ver { margin-left: auto; color: var(--color-primary); font-size: var(--t-md); }
.red-medidores { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: .5rem .9rem; }
.red-medidores li { display: grid; gap: .15rem; min-width: 0; }
.red-medidor-cab { display: flex; justify-content: space-between; gap: .5rem; font-size: var(--t-md); }
.red-medidor-cab strong { white-space: nowrap; flex: none; }
.red-medidor-barra { height: .45rem; border-radius: 999px; background: var(--color-surface-2); overflow: hidden; }
.red-medidor-barra > span { display: block; height: 100%; border-radius: inherit; background: var(--color-success); }
.red-medidor-aviso .red-medidor-barra > span { background: var(--color-warning); }
.red-medidor-mal .red-medidor-barra > span { background: var(--color-danger); }
.red-medidor-nose .red-medidor-barra > span { background: var(--color-text-muted); }
.red-medidores small { font-size: var(--t-xs); overflow-wrap: anywhere; }
.red-curvas { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: .6rem .9rem; }
.red-curvas-grandes { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
.red-curva-fig { margin: 0; min-width: 0; display: grid; gap: .15rem; }
.red-curva-fig figcaption { font-size: var(--t-sm); color: var(--color-text-2); }
.red-curva-fig small { font-size: var(--t-xs); }
.red-curva { width: 100%; height: 2.75rem; display: block; }
.red-curvas-grandes .red-curva { height: 5rem; }
.red-curva-eje { stroke: var(--color-border); stroke-width: 1; }
.red-curva-linea { fill: none; stroke: var(--color-primary); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.red-curva-area { fill: var(--color-primary); opacity: .12; }
.red-curva-punto { fill: var(--color-primary); }
.red-curva-red .red-curva-linea { stroke: var(--graf-dona-2, var(--color-primary)); }
.red-curva-red .red-curva-area { fill: var(--graf-dona-2, var(--color-primary)); }
.red-curva-temp .red-curva-linea { stroke: var(--color-warning); }
.red-curva-temp .red-curva-area { fill: var(--color-warning); }
.red-revisiones { list-style: none; margin: 0 0 .75rem; padding: 0; display: grid; gap: .35rem; }
.red-revisiones li { display: flex; gap: .5rem; align-items: baseline; }
.red-revisiones .red-sem { flex: none; position: relative; top: .1rem; }
.red-dato-par { display: contents; }
.red-datos { display: grid; grid-template-columns: auto 1fr; gap: .25rem .8rem; margin: 0; font-size: var(--t-base); }
.red-datos dt { color: var(--color-text-2); }
/* El VALOR no se parte (IP, memoria, versión son cortos y partidos no se leen:
   con `overflow-wrap: anywhere` salía «192.168./3.26/24»); si falta espacio en
   un teléfono chico, lo que se acomoda en dos renglones es la etiqueta. */
.red-datos dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.red-graficas { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr)); gap: 1rem; margin-top: .6rem; }
.red-figura { margin: 0; }
.red-figura figcaption { font-size: var(--t-sm); color: var(--color-text-2); margin-bottom: .3rem; }
.red-graf { width: 100%; height: auto; display: block; }
.red-graf rect { fill: var(--color-primary); opacity: .85; }
.red-graf-bloq rect { fill: var(--color-danger); }
/* Se toca una barra para ver el detalle de esa hora (0195). */
.red-graf-clic .red-graf-bloq rect { cursor: pointer; }
.red-graf-clic .red-graf-bloq rect:hover { opacity: 1; }
.red-bloq { margin-top: .8rem; }
/* En Red, las tarjetas de formulario (más angostas que las tablas) van centradas
   (Routers, Filtro, Hotspot), no pegadas a la izquierda (Jore, 2026-09-29). */
.red-panel .card-forma { margin-inline: auto; width: 100%; }
/* Red es de tablas anchas (Dispositivos llega a la columna de IP reservada sin
   barra de desplazamiento): en pantallas grandes, más ancho que las demás. */
.contenido.contenido-panel.red-panel { padding-inline: max(var(--contenido-pad), calc((100% - 92rem) / 2 + var(--contenido-pad))); }
/* Servicios con casilla en el Filtro (0197). */
.red-filtro-servicios { border: 1px solid var(--color-border); border-radius: 10px; padding: .6rem .9rem .8rem; margin: 0; display: flex; flex-direction: column; gap: .6rem; }
.red-filtro-servicios legend { font-weight: 600; padding: 0 .3rem; }
.red-filtro-todas { display: flex; align-items: center; gap: .45rem; }
.red-filtro-casillas { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(9.5rem, 100%), 1fr)); gap: .3rem .8rem; margin: .35rem 0 0 1.5rem; }
.red-filtro-casilla { display: flex; align-items: center; gap: .4rem; font-size: var(--t-base); }
/* ── Mapa de la red (0196): un árbol vertical, legible en el teléfono. ── */
.red-mapa { display: flex; flex-direction: column; gap: .5rem; }
.red-mapa-internet, .red-mapa-router { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.red-mapa-internet svg, .red-mapa-rama-cab svg, .red-mapa-vecino svg { width: 18px; height: 18px; flex: none; }
.red-mapa-router { border: 1px solid var(--color-border); border-radius: 10px; padding: .6rem .8rem; background: var(--color-surface-2, var(--color-bg)); }
.red-mapa-ramas { list-style: none; margin: 0 0 0 1rem; padding: 0 0 0 1rem; border-left: 2px solid var(--color-border); display: flex; flex-direction: column; gap: .6rem; }
.red-mapa-rama { position: relative; }
.red-mapa-rama::before { content: ''; position: absolute; left: -1rem; top: .75rem; width: .8rem; border-top: 2px solid var(--color-border); }
.red-mapa-rama-cab { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; }
.red-mapa-apagada { opacity: .55; }
.red-mapa-vecino { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin: .3rem 0 0 1.4rem; font-size: var(--t-base); }
.red-mapa-equipos { display: flex; flex-wrap: wrap; gap: .4rem; margin: .4rem 0 0 1.4rem; }
.red-mapa-eq { display: inline-flex; align-items: center; gap: .45rem; text-align: left; font: inherit; color: var(--color-text);
    background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 8px; padding: .35rem .6rem; cursor: pointer; max-width: 100%; }
.red-mapa-eq:hover { border-color: var(--color-primary); }
.red-mapa-eq-txt { display: flex; flex-direction: column; min-width: 0; }
.red-mapa-eq-txt strong { font-size: var(--t-base); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.red-mapa-eq-txt small { font-size: var(--t-xs); color: var(--color-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.red-mapa-punto { width: .6rem; height: .6rem; border-radius: 50%; flex: none; display: inline-block; }
.red-mapa-conocido .red-mapa-punto, .red-mapa-punto.red-mapa-conocido { background: var(--color-success); }
.red-mapa-desconocido .red-mapa-punto, .red-mapa-punto.red-mapa-desconocido { background: var(--color-warning); }
.red-constelacion { width: 100%; height: 300px; display: block; border-radius: var(--radius-md); background: radial-gradient(ellipse at 50% 60%, var(--color-surface-2), transparent 70%); }
@media (max-width: 640px) { .red-constelacion { height: 230px; } }
.red-mapa-leyenda { font-size: var(--t-sm); margin: .3rem 0 0; display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
@media (max-width: 640px) { .red-mapa-eq-txt small { white-space: normal; } .red-mapa-ramas { margin-left: .4rem; } }
.red-graf text { font-size: 10px; fill: var(--color-text-2); }
.red-graf-eje { stroke: var(--color-border); stroke-width: 1; }
.red-alerta { display: flex; align-items: flex-start; gap: .6rem; padding: .55rem 0; border-bottom: 1px solid var(--color-border); cursor: pointer; }
.red-alerta:last-child { border-bottom: 0; }
.red-alerta-txt { flex: 1; min-width: 0; font-size: var(--t-base); }
.red-alerta-msg { font-size: var(--t-sm); color: var(--color-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tk-chip.red-sev-alerta { border-color: var(--color-danger); color: var(--color-danger); }
.tk-chip.red-sev-aviso { border-color: var(--color-warning); color: var(--color-warning); }
.tk-chip.red-sev-info { color: var(--color-text-2); }
.tk-chip.red-conectado { border-color: var(--color-success); color: var(--color-success); }
.red-tabla td { vertical-align: middle; }
/* IPs bloqueadas (0208) */
.red-ips-acc { min-width: 7rem; }
.red-ips-hist { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; font-size: var(--t-base); }
.red-por-nombre { display: flex; align-items: center; gap: 0.25rem; font-size: var(--t-xs); color: var(--color-text-2); margin-top: 0.2rem; white-space: nowrap; }
/* En el teléfono, cada IP es una tarjeta: la tabla de 6 columnas dejaba el
   botón «Desbloquear» fuera de la pantalla. */
@media (max-width: 768px) {
    .red-ips-tabla thead { display: none; }
    .red-ips-tabla, .red-ips-tabla tbody, .red-ips-tabla tr, .red-ips-tabla td { display: block; width: 100%; }
    .red-ips-tabla tr { padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--color-border); }
    .red-ips-tabla td { padding: 0.1rem 0; border: 0; white-space: normal; }
    .red-ips-tabla td[data-et]::before { content: attr(data-et) ': '; color: var(--color-text-2); font-size: 0.85em; }
    .red-ips-tabla .red-ips-ip { font-weight: 600; }
    .red-ips-tabla .red-ips-acc { padding-top: 0.4rem; }
}
.red-tr { border-bottom: 1px solid var(--color-border); }
.red-tr.red-baja { opacity: .6; }
.red-nombre { min-width: 9rem; padding: .25rem .45rem; }
/* Los scripts del router (0201), bajo su estado. */
.red-scripts { display: block; font-size: var(--t-sm); color: var(--color-text-2); margin-top: .15rem; }
.red-scripts-vieja, .red-scripts-manual { color: var(--color-warning); }
.red-scripts-fallo { color: var(--color-danger); }
/* «Sin internet» (0203): la casilla marcada en rojo, para que se note. */
.red-check-peligro:checked { accent-color: var(--color-danger); }
/* «Quitar de la lista» bajo el estado del equipo; el segundo clic confirma. */
.red-disp-quitar { display: block; margin-top: .3rem; padding: 0; border: 0; background: none; color: var(--color-text-2); font-size: var(--t-sm); cursor: pointer; text-align: left; }
.red-disp-quitar:hover { color: var(--color-danger); text-decoration: underline; }
.red-disp-quitar.confirmando { color: var(--color-danger); font-weight: 600; }
/* «Bloquear anuncios» (0202). */
.red-filtro-anuncios { max-width: 26rem; margin-top: .4rem; }
.red-filtro-credito { display: block; margin-top: .3rem; font-size: var(--t-xs); }
/* Reserva de DHCP (0200): la IP, con su estado debajo. */
.red-reserva-ip { min-width: 8rem; font-variant-numeric: tabular-nums; }
.red-reserva .tk-ref.red-reserva-error { color: var(--color-danger); }
/* «Reservar 192.168.1.10»: un enlace discreto bajo el campo vacío. */
.red-reserva-actual { display: block; margin-top: .2rem; padding: 0; border: 0; background: none; color: var(--color-primary); font-size: var(--t-sm); cursor: pointer; text-align: left; }
.red-reserva-actual:hover { text-decoration: underline; }
.red-identidad { display: block; min-width: 9rem; margin-top: .25rem; padding: .15rem .45rem; font-size: var(--t-sm); color: var(--color-text-2); }
.red-check { width: 1.05rem; height: 1.05rem; }
.red-msg { display: inline-block; max-width: 26rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.red-fecha { width: auto; padding: .25rem .4rem; }
/* Los botones bajan a otro renglón en vez de obligar a desplazar la tabla de
   lado (Jore, 2026-10-13, con captura): cada botón sí va entero. */
.red-acciones { text-align: right; }
.red-acciones > .btn, .red-acciones > select { white-space: nowrap; margin: .15rem 0 .15rem .25rem; vertical-align: middle; }
.red-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr)); gap: .8rem; align-items: start; }
/* El botón, en su propio renglón a la derecha: la identidad lleva su ayuda
   debajo y, con el botón en la misma fila, los campos quedaban desparejos. */
.red-form > .btn { grid-column: 1 / -1; justify-self: end; }
/* El modelo en la lista: se ve como los otros campos, pero no se edita. */
.red-identidad[readonly] { color: var(--color-text-2); cursor: default; }
.red-identidad[readonly]:focus { outline: none; box-shadow: none; }
.red-form .campo { margin: 0; }
.red-mensaje-completo, .red-token {
    font-family: var(--font-mono, ui-monospace, Consolas, monospace); font-size: var(--t-sm);
    background: var(--color-surface-2); border-radius: var(--radius-sm); padding: .6rem .7rem; margin: 0 0 .5rem;
}
.red-mensaje-completo { white-space: pre-wrap; overflow-wrap: anywhere; }
/* El token y el texto del script NO se parten: un salto metido al copiar
   rompe la línea en el router. Se desplaza de lado dentro de su caja. */
.red-token { white-space: pre; overflow-x: auto; user-select: all; }
.red-modal-token { max-width: 40rem; }
/* «Configuración del equipo» de un Servidor EnlacesPYME (0225, §41.21). */
.red-modal-equipo { max-width: 46rem; max-height: 92vh; overflow-y: auto; }
.red-equipo-campos { border: 0; padding: 0; margin: 0; min-width: 0; }
.red-equipo-campos .card-titulo { margin-top: 1rem; }
.red-equipo-campos .tabla select.input { min-width: 11rem; }
.red-equipo-ayuda { font-size: var(--t-sm); margin: .1rem 0 .5rem; }
.red-equipo-vlan { max-width: 7rem; }
.red-equipo-estado { font-weight: 600; padding: .3rem .6rem; border-radius: var(--radius-sm); background: var(--color-surface-2); border-left: 3px solid var(--color-text-muted); }
.red-equipo-estado.eq-aplicado { border-left-color: var(--color-success); }
.red-equipo-estado.eq-pendiente { border-left-color: var(--color-warning); }
.red-equipo-estado.eq-error { border-left-color: var(--color-danger); }
.red-equipo-avisos { margin: .8rem 0 0; padding-left: 1.2rem; color: var(--color-text); }
.red-equipo-avisos li { margin-bottom: .3rem; }
.red-equipo-avisos li::marker { color: var(--color-warning); }
/* «Puertos» (0240, §41.28): los tres puertos en un renglón; en el teléfono, uno bajo otro. */
/* Más ancha que la del equipo: la tabla de puertos lleva siete columnas (Jore, 2026-10-13). */
.red-modal-puertos { max-width: 72rem; max-height: 94vh; }
.red-pu-puertos { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0 .8rem; }
.red-pu-prueba { display: block; margin-top: .25rem; padding-left: .5rem; border-left: 3px solid var(--color-text-muted); }
.red-pu-prueba.pu-conecta { border-left-color: var(--color-success); }
.red-pu-prueba.pu-rechazado, .red-pu-prueba.pu-sin_respuesta, .red-pu-prueba.pu-error { border-left-color: var(--color-danger); }
/* Cerrado por un ataque desde muchas IPs (0283): el porqué y cómo reabrirlo, debajo del nombre. */
.red-pu-ataque { display: block; margin-top: .25rem; max-width: 34rem; white-space: normal; }
.red-pu-ultima { display: block; white-space: nowrap; }
.red-pu-acciones span { display: flex; flex-wrap: wrap; gap: .3rem; align-items: center; }
/* La MAC y el modelo del disco se quedan también en el teléfono (2026-10-09): la tabla ya se desplaza de lado en su caja. */
/* Alta con código (0226): se lee de la pantalla del equipo y se teclea igual. */
.red-vinc-codigo { font-family: var(--font-mono, ui-monospace, monospace); text-transform: uppercase; letter-spacing: .12em; max-width: 12rem; }
.red-aviso { border-left: 3px solid var(--color-warning); background: var(--color-surface-2); padding: .5rem .7rem; border-radius: var(--radius-sm); }
.red-rotulo { font-size: var(--t-sm); margin: .8rem 0 .25rem; }
/* ── Red · Clientes (socio) ──────────────────────────────────────────────
   Reusa todo lo de arriba; aquí solo el chip del cliente y la fila del
   tablero, que ahí sí lleva una columna más que la del cliente único. */
/* Un renglón por cliente con alertas pendientes, en el tablero del socio: se
   entra a su bandeja con un clic, así que se comporta como la fila de una lista. */
.socio-cliente { display: flex; align-items: center; gap: .6rem; padding: .5rem 0; border-bottom: 1px solid var(--color-border); cursor: pointer; }
.socio-cliente:last-child { border-bottom: 0; }
.socio-cliente:hover { color: var(--color-primary); }
/* Lo ya atendido se queda a la vista, pero sin pedir atención. */
.red-alerta-atendida { opacity: .62; }
.socio-router-cab { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.socio-aviso { border-left: 3px solid var(--color-primary); background: var(--color-surface-2); padding: .5rem .7rem; border-radius: var(--radius-sm); font-size: var(--t-base); margin-bottom: 1rem; }

/* El número de alertas encima del icono de la barra. */
.btn-icono.con-globo { position: relative; }
.red-globo {
    position: absolute; top: -3px; right: -5px; min-width: 1.05rem; height: 1.05rem; padding: 0 .25rem;
    border-radius: 999px; background: var(--color-danger); color: #fff;
    font-size: var(--t-2xs); font-weight: 700; line-height: 1.05rem; text-align: center; pointer-events: none;
}

/* Notas en la búsqueda principal: tarjetas cortas con el color de la nota. */
.busq-notas-lista { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 0.6rem; }
.busq-nota {
    display: flex; flex-direction: column; gap: 0.25rem; text-align: left; cursor: pointer;
    padding: 0.7rem 0.8rem; border-radius: var(--radius-md); border: 1px solid var(--nota-bd, var(--color-border));
    background: var(--nota-bg, var(--color-surface)); color: var(--nota-fg, var(--color-text));
}
.busq-nota:hover { filter: brightness(0.97); }
.busq-nota-tit { font-weight: 600; }
.busq-nota-txt { font-size: var(--t-base); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; color: inherit; opacity: 0.8; }
.busq-nota-meta { font-size: var(--t-sm); display: flex; gap: 0.6rem; color: inherit; opacity: 0.7; }

/* Recuadros de caracteres de caja en las notas: monoespaciado y sin
   interlineado, o las líneas verticales salen cortadas. */
.nota-rt-editor pre, .nota-card-html pre, .nota-card-cont.con-cajas, .nota-cont-in.con-cajas {
    font-family: ui-monospace, Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: var(--t-md); line-height: normal; white-space: pre; overflow-x: auto; margin: 0.2rem 0;
}
/* Nota CON formato que trae un recuadro pegado como renglones sueltos con <br>
   (las de antes del arreglo): con el interlineado normal las verticales se
   tocan; monoespaciado ya lo trae el propio pegado. */
.con-cajas-html, .con-cajas-html * { line-height: normal; }
/* El «Courier New» del pegado se sustituye en Linux por una fuente cuyas
   verticales no llegan al borde del renglón (Jore, 2026-09-21): a lo que venga
   en monoespaciado se le pone la misma letra que a los <pre>, y un poco más
   apretado. */
.con-cajas-html span[style*="monospace"], .con-cajas-html font[face*="Courier"] {
    font-family: ui-monospace, Menlo, Consolas, "DejaVu Sans Mono", monospace !important;
    /* SIN PARTIR renglones (un recuadro partido es un recuadro roto) y con
       interlineado 1, para que las verticales se toquen sea cual sea la fuente. */
    white-space: pre; overflow-wrap: normal; line-height: 1;
}
/* El span MÁS INTERNO (el que trae los renglones) va como bloque en línea con
   su propio desplazamiento lateral. Va en línea y no en bloque porque el
   pegado deja la sangría del primer renglón FUERA, en el span de arriba: como
   bloque, ese renglón perdía la sangría y salía corrido dos columnas. */
.con-cajas-html span[style*="monospace"]:not(:has(span)) {
    display: inline-block; vertical-align: top; max-width: 100%; overflow-x: auto;
}
.nota-rt-editor pre, .nota-card-html pre { line-height: 1.05; }

/* ── Notas: tamaño y anchos (Jore, 2026-09-21) ────────────────────────────── */
/* En la computadora la nota abierta se puede ESTIRAR desde la esquina inferior
   derecha; el ancho tope pasa a ser la pantalla, no los 34rem de siempre. El
   `style="max-width:34rem"` del HTML es el ancho inicial: aquí se deja como
   mínimo y se permite crecer. */
@media (min-width: 769px) {
    /* `width` fija (el inline trae max-width:34rem) para que el tirador tenga
       de dónde partir; luego crece hasta casi la pantalla. */
    /* 38rem: con el relleno del diálogo deja los 550 px que mide la barra de
       formato entera, como en el cuadro de nota nueva (Jore, 2026-09-22). */
    .modal.nota-editor { resize: both; overflow-y: auto; overflow-x: hidden; width: 38rem; min-width: 22rem; min-height: 16rem; max-width: 96vw !important; }
    .nota-rt-editor { resize: vertical; max-height: none; }
    /* En la computadora NADA lleva desplazamiento lateral propio: la nota se
       estira con el tirador si algo no cabe. Barras que aparecen «por si acaso»
       estorban (Jore, 2026-09-21). */
    .nota-rt-editor, .nota-card-cont, .nota-card-html, .nota-rt-editor pre, .nota-card-html pre,
    .con-cajas-html span[style*="monospace"]:not(:has(span)) { overflow-x: hidden; }
    /* El editor de la nota NUEVA empieza bajo, como el textarea que sustituye. */
    .nota-rt-editor-nueva { min-height: 5rem; max-height: 50vh; }
}
/* En el teléfono, lo que no cabe a lo ancho —un recuadro, una tabla, una línea
   larga sin espacios— se desplaza en horizontal en vez de recortarse. */
@media (max-width: 768px) {
    .nota-card-cont, .nota-card-html, .nota-rt-editor { overflow-x: auto; }
    .nota-card-html pre, .nota-rt-editor pre, .con-cajas-html span[style*="monospace"]:not(:has(span)) { max-width: none; overflow-x: auto; }
}
/* La X de arriba de la nota abierta (solo escritorio; en el móvil está la barrita). */
.nota-cab-pc { display: flex; justify-content: flex-end; margin: -0.3rem -0.4rem 0 0; }
.nota-cab-pc .btn-icono { color: inherit; }

/* ── Pestañas de correos abiertos (escritorio) ───────────────────────────── */
.buzon-pestanas { display: flex; align-items: flex-end; gap: 0.25rem; padding: 0.35rem 0.6rem 0; border-bottom: 1px solid var(--color-border); background: var(--color-surface); overflow: hidden; }
.buzon-pestana {
    display: inline-flex; align-items: center; gap: 0.35rem; max-width: 12rem; min-width: 6rem;
    padding: 0.35rem 0.4rem 0.35rem 0.7rem; border: 1px solid var(--color-border); border-bottom: 0;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0; background: var(--color-surface-2); color: var(--color-text-muted);
    font-size: var(--t-md); cursor: pointer; user-select: none;
}
.buzon-pestana.activa { background: var(--color-bg); color: var(--color-text); font-weight: 600; margin-bottom: -1px; border-bottom: 1px solid var(--color-bg); }
.buzon-pestana-tit { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-pestana-x { display: inline-flex; padding: 0.1rem; border: 0; background: transparent; color: inherit; cursor: pointer; border-radius: 50%; opacity: 0.6; }
.buzon-pestana-x:hover { opacity: 1; background: color-mix(in srgb, currentColor 14%, transparent); }
.buzon-pestana-x svg { width: 0.85rem; height: 0.85rem; }
.buzon-pestana-mas { min-width: 0; padding: 0.35rem 0.6rem; }
/* Los correos A MEDIO ESCRIBIR: pestañas en la barra del correo, a la
   izquierda de «Redactar». Si no caben, la tira se desplaza de lado; el nombre
   de la cuenta es lo primero que cede sitio. */
.buzon-redactores { display: flex; align-items: center; gap: 0.25rem; flex: 0 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: thin; }
.buzon-redactores .buzon-pestana {
    flex: 0 0 auto; min-width: 5rem; max-width: 11rem; padding: 0.25rem 0.3rem 0.25rem 0.5rem;
    border-bottom: 1px solid var(--color-border); border-radius: var(--radius-sm);
}
.buzon-redactores .buzon-pestana:hover { color: var(--color-text); border-color: var(--color-primary); }
.buzon-redactores .buzon-pestana.activa { margin-bottom: 0; background: var(--color-bg); border-color: var(--color-primary); box-shadow: inset 0 -2px 0 var(--color-primary); }
.buzon-redactor-ic { display: inline-flex; flex: none; }
.buzon-redactor-ic svg { width: 0.9rem; height: 0.9rem; }
@media (min-width: 769px) {
    /* En la PC el redactor ocupa SOLO el panel de lectura: la lista sigue a la
       vista para consultar otros correos mientras se escribe. Fuera queda la
       pestaña propia del redactor, que sigue a pantalla completa. */
    .buzon-pane-preview { position: relative; }
    body:not(.redactor-solo) .buzon-pane-preview > .buzon-redactar { position: absolute; inset: 0; z-index: 3; padding-bottom: 0; }
    /* ⚠️ Y LO DE DEBAJO NO SE ASOMA. El lector sigue dibujado bajo el
       redactor (para volver a él tal cual), y sus menús llevan z-index 50: uno
       que se quedara abierto —el de IA al pulsar «Responder»— salía ENCIMA del
       campo «Para» (Jore, 2026-09-26). `visibility` y no `display`: el lector
       conserva su desplazamiento para cuando se aparte el redactor. */
    body:not(.redactor-solo) .buzon-pane-preview:has(> .buzon-redactar:not(.minimizado)) > :not(.buzon-redactar) { visibility: hidden; }
    /* El buzón falló con un correo a medias: sin lista ni carpetas, el
       redactor ocupa todo el ancho bajo el aviso del error. */
    .buzon-panes.solo-redactor { display: flex; }
    .buzon-panes.solo-redactor > .buzon-pane-preview { flex: 1; }
}
.buzon-panes.solo-redactor > :not(.buzon-pane-preview),
.buzon-panes.solo-redactor > .buzon-pane-preview > :not(.buzon-redactar) { display: none !important; }
@media (min-width: 769px) {
    .buzon-pane-preview { display: flex; flex-direction: column; }
    .buzon-pane-preview > .buzon-lector, .buzon-pane-preview > .buzon-preview-vacio { flex: 1; min-height: 0; }
}

/* ── Comunicados (0183) ──────────────────────────────────────────────────── */
.comunicados { display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 1rem; }
.comunicado {
    border: 1px solid var(--color-border); border-left: 5px solid var(--com-bd, var(--color-border));
    border-radius: var(--radius-md); background: var(--color-surface); padding: 0.7rem 0.9rem;
}
.comunicado.urgente { border-left-color: var(--color-danger); }
.comunicado-cab { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.comunicado-titulo { font-size: var(--t-lg); }
.comunicado-meta { font-size: var(--t-sm); min-width: 0; }
/* En el teléfono, quién y cuándo bajan a su propio renglón y pueden partirse;
   la ✕ se queda arriba, junto al título. Con `nowrap` se salían de la tarjeta. */
@media (max-width: 768px) {
    .comunicado-meta { order: 10; flex-basis: 100%; }
    .comunicado-titulo { min-width: 0; overflow-wrap: anywhere; }
}
.comunicado-cuerpo { margin-top: 0.4rem; font-size: var(--t-lg); line-height: 1.45; overflow-wrap: anywhere; }
.comunicado-tipo {
    display: inline-flex; align-items: center; gap: 0.3rem; font-size: var(--t-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
    padding: 0.1rem 0.5rem; border-radius: 999px; background: var(--com-bd, var(--color-surface-2)); color: var(--com-fg, var(--color-text));
}
.comunicado-urgente { font-size: var(--t-xs); font-weight: 700; color: var(--color-danger); text-transform: uppercase; }
.comunicado-plegado summary { cursor: pointer; }
.com-color-default  { --com-bd: var(--color-border); --com-fg: var(--color-text); }
.com-color-azul     { --com-bd: #3b82f6; --com-fg: #fff; }
.com-color-verde    { --com-bd: #10b981; --com-fg: #fff; }
.com-color-amarillo { --com-bd: #fbbc04; --com-fg: #202124; }
.com-color-naranja  { --com-bd: #f97316; --com-fg: #fff; }
.com-color-rojo     { --com-bd: #ef4444; --com-fg: #fff; }
.com-color-morado   { --com-bd: #8b5cf6; --com-fg: #fff; }
.com-tipo-chip .nota-etq-x { margin-left: 0.2rem; border: 0; background: transparent; color: inherit; cursor: pointer; font-size: var(--t-base); }
.com-lista { max-height: 14rem; overflow-y: auto; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 0.3rem 0.5rem; }
.com-opcion { display: flex; align-items: center; gap: 0.45rem; padding: 0.2rem 0; cursor: pointer; }
.com-editor { min-height: 8rem; max-height: 50vh; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 0.5rem 0.7rem; background: var(--color-surface); }
.com-fila .comunicado-cab .badge { margin-left: auto; }

/* ── Inicio de adm: salud de los servidores ──────────────────────────────────
   Gemelo del tablero de MexMail (adm.mexmail.com.mx/salud): mismos puntos,
   mismos colores, mismas tarjetas. El estado nunca va solo en el color: cada
   punto lleva su título y cada renglón su texto. */
.salud-punto { display: inline-block; width: 0.8rem; height: 0.8rem; border-radius: 50%; flex: none; background: var(--color-text-muted); vertical-align: middle; }
.salud-bien .salud-punto, .salud-punto.salud-bien { background: var(--color-success); }
.salud-aviso .salud-punto, .salud-punto.salud-aviso { background: var(--color-warning); }
.salud-mal .salud-punto, .salud-punto.salud-mal { background: var(--color-danger); }
.salud-desconocido .salud-punto, .salud-punto.salud-desconocido { background: transparent; outline: 2px dashed var(--color-text-muted); outline-offset: 1px; }
.salud-general { display: flex; align-items: center; gap: 0.8rem; padding: 0.9rem 1.1rem; border-radius: 10px; border: 1px solid var(--color-border); background: var(--color-surface); }
.salud-general .salud-punto { width: 1.4rem; height: 1.4rem; }
.salud-general strong { display: block; font-size: var(--t-xl); }
.salud-general.salud-mal { border-color: var(--color-danger); }
.salud-general.salud-aviso { border-color: var(--color-warning); }
.salud-meta { display: block; font-size: var(--t-md); color: var(--color-text-muted); }
.salud-servidores { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 1rem; }
/* `.card + .card` les da margen arriba a todas menos la primera: en la rejilla
   eso las desalineaba. */
.salud-servidores > .card, .salud-secciones > .card { margin-top: 0; }
.salud-servidor { border-top: 4px solid var(--color-border); }
.salud-servidor.salud-bien { border-top-color: var(--color-success); }
.salud-servidor.salud-aviso { border-top-color: var(--color-warning); }
.salud-servidor.salud-mal { border-top-color: var(--color-danger); }
.salud-servidor .salud-ir { display: inline-block; margin-top: 0.5rem; }
.salud-lista { list-style: none; margin: 0.6rem 0 0; padding: 0; }
.salud-lista li { display: flex; align-items: flex-start; gap: 0.7rem; padding: 0.55rem 0; border-top: 1px solid var(--color-border); }
.salud-lista li:first-child { border-top: 0; }
.salud-lista .salud-punto { margin-top: 0.3rem; }
.salud-que { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.salud-bloque { display: block; color: var(--color-text-muted); }
.salud-chip { display: inline-block; font-size: var(--t-xs); padding: 0 0.45rem; margin-right: 0.3rem; border-radius: 999px; border: 1px solid var(--color-border); color: var(--color-text-muted); }
.salud-ir { flex: none; color: var(--color-primary); text-decoration: none; white-space: nowrap; }
.salud-titulo-servidor { display: flex; align-items: center; gap: 0.5rem; margin: 0.8rem 0 0; font-size: var(--t-xl); }
/* Mosaico: las columnas las reparte super.js (`saludColumnas`), ver ahí por
   qué ni rejilla simple ni `columns` de CSS. */
.salud-secciones { display: grid; gap: 1rem; align-items: stretch; }
.salud-columna { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.salud-columna > .card { margin-top: 0; }
/* Sin huecos: la última tarjeta de cada columna se estira hasta el alto de la
   columna más larga, y todas terminan parejas abajo (2026-09-28). */
.salud-columna > .card:last-child { flex: 1; }
.salud-seccion h3 { display: flex; align-items: center; gap: 0.5rem; margin: 0; font-size: var(--t-lg); }
.salud-tabla { width: 100%; border-collapse: collapse; margin-top: 0.5rem; }
.salud-tabla td { padding: 0.4rem 0.3rem; border-top: 1px solid var(--color-border); vertical-align: top; overflow-wrap: anywhere; }
.salud-tabla tbody:first-child tr:first-child td { border-top: 0; }
.salud-tabla small { color: var(--color-text-muted); }
.salud-tabla a { color: var(--color-text); }
.salud-col-punto { width: 1.2rem; padding-top: 0.55rem !important; }
.salud-valor { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.salud-tenue { opacity: 0.75; }
.salud-tabla .salud-det td { border-top: 0; padding-top: 0; }
@media (max-width: 640px) { .salud-valor { white-space: normal; } }
/* Hasta 4 por renglón, como las tarjetas: en pantallas muy anchas iban 9 en
   fila y cada una quedaba diminuta. */
.salud-graficas { display: grid; grid-template-columns: repeat(auto-fill, minmax(max(20rem, calc((100% - 3.6rem) / 4)), 1fr)); gap: 1rem 1.2rem; margin-top: 0.8rem; }
.salud-grafica { margin: 0; }
.salud-grafica figcaption strong { display: block; font-size: var(--t-base); }
.grafica-tendencia { width: 100%; height: auto; max-height: 12rem; display: block; margin-top: 0.3rem; overflow: visible; }
.grafica-tendencia .rejilla { stroke: var(--color-border); stroke-width: 1; }
.grafica-tendencia .cifra { fill: var(--color-text-muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.grafica-tendencia .punto-t { opacity: 0; }
.grafica-tendencia .punto-t:hover { opacity: 1; stroke: var(--color-surface); stroke-width: 2; }
/* «Atendiéndose» (2026-09-28): verde CLARO, distinto del verde de «bien». Lo
   pendiente que ya tiene dueño deja de gritar, pero no se confunde con resuelto.
   Gemelo en panel.css de MexMail. */
.salud-atendiendo .salud-punto, .salud-punto.salud-atendiendo { background: color-mix(in srgb, var(--color-success) 40%, var(--color-surface)); outline: 2px solid var(--color-success); outline-offset: -2px; }
.salud-general.salud-atendiendo { border-color: color-mix(in srgb, var(--color-success) 50%, var(--color-border)); }
.salud-servidor.salud-atendiendo { border-top-color: color-mix(in srgb, var(--color-success) 45%, var(--color-surface)); }
.salud-lista li.salud-atendiendo { background: color-mix(in srgb, var(--color-success) 8%, transparent); }
.salud-quien { font-style: italic; }
.salud-acciones { flex: none; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 0.4rem; }
@media (max-width: 640px) { .salud-lista li { flex-wrap: wrap; } .salud-acciones { width: 100%; justify-content: flex-start; padding-left: 1.5rem; } }
/* «Pausar avisos» de un router (0187). */
.red-pausa-sel { width: auto; display: inline-block; padding: 0.25rem 0.5rem; font-size: var(--t-md); min-height: 0; }
.red-pausa { display: block; color: var(--color-warning); font-size: var(--t-sm); margin-top: 0.15rem; }
/* Filtro de sitios de Red (0188). */
.red-filtro-niveles { border: 0; padding: 0; margin: 0.8rem 0; display: grid; gap: 0.5rem; }
.red-filtro-niveles legend { font-weight: 600; margin-bottom: 0.4rem; }
.red-filtro-nivel { display: flex; gap: 0.7rem; align-items: flex-start; padding: 0.6rem 0.8rem; border: 1px solid var(--color-border); border-radius: 10px; cursor: pointer; }
.red-filtro-nivel.activo { border-color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 8%, transparent); }
.red-filtro-nivel input { margin-top: 0.25rem; }
.red-filtro-nivel small { display: block; }
.red-filtro-listas { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 1rem; }
.red-filtro-listas textarea { font-family: var(--font-mono, monospace); font-size: var(--t-base); }
.red-filtro-estado { padding: 0.6rem 0.8rem; border-radius: 8px; border: 1px solid var(--color-border); font-size: var(--t-base); margin: 0.4rem 0; }
.red-filtro-aplicada { border-color: var(--color-success); }
.red-filtro-pendiente, .red-filtro-sin_script, .red-filtro-sin_consultar { border-color: var(--color-warning); }
.red-filtro-error { border-color: var(--color-danger); }
/* Hotspot de Red (0189). */
.red-hs-usar { display: flex; gap: 0.7rem; align-items: flex-start; padding: 0.6rem 0.8rem; border: 1px solid var(--color-border); border-radius: 10px; cursor: pointer; margin-top: 0.4rem; }
.red-hs-usar input { margin-top: 0.25rem; }
/* La dirección en la VPN de soporte, en «Servidores y routers» */
.red-vpn-ip { display: block; font-family: var(--font-mono); opacity: 0.85; user-select: all; }
/* Listas de IPs maliciosas (0249) */
.red-ab-cifras { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.6rem; }
.red-ab-cifras > div { display: flex; flex-direction: column; padding: 0.5rem 0.7rem; border: 1px solid var(--color-border); border-radius: 10px; }
.red-ab-cifras strong { font-size: var(--t-2xl); }
.red-ab-error { color: var(--color-danger); }
.red-ab-exc { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.red-ab-exc li { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
/* La sección Seguridad (§41.46): las protecciones de cada EnlacesPYME y las alertas. */
.seg-prot { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 0.35rem 1rem; }
.seg-prot li { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.seg-prot li > span:first-child { display: inline-flex; flex: none; }
.seg-prot li > span:first-child svg { width: 1.1rem; height: 1.1rem; }
.seg-prot-ok > span:first-child { color: var(--color-success); }
.seg-prot-falta > span:first-child { color: var(--color-warning); }
.seg-alertas { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.seg-alerta { display: flex; align-items: center; gap: 0.7rem; padding: 0.6rem 0.8rem; border: 1px solid var(--color-border); border-left-width: 4px; border-radius: 10px; }
.seg-alerta.seg-sev-alerta { border-left-color: var(--color-danger); }
.seg-alerta.seg-sev-aviso { border-left-color: var(--color-warning); }
/* La alerta que abrió el botón de un correo de aviso: resaltada unos segundos. */
.seg-alerta.seg-alerta-resaltada { background: color-mix(in srgb, var(--color-primary) 14%, transparent); box-shadow: 0 0 0 2px var(--color-primary); transition: background .4s, box-shadow .4s; }
.seg-alerta-texto { display: flex; flex-direction: column; gap: 0.15rem; flex: 1; min-width: 0; overflow-wrap: anywhere; }
/* La consola SOC (§41.47). */
.soc-filtros { flex-wrap: wrap; gap: 0.5rem; }
.soc-filtros select { width: auto; min-width: 11rem; }
.soc-caso { cursor: pointer; }
.soc-caso:hover, .soc-caso:focus-visible { background: var(--color-surface-2, rgba(127, 127, 127, 0.08)); }
.soc-caso.soc-resuelto { opacity: 0.7; }
.soc-etiquetas { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0.35rem; }
.soc-etiqueta { font-size: var(--t-xs); padding: 0.1rem 0.5rem; border-radius: 999px; border: 1px solid var(--color-border); white-space: nowrap; }
.soc-et-urgente, .soc-et-rojo { background: var(--color-danger); color: #fff; border-color: transparent; }
.soc-et-vencido, .soc-et-ambar { background: var(--color-warning); color: #1a1a1a; border-color: transparent; }
.soc-et-verde { background: var(--color-success); color: var(--color-success-fg); border-color: transparent; }
.soc-cliente { border-left: 4px solid var(--color-border); }
.soc-cliente.soc-sem-rojo { border-left-color: var(--color-danger); }
.soc-cliente.soc-sem-ambar { border-left-color: var(--color-warning); }
.soc-cliente.soc-sem-verde { border-left-color: var(--color-success); }
.soc-cliente .red-ab-exc li > span:first-child { display: inline-flex; color: var(--color-warning); }
.soc-cliente .red-ab-exc svg { width: 1rem; height: 1rem; }
.soc-linea { list-style: none; margin: 0; padding: 0 0 0 0.9rem; border-left: 2px solid var(--color-border); display: flex; flex-direction: column; gap: 0.55rem; }
.soc-linea li { display: flex; flex-direction: column; gap: 0.1rem; position: relative; overflow-wrap: anywhere; }
.soc-linea li::before { content: ''; position: absolute; left: -1.27rem; top: 0.35rem; width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--color-border); }
.soc-linea li.seg-sev-alerta::before { background: var(--color-danger); }
.soc-linea li.seg-sev-aviso::before { background: var(--color-warning); }
.soc-linea li.soc-linea-nota::before { background: var(--color-primary); }
.soc-nota-texto { white-space: pre-line; }
/* El análisis de IA de un caso (§41.49). */
.soc-ia { border-left: 4px solid var(--color-primary); }
.soc-ia .soc-etiquetas { justify-content: flex-start; }
.soc-ia-baja { background: var(--color-success); color: var(--color-success-fg); border-color: transparent; }
.soc-ia-media { background: var(--color-warning); color: #1a1a1a; border-color: transparent; }
.soc-ia-alta, .soc-ia-urgente { background: var(--color-danger); color: #fff; border-color: transparent; }
.soc-ia-falsa { border-style: dashed; color: var(--color-text-muted, inherit); }
.soc-preg { border-left: 4px solid var(--color-primary); }
.soc-preg-resp { margin: 0.35rem 0 0; white-space: pre-line; }
.seg-resumen-texto { margin: 0; white-space: pre-line; }
.seg-resumen-cifras { border-collapse: collapse; font-size: var(--t-base); }
.seg-resumen-cifras td { padding: 0.2rem 0.75rem 0.2rem 0; border-bottom: 1px solid var(--color-border); }
.seg-resumen-cifras td:last-child { text-align: right; font-weight: 600; }
.soc-uj-normal { background: var(--color-success); color: var(--color-success-fg); border-color: transparent; }
.soc-uj-alto { background: var(--color-warning); color: #1a1a1a; border-color: transparent; }
.soc-uj-tope { background: var(--color-danger); color: #fff; border-color: transparent; }
.soc-ia-sugiere { border: 1px dashed var(--color-primary); border-radius: 8px; padding: 0.5rem 0.75rem; display: flex; flex-direction: column; gap: 0.35rem; }
.soc-ia-pasos { margin: 0.25rem 0 0; padding-left: 1.3rem; display: flex; flex-direction: column; gap: 0.25rem; }
.soc-ia-mensaje { margin: 0; padding: 0.5rem 0.75rem; border-left: 3px solid var(--color-border); background: var(--color-surface-2, rgba(127, 127, 127, 0.08)); border-radius: 6px; white-space: pre-line; }
/* Redes Wi-Fi (0248) */
.red-wifi-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.red-wifi-red { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; flex-wrap: wrap;
    padding: 0.6rem 0.8rem; border: 1px solid var(--color-border); border-radius: 10px; }
.red-wifi-datos { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 0.6rem; min-width: 0; }
.red-wifi-datos strong { overflow-wrap: anywhere; }
.red-wifi-datos small { flex-basis: 100%; }
.red-wifi-acciones { display: flex; gap: 0.4rem; }
.red-wifi-etq { font-size: var(--t-xs); padding: 0.05rem 0.5rem; border-radius: 999px; border: 1px solid var(--color-border); white-space: nowrap; }
.red-wifi-principal { border-color: var(--color-primary); color: var(--color-primary); }
.red-wifi-compatible { border-color: var(--color-warning); }
.red-wifi-hotspot { border-color: var(--carpeta-oficina, var(--color-border)); }
.red-wifi-sugerencia { flex-basis: 100%; padding-left: 0.5rem; border-left: 3px solid var(--color-warning); }
.red-wifi-aviso { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; padding: 0.5rem 0.7rem; border: 1px dashed var(--color-warning); border-radius: 10px; }
.red-modal-wifi { max-width: 32rem; max-height: 92vh; overflow-y: auto; }
/* Los pasos para dar de alta un Cudy (0254). */
.red-cudy-modo { display: flex; flex-direction: column; gap: 0.4rem; padding: 0.75rem 0.9rem; border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-surface-2); }
.red-cudy-modo p { margin: 0; }
.red-cudy-radio { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem 0.8rem; padding-top: 0.5rem; border-top: 1px solid var(--color-border); }
.red-cudy-radio-cab { display: flex; flex-direction: column; min-width: 9rem; flex: 1 1 9rem; }
.red-cudy-radio-cab span { font-weight: 600; }
.red-cudy-radio label { display: flex; flex-direction: column; gap: 0.15rem; font-size: var(--t-md); }
.red-cudy-pasos { margin: 0 0 0.8rem; padding-left: 1.2rem; font-size: var(--t-base); color: var(--color-text-muted); display: flex; flex-direction: column; gap: 0.35rem; overflow-wrap: anywhere; }
.red-wifi-tipos { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.red-wifi-tipos legend { margin-bottom: 0.3rem; }
.red-wifi-opcion { display: flex; gap: 0.6rem; align-items: flex-start; padding: 0.5rem 0.7rem; border: 1px solid var(--color-border); border-radius: 10px; cursor: pointer; }
.red-wifi-opcion input { margin-top: 0.25rem; }
.red-wifi-opcion span { display: flex; flex-direction: column; }
.red-wifi-mas { align-self: flex-start; }
@media (max-width: 640px) { .red-modal-wifi { max-width: none; width: 100%; max-height: 100vh; border-radius: 0; } }
.red-hs-usar small { display: block; }
.red-hs-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 0 1rem; }
.red-hs-fichas { display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); gap: 0.5rem; margin-top: 0.8rem; }
.red-hs-ficha { border: 1px dashed var(--color-border); border-radius: 8px; padding: 0.5rem 0.7rem; display: grid; gap: 0.2rem; }

/* Asas para cambiar el tamaño de una imagen en el editor de correo (rtImgAsas).
   La capa no atrapa el ratón (el clic sigue llegando a la imagen); solo las asas. */
.rt-img-asas { position: fixed; z-index: 3000; pointer-events: none; outline: 1px dashed var(--color-primary); }
.rt-img-asas[hidden] { display: none; }
.rt-img-asa {
    position: absolute; width: 12px; height: 12px; pointer-events: auto; touch-action: none;
    background: var(--color-surface); border: 2px solid var(--color-primary); border-radius: 2px;
}
.rt-img-asa-nw { left: -7px; top: -7px; cursor: nwse-resize; }
.rt-img-asa-se { right: -7px; bottom: -7px; cursor: nwse-resize; }
.rt-img-asa-ne { right: -7px; top: -7px; cursor: nesw-resize; }
.rt-img-asa-sw { left: -7px; bottom: -7px; cursor: nesw-resize; }

/* adm · Ayuda: resumen semanal del agente de ayuda. */
.ayuda-cifras { display: grid; grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: 0.8rem; }
.ayuda-cifras > div { display: flex; flex-direction: column; gap: 0.1rem; }
.ayuda-cifras strong { font-size: var(--t-2xl); font-variant-numeric: tabular-nums; }
.ayuda-cifras span { font-size: var(--t-sm); color: var(--color-text-2); }
.ayuda-no-util { border-top: 1px solid var(--color-border); padding: 0.7rem 0; }
.ayuda-no-util:first-of-type { border-top: 0; }
.ayuda-respuesta { white-space: pre-wrap; font: inherit; font-size: var(--t-md); background: var(--color-surface-2); border-radius: 6px; padding: 0.6rem 0.8rem; margin: 0.4rem 0 0; max-height: 24rem; overflow: auto; }

/* La primera vez en cada sección (2026-10-04): flota abajo a la derecha, sin
   mover nada; en el teléfono, encima de la barra de abajo. */
.recorrido {
    position: fixed; right: 1rem; bottom: 1rem; z-index: 45;
    width: min(calc(100vw - 2rem), 22rem);
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-md); box-shadow: 0 8px 32px var(--color-shadow);
    padding: 0.8rem 0.9rem; font-size: var(--t-md);
    animation: toast-in 0.2s ease;
}
.recorrido-cab { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.recorrido-cab strong { font-size: var(--t-lg); }
.recorrido ul { margin: 0.4rem 0 0.7rem; padding-left: 1.1rem; display: flex; flex-direction: column; gap: 0.35rem; color: var(--color-text-2); }
.recorrido-acciones { display: flex; justify-content: flex-end; gap: 0.4rem; flex-wrap: wrap; }
@media (max-width: 768px) {
    /* Por encima de la barra de abajo Y del botón redondo de «Redactar» (y
       otros flotantes de la esquina), que es justo lo que explica la tarjeta. */
    .recorrido { left: 1rem; right: 1rem; width: auto; bottom: calc(11rem + env(safe-area-inset-bottom)); }
}

/* «Preguntarle a su correo» (0207): el selector en la franja de la búsqueda y
   la tarjeta de la respuesta encima de los correos leídos. */
.buzon-modo { display: inline-flex; border: 1px solid var(--color-border); border-radius: 999px; overflow: hidden; flex: none; }
.buzon-modo button { background: none; border: 0; padding: 0.2rem 0.65rem; font: inherit; font-size: var(--t-sm); color: var(--color-text-2); cursor: pointer; }
.buzon-modo button.activo { background: var(--color-primary); color: var(--color-primary-fg); }
.buzon-pregunta {
    margin: 0.5rem 0.6rem; padding: 0.75rem 0.9rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--t-base);
    display: flex; flex-direction: column; gap: 0.5rem; flex: none;
}
.buzon-pregunta-cab { display: flex; align-items: center; gap: 0.4rem; color: var(--color-primary); }
.buzon-pregunta-cab svg { width: 1.1rem; height: 1.1rem; }
.buzon-pregunta-cab strong { color: var(--color-text); }
.buzon-pregunta-estado, .buzon-pregunta-pie, .buzon-pregunta-aviso { margin: 0; font-size: var(--t-sm); }
.buzon-pregunta-pie span + span::before { content: ' · '; }
.buzon-pregunta-citas { display: flex; flex-direction: column; gap: 0.25rem; }
.buzon-pregunta-citas > .texto-muted { font-size: var(--t-sm); }
/* En dos renglones SIEMPRE: la lista es una columna angosta también en PC
   (~330 px) y en uno solo el asunto se quedaba sin espacio. */
.buzon-pregunta-cita {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.1rem 0.6rem; align-items: baseline;
    text-align: left; background: var(--color-surface-2); border: 0; border-radius: 6px;
    padding: 0.35rem 0.55rem; font: inherit; font-size: var(--t-sm); color: var(--color-text); cursor: pointer;
}
.buzon-pregunta-cita:hover { outline: 1px solid var(--color-primary); }
.buzon-pregunta-de { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-pregunta-asunto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-pregunta-seguir { display: flex; gap: 0.4rem; }
.buzon-pregunta-seguir .input { flex: 1; min-width: 0; }
.buzon-pregunta-asunto { grid-column: 1 / -1; grid-row: 2; }

/* Un aviso que hay que atender en una tarjeta de adm (p. ej. precios de IA que faltan). */
.aviso-alerta { margin: 0; padding: 0.5rem 0.7rem; border-left: 3px solid var(--color-warning); background: var(--color-surface-2); border-radius: 6px; font-size: var(--t-md); }
.fila-desglose td { font-size: var(--t-md); color: var(--color-text-2); background: var(--color-surface-2); }

/* «Pregúntele a su correo» dentro del panel de ayuda: separado de las preguntas
   para el agente, porque estas van al correo. */
.soporte-correo-preg { border: 1px solid var(--color-border); border-radius: 10px; padding: 0.6rem 0.7rem; margin-bottom: 0.6rem; }
.soporte-correo-preg strong { display: flex; align-items: center; gap: 0.35rem; color: var(--color-text); font-size: var(--t-md); }
.soporte-correo-preg strong svg { width: 1rem; height: 1rem; color: var(--color-primary); }
/* Hotspot: compartir la cuenta recién creada (2026-10-05) */
.red-hs-compartir { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 0.75rem; padding: 0.6rem 0.75rem; border: 1px solid var(--color-success); border-radius: var(--radius-sm); }
/* Recordatorio rápido y su alarma (2026-10-05) */
.rr-form { display: flex; flex-direction: column; gap: 0.6rem; width: 100%; max-width: 26rem; margin-top: 1rem; text-align: left; }
.rr-cuando { display: block; font-size: var(--t-xl); }
.rr-alarma .voz-circulo { animation: rr-latido 1s ease-in-out infinite; }
@keyframes rr-latido { 50% { transform: scale(1.12); } }
button.voz-circulo { border: 0; cursor: pointer; }
/* Recordatorios en curso en Inicio (2026-10-05) */
.panel-rec { display: flex; align-items: center; gap: 0.4rem; }
.panel-rec .panel-ev { flex: 1; min-width: 0; }
.panel-rec-sonando .panel-ev-hora { color: var(--color-warning); font-weight: 600; }

/* «Compartir con MexCloud»: qué hacer con lo que llegó (2026-10-05). Botones
   grandes: se usa con el pulgar, recién llegado desde otra app. */
.compartido-resumen { margin: 0 0 .8rem; font-size: var(--t-base); color: var(--color-text-2); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.compartido-opciones { display: flex; flex-direction: column; gap: .45rem; }
.compartido-opcion { display: flex; align-items: center; gap: .8rem; width: 100%; padding: .75rem .85rem; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); color: inherit; text-align: left; cursor: pointer; font: inherit; }
.compartido-opcion:hover:not(:disabled) { background: var(--color-surface-2); }
.compartido-opcion:first-child { border-color: var(--color-primary); }
.compartido-opcion:disabled { opacity: .6; cursor: default; }
.compartido-opcion-ico { flex: none; width: 1.5rem; height: 1.5rem; color: var(--color-primary); }
.compartido-opcion-ico svg { width: 100%; height: 100%; }
.compartido-opcion-txt { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.compartido-opcion-etq { font-weight: 600; }
.compartido-opcion-desc { font-size: var(--t-md); }

/* ── Red: acceso delegado (0216) ─────────────────────────────────────────── */
/* «Solo ver»: la zona editable va en un fieldset deshabilitado; se ve igual,
   sin borde, y los controles atenuados dicen que no se pueden tocar. */
.red-solo-ver { border: 0; padding: 0; margin: 0; min-width: 0; }
.red-solo-ver:disabled input, .red-solo-ver:disabled select, .red-solo-ver:disabled button,
.red-solo-ver:disabled textarea { cursor: not-allowed; opacity: 0.6; }
.red-perm-lista { display: grid; gap: 0.5rem; margin-top: 0.8rem; }
.red-perm { border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-surface); }
.red-perm.abierto { border-color: var(--color-primary); }
.red-perm-fila { display: flex; align-items: center; gap: 0.6rem; width: 100%; padding: 0.65rem 0.8rem; background: none; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.red-perm-nombre { font-weight: 600; white-space: nowrap; }
.red-perm-resumen { flex: 1; min-width: 0; font-size: var(--t-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.red-perm-cuerpo { padding: 0 0.8rem 0.8rem; display: grid; gap: 0.8rem; }
/* Hijos de grid y de flex traen `min-width: auto`: sin esto, la descripción
   larga de un área ensanchaba la tarjeta fuera de la pantalla del teléfono. */
.red-perm, .red-perm-cuerpo > *, .red-perm-areas > * { min-width: 0; }
.red-perm-area small { overflow-wrap: anywhere; }
.red-perm-perfil { max-width: 22rem; }
.red-perm-areas { display: grid; gap: 0.5rem; }
.red-perm-area { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.4rem 1rem; padding: 0.5rem 0; border-top: 1px solid var(--color-border); }
.red-perm-area > div:first-child { display: flex; flex-direction: column; min-width: 0; flex: 1 1 12rem; }
.red-perm-area small { font-size: var(--t-sm); }
.red-perm-niveles { display: inline-flex; border: 1px solid var(--color-border); border-radius: 8px; overflow: hidden; }
.red-perm-nivel { position: relative; padding: 0.3rem 0.7rem; font-size: var(--t-md); cursor: pointer; }
.red-perm-nivel + .red-perm-nivel { border-left: 1px solid var(--color-border); }
.red-perm-nivel input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.red-perm-nivel.activo { background: var(--color-primary); color: #fff; }
.red-perm-routers { display: grid; gap: 0.3rem; }
.red-perm-lista-rt { display: grid; gap: 0.2rem; padding-left: 1.6rem; }
.red-perm-avisos { display: flex; align-items: flex-start; gap: 0.5rem; flex-wrap: nowrap; }
.red-perm-avisos > input { flex: none; margin-top: 0.2rem; }
.red-perm-avisos > span { flex: 1; min-width: 0; }
.red-perm-avisos small { display: block; font-size: var(--t-sm); }
.red-bit-detalle { font-size: var(--t-md); overflow-wrap: anywhere; }

/* Red · Archivos de la oficina (0218): carpetas compartidas de un servidor Linux. */
.red-arch-nuevo { gap: .5rem; flex-wrap: wrap; margin-bottom: .75rem; }
.red-arch-nuevo .input { flex: 1 1 14rem; min-width: 0; }
.red-arch-recurso { border-top: 1px solid var(--color-border); padding: .75rem 0; display: grid; gap: .35rem; }
/* Intentos desde equipos no asignados (§41.24): uno por renglón, con sus botones. */
.red-arch-negado { border-top: 1px solid var(--color-border); padding: .65rem 0; display: grid; gap: .3rem; }
.red-arch-negado .fila { gap: .5rem; flex-wrap: wrap; }
/* Ransomware (0246): las PCs aisladas, en rojo y arriba de todo. */
.red-aislados { border: 2px solid var(--color-danger); }
.red-aislado { border-top: 1px solid var(--color-border); padding: .7rem 0; display: grid; gap: .3rem; }
.red-aislado .fila { gap: .5rem; flex-wrap: wrap; }
.red-aislado-ej { margin: 0; padding-left: 1.1rem; font-size: var(--t-md); overflow-wrap: anywhere; }
.red-arch-cab { gap: .5rem; align-items: center; flex-wrap: wrap; }
.red-arch-cab .red-nombre { flex: 1 1 12rem; min-width: 0; font-weight: 600; }
.red-arch-quien, .red-arch-personas, .red-arch-equipos { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.red-arch-quien li, .red-arch-equipos li { gap: .5rem; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.red-arch-persona { flex: 1 1 10rem; min-width: 0; overflow-wrap: anywhere; }
.red-arch-nivel { flex: 0 1 12rem; min-width: 0; }
.red-arch-personas li { display: grid; gap: .1rem; padding: .4rem 0; border-top: 1px solid var(--color-border); }
.red-arch-personal { gap: .4rem; align-items: center; font-size: var(--t-base); margin-top: .2rem; }
/* La pestaña «Servidor» se ordena por dónde se trabaja cada carpeta (§41.25):
   arriba, los dos sentidos como botones; abajo, una cabecera por sección. */
.red-flujos { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .5rem; margin-top: .75rem; }
.red-flujo { display: flex; gap: .65rem; align-items: center; text-align: left; padding: .6rem .75rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); color: var(--color-text); font: inherit; cursor: pointer; min-width: 0; }
.red-flujo:hover { border-color: var(--color-primary); }
.red-flujo > span:last-child { display: grid; gap: .1rem; min-width: 0; }
.red-flujo small { font-size: var(--t-sm); }
.red-flujo-ic, .red-seccion-ic { flex: none; color: var(--color-primary); display: inline-flex; }
.red-flujo-ic svg { width: 1.5rem; height: 1.5rem; }
.red-seccion { display: flex; gap: .7rem; align-items: center; justify-content: center; text-align: center; margin: 1.25rem auto 0; width: 100%; max-width: min(52rem, 100%); padding: 0 .25rem; scroll-margin-top: 5rem; }
.red-seccion-ic svg { width: 1.6rem; height: 1.6rem; }
.red-seccion h2 { margin: 0; font-size: var(--t-xl); font-weight: 600; font-family: var(--font-title); }
.red-seccion p { margin: .2rem 0 0; font-size: var(--t-base); }
.red-rest-que { border: 0; padding: 0; margin: .5rem 0; display: grid; gap: .35rem; }
/* Acceso remoto por VPN de soporte (§41.26): adm y panel del socio. */
.vpn-soporte .card-forma { margin-inline: auto; width: 100%; }
.vpn-lista { list-style: none; margin: 0 0 .75rem; padding: 0; display: grid; }
.vpn-lista li { display: flex; align-items: center; gap: .6rem; padding: .5rem 0; border-top: 1px solid var(--color-border); }
.vpn-dato { flex: 1 1 auto; min-width: 0; display: grid; gap: .1rem; }
.vpn-dato strong { overflow-wrap: anywhere; }
.vpn-dato small { font-size: var(--t-sm); }
.vpn-punto { flex: none; width: .6rem; height: .6rem; border-radius: 50%; background: var(--color-border); }
.vpn-punto.si { background: var(--color-success); }
.vpn-comando { font-size: var(--t-sm); background: var(--color-surface-2); padding: .15rem .4rem; border-radius: var(--radius-sm); overflow-wrap: anywhere; justify-self: start; }
.vpn-llaves { width: 100%; font-family: ui-monospace, monospace; font-size: var(--t-sm); margin-bottom: .5rem; }
.vpn-designar { gap: .4rem; align-items: center; flex: none; font-size: var(--t-base); }
.vpn-qr { display: flex; justify-content: center; margin: .75rem 0; }
.vpn-qr svg { width: min(18rem, 80vw); height: auto; background: #fff; padding: .5rem; border-radius: var(--radius-md); }
/* El selector de carpetas de la nube, en árbol: flecha, nombre y peso, y el
   botón a la derecha. La sangría sale del nivel (--nivel). */
.red-nube-arbol { list-style: none; margin: .5rem 0; padding: 0; max-height: min(60vh, 32rem); overflow-y: auto; border-top: 1px solid var(--color-border); }
.red-nube-fila { display: flex; align-items: center; gap: .5rem; padding: .45rem .25rem .45rem calc(.25rem + var(--nivel, 0) * 1.25rem); border-bottom: 1px solid var(--color-border); }
.red-nube-dato { flex: 1 1 auto; min-width: 0; display: grid; gap: .05rem; }
.red-nube-dato strong { overflow-wrap: anywhere; }
.red-nube-dato small { font-size: var(--t-sm); }
.red-nube-fila > .btn { flex: none; }
.red-nube-flecha, .red-nube-flecha-vacia { flex: none; width: 1.75rem; height: 1.75rem; }
.red-nube-flecha { display: inline-flex; align-items: center; justify-content: center; border: 0; background: none; color: var(--color-text-2); border-radius: var(--radius-sm); cursor: pointer; padding: 0; }
.red-nube-flecha:hover { background: var(--color-surface-2); }
.red-nube-flecha svg { width: 1.1rem; height: 1.1rem; transition: transform .15s; }
.red-nube-flecha.abierta svg { transform: rotate(90deg); }
.red-rest-que legend { font-weight: 600; margin-bottom: .25rem; }
.red-rest-que .fila { gap: .5rem; align-items: center; }

/* Ordenar tickets en el teléfono (las cabeceras de la tabla no se ven). */
.tk-orden-movil { display: flex; gap: 0.4rem; align-items: center; margin: 0.4rem 0; }
.tk-orden-movil select { flex: 1; min-width: 0; }
@media (max-width: 768px) { .tk-orden-movil.solo-movil { display: flex !important; } }
/* El rescate tras un ransomware (0247): las carpetas que tocó la PC aislada. */
.red-aislado-carpetas { display: grid; gap: .45rem; margin: .3rem 0; }
.red-aislado-carpeta { display: grid; gap: .3rem; padding: .4rem .6rem; border-radius: 8px; background: var(--color-surface-2, rgba(127,127,127,.08)); }
.red-aislado-carpeta .fila { gap: .5rem; flex-wrap: wrap; }

/* ── «Mi perfil → MasAdmin» (0256) ─────────────────────────────────────────── */
.masadmin-lista { display: flex; flex-direction: column; gap: 0.6rem; }
.masadmin-vinculo {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    padding: 0.7rem 0.85rem;
}
.masadmin-vinculo.vencida { border-color: var(--color-warning); }
.masadmin-vinculo-cab { display: flex; align-items: center; gap: 0.45rem; }
.masadmin-vinculo-cab svg { width: 18px; height: 18px; flex: none; }
.masadmin-estado {
    margin-left: auto;
    font-size: var(--t-xs);
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--color-surface-2);
}
.masadmin-estado.estado-activa { color: var(--color-success); }
.masadmin-estado.estado-vencida { color: var(--color-warning); }
.masadmin-vinculo-det { display: flex; flex-direction: column; gap: 0.1rem; font-size: var(--t-sm); margin-top: 0.3rem; }
.masadmin-form {
    margin-top: 0.8rem;
    padding: 0.8rem 0.85rem;
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-md);
}
.masadmin-casilla { display: flex; align-items: flex-start; gap: 0.5rem; font-size: var(--t-md); margin: 0.2rem 0 0.6rem; cursor: pointer; }
.masadmin-casilla input { margin-top: 0.2rem; flex: none; }

/* ── La Bóveda (§45): franja dentro de ella y su diálogo ── */
.boveda-franja { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem 0.6rem; margin: 0.4rem 0; padding: 0.5rem 0.75rem; border: 1px solid var(--color-border); border-left: 4px solid var(--color-primary); border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--t-base); }
.boveda-franja-icono { display: inline-flex; color: var(--color-primary); }
.boveda-franja-icono svg { width: 1.1rem; height: 1.1rem; }
.boveda-franja-texto { flex: 1 1 16rem; min-width: 0; }
.boveda-franja-botones { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.boveda-aviso { padding: 0.6rem 0.75rem; border-radius: var(--radius-md); border: 1px solid var(--color-warning); background: color-mix(in srgb, var(--color-warning) 12%, transparent); font-size: var(--t-base); }
.boveda-llave { font-family: var(--font-mono); font-size: var(--t-sm); word-break: break-all; padding: 0.5rem; border-radius: var(--radius-sm); border: 1px solid var(--color-border); background: var(--color-bg); }
.boveda-error { color: var(--color-danger); font-size: var(--t-base); margin: 0.25rem 0 0; }
.boveda-titulo { display: flex; align-items: center; gap: 0.5rem; }
.boveda-titulo > span:not(.boveda-franja-icono) { flex: 1; }
.boveda-titulo .boveda-franja-icono { color: var(--carpeta-boveda, var(--color-primary)); }
.boveda-franja { border-left-color: var(--carpeta-boveda, var(--color-primary)); }
.boveda-franja-icono { color: var(--carpeta-boveda, var(--color-primary)); }
.boveda-info { margin: 0 0 1rem; display: grid; gap: 0.75rem; max-height: 60vh; overflow-y: auto; }
.boveda-info dt { font-weight: 600; margin-bottom: 0.15rem; }
.boveda-info dd { margin: 0; font-size: var(--t-base); color: var(--color-text-muted); line-height: 1.45; }
.boveda-olvide { background: none; border: 0; padding: 0; color: var(--color-primary); text-decoration: underline; cursor: pointer; font: inherit; font-size: var(--t-base); }

/* «Pruébelo gratis» bajo el formulario de entrar (§46). */
.login-registro { text-align: center; font-size: var(--t-base); margin: 1rem 0 0; }
.login-registro a { color: var(--color-primary); font-weight: 600; }

/* La prueba gratis (§46): franja en Inicio y en Archivos. */
.prueba-franja { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem 0.6rem; margin: 0.4rem 0 0.75rem; padding: 0.55rem 0.75rem; border: 1px solid var(--color-border); border-left: 4px solid var(--color-primary); border-radius: var(--radius-md); background: var(--color-surface); font-size: var(--t-base); }
.prueba-franja.vencida { border-left-color: var(--color-warning); background: color-mix(in srgb, var(--color-warning) 10%, var(--color-surface)); }
.prueba-franja-icono { display: inline-flex; color: var(--color-primary); }
.prueba-franja.vencida .prueba-franja-icono { color: var(--color-warning); }
.prueba-franja-icono svg { width: 1.1rem; height: 1.1rem; }
.prueba-franja-texto { flex: 1 1 16rem; min-width: 0; }

/* «Mi dominio de correo» (§46, fase 2). */
.prueba-franja-dom { display: block; font-size: var(--t-md); color: var(--color-text-muted); }
.prueba-dom { max-height: 90vh; overflow-y: auto; }
.prueba-dom-paso { font-size: var(--t-lg); margin: 1rem 0 0.4rem; }
.prueba-dom-tabla { display: grid; gap: 0.4rem; margin: 0.6rem 0; }
.prueba-dom-fila { display: grid; grid-template-columns: auto 4rem 1fr auto; gap: 0.5rem; align-items: center; padding: 0.45rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
.prueba-dom-fila:not(:has(.prueba-dom-estado)) { grid-template-columns: 4rem 1fr auto; }
.prueba-dom-fila.bien { border-left: 4px solid var(--color-success); }
.prueba-dom-fila.mal { border-left: 4px solid var(--color-danger); }
.prueba-dom-estado { font-weight: 700; }
.prueba-dom-fila.bien .prueba-dom-estado { color: var(--color-success); }
.prueba-dom-fila.mal .prueba-dom-estado { color: var(--color-danger); }
.prueba-dom-tipo { font-family: var(--font-mono); font-size: var(--t-sm); font-weight: 600; }
.prueba-dom-dato { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; font-size: var(--t-md); }
.prueba-dom-dato code { font-family: var(--font-mono); font-size: var(--t-sm); word-break: break-all; }
.prueba-dom-listo { font-weight: 600; color: var(--color-success); }
.prueba-dom-buzones { margin: 0.4rem 0; padding-left: 1.2rem; }
.prueba-dom-arroba { display: flex; align-items: center; gap: 0.4rem; }
.prueba-dom-arroba .input { flex: 1; min-width: 0; }
.prueba-dom-arroba span { font-size: var(--t-base); color: var(--color-text-muted); white-space: nowrap; }
@media (max-width: 640px) {
    .prueba-dom-fila, .prueba-dom-fila:not(:has(.prueba-dom-estado)) { grid-template-columns: auto 1fr; }
    .prueba-dom-fila .btn { grid-column: 1 / -1; justify-self: end; }
}

/* Notas por partes (2026-10-23): «Ver más notas» al final de la lista. */
.notas-mas { display: flex; justify-content: center; padding: 1rem 0 1.5rem; }

/* Dónde buscar en el correo (2026-10-24): el nombre de la carpeta puede ser largo. */
.buzon-donde button { max-width: 11rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 640px) { .buzon-busq-info { flex-wrap: wrap; } .buzon-donde button { max-width: 8rem; } }

/* ── Filtros de la búsqueda del correo («como Thunderbird», 2026-10-24) ──── */
.busqueda-filtros { position: relative; }
.busqueda-filtros.activo { color: var(--color-primary); }
.busqueda-filtros-n {
    position: absolute; top: 0; right: 0; min-width: 0.95rem; height: 0.95rem; padding: 0 0.2rem;
    border-radius: var(--radius-full); background: var(--color-primary); color: #fff;
    font-size: var(--t-2xs); font-weight: 600; line-height: 0.95rem; text-align: center;
}
.correo-filtros { max-width: 34rem; }
.correo-filtros-en { display: flex; flex-direction: column; gap: 0.3rem; }
.correo-filtros-rejilla { display: grid; grid-template-columns: auto 1fr; gap: 0.5rem 0.75rem; align-items: center; margin-bottom: 0.75rem; }
.correo-filtros-fechas { display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; }
.correo-filtros-fechas label { display: flex; align-items: center; gap: 0.4rem; }
.correo-filtros-fechas .input { width: auto; }
.correo-filtros-adj { margin-bottom: 0.5rem; }
.correo-filtros-pista { font-size: var(--t-sm); margin: 0.25rem 0 0.5rem; }
.correo-filtros-error { color: var(--color-danger); font-size: var(--t-md); margin: 0 0 0.5rem; }
.correo-filtros .fila-fin { display: flex; align-items: center; gap: 0.5rem; }
.correo-filtros .fila-fin .crece { flex: 1; }
@media (max-width: 640px) {
    .modal-fondo:has(> .correo-filtros) { padding: 0; }
    .modal.correo-filtros { max-width: none; width: 100%; height: 100%; max-height: none; border-radius: 0; margin: 0; overflow-y: auto; }
    .correo-filtros-rejilla { grid-template-columns: 1fr; gap: 0.25rem; }
    .correo-filtros-rejilla > label, .correo-filtros-rejilla > span { margin-top: 0.4rem; }
}
/* Las fichas de los filtros en la franja de la búsqueda. */
.buzon-ficha {
    display: inline-flex; align-items: center; max-width: 16rem; flex: none;
    border: 1px solid var(--color-border); border-radius: var(--radius-full); background: var(--color-surface);
}
.buzon-ficha-txt { background: none; border: none; padding: 0.1rem 0.15rem 0.1rem 0.55rem; font: inherit; font-size: var(--t-sm); color: inherit; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.buzon-ficha-x { display: inline-flex; background: none; border: none; padding: 0.15rem 0.35rem 0.15rem 0.2rem; color: var(--color-text-muted); cursor: pointer; }
.buzon-ficha-x:hover { color: var(--color-danger); }
.buzon-ficha-x svg { width: 0.75rem; height: 0.75rem; }
.buzon-busq-filtros svg { width: 1rem; height: 1rem; }
.buzon-adj-tope { margin: 0; padding: 0.35rem 0.6rem; font-size: var(--t-sm); background: var(--color-surface-2); border-bottom: 1px solid var(--color-border); }

/* Archivos arrastrados sobre una ventana del escritorio (Correo, Notas,
   Mensajes, Chat IA): el letrero de lo que pasará al soltar. No intercepta
   nada: el soltar lo recibe la ventana entera. */
.soltar-aviso {
    position: fixed; inset: 0.5rem; z-index: 90; pointer-events: none;
    display: flex; align-items: center; justify-content: center; gap: 0.6rem; padding: 1rem;
    border: 2px dashed var(--color-primary); border-radius: var(--radius-lg, 12px);
    background: color-mix(in srgb, var(--color-primary) 10%, transparent);
    color: var(--color-primary); font-weight: 600; font-size: var(--t-xl); text-align: center;
}
.soltar-aviso svg { width: 1.4rem; height: 1.4rem; flex: none; }
.soltar-aviso span:last-child {
    background: var(--color-surface); padding: 0.55rem 0.9rem; border-radius: var(--radius-full);
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.15); max-width: 32rem;
}

/* Control de MasAdmin, etapa 2 (2026-10-25): filtros como etiquetas con ✕ y el
   buscador de clientes y proveedores (Resumen y widget del escritorio). */
.ctx-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; }
.ctx-chip { display: inline-flex; align-items: center; gap: 0.25rem; max-width: 100%; padding: 1px 4px 1px 9px; border-radius: 999px; background: var(--color-primary); color: var(--color-primary-fg); font-size: var(--t-xs); }
.ctx-chip > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ctx-chip button { border: 0; background: rgba(0, 0, 0, 0.18); color: inherit; border-radius: 50%; width: 1.15rem; height: 1.15rem; font-size: var(--t-2xs); line-height: 1; cursor: pointer; flex: none; }
.ctx-chip-mas { border: 1px dashed var(--color-border); background: none; color: inherit; border-radius: 999px; padding: 1px 9px; font-size: var(--t-xs); cursor: pointer; opacity: 0.85; }
.ctx-busca { position: relative; }
.ctx-busca .ctx-chip { margin-bottom: 0.3rem; }
.ctx-busca-lista { position: absolute; z-index: 20; left: 0; right: 0; top: 100%; margin-top: 2px; max-height: 14rem; overflow: auto; padding: 0.25rem; border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-surface); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18); }
.ctx-busca-lista p { margin: 0.3rem 0.4rem; font-size: var(--t-sm); }
.ctx-busca-lista button { display: block; width: 100%; text-align: left; padding: 0.35rem 0.5rem; border: 0; border-radius: 6px; background: none; color: inherit; font-size: var(--t-md); cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctx-busca-lista button:hover { background: var(--color-surface-2, var(--color-bg)); }
.res-erp-ctx { flex: 1 1 auto; min-width: 0; font-size: var(--t-xs); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.res-erp-ctrl { display: flex; flex-direction: column; gap: 0.55rem; }
.res-erp-ctrl-periodos { flex-wrap: wrap; align-self: flex-start; }
.res-erp-ctrl-fila { display: flex; flex-wrap: wrap; gap: 0.5rem 0.8rem; }
.res-erp-ctrl-fila > label { display: flex; flex-direction: column; gap: 0.15rem; flex: 1 1 11rem; min-width: 0; font-size: var(--t-sm); color: var(--color-text-muted); }
.res-erp-ctrl-fila .input { font-size: var(--t-md); padding: 0.3rem 0.45rem; color: var(--color-text); }
/* «Todas las empresas» (2026-10-25): de qué empresa es cada renglón y cuánto pone cada una. */
.erp-emp { display: inline-block; margin-right: 0.35rem; padding: 0 5px; border-radius: 4px; background: var(--color-surface-2, rgba(127, 127, 127, 0.18)); border: 1px solid var(--color-border); font-size: var(--t-2xs); font-weight: 600; letter-spacing: 0.02em; vertical-align: 1px; }
.esc-w-erp-desglose, .res-erp-desglose { margin: 0.35rem 0 0; font-size: var(--t-xs); opacity: 0.75; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.res-erp-desglose { color: var(--color-text-muted); opacity: 1; white-space: normal; }

/* «Mi indicador» de MasAdmin (etapa 3, 2026-10-25): widget del escritorio, cuadro
   del Resumen y su armador. Hereda los colores del lugar donde está. */
.ind { display: flex; flex-direction: column; gap: 0.35rem; min-height: 0; flex: 1; overflow: hidden; }
.ind-ctx { margin: 0; font-size: var(--t-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ind-cifra { display: flex; flex-direction: column; align-items: flex-start; gap: 0.1rem; border: 0; background: none; color: inherit; cursor: pointer; text-align: left; padding: 0; }
.ind-cifra strong { font-size: var(--t-3xl); font-variant-numeric: tabular-nums; line-height: 1.15; }
.ind.tam-c .ind-cifra strong { font-size: var(--t-2xl); }
.ind-cifra > span { font-size: var(--t-sm); opacity: 0.8; }
.ind-delta.sube { color: var(--color-success); opacity: 1 !important; }
.ind-delta.baja { color: var(--color-danger); opacity: 1 !important; }
.ind-rank { display: flex; flex-direction: column; gap: 0.15rem; overflow: auto; min-height: 0; }
.ind-rank-fila { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto 4px; column-gap: 0.6rem; row-gap: 2px; width: 100%; padding: 0.2rem 0.15rem; border: 0; background: none; color: inherit; cursor: pointer; text-align: left; font-size: var(--t-sm); border-radius: 4px; }
.ind-rank-fila:hover { background: rgba(127, 127, 127, 0.12); }
.ind-rank-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ind-rank-val { font-variant-numeric: tabular-nums; }
.ind-rank-barra { grid-column: 1 / -1; height: 4px; border-radius: 2px; background: rgba(127, 127, 127, 0.15); overflow: hidden; }
.ind-rank-barra i { display: block; height: 100%; border-radius: 2px; background: var(--color-primary); }
.ind-tend { display: flex; flex-direction: column; gap: 0.2rem; min-height: 0; }
.ind-tend-graf svg { display: block; width: 100%; height: 120px; }
.ind.tam-c .ind-tend-graf svg { height: 70px; }
.ind-graf-barra { fill: var(--color-primary); opacity: 0.85; }
.ind-graf-barra.neg { fill: var(--color-danger); }
.ind-graf-barra:hover { opacity: 1; }
.ind-graf-cero { stroke: currentColor; stroke-opacity: 0.25; stroke-width: 1; }
.ind-graf-etq { fill: currentColor; fill-opacity: 0.65; font-size: 10px; }
.ind-tend-pie { margin: 0; font-size: var(--t-xs); opacity: 0.8; }
.ind-cruce { overflow: auto; min-height: 0; max-width: 100%; }
.ind-cruce table { border-collapse: collapse; font-size: var(--t-xs); width: 100%; }
.ind-cruce th, .ind-cruce td { padding: 0.2rem 0.4rem; text-align: right; white-space: nowrap; border-bottom: 1px solid rgba(127, 127, 127, 0.2); font-variant-numeric: tabular-nums; }
.ind-cruce thead th { font-weight: 600; opacity: 0.8; }
.ind-cruce tbody th { text-align: left; font-weight: 500; max-width: 12rem; overflow: hidden; text-overflow: ellipsis; }
.ind-cruce tr.filtrable, .res-erp-card .ind-cruce tbody tr { cursor: pointer; }
.ind-cruce-tot { font-weight: 600; }
.ind-dlg { max-width: 34rem; width: 100%; }
.ind-pista { font-size: var(--t-md); margin: 0 0 0.6rem; }
.ind-campos { display: flex; flex-direction: column; gap: 0.6rem; }
.ind-campos .campo { display: flex; flex-direction: column; gap: 0.2rem; margin: 0; }
.ind-campos .campo > span { font-size: var(--t-sm); color: var(--color-text-muted); }
.ind-vistas { align-self: flex-start; flex-wrap: wrap; }
.ind-vistas button:disabled { opacity: 0.4; cursor: default; }
.ind-existentes { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; margin-bottom: 0.7rem; font-size: var(--t-md); }
.ind-perfil-fila { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; padding: 0.15rem 0; }
.ind-perfil-acc { display: inline-flex; gap: 0.3rem; }

/* ---- Markdown de archivos (.md, 2026-10-25): vista previa, chat y editor ---- */
.md-barra { display: flex; justify-content: flex-end; margin-bottom: 0.5rem; }
.md-remotas { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 0 0 0.6rem; padding: 0.45rem 0.7rem; border-radius: var(--radius-md); background: var(--color-surface-2, var(--color-surface)); border: 1px solid var(--color-border); font-size: var(--t-md); }
.md-vista { line-height: 1.6; overflow-wrap: anywhere; color: var(--color-text); padding: 0.2rem 0.4rem; }
.md-vista > :first-child { margin-top: 0; }
.md-vista h1 { font-size: var(--t-3xl); margin: 1.2rem 0 0.6rem; padding-bottom: 0.25rem; border-bottom: 1px solid var(--color-border); }
.md-vista h2 { font-size: var(--t-2xl); margin: 1.1rem 0 0.5rem; padding-bottom: 0.2rem; border-bottom: 1px solid var(--color-border); }
.md-vista h3 { font-size: var(--t-xl); margin: 1rem 0 0.4rem; }
.md-vista h4, .md-vista h5, .md-vista h6 { font-size: var(--t-lg); margin: 0.9rem 0 0.35rem; }
.md-vista p { margin: 0.55rem 0; }
.md-vista ul, .md-vista ol { padding-left: 1.5rem; margin: 0.5rem 0; }
.md-vista li + li { margin-top: 0.15rem; }
.md-vista blockquote { margin: 0.7rem 0; padding: 0.4rem 0.9rem; border-left: 3px solid var(--color-primary); background: var(--color-surface-2, var(--color-surface)); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; color: var(--color-text-muted); }
.md-vista pre { background: var(--color-surface-2, var(--color-surface)); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.7rem 0.85rem; overflow-x: auto; font-size: var(--t-md); }
.md-vista code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.88em; }
.md-vista :not(pre) > code { background: var(--color-surface-2, var(--color-surface)); border: 1px solid var(--color-border); border-radius: 0.3rem; padding: 0.1rem 0.35rem; }
.md-vista table { border-collapse: collapse; margin: 0.7rem 0; display: block; max-width: 100%; overflow-x: auto; }
.md-vista th, .md-vista td { border: 1px solid var(--color-border); padding: 0.35rem 0.6rem; text-align: left; }
.md-vista th { background: var(--color-surface-2, var(--color-surface)); }
.md-vista img { max-width: 100%; height: auto; border-radius: var(--radius-sm); }
.md-vista hr { border: 0; border-top: 1px solid var(--color-border); margin: 1.2rem 0; }
.md-vista a { color: var(--color-primary); }
.md-img-bloq { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.15rem 0.5rem; border: 1px dashed var(--color-border); border-radius: var(--radius-sm); font-size: var(--t-sm); color: var(--color-text-muted); }
.md-img-falta { min-width: 2rem; min-height: 1.2rem; outline: 1px dashed var(--color-border); }
.preview-texto-wrap .md-vista { max-width: 52rem; }

/* ---- El editor como aplicación (2026-10-25): inicio, recientes, nuevo y vista de Markdown ---- */
.editor-inicio { display: flex; flex-direction: column; gap: 0.6rem; flex: 1 1 auto; min-height: 9rem; overflow-y: auto; padding: 0.4rem 0.2rem; }
.editor-inicio > p { margin: 0; }
.editor-rec-tit { font-size: var(--t-lg); margin: 0.8rem 0 0.2rem; }
.editor-recientes { list-style: none; margin: 0; padding: 0; border: 1px solid var(--color-border); border-radius: var(--radius-md); }
.editor-recientes li { display: flex; align-items: center; }
.editor-recientes li + li { border-top: 1px solid var(--color-border); }
.editor-recientes li.texto-muted { padding: 0.7rem; font-size: var(--t-base); }
.editor-rec { flex: 1; min-width: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto; column-gap: 0.6rem; align-items: center; padding: 0.45rem 0.7rem; border: 0; background: none; color: var(--color-text); text-align: left; cursor: pointer; }
.editor-rec:hover { background: var(--color-surface-2, var(--color-surface)); }
.editor-rec > span:first-child { grid-row: 1 / 3; display: inline-flex; opacity: 0.7; }
.editor-rec > span:first-child svg { width: 1.05rem; height: 1.05rem; }
.editor-rec-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-base); }
.editor-rec-donde { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-xs); }
.editor-rec-x { margin-right: 0.3rem; opacity: 0.6; }
.editor-nuevo { padding: 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2, var(--color-surface)); }
.editor-nuevo p { margin: 0; font-size: var(--t-md); }
.editor-exp-rec { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; font-size: var(--t-sm); }
.editor-exp-rec .btn { max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.editor > .editor-cuerpo { flex: 1 1 auto; min-height: 9rem; display: flex; gap: 0.6rem; }
.editor-cuerpo > .editor-cm { flex: 1 1 0; min-width: 0; }
.editor-cuerpo > .editor-md { flex: 1 1 0; min-width: 0; overflow-y: auto; border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.6rem 0.9rem; }
/* En el teléfono no caben los dos: con la vista previa puesta se ve solo ella. */
@media (max-width: 768px) {
    .editor-cuerpo.con-vista > .editor-cm { display: none; }
}

/* ── Utilidades (revisión visual, etapa 0, 2026-10-28) ──────────────────────────
   Sustituyen los style="…" más repetidos de app.html, con los MISMOS valores. Llevan
   !important a propósito: un style en línea le ganaba a cualquier regla del componente,
   y la clase tiene que seguir ganando igual o la pantalla cambia. Nada de `display`
   aquí: le ganaría a x-show (que pone display en línea). */
.u-t-sm   { font-size: var(--t-sm) !important; }
.u-t-md   { font-size: var(--t-md) !important; }
.u-t-base { font-size: var(--t-base) !important; }
.u-t-lg   { font-size: var(--t-lg) !important; }
.u-gap-s  { gap: 0.4rem !important; }
.u-gap-m  { gap: 0.5rem !important; }
.u-envuelve { flex-wrap: wrap !important; }
.u-flex1  { flex: 1 !important; }
.u-crece  { flex: 1 !important; min-width: 0 !important; }
.u-m0     { margin: 0 !important; }
.u-mt-2   { margin-top: 0.5rem !important; }
.u-mt-4   { margin-top: 1rem !important; }
.u-mb-4   { margin-bottom: 1rem !important; }
.u-una-col { grid-template-columns: 1fr !important; }
.u-ancho-centro { width: 100% !important; justify-content: center !important; }
.u-peligro { color: var(--color-danger) !important; }
.u-al-final { justify-content: flex-end !important; }
.u-der    { text-align: right !important; }
.u-fila-completa { grid-column: 1 / -1 !important; }

/* ── Esqueletos de carga (revisión visual, etapa 1, 2026-10-28) ────────────────
   En lugar de «Cargando…»: la forma de lo que viene (renglones con su ícono). La app
   se siente más rápida aunque tarde lo mismo. Quietos con «reducir movimiento». */
.esqueleto { display: grid; gap: 0.75rem; padding: 0.5rem 0.25rem; }
.esqueleto > span { display: grid; grid-template-columns: 2rem 1fr; gap: 0.75rem; align-items: center; }
.esqueleto > span::before, .esqueleto > span::after {
    content: ''; display: block; height: 0.8rem; border-radius: var(--radius-sm);
    background: linear-gradient(90deg, var(--color-surface-2) 0%, color-mix(in srgb, var(--color-surface-2) 35%, var(--color-border)) 50%, var(--color-surface-2) 100%);
    background-size: 200% 100%; animation: esq-brillo 1.4s linear infinite;
}
.esqueleto > span::before { height: 2rem; border-radius: var(--radius-md); }
.esqueleto > span:nth-child(3n+1)::after { width: 78%; }
.esqueleto > span:nth-child(3n+2)::after { width: 56%; }
.esqueleto > span:nth-child(3n)::after { width: 66%; }
.esqueleto.sin-icono > span { grid-template-columns: 1fr; }
.esqueleto.sin-icono > span::before { display: none; }
.esqueleto-hilo { width: 100%; padding: 1rem; }
@keyframes esq-brillo { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .esqueleto > span::before, .esqueleto > span::after { animation: none; } }

/* ── Vacíos ilustrados (revisión visual, etapa 2, 2026-10-28) ──────────────────
   Una carpeta vacía, la papelera limpia o un buzón sin correos dejan de ser un renglón
   gris: llevan su ícono 3D (los de Fluent que ya usa el escritorio, 4-13 KB). */
.vacio-ilustrado { text-align: center; padding: var(--e-7) var(--e-4) !important; }
.vacio-ilustrado::before {
    content: ''; display: block; width: 72px; height: 72px; margin: 0 auto var(--e-3);
    background: center / contain no-repeat; opacity: 0.92;
    animation: vacio-flota 4s ease-in-out infinite;
}
.vacio-ilustrado[data-ilus="carpeta"]::before { background-image: url('../iconos/fluent3d/carpeta.png'); }
.vacio-ilustrado[data-ilus="papelera"]::before { background-image: url('../iconos/fluent3d/papelera.png'); }
.vacio-ilustrado[data-ilus="correo"]::before { background-image: url('../iconos/fluent3d/correo.png'); }
.vacio-ilustrado[data-ilus="mensajes"]::before { background-image: url('../iconos/fluent3d/mensajes.png'); }
.vacio-ilustrado[data-ilus="busqueda"]::before { background-image: url('../iconos/fluent3d/busqueda.png'); }
@keyframes vacio-flota { 50% { transform: translateY(-4px); } }

/* ── Al cambiar de sección, la nueva entra con un fundido breve (etapa 2) ─────────
   Solo opacidad: un transform en el contenedor rompería por un instante los paneles
   fijos de adentro (lector de correo, redactor). Las secciones entran por x-if o
   x-show, y en los dos casos la animación arranca sola al aparecer. */
.app-cuerpo { animation: seccion-entra 0.18s ease-out; }
@keyframes seccion-entra { from { opacity: 0; } }

/* ── Microinteracciones (etapa 2) ───────────────────────────────────────────── */
.btn:active:not(:disabled), .btn-icono:active:not(:disabled) { transform: scale(0.96); }
.btn, .btn-icono { transition: background var(--transition), border-color var(--transition), transform 0.08s ease-out; }
.toast-exito::before {
    content: '✓'; flex: none; display: grid; place-items: center;
    width: 1.15rem; height: 1.15rem; margin-top: 0.1rem; border-radius: 50%;
    background: var(--color-success); color: var(--color-success-fg);
    font-size: var(--t-2xs); font-weight: 800; line-height: 1;
    animation: palomita 0.35s cubic-bezier(.3, 1.6, .5, 1);
}
@keyframes palomita { from { transform: scale(0.3); opacity: 0; } }

/* ── Carpetas con profundidad en la galería (revisión visual, etapa 3) ─────────────
   Tres capas en CSS 3D: respaldo (con su pestaña), lo de dentro (las fotos de la carpeta
   o dos hojas) y un frente semitransparente que bisagra por abajo. Cursor encima: se abre
   un poco; algo arrastrado encima (sobreId): se abre del todo. Color: el de la carpeta. */
.c3d { position: relative; display: block; width: 76%; aspect-ratio: 5 / 4; perspective: 700px; transform-style: preserve-3d; --c3d: var(--color-primary); }
.c3d-boveda { --c3d: var(--carpeta-boveda, var(--color-primary)); }
.c3d-oficina { --c3d: var(--carpeta-oficina, var(--color-primary)); }
.c3d-atras { position: absolute; inset: 9% 0 0 0; border-radius: 9px; background: color-mix(in srgb, var(--c3d) 72%, black); }
.c3d-atras::before { content: ''; position: absolute; left: 0; top: -9%; width: 40%; height: 14%; border-radius: 7px 7px 0 0; background: inherit; }
.c3d-hojas { position: absolute; inset: 2% 7% 24% 7%; transition: transform 0.28s cubic-bezier(.3, 1.3, .5, 1); }
.c3d .galeria-pila { position: absolute; inset: 0; aspect-ratio: auto; }
.c3d-hoja { position: absolute; inset: 12% 10% 6% 10%; border-radius: 3px; background: color-mix(in srgb, white 92%, var(--c3d)); box-shadow: 0 1px 4px var(--color-shadow); }
.c3d-hoja + .c3d-hoja { inset: 18% 6% 4% 16%; transform: rotate(4deg); }
.c3d-frente {
    position: absolute; left: 0; right: 0; bottom: 0; height: 66%; border-radius: 9px;
    background: linear-gradient(172deg, color-mix(in srgb, var(--c3d) 78%, white), var(--c3d) 70%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 10px 20px var(--color-shadow);
    opacity: 0.95; transform-origin: 50% 100%; transform: rotateX(-6deg);
    transition: transform 0.3s cubic-bezier(.3, 1.4, .5, 1);
    display: flex; align-items: flex-end; padding: 7%;
}
.c3d-candado { display: flex; color: white; opacity: 0.9; }
.c3d-candado svg { width: 18px; height: 18px; }
.galeria-thumb:hover .c3d-frente { transform: rotateX(-24deg); }
.galeria-thumb:hover .c3d-hojas { transform: translateY(-7%); }
.c3d-abierta .c3d-frente, .galeria-thumb:hover .c3d-abierta .c3d-frente { transform: rotateX(-50deg); }
.c3d-abierta .c3d-hojas, .galeria-thumb:hover .c3d-abierta .c3d-hojas { transform: translateY(-14%); }
@media (prefers-reduced-motion: reduce) { .c3d-frente, .c3d-hojas { transition: none; } }

/* ── «¿Qué ocupa espacio?» (anillo.js; revisión visual, etapa 3) ─────────────────── */
.anillo { display: grid; gap: var(--e-3); }
.anillo-cuerpo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--e-5); align-items: center; }
.anillo-lienzo { position: relative; width: 100%; max-width: 380px; margin: 0 auto; aspect-ratio: 1 / 1; }
.anillo-grafica, .anillo-svg { width: 100%; height: 100%; display: block; }
.anillo-svg { filter: drop-shadow(0 10px 18px var(--color-shadow)); overflow: visible; }
.anillo-p { stroke: var(--color-surface); stroke-width: 1; transform-origin: 160px 160px; transition: transform 0.15s ease-out, opacity 0.15s; animation: anillo-entra 0.5s cubic-bezier(.2, .8, .3, 1) both; }
.anillo-fuera { opacity: 0.62; }
.anillo-p:hover { transform: scale(1.035); opacity: 1; }
.anillo-p.entrable { cursor: pointer; }
@keyframes anillo-entra { from { transform: scale(0.6) rotate(-20deg); opacity: 0; } }
.anillo-centro { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; pointer-events: none; padding: 32%; }
.anillo-centro strong { display: block; font-size: var(--t-xl); font-variant-numeric: tabular-nums; }
.anillo-centro small { display: block; color: var(--color-text-muted); font-size: var(--t-xs); overflow-wrap: anywhere; line-height: 1.3; }
.anillo-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--e-1); max-height: 380px; overflow-y: auto; }
.anillo-lista li { display: grid; grid-template-columns: 0.8rem minmax(0, 1fr) auto; gap: var(--e-2); align-items: center; padding: var(--e-1) var(--e-2); border-radius: var(--radius-md); }
.anillo-lista li:hover { background: var(--color-surface-2); }
.anillo-color { width: 0.8rem; height: 0.8rem; border-radius: 3px; }
.anillo-nombre { all: unset; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.anillo-nombre:not(:disabled):hover { text-decoration: underline; color: var(--color-primary); }
.anillo-nombre:disabled { cursor: default; }
.anillo-nombre:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: 2px; }
.anillo-tam { white-space: nowrap; font-variant-numeric: tabular-nums; }
.anillo-tam small { color: var(--color-text-muted); }
.anillo-nota { font-size: var(--t-xs); margin: 0; }
@media (max-width: 768px) {
    .anillo-cuerpo { grid-template-columns: 1fr; }
    .anillo-lienzo { max-width: 300px; }
}

/* ── El globo de ataques del SOC (globo.js; revisión visual, etapa 3) ─────────── */
.globo-card { display: grid; gap: var(--e-3); }
.globo-cab { display: flex; align-items: center; justify-content: space-between; gap: var(--e-3); flex-wrap: wrap; }
.globo-cab .card-titulo { margin: 0; }
.globo-periodos { display: flex; gap: var(--e-1); }
.globo-cuerpo { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: var(--e-5); align-items: center; }
.globo-lienzo { width: 100%; aspect-ratio: 1 / 1; max-height: 420px; display: block; cursor: grab; }
.globo-lienzo:active { cursor: grabbing; }
.globo-lado { display: grid; gap: var(--e-3); align-content: start; min-width: 0; }
.globo-resumen { margin: 0; font-size: var(--t-xl); font-weight: 700; font-family: var(--font-title); line-height: 1.25; }
.globo-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--e-1); counter-reset: g; }
.globo-lista li { display: grid; grid-template-columns: 2.2rem minmax(0, 1fr) auto; gap: var(--e-2); align-items: center; padding: var(--e-1) var(--e-2); border-radius: var(--radius-md); }
.globo-lista li:nth-child(odd) { background: var(--color-surface-2); }
.globo-cc { font: 600 var(--t-2xs) var(--font-mono); color: var(--color-danger); text-align: center; border: 1px solid currentColor; border-radius: var(--radius-sm); padding: 1px 0; }
.globo-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.globo-lista strong { font-variant-numeric: tabular-nums; }
.globo-fuente { font-size: var(--t-2xs); color: var(--color-text-muted); justify-self: start; }
@media (max-width: 768px) {
    .globo-cuerpo { grid-template-columns: 1fr; }
    .globo-lienzo { max-width: 360px; margin: 0 auto; }
}

/* ── La paleta «Ctrl K» (paleta.js; revisión visual, etapa 4) ────────────────────
   Entre los diálogos (70-80) y los avisos (100): sale encima de lo abierto. */
.paleta-fondo { position: fixed; inset: 0; z-index: 85; background: var(--color-overlay); display: flex; justify-content: center; align-items: flex-start; padding: max(10vh, 1rem) 1rem 1rem; }
.paleta {
    width: min(38rem, 100%); max-height: min(32rem, 80vh); display: flex; flex-direction: column;
    background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg); overflow: hidden; animation: dialogo-entra 0.14s ease-out;
}
.paleta-cab { display: flex; align-items: center; gap: var(--e-2); padding: var(--e-3) var(--e-4); border-bottom: 1px solid var(--color-border); }
.paleta-cab .busqueda-icono { position: static; display: flex; color: var(--color-text-muted); }
.paleta-entrada { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--color-text); font: inherit; font-size: var(--t-lg); padding: var(--e-2) 0; }
.paleta kbd, .paleta-atajo kbd {
    font: 600 var(--t-2xs) var(--font-mono); padding: 2px 6px; border-radius: var(--radius-sm);
    border: 1px solid var(--color-border); background: var(--color-surface-2); color: var(--color-text-muted);
}
.paleta-lista { list-style: none; margin: 0; padding: var(--e-2); overflow-y: auto; flex: 1; }
.paleta-grupo { font-size: var(--t-2xs); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); padding: var(--e-3) var(--e-3) var(--e-1); }
.paleta-item { width: 100%; display: flex; align-items: center; gap: var(--e-3); padding: var(--e-2) var(--e-3); border: 0; border-radius: var(--radius-md); background: transparent; color: var(--color-text); font: inherit; text-align: left; cursor: pointer; }
.paleta-item.activo { background: color-mix(in srgb, var(--color-primary) 14%, transparent); }
.paleta-ic { display: flex; color: var(--color-text-muted); }
.paleta-ic svg { width: 18px; height: 18px; }
.paleta-item.activo .paleta-ic { color: var(--color-primary); }
.paleta-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.paleta-nada { padding: var(--e-5) var(--e-3); text-align: center; }
.paleta-pie { display: flex; gap: var(--e-4); padding: var(--e-2) var(--e-4); border-top: 1px solid var(--color-border); font-size: var(--t-xs); }
.paleta-atajo { width: auto !important; padding: 0 var(--e-1); }
@media (max-width: 640px) {
    .paleta-fondo { padding-top: 0.75rem; }
    .paleta { max-height: 75vh; }
    .paleta-pie { display: none; }
}

/* ── Diálogos de confirmación (dialogo.js; revisión visual, etapa 2, 2026-10-28) ──
   Un <dialog> en la capa superior del navegador: no necesita z-index. */
.dialogo {
    padding: 0; border: 0; background: transparent; color: var(--color-text);
    max-width: min(26rem, calc(100vw - 2rem)); width: 100%; overflow: visible;
}
.dialogo::backdrop { background: var(--color-overlay); }
.dialogo-caja {
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
    padding: var(--e-5) var(--e-5) var(--e-4); display: grid; gap: var(--e-4);
}
.dialogo-texto { margin: 0; font-size: var(--t-lg); line-height: 1.5; white-space: pre-line; overflow-wrap: anywhere; }
.dialogo-botones { display: flex; justify-content: flex-end; gap: var(--e-2); flex-wrap: wrap; }
.dialogo-botones .btn { min-width: 6.5rem; justify-content: center; }
.dialogo[open] .dialogo-caja { animation: dialogo-entra 0.16s ease-out; }
.dialogo[open]::backdrop { animation: dialogo-velo 0.16s ease-out; }
@keyframes dialogo-entra { from { opacity: 0; transform: translateY(6px) scale(0.98); } }
@keyframes dialogo-velo { from { opacity: 0; } }
@media (max-width: 640px) {
    /* En el teléfono, los botones a todo lo ancho y a la mano del pulgar. */
    .dialogo-botones .btn { flex: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .dialogo[open] .dialogo-caja, .dialogo[open]::backdrop { animation: none; }
}

/* ── Aurora y Amanecer: vidrio sobre luz viva (revisión visual, etapas 1 y 5) ───────
   aurora.js pone <canvas class="aurora-fondo"> y html.aurora-viva. Sin él (ventana del
   escritorio, sin WebGL) queda un degradado quieto en el <body> con la misma paleta.
   Los dos temas comparten estas reglas; lo que cambia de noche a día son las fichas
   --aurora-* de cada uno (sistema-diseno.css). */
.aurora-fondo { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: -1; display: block; pointer-events: none; }
:is([data-theme="aurora"], [data-theme="amanecer"]) body { background: var(--aurora-cielo); }
html.aurora-viva body { background: transparent; }
html.aurora-viva { background: var(--aurora-noche); }
/* El vidrio: barras, tarjetas, menús y diálogos se desenfocan sobre la luz.
   ⚠️ backdrop-filter vuelve al elemento el «marco» de todo lo position:fixed que lleve
   dentro: un menú que se coloca con coordenadas de la pantalla sale corrido (el «⋮» del
   visor caía a la derecha, fuera de la vista: Jore, 2026-10-29). Por eso .modal y la
   cabecera de Archivos NO lo llevan en sí: la ventana se desenfoca con el fondo del
   modal y la cabecera con un ::before. Antes de añadir aquí algo que contenga menús
   flotantes, mírelo así. */
:is([data-theme="aurora"], [data-theme="amanecer"]) :is(.navbar, .sidebar, .tabbar-movil, .card, .menu-pop, .buzon-sel-barra, .dialogo-caja, .paleta) {
    -webkit-backdrop-filter: blur(18px) saturate(1.35);
    backdrop-filter: blur(18px) saturate(1.35);
}
:is([data-theme="aurora"], [data-theme="amanecer"]) .navbar { box-shadow: inset 0 -1px 0 var(--aurora-linea); }
:is([data-theme="aurora"], [data-theme="amanecer"]) :is(.card, .modal) { box-shadow: var(--shadow-md), inset 0 1px 0 var(--aurora-brillo); }
/* El fondo de un modal desenfoca más que el de un diálogo: es el vidrio de la ventana
   (que no lo lleva en sí, ver arriba). Ocupa toda la pantalla, así que ser el «marco» de
   lo fijo no corre nada. */
:is([data-theme="aurora"], [data-theme="amanecer"]) .modal-fondo { -webkit-backdrop-filter: blur(14px) saturate(1.3); backdrop-filter: blur(14px) saturate(1.3); }
:is([data-theme="aurora"], [data-theme="amanecer"]) .dialogo::backdrop { -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
/* La cabecera fija de Archivos era del color del fondo (opaco): aquí, vidrio, en un
   ::before (en el teléfono la barra de selección, fija abajo, vive dentro de ella). */
:is([data-theme="aurora"], [data-theme="amanecer"]) .cabecera-gestor { background: transparent; }
:is([data-theme="aurora"], [data-theme="amanecer"]) .cabecera-gestor::before {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background: var(--aurora-cabecera);
    -webkit-backdrop-filter: blur(16px) saturate(1.3);
    backdrop-filter: blur(16px) saturate(1.3);
}
/* Las carpetas de Correo, con el mismo fondo que las de Archivos (.sidebar): sobre un
   fondo oscuro, la transparencia no dejaba leerlas en Amanecer (Jore, 2026-10-29). */
:is([data-theme="aurora"], [data-theme="amanecer"]) .buzon-pane-tree {
    background: var(--color-sidebar-bg);
    -webkit-backdrop-filter: blur(18px) saturate(1.35);
    backdrop-filter: blur(18px) saturate(1.35);
}
:is([data-theme="aurora"], [data-theme="amanecer"]) .sidebar a.activo { color: var(--aurora-act-fg); }
/* El rojo de Aurora es claro: con texto blanco no llegaba a 3:1; oscuro, 6.6:1. */
[data-theme="aurora"] .btn-danger,
[data-theme="obsidiana"] .btn-danger,
[data-theme="commodore"] .btn-danger { color: var(--color-primary-fg); }
/* El botón principal con la luz de la marca. */
:is([data-theme="aurora"], [data-theme="amanecer"]) .btn-primary {
    background: var(--aurora-luz);
    border-color: transparent; color: var(--color-primary-fg);
    box-shadow: 0 6px 22px var(--aurora-boton-sombra);
}
:is([data-theme="aurora"], [data-theme="amanecer"]) .btn-primary:hover:not(:disabled) { background: var(--aurora-luz-h); }
/* La entrada: tarjeta de vidrio más profunda, con el logo encendido. */
:is([data-theme="aurora"], [data-theme="amanecer"]) .panel-login {
    background: var(--aurora-login-fondo);
    border-color: var(--aurora-login-borde);
    border-radius: 22px;
    box-shadow: var(--aurora-login-sombra);
    -webkit-backdrop-filter: blur(22px) saturate(1.4);
    backdrop-filter: blur(22px) saturate(1.4);
}
:is([data-theme="aurora"], [data-theme="amanecer"]) .panel-login :is(.marca svg, img) { filter: drop-shadow(0 0 14px var(--aurora-logo-brillo)); }
:is([data-theme="aurora"], [data-theme="amanecer"]) .panel-login :is(.input, input:not([type="checkbox"])) { background: var(--aurora-input); }
/* Sin backdrop-filter (fichas opacas en sistema-diseno.css), la entrada también. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    :is([data-theme="aurora"], [data-theme="amanecer"]) .panel-login { background: var(--color-surface); }
}

/* ── Commodore: los títulos en letra de terminal se leen mejor un poco más grandes y en
   mayúsculas, como en la C64 (revisión visual, etapa 4). */
[data-theme="commodore"] .card-titulo,
[data-theme="commodore"] .modal-titulo,
[data-theme="commodore"] h1, [data-theme="commodore"] h2, [data-theme="commodore"] h3 { text-transform: uppercase; letter-spacing: 0.04em; font-size: 1.25em; font-weight: 400; }
[data-theme="commodore"] .navbar { border-bottom: 3px solid var(--color-border); }
[data-theme="commodore"] .sidebar a.activo { color: var(--color-primary-fg); }

/* El antifraude de MexMail apartó este correo (2026-10-29): la franja con sus razones. */
.buzon-fraude { border-left: 4px solid var(--color-danger); }
.buzon-fraude-motivos { margin: 0.4rem 0 0; padding-left: 1.2rem; font-size: var(--t-md); }
.buzon-fraude-motivos li { margin: 0.15rem 0; }

/* adm · los routers de una empresa en su ficha (Regenerar token, Dar de baja). */
.adm-router { gap: .5rem; align-items: center; padding: .35rem 0; border-bottom: 1px solid var(--color-border); }
.adm-router-nombre { flex: 1; min-width: 0; }
.adm-router-token { margin-top: .75rem; padding: .75rem; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-2); }
.adm-router-cmd { white-space: pre-wrap; word-break: break-all; font-size: var(--t-sm); margin: .5rem 0; }

/* «Antispam» de adm (§47): casos de spam reportado y reglas de la IA. */
.as-boton { position: relative; }
.as-caso.as-nuevo { border-left-color: var(--color-danger); }
.as-titulo { overflow-wrap: anywhere; }
.as-etiquetas { justify-content: flex-start; margin-block: 0.4rem; }
.as-explicacion { white-space: pre-line; overflow-wrap: anywhere; }
.as-reglas td { vertical-align: top; }
.as-regla { display: flex; flex-direction: column; gap: 0.25rem; min-width: 16rem; max-width: 34rem; }
.as-patron { display: block; padding: 0.3rem 0.5rem; border-radius: 6px; background: var(--color-surface-2, rgba(127, 127, 127, 0.1)); font-size: var(--t-xs); white-space: pre-wrap; overflow-wrap: anywhere; }
.as-linea { display: block; margin-top: 0.2rem; }
.as-peso { width: 5rem; }
.as-acciones { flex-wrap: wrap; gap: 0.4rem; }
.as-regla-descartada, .as-regla-retirada { opacity: 0.6; }
.as-muestra { border-top: 1px solid var(--color-border); padding-block: 0.4rem; }
.as-muestra summary { cursor: pointer; }
.as-muestra-texto { max-height: 28rem; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--t-xs); padding: 0.5rem; border-radius: 6px; background: var(--color-surface-2, rgba(127, 127, 127, 0.1)); }
