﻿/* =============================================
   ImagineCloudDeCA — lo propio del producto
   ---------------------------------------------
   Todo lo genérico (lateral, barra superior, tablas, formularios, badges, botones)
   viene de imagine.css. Aquí sólo va lo que no existe allí porque es del DeCA:
   estados del documento, enlaces públicos, trazabilidad y la ficha.
   ============================================= */

:root {
    --deca-borde: #e0e7ef;
    --deca-texto: #1a2942;
    --deca-texto-suave: #6b7c93;
    --deca-fondo-suave: #f8fafc;
}

/* El contenido respira menos en pantallas pequeñas que en el CRM, donde el lateral
   ocupa más. 4,5rem a los lados deja los formularios muy estrechos en un portátil. */
.app-main {
    padding: 1.5rem 2rem 4rem;
}

@media (min-width: 1400px) {
    .app-main {
        padding: 1.5rem 4rem 4rem;
    }
}

/* ---- Estados del documento ---- */

.estado-doc {
    display: inline-block;
    padding: .15rem .55rem;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    letter-spacing: .01em;
}

.estado-doc.ok      { background: #d4edda; color: #155724; }
.estado-doc.curso   { background: #e0eaff; color: #1e3a8a; }
.estado-doc.aviso   { background: #fef3c7; color: #78350f; }
.estado-doc.mal     { background: #f8d7da; color: #721c24; }
.estado-doc.apagado { background: #eef2f7; color: #6b7c93; }

/* ---- Fichas de datos ---- */

.deca-datos {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .5rem 1.5rem;
    margin: 0;
    font-size: .875rem;
}

.deca-datos dt {
    font-weight: 600;
    color: var(--deca-texto-suave);
}

.deca-datos dd {
    margin: 0;
    color: var(--deca-texto);
}

.deca-datos dd small {
    display: block;
    margin-top: .15rem;
    color: var(--deca-texto-suave);
    font-size: .78rem;
    font-weight: 400;
}

/* Tarjeta blanca de sección, el envoltorio por defecto de las pantallas del producto. */
.deca-card {
    background: #fff;
    border: 1px solid var(--deca-borde);
    border-radius: 10px;
    padding: 1.25rem 1.5rem;
    margin-bottom: 1.25rem;
    box-shadow: 0 2px 10px rgba(0,0,0,.05);
}

.deca-card > h2,
.deca-card > h3 {
    font-size: 1rem;
    font-weight: 700;
    color: var(--deca-texto);
    margin: 0 0 .35rem;
    display: flex;
    align-items: center;
    gap: .45rem;
}

.deca-card > h2 i,
.deca-card > h3 i {
    color: #00a0e3;
}

.deca-sub {
    color: var(--deca-texto-suave);
    font-size: .82rem;
    margin: 0 0 1rem;
}

/* ---- Enlace del conductor ---- */

.enlace-conductor {
    display: block;
    padding: .55rem .75rem;
    border: 1px dashed #b3e0f7;
    border-radius: 7px;
    background: #f2fbff;
    color: #005f8a;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .82rem;
    overflow-wrap: anywhere;
}

/* ---- Trazabilidad ---- */

.trazabilidad-lista {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}

.trazabilidad-lista::before {
    content: '';
    position: absolute;
    left: 7px;
    top: .4rem;
    bottom: .4rem;
    width: 2px;
    background: #e0e7ef;
}

.trazabilidad-lista li {
    position: relative;
    padding: 0 0 1rem 1.75rem;
}

.trazabilidad-lista li::before {
    content: '';
    position: absolute;
    left: 2px;
    top: .35rem;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #fff;
    border: 2px solid #00a0e3;
}

.trazabilidad-lista .hito {
    font-weight: 600;
    color: var(--deca-texto);
    font-size: .875rem;
}

.trazabilidad-lista .detalle-hito {
    font-size: .82rem;
    color: #4a5568;
}

.trazabilidad-lista .cuando {
    font-size: .75rem;
    color: var(--deca-texto-suave);
}

/* ---- Celdas técnicas (JSON de auditoría, user-agent) ---- */

.celda-tecnica {
    max-width: 22rem;
    overflow-wrap: anywhere;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .75rem;
    color: var(--deca-texto-suave);
}

.celda-nowrap {
    white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════════════════════
   EL RAIL DE ICONOS (el lateral plegado)
   ═══════════════════════════════════════════════════════════════════════════

   `imagine.css` ya pliega el lateral a 64 px y esconde los rótulos, pero lo que
   quedaba era una columna de iconos muda y apretada: sin saber qué es cada uno y
   con el resalte del activo ocupando la fila entera, que a ese ancho es una barra
   y no una selección.

   Lo que se trae del rail de Gmail son tres cosas y ninguna es el color:

   1. El rótulo aparece al pasar por encima. Es lo que hace que un rail SIRVA.
   2. El activo es una pastilla redonda detrás del icono, no una franja.
   3. Aire entre iconos: a 64 px, lo que distingue una lista de una columna de
      manchas es el hueco.

   Lo que NO se trae: el botón grande de la acción principal arriba del todo
   —«Redactar» en Gmail, «Emitir DeCA» aquí—. Eso cambia también el lateral
   abierto, y lo que se pidió es el rail.
   ───────────────────────────────────────────────────────────────────────── */

/* Todo lleva prefijo `html` porque `imagine.css` redefine `.nav-item` y
   `.nav-item.active` dentro de bloques de tema —(0,3,1)—, y tres clases no les
   ganan. Es la trampa de siempre con esa hoja. */

html .app-sidebar.sidebar-collapsed .nav-item {
    padding: .3rem 0;
}

/* Ni fondo de fila ni filo a la izquierda: el resalte se muda a la pastilla. A 64 px
   una franja de borde a borde no señala un elemento, señala la fila.

   Va con `.active` y `:hover` escritos —(0,4,1)— y no en la regla de arriba: los
   bloques de tema de `imagine.css` llevan `html[data-theme="light"] .nav-item.active`,
   que es (0,3,1) y empataría, dejando la decisión al orden de carga. */
html .app-sidebar.sidebar-collapsed .nav-item,
html .app-sidebar.sidebar-collapsed .nav-item:hover,
html .app-sidebar.sidebar-collapsed .nav-item.active {
    background: transparent;
    border-left-color: transparent;
}

html .app-sidebar.sidebar-collapsed .nav-item .item-icon {
    width: 2.4rem;
    height: 2.4rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    font-size: 1rem;
    transition: background .15s, color .15s;
}

html .app-sidebar.sidebar-collapsed .nav-item:hover .item-icon {
    background: rgba(255, 255, 255, .12);
    color: #fff;
}

html .app-sidebar.sidebar-collapsed .nav-item.active .item-icon {
    background: var(--im-primary);
    color: #fff;
}

/* El tema claro del CRM pinta el lateral en claro, y ahí un `rgba` blanco no se ve. */
html[data-theme="light"] .app-sidebar.sidebar-collapsed .nav-item:hover .item-icon {
    background: var(--tm-side-hover);
    color: var(--tm-acento);
}

html[data-theme="light"] .app-sidebar.sidebar-collapsed .nav-item.active .item-icon {
    background: var(--tm-acento);
    color: #fff;
}

/* ---- El rótulo flotante ----

   Va en el <body> y posicionado por JavaScript, y no es por gusto: `.app-sidebar`
   lleva `overflow: hidden` y `.sidebar-nav` lleva `overflow-x: hidden` —lo necesita
   para poder scrollear en vertical—, así que un pseudo-elemento del propio icono se
   recortaría contra el borde del rail. `position: fixed` escapa de los dos, y
   funciona porque ningún contenedor del armazón lleva `transform`, que crearía un
   bloque contenedor; está comprobado y anotado también en el modal de avisos.

   El texto NO se duplica en un atributo: se lee del <span> del rótulo, que ya está
   en el DOM y sólo está oculto. Una segunda copia de cada entrada del menú es
   exactamente lo que un día dice una cosa distinta. */

.rail-tip {
    position: fixed;
    z-index: 1200;
    padding: .3rem .6rem;
    border-radius: 6px;
    background: #1a2942;
    color: #fff;
    font-size: .78rem;
    font-weight: 600;
    white-space: nowrap;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .25);

    /* No puede recibir el puntero: si lo hiciera, aparecer debajo del ratón
       dispararía el `mouseleave` del icono y el rótulo parpadearía. */
    pointer-events: none;

    opacity: 0;
    transition: opacity .12s;
}

.rail-tip.visible {
    opacity: 1;
}

html[data-theme="dark"] .rail-tip {
    background: var(--bg-card-2);
    border: 1px solid var(--border);
    color: var(--text);
}

/* En papel no pinta nada, como el menú entero. */
@media print {
    .rail-tip { display: none; }
}

/* ---- La columna de acciones ----

   Iba centrada, y con botones que no miden lo mismo —«Activar» frente a «Desactivar»,
   «Retirar» frente a «Reinstaurar»— eso deja cada fila empezando en un sitio distinto:
   el grupo entero se desplaza según qué botón le toque, y los de arriba y los de abajo
   no caen en la misma columna. Alineada a la izquierda, el primer botón está siempre
   en el mismo sitio y el de al lado también, que es lo que permite recorrer la lista
   con la vista en vez de ir buscando cada botón.

   NO se iguala el ancho de los botones con un `min-width`, que era la otra salida:
   habría que ajustarlo al rótulo más largo de cada pantalla y se queda viejo en cuanto
   alguien cambia una palabra.

   Y tampoco se pone `display: flex` en el `<td>`: un elemento con `display` de tabla al
   que se le cambia deja de participar como celda y el navegador le envuelve una celda
   anónima, con lo que el reparto de anchos de la columna pasa a depender del motor. El
   hueco entre botones lo dan los espacios del marcado, como hasta ahora.

   `nowrap` porque el grupo de acciones de una fila se lee junto; si no cabe, el que
   desplaza es `.admin-table-wrapper`, que ya scrollea en horizontal. */

.admin-table th.celda-acciones,
.admin-table td.celda-acciones {
    text-align: left;
    white-space: nowrap;
}

/* Fila de una versión que es la que sirve el enlace ahora mismo. */
.admin-table tbody tr.vigente td {
    background: #f2fbff;
}

.marca-vigente {
    display: inline-block;
    margin-left: .4rem;
    padding: 0 .4rem;
    border-radius: 999px;
    background: #00a0e3;
    color: #fff;
    font-size: .62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.admin-table tbody tr.fallo td {
    background: #fdf3f4;
}

/* ---- Avisos ---- */

.deca-aviso {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .7rem 1rem;
    border-radius: 8px;
    font-size: .85rem;
    margin-bottom: 1rem;
}

.deca-aviso i {
    margin-top: .1rem;
    font-size: 1rem;
}

.deca-aviso.ok   { background: #d4edda; color: #155724; }
.deca-aviso.mal  { background: #f8d7da; color: #721c24; }
.deca-aviso.info { background: #e0eaff; color: #1e3a8a; }

/* Ámbar: no ha pasado nada malo, hay algo que mirar. Faltaba, y «faltar» aquí significa que
   un `deca-aviso aviso` se pintaba como un párrafo suelto sin fondo ni color — la trampa de
   la clase sin regla, que no da error y sólo se descubre mirando la pantalla. Mismo criterio
   de color que la barra de la demo: el rojo se reserva para los errores. */
.deca-aviso.aviso { background: #fff3cd; color: #7a5b00; }

/* Aviso pegado al botón que lo provoca, no en la cabecera: en un formulario largo el
   usuario está mirando abajo y arriba no ve nada. */
.deca-aviso.junto-al-boton {
    margin-bottom: 0;
    flex: 1 1 18rem;
}

/* El pie envuelve para que el aviso no estruje el botón en pantallas estrechas. */
.admin-form-footer {
    flex-wrap: wrap;
    row-gap: .6rem;
}

/* ---- La rejilla de los formularios va en UNA columna ----

   `imagine.css` la trae en dos, y es lo que tiene sentido en el CRM del que viene: allí los
   hijos directos son campos sueltos que se emparejan solos. Aquí no: todas las pantallas
   escriben filas explicitas con `form-row-2` y `form-row-3`, así que la rejilla de dos
   columnas las reparte en dos montones y el resultado depende de cuántos hijos haya.

   Eso es lo que dejaba «Guardar» a la derecha de los campos en «Mi perfil» —el pie caía en
   la segunda celda de la primera fila— mientras «Cambiar contraseña», que es hijo único de
   su rejilla, aparecía debajo. Con una sola columna cada fila ocupa el ancho que ya se
   había repartido por dentro y el pie queda siempre al final, que es lo que espera quien
   acaba de rellenar el formulario. */
.admin-form-grid {
    grid-template-columns: 1fr;
    gap: 1rem;
}

/* ---- Subida de documentos ---- */

/* Recortada por los lados y mas baja que antes: ocupando todo el ancho de la tarjeta se
   confundia con una seccion mas del formulario. Centrada y estrecha se lee como lo que es,
   un sitio donde soltar algo. */
.deca-dropzone {
    border: 2px dashed #b7c6d9;
    border-radius: 10px;
    padding: 1.1rem 1.25rem;
    max-width: 34rem;
    margin: 0 auto;
    text-align: center;
    background: var(--deca-fondo-suave);
    color: var(--deca-texto-suave);
    font-size: .85rem;
    transition: border-color .12s, background-color .12s;
}

/* Mientras el fichero está encima del recuadro. Sin un cambio visible no hay forma de
   saber dónde hay que soltarlo. */
.deca-dropzone.arrastrando {
    border-color: #00a0e3;
    border-style: solid;
    background: #e8f6fd;
}

.deca-dropzone.arrastrando * {
    /* Los hijos no deben recibir dragleave: si no, el recuadro parpadea al mover el ratón. */
    pointer-events: none;
}

.deca-dropzone i {
    display: block;
    font-size: 1.5rem;
    color: #00a0e3;
    margin-bottom: .25rem;
}

.deca-dropzone input[type="file"] {
    margin-top: .5rem;
    /* El selector nativo es ancho y descuadraba el recuadro estrecho. */
    max-width: 100%;
}

/* ---- Campos obligatorios ---- */

/* El asterisco va en la hoja de estilos y no en el texto de cada etiqueta: asi no se puede
   escribir una etiqueta obligatoria y olvidarse de marcarla, ni al reves. */
label.requerido::after {
    content: " *";
    color: #dc2626;
    font-weight: 700;
}

/* El recuadro en rojo SOLO despues del primer intento de emitir; lo decide el componente.
   Un formulario recien abierto esta vacio por definicion y pintarlo entero de rojo al
   entrar no avisa de nada, alarma. */
.admin-input.falta {
    border-color: #dc2626;
    background: #fef2f2;
}

.admin-input.falta:focus {
    border-color: #dc2626;
    box-shadow: 0 0 0 3px rgba(220, 38, 38, .15);
}

/* Campo rellenado leyendo el PDF del cliente.

   Va en ambar y NO en rojo a proposito: no hay nada mal, hay algo que mirar. El rojo de
   `.falta` significa «esto impide emitir» y gastarlo aqui le quitaria fuerza alli.

   La marca se quita sola en cuanto el valor deja de coincidir con lo propuesto, asi que en
   cuanto alguien corrige el campo vuelve a verse como cualquier otro. */
.admin-input.sugerido {
    border-color: #d97706;
    background: #fffbeb;
}

.admin-input.sugerido:focus {
    border-color: #d97706;
    box-shadow: 0 0 0 3px rgba(217, 119, 6, .15);
}

/* Marca de que un DeCA ampara varios envios. Reaprovecha el aspecto de `marca-vigente`
   porque es lo mismo: una pista corta al lado de un dato. */
.marca-agrupado {
    display: inline-block;
    margin-left: .35rem;
    padding: .05rem .35rem;
    border-radius: 999px;
    background: #e8f4fd;
    color: #0369a1;
    font-size: .68rem;
    font-weight: 700;
}

/* ---- Envíos del formulario de emisión ---- */

.envio-bloque {
    border: 1px solid var(--deca-borde);
    border-radius: 8px;
    padding: 1rem 1.15rem;
    margin-bottom: .85rem;
    background: var(--deca-fondo-suave);
}

.envio-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    margin-bottom: .75rem;
}

.envio-titulo {
    font-size: .82rem;
    font-weight: 700;
    color: var(--deca-texto-suave);
    text-transform: uppercase;
    letter-spacing: .04em;
}

.envio-bloque h4 {
    font-size: .82rem;
    font-weight: 700;
    color: var(--deca-texto-suave);
    text-transform: uppercase;
    letter-spacing: .04em;
    margin: 0 0 .75rem;
}

/* ---- Inicio ---- */

.deca-accesos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 1rem;
}

.deca-acceso {
    display: flex;
    gap: .9rem;
    align-items: flex-start;
    padding: 1.1rem 1.25rem;
    background: #fff;
    border: 1px solid var(--deca-borde);
    border-radius: 10px;
    text-decoration: none;
    color: inherit;
    box-shadow: 0 2px 10px rgba(0,0,0,.05);
    transition: border-color .15s, transform .15s;
}

.deca-acceso:hover {
    border-color: #00a0e3;
    transform: translateY(-2px);
    text-decoration: none;
    color: inherit;
}

.deca-acceso .icono {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    border-radius: 10px;
    background: #e8f4fd;
    color: #00a0e3;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.15rem;
}

.deca-acceso .titulo {
    font-weight: 600;
    color: var(--deca-texto);
}

.deca-acceso .texto {
    font-size: .8rem;
    color: var(--deca-texto-suave);
}

/* ---- Indicadores del inicio ---- */

.deca-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.deca-kpi {
    background: #fff;
    border: 1px solid var(--deca-borde);
    border-radius: 10px;
    padding: 1rem 1.15rem;
    box-shadow: 0 2px 10px rgba(0,0,0,.05);
}

.deca-kpi .valor {
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--deca-texto);
    line-height: 1.1;
}

.deca-kpi .etiqueta {
    font-size: .78rem;
    color: var(--deca-texto-suave);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 600;
}

/* La matización que acompaña a algunas cifras («3 documentos consultados»). En minúscula y
   sin espaciar, para que se lea como una nota y no compita con el rotulo. */
.deca-kpi .apunte {
    font-size: .72rem;
    color: var(--deca-texto-suave);
    margin-top: .2rem;
    line-height: 1.3;
}

/* Una cifra que pide que alguien haga algo. El fondo se queda igual —son seis cifras
   juntas y seis fondos de colores no se leen—: lo que cambia es el filo de la izquierda y
   el numero, que es donde se mira. */
.deca-kpi.mal {
    border-left: 4px solid #c0392b;
}

.deca-kpi.mal .valor {
    color: #c0392b;
}

/* ---- Fila de filtros ---- */

/* imagine.css la alinea con `align-items: flex-end`, y alli funciona porque todos los campos
   miden lo mismo. En cuanto uno lleva texto de ayuda debajo crece, y alinear por ABAJO empuja
   a los demas: sus rotulos quedaban un renglon mas abajo que el del campo alto.

   Alineados arriba, todos los rotulos van a la misma linea y la ayuda cuelga sin mover nada. */
.admin-filters .filter-row {
    align-items: flex-start;
}

/* El buscador pide mas sitio que un desplegable de dos opciones: lleva un texto largo dentro
   y es el que mas se usa. */
.admin-filters .filter-field.ancho {
    flex: 2 1 22rem;
}

/* La ayuda del filtro, para que no compita con el rotulo. */
.admin-filters .filter-field .admin-meta {
    font-size: .72rem;
    line-height: 1.3;
}

/* ---- Cabeceras de tabla ---- */

/* imagine.css pinta `.admin-table thead th` en azul marino macizo (#1a2942), que es su
   estilo antiguo. El nuevo del CRM —`.ct-table`, el de Contactos y Empresas— es blanco con
   el rotulo en gris pequeno y una linea fina debajo: pesa menos y deja que la vista vaya a
   los datos, que es lo que se ha venido a mirar. Se copia ese.

   No hace falta prefijo `html`: no hay ninguna regla de tema para este selector, y deca.css
   carga despues. (Al sobrescribir otra cosa de imagine.css, comprobarlo primero: el area de
   plataforma si lo necesito.) */
.admin-table thead th {
    background: #fff;
    color: var(--deca-texto-suave);
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--deca-borde);
    white-space: nowrap;
}

/* La cabecera que ordena es un boton de verdad —se pulsa con el teclado y se anuncia como
   tal—, disfrazado de rotulo. */
.orden-cabecera {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    width: 100%;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
    text-align: inherit;
}

.orden-cabecera:hover { color: #00a0e3; }

.orden-cabecera:focus-visible {
    outline: 2px solid #00a0e3;
    outline-offset: 2px;
    border-radius: 3px;
}

/* La flecha de la columna inactiva se insinua y se enciende al pasar por encima: marcarlas
   todas a plena tinta convierte la cabecera en un muro de simbolos. */
.orden-cabecera i {
    font-size: .8rem;
    opacity: .3;
    transition: opacity .12s;
}

.orden-cabecera:hover i { opacity: .7; }

.admin-table thead th.ordenada { color: var(--deca-texto); }

.admin-table thead th.ordenada .orden-cabecera i {
    opacity: 1;
    color: #00a0e3;
}

/* Las alineadas a la derecha o al centro llevan el boton con ellas. */
.admin-table thead th.text-end .orden-cabecera { justify-content: flex-end; }
.admin-table thead th.text-center .orden-cabecera { justify-content: center; }

/* ---- Aviso del resultado de una accion ---- */

/* Va en un modal y no en una franja arriba porque las acciones estan abajo: el pie de un
   formulario largo, un boton al final de una ficha. El mensaje quedaba fuera de la vista y
   quien acababa de pulsar «Guardar» no se enteraba del resultado. */
.deca-modal-fondo {
    position: fixed;
    inset: 0;
    z-index: 1080;                 /* por encima del lateral y de la barra superior */
    background: rgba(16, 24, 40, .45);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    animation: deca-modal-entra .12s ease-out;
}

/* El display:flex de arriba gana al [hidden] del navegador, y el modal del correo de
   respuesta llega oculto a propósito: sin esto se vería siempre. */
.deca-modal-fondo[hidden] {
    display: none;
}

.deca-modal {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 16px 48px rgba(0,0,0,.25);
    padding: 1.75rem 1.75rem 1.5rem;
    max-width: 30rem;
    width: 100%;
    text-align: center;
    border-top: 4px solid #16a34a;
}

.deca-modal.mal { border-top-color: #dc2626; }

.deca-modal > i {
    font-size: 2.1rem;
    line-height: 1;
    color: #16a34a;
}

.deca-modal.mal > i { color: #dc2626; }

.deca-modal > p {
    margin: .75rem 0 1.25rem;
    color: var(--deca-texto);
    font-size: .95rem;
    line-height: 1.45;
    /* Un mensaje de error puede traer la explicacion del servidor y ser largo. */
    overflow-wrap: anywhere;
}

/* ---- Vista de documentos por carpetas diarias ---- */

/* La carpeta es un boton, no un enlace: no navega, despliega. Se le quita el aspecto de boton
   del navegador y se deja el del renglon, que es lo que la hace parecer una carpeta. */
.btn-carpeta {
    background: none;
    border: 0;
    padding: 0;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

.btn-carpeta:hover { color: var(--deca-azul, #00a0e3); }
.btn-carpeta .bi { color: #f0a231; }

/* El desplegable de la carpeta cuelga del renglon de su dia, con un filete a la izquierda que
   deja ver de un vistazo donde empieza y donde acaba. */
.celda-carpeta {
    background: #f8fafc;
    border-left: 3px solid #f0a231;
}

.lista-carpeta {
    list-style: none;
    margin: 0;
    padding: .25rem 0 .25rem 1.75rem;
}

.lista-carpeta li {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .75rem;
    padding: .4rem 0;
    border-bottom: 1px solid #eef2f6;
}

.lista-carpeta li:last-child { border-bottom: 0; }
.lista-carpeta a { text-decoration: none; }

/* ---- Un boton al lado de un campo mide lo que el campo ---- */

/* El idioma de la casa para poner un boton junto a un campo es un `admin-field` con el rotulo
   vacio y un `d-flex gap-2` dentro. Lo que faltaba era que midieran igual, y no median:

     .admin-input   letra .875rem + .45rem de relleno + 3px de BORDE
     .btn-nuevo     letra .85rem  + .45rem de relleno + SIN borde   -> unos 3px mas bajo
     .btn-cancel    height: 48px FIJOS                              -> bastante mas alto

   Los 48px de .btn-cancel vienen del CRM, donde es el boton de pie de un formulario grande;
   dentro de una celda desentona. Y no se puede arreglar por el otro lado dandole altura a
   .admin-input, porque cuatro `textarea` la usan y se quedarian de una linea.

   Asi que se igualan los botones AL CAMPO: mismo relleno, misma letra y un borde transparente
   que compensa los 3px del campo. Sale la misma caja por construccion, no por tanteo. */
.admin-field .btn-nuevo,
.admin-field .btn-cancel {
    height: auto;
    padding: .45rem 1rem;
    font-size: .875rem;
    line-height: 1.5;
    border: 1.5px solid transparent;
    border-radius: 7px;
    box-sizing: border-box;
}

.admin-field .btn-cancel { border-color: #e2e8f0; }

/* El min-width es lo que destapa un descuido de imagine.css: .btn-nuevo y .btn-cancel son
   inline-flex SIN justify-content, o sea flex-start. Midiendo lo que su texto no se nota,
   pero en cuanto se les fija un ancho el rotulo se queda pegado a la izquierda. El
   text-align:center del modal no llega: no gobierna a los hijos de un contenedor flex. */
.deca-modal > button {
    min-width: 8rem;
    justify-content: center;
}

@keyframes deca-modal-entra {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Quien ha pedido menos animacion no quiere que la pantalla se le mueva. */
@media (prefers-reduced-motion: reduce) {
    .deca-modal-fondo { animation: none; }
}

/* ---- Elegir empresa ---- */

/* Nace de una lista porque eso es: un puñado de opciones entre las que se elige una. Lo que
   se quita aquí es el aspecto de lista —viñetas, margenes y el boton del navegador— sin
   perder que un lector de pantalla siga anunciando «lista de 2 elementos». */
.lista-empresas {
    list-style: none;
    margin: 0 0 .5rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

.lista-empresas button {
    width: 100%;
    display: flex;
    align-items: center;
    gap: .85rem;
    padding: .8rem .9rem;
    background: #fff;
    border: 1px solid var(--deca-borde);
    border-radius: 12px;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s, box-shadow .15s, transform .15s;
}

.lista-empresas button:hover {
    border-color: #00a0e3;
    box-shadow: 0 4px 16px rgba(0, 160, 227, .15);
    transform: translateY(-1px);
}

.lista-empresas button:focus-visible {
    outline: 2px solid #00a0e3;
    outline-offset: 2px;
}

.lista-empresas button:active {
    transform: translateY(0);
}

/* El distintivo de color. Tamaño fijo para que dos empresas de nombre muy distinto no
   descuadren la fila una respecto de la otra. */
.lista-empresas .marca {
    flex: 0 0 42px;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: .92rem;
    letter-spacing: .02em;
}

.lista-empresas .datos {
    display: flex;
    flex-direction: column;
    min-width: 0;        /* sin esto, un nombre largo desborda la tarjeta en vez de recortarse */
    flex: 1;
}

.lista-empresas .nombre {
    font-weight: 600;
    color: var(--deca-texto);
    font-size: .95rem;
    line-height: 1.25;
    overflow-wrap: anywhere;
}

.lista-empresas .rol {
    font-size: .76rem;
    color: var(--deca-texto-suave);
    margin-top: .1rem;
}

.lista-empresas .bi-arrow-right-short {
    font-size: 1.4rem;
    color: #c3cede;
    flex: 0 0 auto;
    transition: color .15s, transform .15s;
}

.lista-empresas button:hover .bi-arrow-right-short {
    color: #00a0e3;
    transform: translateX(3px);
}

/* Seis colores, asignados por el nombre de la empresa: quien entra en dos o tres reconoce
   la suya por el color antes de leerla. Todos sobre fondo claro con el texto en el tono
   fuerte, para que el contraste aguante. */
.lista-empresas .marca-c0 { background: #e0f2fe; color: #0369a1; }
.lista-empresas .marca-c1 { background: #dcfce7; color: #15803d; }
.lista-empresas .marca-c2 { background: #fef3c7; color: #b45309; }
.lista-empresas .marca-c3 { background: #ede9fe; color: #6d28d9; }
.lista-empresas .marca-c4 { background: #ffe4e6; color: #be123c; }
.lista-empresas .marca-c5 { background: #ccfbf1; color: #0f766e; }

@media (prefers-reduced-motion: reduce) {
    .lista-empresas button,
    .lista-empresas .bi-arrow-right-short {
        transition: none;
    }

    .lista-empresas button:hover {
        transform: none;
    }

    .lista-empresas button:hover .bi-arrow-right-short {
        transform: none;
    }
}

/* ---- El QR de fondo del inicio ---- */

.inicio {
    position: relative;
}

/* Sobre el QR, no debajo: sin esto el desenfoque se come el borde de las tarjetas. */
.inicio > *:not(.inicio-qr) {
    position: relative;
    z-index: 1;
}

.inicio-qr {
    position: absolute;
    top: -3rem;
    right: -2.5rem;
    width: 26rem;
    height: 26rem;
    background: url("img/qr-fondo.svg") center / contain no-repeat;
    filter: blur(6px);
    opacity: .07;
    pointer-events: none;
    z-index: 0;
}

/* En un portátil estrecho o en el móvil se comería el sitio de las tarjetas. */
@media (max-width: 992px) {
    .inicio-qr { display: none; }
}

/* Quien ha pedido menos animacion tampoco quiere adornos que distraigan. */
@media (prefers-reduced-motion: reduce) {
    .inicio-qr { opacity: .04; }
}

/* ---- Errores de Blazor ---- */

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1080;
    padding: .8rem 1.25rem;
    background: #fef3c7;
    color: #78350f;
    box-shadow: 0 -2px 12px rgba(0,0,0,.12);
    font-size: .85rem;
}

#blazor-error-ui .dismiss {
    position: absolute;
    right: 1rem;
    top: .7rem;
    cursor: pointer;
}

/* =============================================
   ÁREA DE PLATAFORMA
   ---------------------------------------------
   Administrar la plataforma y trabajar dentro de una empresa son dos cosas distintas y
   tienen que parecerlo: el lateral se pone oscuro para que nadie confunda «estoy tocando
   la configuración de la casa» con «estoy emitiendo un DeCA de un cliente».

   OJO CON LA ESPECIFICIDAD. imagine.css trae bloques de tema completos que redefinen
   .nav-item cualificando con `html[data-theme="light"]` y `html[data-theme="dark"]`, y esos
   colores están pensados para un lateral CLARO: el de «hover» es un gris azulado oscuro que
   sobre este fondo no se lee. Un selector de tres clases NO les gana —(0,3,1) contra
   (0,3,0)—, así que todas las reglas de aquí llevan el prefijo `html`, que las deja en
   (0,4,1). Sin él el menú se ve en blanco al pasar por encima.
   ============================================= */

html .app-wrapper.area-plataforma .app-sidebar {
    background: #0d1b2a;
    border-right-color: #14263a;
}

html .area-plataforma .sidebar-header {
    border-bottom-color: #1e3448;
}

html .area-plataforma .sidebar-logo-text strong,
html .area-plataforma .sidebar-user-footer .sidebar-user-name {
    color: #eaf2fa;
}

html .area-plataforma .sidebar-logo-text .ver,
html .area-plataforma .sidebar-user-footer .sidebar-user-role,
html .area-plataforma .nav-section-label {
    color: #8ba6c1;
}

html .area-plataforma .sidebar-logo-icon {
    background: #00a0e3;
    color: #fff;
}

html .area-plataforma .sidebar-nav .nav-item {
    color: #c8d8e8;
    border-left-color: transparent;
}

html .area-plataforma .sidebar-nav .nav-item:hover {
    background: rgba(0, 160, 227, .16);
    color: #ffffff;
}

html .area-plataforma .sidebar-nav .nav-item.active {
    background: rgba(0, 160, 227, .24);
    color: #ffffff;
    border-left-color: #00a0e3;
}

/* El icono hereda el color del texto; imagine.css lo deja al 70 % de opacidad y sobre
   fondo oscuro eso ya se nota demasiado. */
html .area-plataforma .sidebar-nav .nav-item .item-icon {
    color: inherit;
    opacity: .85;
}

html .area-plataforma .sidebar-nav .nav-item:hover .item-icon,
html .area-plataforma .sidebar-nav .nav-item.active .item-icon {
    color: inherit;
    opacity: 1;
}

html .area-plataforma .sidebar-collapse-btn {
    color: #8ba6c1;
}

html .area-plataforma .sidebar-collapse-btn:hover {
    background: rgba(0, 160, 227, .16);
    color: #fff;
}

html .area-plataforma .sidebar-user-footer {
    border-top-color: #1e3448;
}

html .area-plataforma .sidebar-user-footer .sidebar-user-avatar {
    background: #00a0e3;
    color: #fff;
}

/* Distintivo en la barra superior: se ve en todas las pantallas del área. */
.marca-plataforma {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .1rem .5rem;
    border-radius: 999px;
    background: #0d1b2a;
    color: #eaf2fa;
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
}

/* Bloque con la URL completa que se va a usar, para poder comprobarla de un vistazo. */
.url-resultante {
    display: block;
    padding: .5rem .7rem;
    border-radius: 7px;
    background: #f2fbff;
    border: 1px solid #b3e0f7;
    color: #005f8a;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .8rem;
    overflow-wrap: anywhere;
}

/* QR de la ficha del documento. */
.qr-ficha {
    display: flex;
    gap: 1.25rem;
    align-items: flex-start;
    flex-wrap: wrap;
}

.qr-ficha img {
    width: 168px;
    height: 168px;
    border: 1px solid var(--deca-borde);
    border-radius: 8px;
    background: #fff;
    padding: .35rem;
}

.qr-ficha .qr-datos {
    flex: 1 1 18rem;
    min-width: 0;
}

/* Resultado de comprobar si el portal público responde. */
.estado-portal {
    display: inline-block;
    margin-left: .5rem;
    padding: .1rem .55rem;
    border-radius: 999px;
    font-size: .75rem;
    font-weight: 600;
}

.estado-portal:empty         { display: none; }
.estado-portal.comprobando   { background: #e0eaff; color: #1e3a8a; }
.estado-portal.ok            { background: #d4edda; color: #155724; }
.estado-portal.mal           { background: #f8d7da; color: #721c24; }

/* El código de licencia se lee y se teclea a mano: monoespaciado, grande y espaciado. */
.codigo-licencia {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 1.05rem;
    letter-spacing: .06em;
    text-transform: uppercase;
}

/* Código recién emitido: es la única vez que se puede ver. */
.codigo-emitido {
    display: block;
    padding: .85rem 1rem;
    border: 2px dashed #00a0e3;
    border-radius: 8px;
    background: #f2fbff;
    color: #005f8a;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-align: center;
    overflow-wrap: anywhere;
}

/* ── Hilo de soporte ───────────────────────────────────────────────────────── */

.hilo-soporte {
    display: flex;
    flex-direction: column;
    gap: .85rem;
}

.hilo-soporte .mensaje {
    padding: .75rem 1rem;
    border-radius: 10px;
    max-width: 46rem;
}

/* El cliente a la izquierda y el soporte a la derecha: de un vistazo se ve de quién es
   cada mensaje sin tener que leer el encabezado. */
.hilo-soporte .de-cliente {
    background: var(--deca-fondo-suave);
    border: 1px solid var(--deca-borde);
    align-self: flex-start;
}

.hilo-soporte .de-soporte {
    background: #e8f4fd;
    border: 1px solid #b3e0f7;
    align-self: flex-end;
}

.hilo-soporte .quien {
    font-size: .78rem;
    font-weight: 600;
    color: var(--deca-texto-suave);
    margin-bottom: .3rem;
}

.hilo-soporte .cuando {
    font-weight: 400;
    margin-left: .5rem;
}

.hilo-soporte .cuerpo {
    font-size: .9rem;
    color: var(--deca-texto);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

textarea.admin-input {
    resize: vertical;
    min-height: 6rem;
    font: inherit;
}

/* Enlace con aspecto de enlace dentro de una tabla, sin serlo. */
.btn-enlace {
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    color: #00a0e3;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.btn-enlace:hover {
    text-decoration: underline;
}

/* ── Ayuda ─────────────────────────────────────────────────────────────────── */

.ayuda-indice {
    position: sticky;
    top: 1rem;
}

.ayuda-indice a {
    display: block;
    padding: .3rem .6rem;
    border-left: 2px solid transparent;
    color: var(--deca-texto-suave);
    font-size: .85rem;
    text-decoration: none;
}

.ayuda-indice a:hover {
    border-left-color: #00a0e3;
    color: #00a0e3;
}

.ayuda-paso {
    display: flex;
    gap: .9rem;
    margin-bottom: 1.1rem;
}

.ayuda-paso .numero {
    flex: 0 0 1.9rem;
    height: 1.9rem;
    border-radius: 50%;
    background: #00a0e3;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: .9rem;
}

.ayuda-paso .titulo {
    font-weight: 600;
    color: var(--deca-texto);
}

.ayuda-paso .texto {
    font-size: .88rem;
    color: #4a5568;
}

.ayuda-faq summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--deca-texto);
    padding: .55rem 0;
    border-bottom: 1px solid var(--deca-borde);
}

.ayuda-faq summary:hover {
    color: #00a0e3;
}

.ayuda-faq p {
    font-size: .88rem;
    color: #4a5568;
    padding: .6rem 0 .9rem;
    margin: 0;
}

/* ---- Confirmar un borrado sin salir de la fila ---- */

.confirmar-borrado {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .4rem;
    font-size: .82rem;
    color: #721c24;

    /* Suelta el `nowrap` de la celda de acciones: aquí hay una frase con un correo
       dentro, y sin esto la fila se estira hasta sacar la tabla de la pantalla. El
       nowrap está para que no se parta el grupo de BOTONES, no un texto. */
    white-space: normal;
}

/* ---- Logotipo de la empresa ---- */

.logo-vista {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 5.5rem;
    padding: .75rem;
    border: 1px solid var(--deca-borde);
    border-radius: 8px;

    /* Tablero de ajedrez claro: un logotipo con fondo transparente se ve igual sobre
       blanco que sobre nada, y así se distingue. */
    background:
        linear-gradient(45deg, #eef2f7 25%, transparent 25%, transparent 75%, #eef2f7 75%),
        linear-gradient(45deg, #eef2f7 25%, #fff 25%, #fff 75%, #eef2f7 75%);
    background-size: 16px 16px;
    background-position: 0 0, 8px 8px;
}

.logo-vista img {
    max-width: 100%;
    max-height: 5rem;
    object-fit: contain;
}

.logo-vacio {
    color: var(--deca-texto-suave);
    font-size: .85rem;
}

/* El logotipo del cliente en el selector de empresa del lateral. Si la empresa no tiene,
   la petición devuelve 404, deca.js retira la imagen y quedan las iniciales de debajo. */
.sidebar-ws-icon {
    position: relative;
    overflow: hidden;
    background: #fff;
}

.sidebar-ws-icon .ws-logo {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* :has() evita tener que avisar a nadie de que la imagen ha cargado: mientras el <img>
   siga en el DOM, las iniciales sobran. */
.sidebar-ws-icon:has(.ws-logo) .ws-iniciales {
    display: none;
}

.sidebar-ws-icon:not(:has(.ws-logo)) {
    background: var(--v3-accent);
}

/* ---- Mientras se carga una pantalla ----

   Existe porque no tenerlo no significaba «no enseñar nada»: significaba enseñar la rama
   de error. Una ficha que se pide por identificador tiene tres estados —cargando, no
   existe, y aquí está— y con un solo nulo para los dos primeros el usuario veía un
   «no encontrado» en rojo cada vez que abría un documento que sí existía. */

.deca-cargando {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: 1.25rem;
    color: var(--deca-texto-suave);
    font-size: .88rem;
}

.deca-spinner {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
    border: 2px solid #cfdbe9;
    border-top-color: #00a0e3;
    border-radius: 50%;
    animation: deca-girar .7s linear infinite;
}

@keyframes deca-girar {
    to { transform: rotate(360deg); }
}

/* Quien haya pedido menos animación no la recibe: el giro no aporta información que no
   dé ya el texto de al lado. */
@media (prefers-reduced-motion: reduce) {
    .deca-spinner { animation: none; }
}

/* ---- Matriculas ----

   El dominio ya las guarda en mayusculas (`NormalizePlate`); esto es para que se vean asi
   mientras se escriben, y no cambie el texto de golpe al guardar. `text-transform` solo
   afecta a como se pinta: lo que viaja es lo que se teclea, y lo normaliza el dominio. */

.admin-input.matricula {
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* ---- Sugerencias propias ----

   Sustituyen a <datalist>, que volvia a filtrar por su cuenta las opciones recibidas
   comparandolas con el texto tal cual: escribiendo «logrono» descartaba «Logroño (La Rioja)»
   aunque el servidor la hubiera encontrado. Ese filtrado es del navegador y no se puede
   desactivar, asi que la lista la pintamos nosotros. */

.sugerencias {
    position: relative;
}

.sugerencias-lista {
    position: absolute;
    z-index: 30;
    top: calc(100% + 2px);
    left: 0;
    right: 0;
    margin: 0;
    padding: .25rem;
    list-style: none;
    background: #fff;
    border: 1px solid var(--deca-borde);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(16, 32, 56, .14);
    max-height: 16rem;
    overflow-y: auto;
}

.sugerencias-lista .sugerencia {
    display: block;
    width: 100%;
    text-align: left;
    padding: .4rem .55rem;
    border: 0;
    border-radius: 6px;
    background: transparent;
    font-size: .85rem;
    color: var(--deca-texto, #1a2942);
    cursor: pointer;
}

.sugerencias-lista .sugerencia:hover,
.sugerencias-lista .sugerencia.resaltada {
    background: #e8f4fd;
}

.sugerencia-texto {
    display: block;
    font-weight: 500;
}

/* El NIF y el domicilio debajo del nombre: es lo que distingue dos intervinientes que se
   llaman parecido, y verlo antes de elegir evita el error en vez de corregirlo despues. */
.sugerencia-detalle {
    display: block;
    font-size: .75rem;
    color: var(--deca-texto-suave);
}

/* ---- Selector visual de la posicion del QR ---- */

.modal-qr,
.modal-pdf {
    position: fixed;
    inset: 0;
    z-index: 1080;
    background: rgba(12, 22, 38, .62);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
}

.modal-qr-caja,
.modal-pdf-caja {
    background: #fff;
    border-radius: 12px;
    width: min(56rem, 100%);
    max-height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.modal-qr-cabecera,
.modal-qr-pie,
.modal-pdf-cabecera {
    padding: .9rem 1.25rem;
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
}

.modal-qr-cabecera,
.modal-pdf-cabecera { border-bottom: 1px solid var(--deca-borde); }
.modal-qr-pie { border-top: 1px solid var(--deca-borde); }

.modal-qr-cuerpo,
.modal-pdf-cuerpo {
    padding: 1rem;
    overflow: auto;
    background: #eef2f7;
    display: flex;
    justify-content: center;
}

/* El lienzo pinta la hoja y la capa de encima recoge el raton. Separarlos evita repintar el
   PDF en cada movimiento, que con una hoja grande se nota. */
.qr-hoja {
    position: relative;
    line-height: 0;
    box-shadow: 0 2px 12px rgba(16, 32, 56, .18);
}

.qr-capa {
    position: absolute;
    inset: 0;
    cursor: crosshair;
    touch-action: none;
}

.qr-marco {
    position: absolute;
    border: 2px solid #00a0e3;
    background: rgba(0, 160, 227, .18);
    box-shadow: 0 0 0 9999px rgba(255, 255, 255, .01);
    pointer-events: none;
}

.modal-qr-medidas {
    font-size: .82rem;
    color: var(--deca-texto-suave);
    margin-left: auto;
}

/* ---- Estadisticas ---- */

/* Las cifras de cabecera usan .deca-kpis / .deca-kpi, las mismas que el inicio. Tuvieron
   clases propias y el resultado fue que no tenian ninguna: salian como texto suelto. */

.deca-dos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
    gap: 1rem;
}

.deca-dos > .deca-card { margin-bottom: 0; }

.grafico-vacio {
    color: var(--deca-texto-suave);
    font-size: .88rem;
    padding: 1.25rem 0;
    margin: 0;
}

/* ---- Barras ---- */

.grafico-caja { width: 100%; }

.grafico {
    width: 100%;
    height: 11rem;
    display: block;
}

.grafico-rejilla {
    stroke: #e4eaf1;
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

.grafico-barra { fill: #00a0e3; }
.grafico-barra:hover { fill: #0080b8; }

.grafico-ejes {
    display: flex;
    margin-top: .35rem;
}

.grafico-eje {
    font-size: .7rem;
    color: var(--deca-texto-suave);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
}

/* ---- Anillo ---- */

.anillo-caja {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    flex-wrap: wrap;
}

.anillo-dibujo {
    position: relative;
    width: 9.5rem;
    flex-shrink: 0;
}

.anillo { width: 100%; display: block; }

.anillo-fondo,
.anillo-porcion {
    fill: none;
    stroke-width: 5;
}

.anillo-fondo { stroke: #eef2f7; }

/* Seis colores y vuelta a empezar. Mas de seis situaciones a la vez no se dan, y con una
   paleta mas larga los tonos empiezan a parecerse entre si y el grafico deja de informar. */
.anillo-c0 { stroke: #00a0e3; }
.anillo-c1 { stroke: #1aa053; }
.anillo-c2 { stroke: #e6a020; }
.anillo-c3 { stroke: #d9534f; }
.anillo-c4 { stroke: #7a5cd0; }
.anillo-c5 { stroke: #5b6472; }

.anillo-centro {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.anillo-total {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1;
    color: var(--deca-texto, #1a2942);
}

.anillo-pie {
    font-size: .68rem;
    color: var(--deca-texto-suave);
}

.anillo-leyenda {
    list-style: none;
    margin: 0;
    padding: 0;
    flex: 1;
    min-width: 11rem;
}

.anillo-leyenda li {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .82rem;
    padding: .15rem 0;
}

.anillo-punto {
    width: .7rem;
    height: .7rem;
    border-radius: 3px;
    flex-shrink: 0;
    /* Los mismos colores que el anillo, pero aqui como relleno. */
    background: currentColor;
    color: inherit;
}

.anillo-punto.anillo-c0 { background: #00a0e3; }
.anillo-punto.anillo-c1 { background: #1aa053; }
.anillo-punto.anillo-c2 { background: #e6a020; }
.anillo-punto.anillo-c3 { background: #d9534f; }
.anillo-punto.anillo-c4 { background: #7a5cd0; }
.anillo-punto.anillo-c5 { background: #5b6472; }

.anillo-nombre { flex: 1; }
.anillo-cifra { font-weight: 600; }

/* ---- Ranking con barra en la propia fila ---- */

.ranking {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ranking li {
    display: grid;
    grid-template-columns: minmax(7rem, 1.4fr) 2fr auto;
    align-items: center;
    gap: .6rem;
    padding: .3rem 0;
    font-size: .85rem;
}

.ranking-nombre {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ranking-barra {
    background: #eef2f7;
    border-radius: 4px;
    height: .65rem;
    overflow: hidden;
}

.ranking-relleno {
    display: block;
    height: 100%;
    background: #00a0e3;
    border-radius: 4px;
}

.ranking-cifra {
    font-weight: 600;
    text-align: right;
    white-space: nowrap;
}

.ranking-cifra small {
    display: block;
    font-weight: 400;
    color: var(--deca-texto-suave);
}

/* ── Condiciones de uso ─────────────────────────────────────────────────────
   El texto se pinta en <pre> porque se guarda tal cual y se acepta tal cual: no
   se interpreta como Markdown ni como HTML. Lo único que hace falta es que los
   saltos de línea se respeten y que las líneas largas no desborden la tarjeta. */
.condiciones-texto {
    margin: 0;
    max-height: 32rem;
    overflow-y: auto;
    padding: 1rem 1.25rem;
    background: #f8f9fb;
    border: 1px solid #e3e7ee;
    border-radius: 8px;
    font-family: inherit;
    font-size: .875rem;
    line-height: 1.6;
    color: #34495e;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Previsualizacion del PDF adjuntado ─────────────────────────────────────────

   El armazon del modal lo comparte con el selector del QR (`.modal-qr*` arriba): son
   dos visores con el mismo marco y duplicar las reglas seria separarlos a la primera
   correccion. Lo que cambia es que aqui no hay nada que dibujar encima de la hoja.

   La miniatura se queda deliberadamente pequena: el recuadro del fichero se recorto a
   proposito para que resaltara, y una vista previa a toda pagina lo desharia. */
.vista-pdf-fila {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-top: 1rem;
    flex-wrap: wrap;
}

.vista-pdf-mini {
    position: relative;
    display: block;
    padding: 0;
    border: 1px solid var(--deca-borde);
    border-radius: 6px;
    background: #fff;
    line-height: 0;
    overflow: hidden;
    cursor: zoom-in;
    box-shadow: 0 1px 6px rgba(16, 32, 56, .12);
}

.vista-pdf-mini:hover,
.vista-pdf-mini:focus-visible {
    border-color: #00a0e3;
    box-shadow: 0 2px 10px rgba(16, 32, 56, .22);
}

/* El lienzo nace sin tamano y el JavaScript se lo pone al pintar. Sin alto minimo, el
   recuadro se ve como una raya durante el instante que tarda en cargar pdf.js. */
.vista-pdf-mini canvas {
    display: block;
    min-width: 60px;
    min-height: 80px;
}

.vista-pdf-mini .lupa {
    position: absolute;
    right: .25rem;
    bottom: .25rem;
    width: 1.5rem;
    height: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(12, 22, 38, .62);
    color: #fff;
    font-size: .75rem;
    line-height: 1;
}

.vista-pdf-hoja {
    line-height: 0;
    box-shadow: 0 2px 12px rgba(16, 32, 56, .18);
}

/* El visor se lee, no se ojea: ocupa la ventana. Va DESPUES de la regla que comparte con
   `.modal-qr-caja` para ganarle el ancho y anadirle el alto. */
.modal-pdf-caja {
    width: min(72rem, 100%);
    height: 100%;
}

.modal-pdf-cuerpo {
    flex: 1;
    /* Arriba y no centrado: una A4 a lo ancho no cabe de alto, y centrarla esconde la
       cabecera del albaran, que es justo donde estan los datos que se van a repasar. */
    align-items: flex-start;
}

/* ── Editor de plantillas: senalar un dato sobre el propio PDF ───────────────────

   Encima de la hoja se pintan las lineas de texto que el servidor ha leido de
   verdad. No se dibuja a mano alzada: se pulsa el renglon, y asi la zona coincide
   exactamente con lo que hay, que es mas preciso que cualquier cuadro a ojo.

   Las cajas van en PORCENTAJE sobre el marco, que envuelve al lienzo sin margen
   alguno. Las coordenadas que guarda el servidor son relativas, asi que encajan sin
   tener que preguntarle nada a JavaScript. */
/* El contenedor que SI tiene ancho propio. El marco de dentro es inline-block porque
   tiene que ceñirse al lienzo, y medir aquel para pintar devolvia los 300 px que trae un
   <canvas> vacio: la hoja salia diminuta en una tarjeta ancha. Medir para pintar siempre
   sobre un contenedor con ancho propio. */
.plantilla-ancho {
    display: block;
    width: 100%;
}

.plantilla-marco {
    position: relative;
    display: inline-block;
    line-height: 0;
    box-shadow: 0 2px 12px rgba(16, 32, 56, .18);
    max-width: 100%;
}

.plantilla-capa {
    position: absolute;
    inset: 0;
}

.plantilla-linea {
    position: absolute;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 2px;
    background: rgba(0, 160, 227, .06);
    cursor: pointer;
}

.plantilla-linea:hover,
.plantilla-linea:focus-visible {
    border-color: #00a0e3;
    background: rgba(0, 160, 227, .22);
}

/* La que ya esta asignada a un campo: en ambar, el mismo color con el que se marca
   un dato leido en el formulario. */
.plantilla-linea.asignada {
    border-color: #d97706;
    background: rgba(217, 119, 6, .20);
}

/* El recuadro dibujado a mano. Es la salida para los impresos que escriben dos datos
   pegados en la misma casilla, donde no hay casilla que señalar que traiga sólo uno. */
.plantilla-capa.dibujando {
    cursor: crosshair;
}

.plantilla-recuadro {
    position: absolute;
    border: 2px solid #d97706;
    border-radius: 2px;
    background: rgba(217, 119, 6, .16);

    /* Sin esto, el recuadro se convierte en el objetivo del puntero en cuanto aparece y la
       posición deja de ser relativa a la capa: el arrastre se vuelve loco a mitad del gesto. */
    pointer-events: none;
}

/* El que se está arrastrando ahora mismo, todavía sin guardar. */
.plantilla-recuadro.vivo {
    border-style: dashed;
    background: rgba(217, 119, 6, .08);
}

/* Un boton de la barra que esta actuando como interruptor y esta encendido. */
.admin-field .btn-cancel.activo,
.btn-cancel.activo {
    border-color: #00a0e3;
    background: #e8f4fd;
    font-weight: 600;
}

/* ── El aviso de que esto no es la instalacion de verdad ─────────────────────

   Ambar y no rojo: no ha pasado nada malo, hay algo que mirar. El rojo esta
   reservado a los errores y gastarlo aqui le quita fuerza donde hace falta.

   Va en el flujo del documento y NO fijo arriba: fijo taparia contenido en cada
   pantalla y obligaria a compensar con relleno en los tres armazones. Aqui empuja
   la pagina hacia abajo, que es lo que se quiere. */
.aviso-entorno {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .5rem 1rem;
    background: #fef3c7;
    border-bottom: 2px solid #d97706;
    color: #78350f;
    font-size: .85rem;
    line-height: 1.35;
}

.aviso-entorno .etiqueta {
    flex: 0 0 auto;
    padding: .1rem .5rem;
    border-radius: 3px;
    background: #d97706;
    color: #fff;
    font-weight: 700;
    font-size: .75rem;
    letter-spacing: .06em;
}

.aviso-entorno .texto {
    flex: 1 1 auto;
    min-width: 0;
}

.aviso-entorno .enlace {
    flex: 0 0 auto;
    color: #78350f;
    font-weight: 600;
    text-decoration: underline;
}

.aviso-entorno .cerrar {
    flex: 0 0 auto;
    padding: .15rem .35rem;
    border: 0;
    border-radius: 3px;
    background: transparent;
    color: #78350f;
    cursor: pointer;
}

.aviso-entorno .cerrar:hover,
.aviso-entorno .cerrar:focus-visible {
    background: rgba(120, 53, 15, .12);
}

/* En un movil, el enlace y el texto se apilan en lugar de encogerse hasta no leerse. */
@media (max-width: 575.98px) {
    .aviso-entorno {
        flex-wrap: wrap;
    }

    .aviso-entorno .texto {
        flex: 1 1 100%;
        order: 3;
    }
}
/* Un enlace en un campo de solo lectura con el boton de copiar DENTRO.
   Dentro y no al lado: al lado se lee como un boton mas de la pantalla, y lo que hace
   es sobre ese campo concreto. */
.enlace-copiable {
    position: relative;
    display: block;
}

.enlace-copiable .admin-input {
    /* Hueco para el boton, para que la URL no pase por debajo. */
    padding-right: 2.6rem;
    font-family: var(--bs-font-monospace, monospace);
    font-size: .8rem;
}

.btn-copiar {
    position: absolute;
    top: 50%;
    right: .35rem;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 4px;
    background: transparent;
    color: var(--deca-texto-suave, #6b7280);
    cursor: pointer;
}

.btn-copiar:hover,
.btn-copiar:focus-visible {
    border-color: var(--deca-borde);
    background: #fff;
    color: #00a0e3;
}

/* Acuse de recibo: el aviso vive en el propio boton, que es donde esta mirando
   quien acaba de pulsar. */
.btn-copiar.copiado {
    color: #16a34a;
}

.plantilla-campos {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-bottom: 1rem;
}

.plantilla-campo {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .3rem .6rem;
    border: 1px solid var(--deca-borde);
    border-radius: 999px;
    background: #fff;
    font-size: .8rem;
    cursor: pointer;
}

.plantilla-campo.activo {
    border-color: #00a0e3;
    background: #e8f4fd;
    font-weight: 600;
}

.plantilla-campo.sabido {
    border-color: #d97706;
}

/* Apagado por el cliente: ese dato no está en su papel y no quiere que se le proponga.
   Se atenúa en lugar de esconderlo, porque hay que poder volver a encenderlo. */
.plantilla-campo.apagado {
    border-style: dashed;
    color: var(--deca-texto-suave, #6b7280);
    text-decoration: line-through;
}

/* ── Campo de contraseña con el ojo dentro ─────────────────────────────────
   El `.toggle-eye` de imagine.css está posicionado respecto de
   `.login-input-group`, que sólo existe en el armazón de acceso. Fuera de él
   —«Cambiar contraseña», por ejemplo— el botón caía al final del flujo, así
   que aquí va su propio contenedor.

   El relleno derecho del campo es lo que impide que el texto pase por debajo
   del icono; sin él, una contraseña larga se lee a medias. */
.campo-clave {
    position: relative;
}

.campo-clave .admin-input {
    padding-right: 2.5rem;
}

.campo-clave .ojo-clave {
    position: absolute;
    right: .55rem;
    top: 2.15rem;
    border: 0;
    background: none;
    padding: 0;
    line-height: 1;
    color: #7a8796;
    cursor: pointer;
}

.campo-clave .ojo-clave:hover {
    color: #1f2933;
}

/* La fecha del transporte: texto en día/mes/año con el calendario dentro del campo, igual
   que el ojo de la contraseña. El type="date" nativo queda debajo del botón, invisible: sólo
   está para abrir su calendario. No va con display:none porque entonces showPicker() no
   tiene dónde anclar el desplegable. */
.campo-fecha {
    position: relative;
}

.campo-fecha .admin-input {
    padding-right: 2.5rem;
}

.campo-fecha-nativo {
    position: absolute;
    right: .4rem;
    bottom: 0;
    width: 1.75rem;
    height: 1px;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

.campo-fecha-boton {
    position: absolute;
    top: 0;
    bottom: 0;
    right: .55rem;
    display: flex;
    align-items: center;
    border: 0;
    background: none;
    padding: 0;
    line-height: 1;
    color: #7a8796;
    cursor: pointer;
}

.campo-fecha-boton:hover {
    color: #1f2933;
}

/* ── Verificación en dos pasos ─────────────────────────────────────────────
   Los códigos de recuperación se enseñan UNA vez y hay que copiarlos o
   imprimirlos, así que se pintan en rejilla y en monoespaciada: en una lista
   corrida se salta uno al teclearlos y no se nota hasta el día que hacen
   falta. `user-select: all` deja coger cada uno de un clic. */
.codigos-recuperacion {
    list-style: none;
    margin: 1rem 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: .5rem;
}

.codigos-recuperacion code {
    display: block;
    padding: .5rem .75rem;
    background: #f5f6f8;
    border: 1px solid #e3e6ea;
    border-radius: 6px;
    font-size: 1rem;
    letter-spacing: .04em;
    color: #1f2933;
    user-select: all;
}

/* Descargar, copiar e imprimir: que guardarlos cueste un clic es lo que hace que se
   guarden, mucho más que cualquier aviso en rojo. */
.guardar-codigos {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* Mismo igualado que dentro de .admin-field: .btn-cancel trae 48 px fijos del CRM y al lado
   de .btn-nuevo saldrían de alturas distintas. El borde transparente compensa el suyo. */
.guardar-codigos .btn-nuevo,
.guardar-codigos .btn-cancel {
    height: auto;
    padding: .45rem 1rem;
    font-size: .875rem;
    line-height: 1.5;
    border: 1.5px solid transparent;
    border-radius: 7px;
    box-sizing: border-box;
    gap: .4rem;
}

.guardar-codigos .btn-cancel { border-color: #e2e8f0; }

.pasos-dos-factores {
    margin: 0 0 1rem 0;
    padding-left: 1.25rem;
    color: #3c4757;
    line-height: 1.6;
}

.pasos-dos-factores > li {
    margin-bottom: 1rem;
}

/* El QR va sobre blanco y con margen propio: la zona de silencio forma parte
   del código, y un fondo gris pegado al borde hace que algunos lectores no lo
   reconozcan. */
/* En bloque y no en línea: dentro del texto del paso, el rótulo quedaba pegado a la
   base del código y la clave manual se iba a su derecha. */
.qr-dos-factores {
    display: block;
    width: fit-content;
    margin: .75rem 0;
    padding: .75rem;
    background: #ffffff;
    border: 1px solid #e3e6ea;
    border-radius: 8px;
}

.qr-dos-factores img {
    display: block;
    width: 190px;
    height: 190px;
    image-rendering: pixelated;
}

/* ─────────────────────────────────────────────────────────────────────────
   Pie legal

   Va en el FLUJO, debajo del contenido, y no fijo abajo: fijo taparía la
   última fila de una tabla larga en cada pantalla del portal, y lo que hay
   aquí no hace falta tenerlo siempre delante.

   En móvil las dos mitades se apilan y los enlaces se centran: en una
   columna de 360 px, cuatro enlaces y el copyright en la misma línea salen
   partidos por cualquier sitio.
   ───────────────────────────────────────────────────────────────────────── */
.pie-legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .35rem 1.25rem;
    margin-top: 2rem;
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--deca-borde);
    color: var(--deca-texto-suave);
    font-size: .8rem;
}

.pie-legal-marca {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .35rem;
}

/* Se esconde en pantallas estrechas: es la parte que menos aporta y la que
   más ocupa. El símbolo y el titular siguen estando. */
.pie-legal-reservado {
    opacity: .75;
}

.pie-legal-enlaces {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem 1rem;
}

.pie-legal-enlaces a {
    color: var(--deca-texto-suave);
    text-decoration: none;
}

.pie-legal-enlaces a:hover,
.pie-legal-enlaces a:focus-visible {
    color: var(--deca-texto);
    text-decoration: underline;
}

@media (max-width: 575.98px) {
    .pie-legal {
        flex-direction: column;
        align-items: center;
        text-align: center;
        padding: 1rem;
    }

    .pie-legal-reservado {
        display: none;
    }
}

/* ---- El pie en el armazón de acceso ----

   Va abajo del todo del panel azul. `margin-top: auto` lo empuja al fondo de
   la columna sin descentrar la marca, y el `position: relative` lo pone por
   encima de los dos círculos decorativos del panel, que son absolutos. */
/* ---- El pie abajo del panel azul, SIN subir la marca al borde de arriba ----

   El `margin-top: auto` del pie es lo que lo pega abajo, pero un margen automático se come
   TODO el hueco libre y gana al `justify-content: center` del panel: al ponerlo, la marca y
   la lista de ventajas se fueron de un salto al borde superior y dejaron medio panel vacío.

   El segundo `margin-top: auto`, en el logotipo, es lo que lo arregla: con dos márgenes
   automáticos el hueco se reparte entre los dos, así que queda tanto espacio por encima de
   la marca como entre ella y el pie. La marca vuelve a su sitio y el pie se queda abajo. */
.login-brand-panel .login-brand-logo {
    margin-top: auto;
}

.pie-acceso-marca {
    position: relative;
    z-index: 1;
    width: 100%;
    margin-top: auto;
}

.pie-acceso-marca .pie-legal {
    justify-content: center;
    border-top: 1px solid rgba(255, 255, 255, .18);
    padding: 1rem 0 0;
    color: rgba(255, 255, 255, .75);
}

.pie-acceso-marca .pie-legal-enlaces a {
    color: rgba(255, 255, 255, .85);
}

.pie-acceso-marca .pie-legal-enlaces a:hover,
.pie-acceso-marca .pie-legal-enlaces a:focus-visible {
    color: #fff;
}

/* El respaldo del móvil, donde el panel azul no existe. */
.pie-acceso-movil {
    display: none;
    width: 100%;
}

.pie-acceso-movil .pie-legal {
    justify-content: center;
    border-top: 0;
    margin-top: 1.25rem;
    padding-bottom: 0;
}

@media (max-width: 768px) {
    /* En columna, para que el pie caiga DEBAJO de la tarjeta y no a su lado:
       el panel es `display:flex` y en fila quedarían uno junto al otro. */
    .login-form-panel {
        flex-direction: column;
    }

    .pie-acceso-movil {
        display: block;
    }
}

/* El lateral del área de plataforma es oscuro, pero el contenido no: el pie
   se queda igual que en el portal del cliente. Esta regla existe sólo para
   dejarlo dicho y que nadie lo "arregle" pintándolo oscuro. */
html .area-plataforma .pie-legal {
    color: var(--deca-texto-suave);
}

/* El horario de soporte. La línea del horario va algo mayor y en el color del
   texto fuerte: es el dato que se viene a buscar, y dentro de un .deca-sub
   quedaba al mismo peso que la explicación de al lado. */
.deca-horario .horario-linea {
    margin: 0 0 .5rem;
    font-size: 1rem;
    font-weight: 600;
    color: var(--deca-texto);
}

/* ─────────────────────────────────────────────────────────────────────────
   Avisos de la casa

   Trece clases nuevas, y se escriben AQUÍ antes de dar la pantalla por
   terminada: una clase sin regla no da error, sólo no se ve, y en este
   repositorio ya ha mordido tres veces.
   ───────────────────────────────────────────────────────────────────────── */

/* El contador del lateral. Va pegado al rótulo y no flotando: el lateral se
   pliega a sólo iconos, y un globo posicionado en absoluto se quedaría
   colgado fuera. */
.nav-contador {
    margin-left: auto;
    min-width: 1.35rem;
    padding: 0 .35rem;
    border-radius: 999px;
    background: #c0392b;
    color: #fff;
    font-size: .72rem;
    font-weight: 700;
    line-height: 1.35rem;
    text-align: center;
}

.aviso-casa-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: .5rem;
    margin-bottom: .5rem;
}

.aviso-casa-titulo {
    margin: 0 0 .25rem;
    font-size: 1.05rem;
}

/* La franja de color va a la izquierda y no de fondo: el texto del aviso se
   lee entero y un fondo de color detrás de siete líneas cansa. */
.aviso-casa {
    border-left: 4px solid var(--deca-borde);
}

.aviso-casa.pendiente {
    border-left-color: #c0392b;
}

.aviso-casa-clase {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
}

.aviso-casa-clase.es-informacion  { color: #1e3a8a; }
.aviso-casa-clase.es-mantenimiento { color: #8a6d1e; }
.aviso-casa-clase.es-incidencia   { color: #721c24; }
.aviso-casa-clase.es-accion       { color: #155724; }

/* El texto, escapado y respetando los saltos de línea tal y como se
   escribieron, como el de las condiciones de uso. `pre-wrap` y no `pre`: sin
   él, una línea larga saca una barra horizontal en el móvil. */
.aviso-casa-texto {
    margin: .5rem 0 0;
    padding: 0;
    background: none;
    border: 0;
    font: inherit;
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--deca-texto);
}

.badge-pendiente {
    display: inline-block;
    padding: .15rem .5rem;
    border-radius: 999px;
    background: #f8d7da;
    color: #721c24;
    font-size: .75rem;
    font-weight: 600;
}

/* La lista de empresas al publicar. Con scroll porque con cincuenta clientes
   el botón de publicar se iría a tres pantallas de distancia. */
.lista-empresas-aviso {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: .35rem 1rem;
    max-height: 18rem;
    overflow-y: auto;
    padding: .6rem;
    border: 1px solid var(--deca-borde);
    border-radius: 8px;
    background: var(--deca-fondo-suave);
}

/* ─────────────────────────────────────────────────────────────────────────
   Cuadro de mando de la plataforma

   Ocho clases nuevas, escritas aquí antes de dar la pantalla por terminada:
   una clase sin regla no da error, sólo no se ve.
   ───────────────────────────────────────────────────────────────────────── */

.panel-avisos {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: .6rem;
}

/* Cada aviso es un ENLACE a donde se resuelve, no un número suelto: un panel
   que obliga a buscar a mano a qué empresa se refiere se deja de usar. */
.panel-aviso {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .7rem .9rem;
    border-radius: 8px;
    border-left: 4px solid transparent;
    background: var(--deca-fondo-suave);
    color: var(--deca-texto);
    text-decoration: none;
}

.panel-aviso:hover,
.panel-aviso:focus-visible {
    background: #eef2f8;
    color: var(--deca-texto);
}

.panel-aviso.mal  { border-left-color: #c0392b; }
.panel-aviso.info { border-left-color: #1e3a8a; }

.panel-aviso-cifra {
    flex: 0 0 auto;
    min-width: 2.2rem;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1;
    text-align: right;
}

.panel-aviso.mal .panel-aviso-cifra  { color: #c0392b; }
.panel-aviso.info .panel-aviso-cifra { color: #1e3a8a; }

.panel-aviso-texto {
    font-size: .82rem;
    line-height: 1.25;
}

/* La variación respecto al mes pasado, dentro de la etiqueta de la cifra. */
.panel-variacion {
    margin-left: .35rem;
    font-weight: 700;
}

.panel-variacion.sube { color: #155724; }
.panel-variacion.baja { color: #c0392b; }

/* El cupo apurado se marca en la propia celda: es donde mira quien está
   repasando la tabla, no en una leyenda aparte. */
.cupo-apurado {
    color: #c0392b;
    font-weight: 700;
}

/* ─────────────────────────────────────────────────────────────────────────
   Acceso de soporte: está dentro de la empresa de un cliente

   Rojo y SIN botón de cerrar, al revés que la barra de DEMO. La diferencia
   es de consecuencia: la de la demo la ve quien trabaja en pruebas a
   propósito y le estorba todo el día; ésta avisa de que lo que se está
   mirando son los datos de un cliente de verdad, y olvidarlo es el riesgo
   entero de esta función. Un aviso que se quita no avisa.

   Va en el flujo, encima del contenido y debajo de la barra superior, para
   que no tape nada ni obligue a compensar con relleno.
   ───────────────────────────────────────────────────────────────────────── */
.barra-soporte {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .6rem 1rem;
    padding: .55rem 1.5rem;
    background: #721c24;
    color: #fff;
    font-size: .85rem;
}

.barra-soporte .etiqueta {
    flex: 0 0 auto;
    padding: .1rem .5rem;
    border-radius: 4px;
    background: #fff;
    color: #721c24;
    font-size: .7rem;
    font-weight: 800;
    letter-spacing: .08em;
}

.barra-soporte .texto {
    flex: 1 1 18rem;
    line-height: 1.3;
}

.barra-soporte .salir {
    flex: 0 0 auto;
    padding: .3rem .7rem;
    border: 1px solid rgba(255, 255, 255, .6);
    border-radius: 6px;
    background: transparent;
    color: #fff;
    font-size: .8rem;
    font-weight: 600;
    cursor: pointer;
}

.barra-soporte .salir:hover,
.barra-soporte .salir:focus-visible {
    background: rgba(255, 255, 255, .15);
}

@media print {
    /* Al imprimir una pantalla del cliente para adjuntarla a una incidencia,
       la banda roja se come media hoja de tinta y no aporta nada al papel. */
    .barra-soporte {
        display: none;
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   Secciones del menú que se pliegan

   El aspecto sale entero de `.nav-group-toggle` y `.nav-group-chevron`, que ya
   vienen en `imagine.css`. Aquí sólo lo que aquel fichero no podía saber.
   ───────────────────────────────────────────────────────────────────────── */

/* Con el lateral plegado a iconos, la cabecera sobra igual que la etiqueta de
   sección a la que sustituye — `imagine.css` esconde aquélla y no ésta, porque
   en el CRM del que viene no conviven las dos formas. */
.app-sidebar.sidebar-collapsed .nav-group-toggle {
    display: none;
}

/* El lateral del área de plataforma es OSCURO. Sin esto, la cabecera heredaría
   el gris pensado para un lateral claro y quedaría ilegible: es exactamente la
   trampa de la especificidad con `imagine.css`, y lleva el prefijo `html` por
   lo mismo que la regla de `.nav-section-label` que hay más arriba — allí ya
   existe `html[data-theme="dark"] .nav-group-toggle`, que empata en
   especificidad y sólo pierde por orden de carga. */
html .area-plataforma .nav-group-toggle {
    color: #8ba6c1;
}

html .area-plataforma .nav-group-toggle:hover {
    color: #fff;
}

/* ─────────────────────────────────────────────────────────────────────────
   Los dos pies, siempre a la vista

   `imagine.css` ya monta el armazón para que scrolle por dentro —el wrapper
   mide 100vh, el menú y el contenido llevan su propio overflow—, así que los
   pies deberían quedarse quietos. Se movían por tres motivos distintos y
   hacían falta los tres arreglos.
   ───────────────────────────────────────────────────────────────────────── */

/* 1. LA BARRA DE DEMO VIVE FUERA DEL ARMAZÓN.
      `<AvisoDemo />` es hermano de `.app-wrapper`, así que en la instalación
      de pruebas el cuerpo mide «barra + 100vh»: los pies caían por debajo del
      borde y había que bajar la página entera para verlos. Poniendo el cuerpo
      en columna, el armazón ocupa lo que queda y la barra no le roba alto.

      Va con `:has()` para no tocar la pantalla de acceso ni el portal
      público, que no tienen armazón. Un navegador que no lo entienda ignora
      la regla y se queda como estaba: sigue funcionando, sólo que con la
      barra de pruebas vuelve el desplazamiento del cuerpo. */
body:has(> .app-wrapper) {
    display: flex;
    flex-direction: column;
    height: 100vh;

    /* Y en el móvil, el alto REAL. Con `100vh` la barra de direcciones del
       navegador se come la franja de abajo, que es justo donde está el pie:
       quedaba fuera de la vista y, con el `overflow:hidden` del armazón, sin
       forma de llegar a él. */
    height: 100dvh;
    overflow: hidden;
}

body:has(> .app-wrapper) > .aviso-entorno {
    flex-shrink: 0;
}

body:has(> .app-wrapper) > .app-wrapper {
    height: auto;
    min-height: 0;
    flex: 1;
}

/* El lateral mide 100vh en `imagine.css`; dentro de este armazón tiene que
   medir lo que mida su contenedor, o vuelve a sobrar justo el alto de la
   barra de pruebas. Como hijo de un flex en fila, se estira solo. */
body:has(> .app-wrapper) .app-sidebar {
    height: auto;
}

/* 2. LOS PIES SE ENCOGÍAN.
      Son elementos de un flex en columna y, por defecto, un elemento flex se
      encoge cuando falta sitio: en una ventana baja no desaparecían, se
      APLASTABAN —de ahí el avatar cortado por la mitad—. Es la misma razón
      por la que `.sidebar-nav` lleva `flex-shrink: 0` en sus hijos. */
.sidebar-user-footer {
    flex-shrink: 0;
}

.app-content > .pie-legal {
    flex-shrink: 0;

    /* Y sin el margen superior: separaba del contenido cuando el pie iba en
       el flujo, pero con el contenido scrollando por su cuenta deja un hueco
       muerto encima. La raya de arriba ya marca la separación. */
    margin-top: 0;
}

/* 3. AL IMPRIMIR NO HAY ARMAZÓN QUE VALGA.
      Con el alto fijo y el `overflow:hidden`, imprimir una pantalla sacaba
      SÓLO lo que cabía en la primera hoja y el resto se perdía. Venía de
      antes, pero fijar los pies lo deja a la vista: el papel no tiene alto de
      ventana. Y el menú y la barra superior no se imprimen, que en papel no
      sirven para nada y se comen el ancho. */
@media print {
    body:has(> .app-wrapper) {
        display: block;
        height: auto;
        overflow: visible;
    }

    body:has(> .app-wrapper) > .app-wrapper {
        display: block;
        height: auto;
        overflow: visible;
    }

    .app-sidebar,
    .app-topbar,
    .sidebar-backdrop {
        display: none;
    }

    .app-content,
    .app-main {
        display: block;
        height: auto;
        overflow: visible;
    }
}

/* ---- El paso a paso del ensayo de soporte ----

   Una lista y no una tabla: cada paso es un titular con su explicación debajo, y el ancho de
   la explicación es lo que importa. En columnas, la segunda se queda con la mitad de la hoja
   y las frases que de verdad dicen algo —«la empresa tiene activado el rechazo de escaneos,
   así que esto impide emitir»— salen partidas en cinco líneas. */
.ensayo-pasos {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ensayo-pasos li {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .6rem 0;
    border-bottom: 1px solid #eef2f7;
}

.ensayo-pasos li:last-child {
    border-bottom: 0;
}

.ensayo-pasos li > i {
    margin-top: .15rem;
    font-size: 1rem;
}

.ensayo-pasos li.ok > i { color: #198754; }
.ensayo-pasos li.aviso > i { color: #c58900; }
.ensayo-pasos li.mal > i { color: #c0392b; }

/* El renglón de un paso con error se marca entero, no sólo su icono: en una lista de ocho
   pasos, un icono rojo de un centímetro pasa inadvertido y lo que se está buscando es
   precisamente ése. */
.ensayo-pasos li.mal {
    background: #fdf2f2;
    border-radius: 6px;
    padding-left: .6rem;
    padding-right: .6rem;
}

/* ═══════════════════════════════════════════════════════════════════════════
   EL PORTAL DEL CONDUCTOR

   No hereda el armazón del cliente y no es ése recortado. Quien entra aquí usa un móvil,
   muchas veces en una cabina o en un arcén y a veces a pleno sol: lo que tiene que caber en
   la primera pantalla es qué lleva hoy y el botón de abrirlo. Mismo criterio que la pantalla
   del conductor del portal público, que tampoco hereda nada.
   ═══════════════════════════════════════════════════════════════════════════ */

.conductor-armazon {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    background: #f4f7fb;
}

.conductor-barra {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 1rem;
    background: var(--im-primary, #0b78c2);
    color: #fff;

    /* Pegada arriba: al bajar por una lista de treinta DeCA, el botón de salir y la cuenta
       con la que se ha entrado tienen que seguir estando. */
    position: sticky;
    top: 0;
    z-index: 10;
    flex-shrink: 0;
}

.conductor-marca {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    font-weight: 700;
    font-size: 1.05rem;
}

.conductor-cuenta {
    display: inline-flex;
    align-items: center;
    gap: .75rem;
    min-width: 0;
}

.conductor-correo {
    font-size: .8rem;
    opacity: .85;

    /* El correo de un conductor puede ser largo y la pantalla de un móvil no: antes de
       empujar el botón de salir fuera de la vista, se recorta. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 14rem;
}

.conductor-salir {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    background: rgba(255, 255, 255, .15);
    border: 1px solid rgba(255, 255, 255, .35);
    color: #fff;
    border-radius: 6px;
    padding: .35rem .7rem;
    font-size: .85rem;
    cursor: pointer;
}

.conductor-salir:hover { background: rgba(255, 255, 255, .25); }

.conductor-cuerpo {
    flex: 1;
    padding: 1rem;
    max-width: 52rem;
    width: 100%;
    margin: 0 auto;
}

.conductor-titulo {
    font-size: 1.35rem;
    font-weight: 700;
    color: #15324b;
    margin-bottom: 1rem;
}

.conductor-filtro {
    margin-bottom: 1rem;
}

.conductor-filtro label {
    display: block;
    font-size: .8rem;
    color: #6b7c93;
    margin-bottom: .25rem;
}

.conductor-dia { margin-bottom: 1.5rem; }

.conductor-dia-titulo {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: 1rem;
    font-weight: 700;
    color: #15324b;
    text-transform: none;
    margin-bottom: .5rem;

    /* También pegado: al recorrer un día con veinte DeCA conviene no perder de vista de qué
       día se está hablando, que es justo lo que se pregunta en un control. */
    position: sticky;
    top: 3.25rem;
    background: #f4f7fb;
    padding: .4rem 0;
    z-index: 5;
}

.conductor-dia-cuenta {
    background: #e0eaff;
    color: #1e3a8a;
    border-radius: 999px;
    padding: 0 .5rem;
    font-size: .75rem;
    font-weight: 700;
}

.conductor-empresa { margin-bottom: .75rem; }

.conductor-empresa-titulo {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: .8rem;
    font-weight: 600;
    color: #6b7c93;
    text-transform: uppercase;
    letter-spacing: .02em;
    margin: .5rem 0 .35rem;
}

.conductor-deca {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    flex-wrap: wrap;
    background: #fff;
    border: 1px solid #e0e7ef;
    border-radius: 10px;
    padding: .75rem .9rem;
    margin-bottom: .5rem;
}

.conductor-deca.no-disponible { opacity: .7; }

.conductor-deca-datos {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
    flex: 1 1 14rem;
}

.conductor-deca-numero {
    font-weight: 700;
    color: #15324b;
}

.conductor-deca-ruta {
    font-size: .9rem;
    color: #35506b;
}

.conductor-deca-botones {
    display: flex;
    gap: .5rem;
    flex-shrink: 0;
}

/* En un móvil los dos botones ocupan la línea entera: se pulsan con el pulgar y con guantes,
   no con un ratón. */
@media (max-width: 575px) {
    .conductor-deca-botones { width: 100%; }
    .conductor-deca-botones > * { flex: 1; justify-content: center; }
    .conductor-correo { max-width: 8rem; }
}

@media print {
    .conductor-barra { display: none; }
    .conductor-armazon { min-height: 0; background: #fff; }
}

/* ---- El modal que pide la dirección de respuesta ----

   Reutiliza `deca-modal` y su fondo: duplicar el armazón los habría separado a la primera
   corrección, igual que pasa con el del selector del QR y el del visor de PDF. Lo que
   añade es lo que éste tiene y aquél no: un título, un campo y dos botones. */
.deca-modal-form {
    text-align: left;
    max-width: 34rem;
}

.deca-modal-form > i {
    display: block;
    text-align: center;
    color: var(--im-primary, #0b78c2);
}

.deca-modal-form h2 {
    font-size: 1.15rem;
    font-weight: 700;
    color: #15324b;
    text-align: center;
    margin: .75rem 0 .5rem;
}

.deca-modal-form p {
    margin: 0 0 .75rem;
    font-size: .95rem;
    line-height: 1.45;
    color: var(--deca-texto, #35506b);
}

.deca-modal-detalle {
    font-size: .85rem !important;
    color: #6b7c93 !important;
}

.deca-modal-error {
    color: #b42318 !important;
    font-size: .85rem !important;
    margin-top: .5rem !important;
}

/* En una sola línea y a lo ancho: es un campo que no se puede leer de un vistazo —una
   dirección de correo larga— y partirlo en dos columnas no ayudaría a nadie. */
.deca-modal-form .admin-input {
    width: 100%;
}

.deca-modal-botones {
    display: flex;
    gap: .5rem;
    justify-content: flex-end;
    margin-top: 1rem;
    flex-wrap: wrap;
}

/* En un móvil los dos botones ocupan la línea entera, como los del portal del conductor. */
@media (max-width: 575px) {
    .deca-modal-botones > * { flex: 1; justify-content: center; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   TEMA OSCURO

   `imagine.css` ya trae el tema entero —casi mil reglas y un juego completo de variables
   bajo `html[data-theme="dark"]`—, así que aquí NO se reinventa nada: lo único que falta es
   lo propio del DeCA, que se escribió con colores fijos porque entonces no había más que un
   tema.

   Tres cosas que conviene saber antes de tocar esto:

   1. El tema vive en `<html data-theme>` porque es de donde tira el sistema de diseño.
      Inventar otro interruptor habría dejado dos mecanismos que un día discrepan.
   2. Se aplica con un script en línea en el `<head>`, ANTES de que se pinte nada. Sin eso
      hay un fogonazo blanco en cada carga, y en una habitación a oscuras ese fogonazo es
      justo lo que el tema viene a evitar.
   3. Se guarda en `localStorage` y NO en el perfil, al revés que el idioma. Y la diferencia
      no es de comodidad: el idioma es de la persona —lo lleva a cualquier equipo— y el tema
      es del sitio donde se está, de noche en el portátil y de día en la oficina. Guardarlo
      en la cuenta obligaría a cambiarlo en los dos sitios.

   Los colores de estado —rojo, ámbar, verde— conservan el tono pero pierden su fondo claro:
   un panel #f8d7da sobre una página oscura es una linterna.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- Superficies ---- */
html[data-theme="dark"] .deca-card,
html[data-theme="dark"] .deca-kpi,
html[data-theme="dark"] .deca-acceso,
html[data-theme="dark"] .celda-carpeta,
html[data-theme="dark"] .conductor-deca,
html[data-theme="dark"] .modal-qr-caja,
html[data-theme="dark"] .modal-pdf-caja,
html[data-theme="dark"] .deca-modal,
html[data-theme="dark"] .sugerencias-lista,
html[data-theme="dark"] .logo-vista,
html[data-theme="dark"] .pasos-dos-factores,
html[data-theme="dark"] .confirmar-borrado {
    background: var(--bg-card);
    color: var(--text);
    border-color: var(--border);
}

html[data-theme="dark"] .deca-card > h2,
html[data-theme="dark"] .deca-card > h3,
html[data-theme="dark"] .conductor-titulo,
html[data-theme="dark"] .conductor-deca-numero,
html[data-theme="dark"] .deca-modal-form h2,
html[data-theme="dark"] .anillo-total,
html[data-theme="dark"] .ranking-nombre {
    color: var(--text);
}

html[data-theme="dark"] .deca-sub,
html[data-theme="dark"] .admin-meta,
html[data-theme="dark"] .conductor-filtro label,
html[data-theme="dark"] .conductor-empresa-titulo,
html[data-theme="dark"] .deca-modal-detalle,
html[data-theme="dark"] .sugerencia-detalle,
html[data-theme="dark"] .anillo-nombre,
html[data-theme="dark"] .ayuda-faq p {
    color: var(--text-muted);
}

html[data-theme="dark"] .conductor-deca-ruta,
html[data-theme="dark"] .deca-modal-form p,
html[data-theme="dark"] .deca-modal > p,
html[data-theme="dark"] .condiciones-texto,
html[data-theme="dark"] .ayuda-paso .texto {
    color: var(--text);
}

/* ---- El armazón del conductor ---- */
html[data-theme="dark"] .conductor-armazon { background: var(--bg-body); }

html[data-theme="dark"] .conductor-dia-titulo {
    background: var(--bg-body);
    color: var(--text);
}

html[data-theme="dark"] .conductor-dia-cuenta {
    background: var(--acento-bg);
    color: var(--acento);
}

/* ---- Tablas ---- */
html[data-theme="dark"] .admin-table thead th {
    background: var(--bg-card);
    color: var(--text-muted);
    border-bottom-color: var(--border-2);
}

html[data-theme="dark"] .admin-table tbody tr.vigente td { background: var(--acento-bg); }
html[data-theme="dark"] .admin-table tbody tr.fallo td { background: #3a2226; }
html[data-theme="dark"] .lista-carpeta li { border-color: var(--border); }

/* ---- Avisos y estados: el tono se conserva, el fondo claro no ---- */
html[data-theme="dark"] .deca-aviso.ok    { background: #17352a; color: #86efac; }
html[data-theme="dark"] .deca-kpi.mal .valor { color: #fca5a5; }
html[data-theme="dark"] .deca-kpi.mal        { border-left-color: #b45309; }
html[data-theme="dark"] .deca-aviso.mal   { background: #3a2226; color: #fca5a5; }
html[data-theme="dark"] .deca-aviso.info  { background: #1d3a52; color: #a5c9f5; }
html[data-theme="dark"] .deca-aviso.aviso { background: #3a2f12; color: #fcd34d; }

html[data-theme="dark"] .estado-doc.ok      { background: #17352a; color: #86efac; }
html[data-theme="dark"] .estado-doc.curso   { background: #1d3a52; color: #a5c9f5; }
html[data-theme="dark"] .estado-doc.aviso   { background: #3a2f12; color: #fcd34d; }
html[data-theme="dark"] .estado-doc.mal     { background: #3a2226; color: #fca5a5; }
html[data-theme="dark"] .estado-doc.apagado { background: var(--bg-hover); color: var(--text-muted); }

html[data-theme="dark"] .badge-pendiente { background: #3a2f12; color: #fcd34d; }
html[data-theme="dark"] .cupo-apurado    { background: #3a2f12; color: #fcd34d; }

html[data-theme="dark"] .panel-aviso.mal  { background: #3a2226; border-color: #7f1d1d; }
html[data-theme="dark"] .panel-aviso.info { background: #1d3a52; border-color: #1e40af; }

html[data-theme="dark"] .ensayo-pasos li { border-bottom-color: var(--border); }
html[data-theme="dark"] .ensayo-pasos li.mal { background: #3a2226; }

html[data-theme="dark"] .deca-modal-error { color: #fca5a5 !important; }

/* ---- Campos ---- */
html[data-theme="dark"] .admin-input.falta        { border-color: #dc2626; background: #3a2226; }
html[data-theme="dark"] .admin-input.sugerido     { border-color: #d97706; background: #3a2f12; }
html[data-theme="dark"] .deca-dropzone            { background: var(--bg-card-2); border-color: var(--border-2); }
html[data-theme="dark"] .deca-dropzone.arrastrando { background: var(--acento-bg); border-color: var(--acento); }
html[data-theme="dark"] .campo-clave .ojo-clave   { color: var(--text-muted); }
html[data-theme="dark"] .campo-fecha-boton        { color: var(--text-muted); }

html[data-theme="dark"] .codigos-recuperacion code,
html[data-theme="dark"] .codigo-emitido,
html[data-theme="dark"] .url-resultante,
html[data-theme="dark"] .celda-tecnica,
html[data-theme="dark"] .enlace-copiable {
    background: var(--bg-card-2);
    color: var(--text);
    border-color: var(--border-2);
}

html[data-theme="dark"] .sugerencias-lista .sugerencia:hover,
html[data-theme="dark"] .sugerencias-lista .sugerencia.resaltada {
    background: var(--bg-hover);
}

/* ---- La traza del documento ---- */
html[data-theme="dark"] .trazabilidad-lista::before { background: var(--border-2); }

html[data-theme="dark"] .trazabilidad-lista li::before {
    background: var(--bg-card);
    border-color: var(--acento);
}

html[data-theme="dark"] .trazabilidad-lista .detalle-hito { color: var(--text-muted); }

/* ---- Los dos modales grandes ---- */
html[data-theme="dark"] .modal-qr-cuerpo,
html[data-theme="dark"] .modal-pdf-cuerpo {
    background: var(--bg-card-2);
}

/* El lienzo del PDF se queda BLANCO a propósito: es una hoja de papel, y teñirla cambiaría
   lo que el usuario está mirando para decidir dónde va el QR. Lo mismo con el QR de la
   ficha, que tiene que leerse. */
html[data-theme="dark"] .qr-marco,
html[data-theme="dark"] .plantilla-marco,
html[data-theme="dark"] .vista-pdf-mini,
html[data-theme="dark"] .qr-ficha img {
    background: #fff;
}

/* ---- Gráficos ---- */
html[data-theme="dark"] .grafico-rejilla { stroke: var(--border-2); }
html[data-theme="dark"] .grafico-eje     { fill: var(--text-muted); }
html[data-theme="dark"] .ranking-barra   { background: var(--bg-hover); }
html[data-theme="dark"] .anillo-fondo    { stroke: var(--bg-hover); }

/* ---- Hilos de soporte y ayuda ---- */
html[data-theme="dark"] .hilo-soporte .de-soporte { background: var(--acento-bg); }
html[data-theme="dark"] .ayuda-indice a:hover     { background: var(--bg-hover); }
html[data-theme="dark"] .ayuda-faq summary:hover  { background: var(--bg-hover); }
html[data-theme="dark"] .ayuda-paso .numero       { background: var(--acento); color: #06222f; }

/* ---- Pies ---- */
html[data-theme="dark"] .pie-legal {
    color: var(--text-dim);
    border-top-color: var(--border);
}

html[data-theme="dark"] .pie-legal-enlaces a { color: var(--text-muted); }

/* ---- El interruptor ---- */
.btn-tema {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.1rem;
    height: 2.1rem;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font-size: 1rem;
    opacity: .75;
}

.btn-tema:hover,
.btn-tema:focus-visible {
    opacity: 1;
    background: rgba(127, 127, 127, .15);
}




/* Al imprimir los códigos de recuperación, los botones de guardarlos sobran en el papel. */
@media print {
    .guardar-codigos {
        display: none !important;
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   Recorrido de bienvenida (driver.js)
   La hoja de driver.js se carga DESPUÉS que ésta —la trae deca-recorrido.js
   al lanzarlo—, así que todo va con `.driver-popover.deca-recorrido`: gana
   por especificidad y no depende del orden de carga, que aquí es el contrario
   del habitual. */
.driver-popover.deca-recorrido {
    font-family: inherit;
    border-radius: 14px;
    padding: 1.25rem 1.25rem 1rem;
    /* Alargados: con la mascota a un lado, una burbuja estrecha se volvía una columna. */
    min-width: 22rem;
    max-width: 30rem;
    box-shadow: 0 18px 50px rgba(16, 24, 40, .25);
    border-top: 4px solid #00A0E3;
}

.driver-popover.deca-recorrido .driver-popover-title {
    font-size: 1.05rem;
    font-weight: 700;
    color: #17252f;
    margin-bottom: .35rem;
}

.driver-popover.deca-recorrido .driver-popover-description {
    font-size: .92rem;
    line-height: 1.55;
    color: #4c6070;
}

.driver-popover.deca-recorrido .driver-popover-progress-text {
    font-size: .78rem;
    color: #8a99a8;
}

.driver-popover.deca-recorrido .driver-popover-footer-btn {
    font-family: inherit;
    font-size: .85rem;
    font-weight: 600;
    padding: .4rem .9rem;
    border-radius: 7px;
    border: 1.5px solid #e2e8f0;
    color: #4c6070;
    text-shadow: none;
}

.driver-popover.deca-recorrido .driver-popover-next-btn,
.driver-popover.deca-recorrido .driver-popover-done-btn {
    background: #00A0E3;
    border-color: #00A0E3;
    color: #fff;
}

.driver-popover.deca-recorrido .driver-popover-next-btn:hover,
.driver-popover.deca-recorrido .driver-popover-done-btn:hover {
    background: #0088c2;
    border-color: #0088c2;
}

.driver-popover.deca-recorrido .driver-popover-close-btn {
    font-size: 22px;
    color: #9aa8b5;
}

html[data-theme="dark"] .driver-popover.deca-recorrido {
    background: var(--bg-card);
    color: var(--text);
}

html[data-theme="dark"] .driver-popover.deca-recorrido .driver-popover-title {
    color: var(--text);
}

html[data-theme="dark"] .driver-popover.deca-recorrido .driver-popover-description {
    color: var(--text-muted);
}

html[data-theme="dark"] .driver-popover.deca-recorrido .driver-popover-prev-btn {
    background: transparent;
    color: var(--text);
    border-color: var(--border);
}

/* La bienvenida lleva la mascota —un QR con gafas y birrete— encima del título, y va
   centrada: es la única burbuja que no señala nada. La imagen va por CSS y no en el texto
   del paso para que los textos sigan siendo sólo texto. */
.driver-popover.deca-recorrido-bienvenida {
    text-align: center;
    min-width: 22rem;
    max-width: 26rem;
}

/* En los demás pasos la mascota va más pequeña y A LA IZQUIERDA del texto: encima del
   título las burbujas volverían a ser altas, que es lo contrario de lo que se quería. Va en
   el ::before de la propia burbuja, que ya está posicionada (driver.js la pone en fixed), y
   el texto se aparta con relleno. El pie recupera el ancho entero con un margen negativo:
   los botones no tienen por qué quedarse debajo del texto, sino debajo de todo. */
.driver-popover.deca-recorrido:not(.deca-recorrido-bienvenida) {
    padding-left: calc(1.25rem + 72px + 1rem);
}

.driver-popover.deca-recorrido:not(.deca-recorrido-bienvenida)::before {
    content: "";
    position: absolute;
    left: 1rem;
    top: 1.15rem;
    width: 72px;
    height: 72px;
    background: url("img/qr-guia.svg") no-repeat center / contain;
}

.driver-popover.deca-recorrido:not(.deca-recorrido-bienvenida) .driver-popover-description {
    min-height: 3.2rem;
}

.driver-popover.deca-recorrido:not(.deca-recorrido-bienvenida) .driver-popover-footer {
    margin-left: calc(-72px - 1rem);
}

.driver-popover.deca-recorrido-bienvenida .driver-popover-title::before {
    content: "";
    display: block;
    width: 120px;
    height: 120px;
    margin: -.25rem auto .5rem;
    background: url("img/qr-guia.svg") no-repeat center / contain;
}

.driver-popover.deca-recorrido-bienvenida .driver-popover-footer {
    text-align: left;
}

/* En un móvil estrecho el ancho mínimo sacaría la burbuja de la pantalla: se suelta, y la
   mascota de los pasos encoge para dejarle sitio al texto. */
@media (max-width: 480px) {
    .driver-popover.deca-recorrido,
    .driver-popover.deca-recorrido-bienvenida {
        min-width: 0;
        max-width: calc(100vw - 2rem);
    }

    .driver-popover.deca-recorrido:not(.deca-recorrido-bienvenida) {
        padding-left: calc(1rem + 48px + .75rem);
    }

    .driver-popover.deca-recorrido:not(.deca-recorrido-bienvenida)::before {
        width: 48px;
        height: 48px;
    }

    .driver-popover.deca-recorrido:not(.deca-recorrido-bienvenida) .driver-popover-footer {
        margin-left: calc(-48px - .75rem);
    }
}
