/* ===========================================================================
   app.css -- RTSS Red Sigma v2.

   La identidad es la de la v1 y las variables son las mismas: tinta casi negra
   con fondo granate, rojo Red Sigma para lo que manda, mono para los datos.
   Lo que se fue es la mitad de la hoja de la v1, que vestia un escaner OSINT
   que en la v2 no existe.

   Regla que se mantiene de la v1 y conviene no olvidar: [hidden] lleva
   !important. El atributo oculta con el display de la hoja del navegador y
   CUALQUIER display que escribamos nosotros le gana; asi es como un panel con
   su `hidden` puesto aparecia abierto.
   =========================================================================== */

:root {
    /* ======================= LOS FONDOS, 05/10/2026 =======================
       Oscar pidio la paleta de la maqueta de la landing: fondo mas oscuro para
       el lienzo, y el acento y el texto mas claros por contraste.

       De donde salen los valores: son los de `landing.css` -`--ink`, `--ink-2`,
       `--surf`, `--surf-2`; estaba en `landing/sitio/assets/css/` y desde el
       18/10/2026 esta al lado de esta hoja-, que es la misma
       familia de vino con la saturacion bajada de ~49% a ~10%. El rojo deja de
       ser el lienzo entero y pasa a ocupar el acento, el borde y lo elegido.

       SOLO SE MUEVEN LOS FONDOS. El acento, el hueso, los campos claros y las
       severidades se quedan donde estaban: ver la cabecera de este bloque y los
       comentarios de cada uno. Bajar el fondo los separa mas, que es justo lo
       que se buscaba. */
    --ink: #171314;
    --ink-2: #201a1b;
    --ink-3: #2b2324;
    --ink-rgb: 23, 19, 20;
    --ink-3-rgb: 43, 35, 36;
    --bone: #f7e8ea;
    --bone-2: #e8c9cd;
    --rule: rgba(var(--bone-rgb), 0.14);
    --gold: #ff4a5e;
    --gold-soft: #ff7e8d;
    --muted: rgba(247, 232, 234, 0.78);

    --font-serif: 'Space Grotesk', 'Inter', system-ui, sans-serif;
    --font-sans: 'Inter', system-ui, -apple-system, sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, monospace;

    --max: 1180px;
    --gutter: clamp(18px, 3.5vw, 48px);
    --ease: cubic-bezier(.2, .7, .2, 1);

    --bien: #4caf7d;
    --aviso: #f5a623;
    --mal: #ff5c6e;

    /* LOS CAMPOS DONDE SE ESCRIBE SON CLAROS, y el resto de la pantalla es
       oscura. Es a proposito: con el campo del mismo color que el fondo no se
       ve donde hay que escribir y se confunde con un rotulo.

       FONDO CLARO OBLIGA A TEXTO OSCURO. Los cuatro colores van juntos aqui
       para que nadie cambie el fondo y deje el texto en hueso, que es como lo
       escrito se vuelve ilegible. Medidos en el navegador sobre --campo, con
       los estilos calculados y no a ojo:
         --campo-texto  15.66:1   lo que se teclea
         --campo-marca   6.68:1   el marcador de posicion
         --campo-icono   6.95:1   el icono de la ranura
       El minimo de WCAG AA para texto es 4.5:1. */
    --campo: #f6eef0;
    --campo-texto: #2a0f12;
    --campo-marca: #6e4a4f;
    --campo-icono: #9c1f2d;
    --campo-borde: rgba(41, 14, 16, .32);

    --sev-critica: #ff2d44;
    --sev-alta: #ff5c6e;
    --sev-media: #f5a623;
    --sev-baja: #4caf7d;
    /* LA QUINTA, QUE FALTABA. `Informativo` era la unica severidad sin color
       propio: su chip caia al gris de `.pg-chip` y se leia como "sin
       clasificar" en vez de como el escalon mas bajo de la escala. Azul
       apagado a proposito: tiene que verse DISTINTO de las cuatro que piden
       accion, no mas suave que la baja. */
    --sev-informativo: #6f8fb0;

    /* Alto de la banda de aplicacion. Es fija, asi que el lienzo tiene que
       reservarle sitio o el primer titulo nace debajo de ella. */
    --banda-alto: 56px;
    /* Ancho de la barra lateral. Lo usan el lienzo y la banda para apartarse:
       si cada uno llevara su numero, cambiar la barra descuadraria los otros
       dos y el fallo se veria como "la pantalla esta torcida". */
    --lat-ancho: 244px;
    /* EL FONDO DEL ITEM ACTIVO de la barra, y es un color SOLIDO a proposito.
       Antes era rojo translucido al 12-16% sobre el granate de la barra: a esa
       opacidad el item elegido y el de al lado se parecian demasiado, y aqui
       equivocarse de fila es lanzar un pentest autorizado contra el objetivo de
       otro cliente. Un solo valor para la herramienta activa y para la
       aplicacion activa: si cada uno llevara el suyo, "lo elegido" dejaria de
       verse igual en los dos grupos de la misma barra. */
    --lat-activo: #4a2027;

    /* ===================== LO QUE EL TEMA INTERCAMBIA =====================
       Windows resuelve el tema en el sistema y la app hereda sus recursos;
       iOS nombra los suyos por funcion. Las dos plataformas hacen lo mismo: el
       tema es un intercambio de VALORES, no un juego de reglas alternas. Por
       eso cada token de aqui existe tambien en `[data-tema="claro"]` y ninguna
       regla de mas abajo pregunta por el tema.

       LOS VALORES DEL TEMA CLARO NO SON NUEVOS NI SE RECALCULAN AQUI: salen de
       `landing de pruebas visuales/v3/estilo.css`, que los tiene medidos sobre
       la superficie en la que de verdad se pintan. */

    /* El tinte del HUECO -la caja rehundida dentro de una tarjeta-. Era negro
       escrito 38 veces con opacidades distintas, y cada opacidad esta medida
       donde se usa. Cambia el TINTE y no las opacidades: en claro un velo negro
       al 45% deja un bloque gris oscuro con texto oscuro encima. */
    --hueco-rgb: 0, 0, 0;
    /* El tinte del hueso, para las reglas y las barras de desplazamiento. */
    --bone-rgb: 246, 199, 206;
    /* Capas "subtle fill" de Fluent: el hover no cambia el color del control,
       le superpone un velo. En oscuro es luz y en claro es sombra, que es la
       unica forma de que el mismo hover se vea sobre los dos fondos. */
    --capa-hover: rgba(255, 255, 255, .05);
    --capa-hover-2: rgba(255, 255, 255, .07);
    /* El chasis del chrome: la barra lateral, la banda y los menus flotantes.
       Es el MARCO de la ventana y no el lienzo, asi que va aparte de --ink. */
    --chrome: rgba(10, 8, 9, .94);
    --chrome-alto: rgba(10, 8, 9, .97);
    /* El fondo de las tarjetas grandes -consola, selector y la puerta-. En
       oscuro es un degradado y en claro es blanco plano con una sombra de 1px:
       en claro la jerarquia se lee por ELEVACION, no por color. */
    --panel: linear-gradient(160deg, rgba(var(--ink-3-rgb), .5) 0%,
                                     rgba(var(--ink-rgb), .7) 100%);
    --panel-sombra: none;
    /* Lo legible ENCIMA del acento, cuando el acento es relleno y no texto. */
    --sobre-acento: var(--ink);
    /* El nombre de la fila elegida de la barra. Blanco puro sobre el granate de
       --lat-activo; en claro ese fondo sube a casi blanco y el blanco puro
       desaparece, asi que ahi es el color de texto primario. */
    --lat-activo-txt: #fff;

    /* Mica de Windows 11: el material tine la ventana con el escritorio detras.
       Se simula con un degradado propio porque aqui no hay wallpaper que
       muestrear. */
    --mica: linear-gradient(160deg, #241d1f 0%, #1b1617 46%, #171314 100%);
    --fondo-escena: radial-gradient(120% 90% at 18% 0%, #2a2022 0%, #141011 55%, #0d0a0b 100%);
    --reflejo: rgba(255, 255, 255, .10);
    --borde-ventana: rgba(0, 0, 0, .55);
    /* Material translucido de las barras de iOS. La opacidad es alta a
       proposito: el blur mezcla lo que pase por debajo, y un material demasiado
       transparente convierte el contraste del rotulo en una loteria. */
    --material: rgba(23, 19, 20, .86);
    --chasis: #0b0909;
    --chasis-borde: #3a3335;
    --relleno: rgba(247, 232, 234, .10);
    /* El gris de sistema de Apple se queda en 2.8:1 sobre el fondo de grupo.
       Este es el que usa la maqueta para la pestana apagada y los chevrons. */
    --tenue: rgba(247, 232, 234, .60);
    --r-ios: 10px;
}

/* ===================== EL TEMA CLARO =====================================
   Ni Windows 11 ni iOS pintan el claro como un gris plano: el lienzo es gris
   muy bajo y las tarjetas suben a blanco puro, de modo que la jerarquia se lee
   por elevacion y no por color.

   EL ROJO DE MARCA SE OSCURECE PORQUE EL ORIGINAL NO LLEGA. #ff4a5e sobre
   blanco se queda en 2.4:1 y hasta #d92d42 se queda en 4.27:1 sobre el fondo
   de grupo -que es donde de verdad se dibuja la mitad de este texto-. #c62233
   da 5.1:1 sobre el lienzo y 5.7:1 sobre la tarjeta, asi que el acento ENTERO
   baja a ese valor y no se parte en dos: en esta consola el acento es texto
   mucho mas a menudo que relleno, y un token que sirve para una cosa y no para
   la otra acaba usado en la equivocada.

   `:root` NO SE TOCA. --gold: #ff4a5e y --ink: #171314 siguen siendo los de la
   marca; esto es el intercambio de valores del tema, no una paleta nueva. */
[data-tema="claro"] {
    --ink: #f2f2f7;
    --ink-2: #ffffff;
    --ink-3: #ebe6e7;
    --ink-rgb: 242, 242, 247;
    --ink-3-rgb: 235, 230, 231;
    --bone: #1a1416;
    --bone-2: #463a3d;
    --bone-rgb: 26, 20, 22;
    --rule: rgba(26, 20, 22, .14);
    --muted: rgba(26, 20, 22, .72);
    --tenue: rgba(26, 20, 22, .78);

    --gold: #c62233;
    /* `--gold-soft` SE INVIERTE: en oscuro es un rojo MAS CLARO que el acento
       -se aleja del fondo subiendo- y en claro tiene que alejarse bajando. No es
       un matiz: es el color del acento cuando cae sobre un HUECO o sobre una
       superficie ya tenida de acento, y los huecos de esta hoja se APILAN -una
       caja dentro de otra dentro de la carpeta del expediente-. Medido en el
       navegador el 06/10/2026 sobre los colores que de verdad se pintan: el
       rotulo ACCESO REQUERIDO acaba sobre rgb(217,212,214), donde #c62233 da
       3.91:1 y #9b1526 da 5.68:1. */
    --gold-soft: #9b1526;
    --sobre-acento: #ffffff;

    /* El hueco deja de ser negro y pasa a ser el gris del sistema: al 18% sobre
       blanco da la caja rehundida de siempre, y al 45% sigue dejando el texto
       primario por encima de 7:1. */
    --hueco-rgb: 170, 160, 163;
    --capa-hover: rgba(26, 20, 22, .05);
    --capa-hover-2: rgba(26, 20, 22, .07);
    --chrome: #f4f0f1;
    --chrome-alto: #ffffff;
    --panel: #ffffff;
    --panel-sombra: 0 1px 2px rgba(0, 0, 0, .06);

    /* El verde y el ambar puros no pasan sobre blanco: 2.4:1 y 2:1. Estos son
       los de la maqueta, medidos sobre la tarjeta y sobre el fondo de grupo. */
    --bien: #19694a;
    /* El ambar baja un escalon mas que el de la maqueta -#8a5a00-: alli se media
       sobre una tarjeta plana y aqui "sin confirmar" cae sobre un hueco tenido
       de ambar DENTRO de otro hueco, y ahi #8a5a00 se queda en 4.26:1. Un ambar
       asi de oscuro se lee marron, y es el precio: el aviso de que un hallazgo no
       se reprodujo tiene que poder leerse, que es justo lo que impide que acabe
       en un entregable como si estuviera confirmado. */
    --aviso: #7a4f00;
    --mal: #c62233;
    --sev-critica: #a81128;
    --sev-alta: #c62233;
    --sev-media: #8a5a00;
    --sev-baja: #19694a;
    --sev-informativo: #3c6381;

    /* La ranura donde se escribe sigue siendo CLARA, pero en un tema claro un
       campo blanco sobre tarjeta blanca no se ve: lo que lo distingue aqui es
       el borde, que sube de .32 a .5, y el hundido interior que ya tenia. */
    --campo: #ffffff;
    --campo-borde: rgba(41, 14, 16, .5);

    /* La fila elegida de la barra. Solido, como en oscuro, y es el mismo valor
       para la herramienta activa y para la aplicacion activa. El acento encima
       da 4.69:1 y el texto primario 14.91:1. */
    --lat-activo: #fbe3e6;
    --lat-activo-txt: var(--bone);

    --mica: linear-gradient(160deg, #fbf9fa 0%, #f6f3f4 48%, #f1eced 100%);
    --fondo-escena: radial-gradient(120% 90% at 18% 0%, #d8d2d4 0%, #bdb5b8 55%, #a79ea1 100%);
    --reflejo: rgba(255, 255, 255, .85);
    --borde-ventana: rgba(0, 0, 0, .18);
    --material: rgba(250, 250, 252, .88);
    --chasis: #d8d2d4;
    --chasis-borde: #f1eef0;
    --relleno: rgba(118, 118, 128, .12);
}

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    scrollbar-gutter: stable;
}

body {
    font-family: var(--font-sans);
    background: var(--ink);
    color: var(--bone);
    line-height: 1.6;
    letter-spacing: 0.005em;
    min-height: 100vh;
}

/* LO QUE HAY DETRAS DEL APARATO. Era el tinte de marca del lienzo entero; desde
   que la consola se dibuja dentro de una ventana -o dentro de un telefono- el
   lienzo es `.lienzo` y esto es el escritorio sobre el que la ventana se apoya.
   Sigue siendo `fixed`: la ventana se mueve con el scroll de la pagina en la
   cara estrecha y el fondo no tiene que moverse con ella. */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -2;
    background: var(--fondo-escena);
}

img, svg { max-width: 100%; height: auto; display: block; }
[hidden] { display: none !important; }
::selection { background: var(--gold); color: var(--ink); }
:focus-visible { outline: 1px solid var(--gold); outline-offset: 2px; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: rgba(var(--ink-rgb), .6); }
::-webkit-scrollbar-thumb { background: rgba(var(--bone-rgb), .16); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255, 126, 141, .34); }

.shell { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
.mono { font-family: var(--font-mono); }
.opcional { opacity: .6; font-weight: 400; }

/* =========================================================================
   LA BARRA LATERAL
   Marca, las dos herramientas y los clientes registrados.

   LO QUE SIGUE AQUI ES EL ASPECTO; EL SITIO LO PONE CADA CARA, al final de esta
   hoja: columna izquierda de la rejilla de la ventana en la cara de Windows y
   listas agrupadas dentro del scroll en la de iPhone. Las declaraciones de
   posicion de abajo son el estado de partida -y el que vale si alguna vez se
   usa esta barra fuera del aparato-; las dos caras lo sustituyen.
   ========================================================================= */
.lateral {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 210;
    width: var(--lat-ancho);
    display: flex; flex-direction: column; gap: 14px;
    padding: 18px 12px;
    /* La barra es MAS OSCURA que el lienzo, no mas clara: es el marco, y lo que
       se mira esta a la derecha. Con el fondo nuevo, `rgba(10, 8, 9, .94)` era
       mas claro que el lienzo y la barra se adelantaba. */
    background: var(--chrome);
    border-right: 1px solid var(--rule);
    backdrop-filter: blur(14px);
    overflow-y: auto;
}

.lat-marca {
    display: flex; align-items: center; gap: 10px;
    padding: 2px 6px 14px; border-bottom: 1px solid var(--rule);
}
.lat-marca img { width: 32px; height: 32px; object-fit: contain; flex: 0 0 32px; }
.lat-sigma {
    display: grid; place-items: center; width: 32px; height: 32px; flex: 0 0 32px;
    border: 1px solid var(--rule); border-radius: 8px;
    font-family: var(--font-mono); font-size: 17px; color: var(--gold);
}
.lat-marca__t {
    font-family: var(--font-mono); font-size: 12.5px; font-weight: 700;
    letter-spacing: .14em; color: var(--bone); line-height: 1.25;
}
.lat-marca__t em {
    display: block; font-style: normal; font-size: 9px;
    letter-spacing: .2em; color: var(--muted);
}

/* ------------------------------- las dos herramientas ------------------- */
.lat-nav { display: flex; flex-direction: column; gap: 7px; }
/* BOTONES DE VERDAD, NO FILAS PLANAS. Oscar, 10/10/2026: "son botones de
   aplicacion modernos, pero no dejan de ser botones". Mismo bisel que ya
   llevan `.hz-inf__b`, `.pest__fin` y el resto: degradado de luz arriba a
   sombra abajo, y una sombra exterior que los levanta del fondo de la
   barra. En reposo el borde es transparente -la barra ya tiene bastante
   linea vertical propia- y aparece al pasar el raton o al elegir la fila. */
.hrm {
    position: relative; text-align: left; cursor: pointer;
    display: grid; grid-template-columns: auto 1fr; gap: 1px 11px;
    padding: 11px 12px; border-radius: 10px;
    border: 1px solid transparent;
    background: linear-gradient(180deg, rgba(255, 255, 255, .035) 0%,
                                        rgba(0, 0, 0, .1) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05),
                0 1px 2px rgba(0, 0, 0, .18);
    transition: background .2s var(--ease), border-color .2s var(--ease),
                box-shadow .15s var(--ease), transform .08s var(--ease);
}
.hrm:hover {
    background: linear-gradient(180deg, rgba(255, 94, 108, .12) 0%,
                                        rgba(255, 74, 94, .05) 100%);
    border-color: rgba(255, 74, 94, .22);
}
/* AL PULSARLA SE HUNDE, igual que cualquier boton solido de esta consola. La
   fila que YA esta elegida tiene su propio hundimiento permanente mas abajo
   -`.hrm.activa`-, asi que este es el de la otra, la que se esta eligiendo
   ahora mismo. */
.hrm:active {
    transform: translateY(1px);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, .3);
}
.hrm > i:first-child {
    grid-row: 1 / span 2; align-self: center;
    color: var(--muted); font-size: 15px;
}
.hrm__t {
    font-family: var(--font-mono); font-size: 11.5px; font-weight: 700;
    letter-spacing: .1em; text-transform: uppercase; color: var(--bone);
}
.hrm__d { font-size: 10.5px; color: var(--muted); line-height: 1.35; padding-right: 14px; }
/* Fondo SOLIDO y esquinas redondeadas en todo el ancho del item: es la senal de
   "aqui estas" y a la opacidad de antes casi no se veia.

   Y HUNDIDA, NO LEVANTADA -Oscar, 10/10/2026-: la fila elegida es la que esta
   "presionada" de las dos, asi que lleva la sombra puesta HACIA DENTRO en vez
   de hacia fuera. El fondo solido NO CAMBIA -sigue siendo `--lat-activo`, el
   mismo token que ya tiene medido el contraste del texto encima, mas abajo en
   este comentario- asi que esas medidas se quedan validas; lo unico que
   cambia es la sombra. */
.hrm.activa { background: var(--lat-activo); border-color: rgba(255, 74, 94, .5);
    box-shadow: inset 0 2px 6px rgba(0, 0, 0, .3),
                inset 0 1px 0 rgba(0, 0, 0, .18);
}
/* EL NOMBRE DE LA FILA ACTIVA NO SE TINE DE ACENTO, Y SE MIDIO. Sobre el fondo
   solido de --lat-activo, el acento da 4.19:1 en oscuro -rgb(74,32,39)-, por
   debajo del minimo; el color de texto primario da 13.75:1 ahi y 14.91:1 en
   claro -rgb(251,227,230)-. Aqui habia ademas un #fff fijo, que sobre el tinte
   claro se quedaba en 1.32:1: es el fallo que destapo el tema claro, y por eso
   el color va en un token y no escrito a mano.

   El acento se queda donde NO es texto: el icono, el borde y el filete. Siguen
   siendo tres senales -fondo solido, filete e icono-, que es lo que esta barra
   exige: equivocarse de fila aqui es lanzar un pentest autorizado contra el
   objetivo de otro cliente. */
.hrm.activa > i:first-child { color: var(--gold); }
.hrm.activa .hrm__t { color: var(--lat-activo-txt); }

/* El candado dice que RTSS necesita un cliente elegido. Se apaga en cuanto lo
   hay: un candado que sigue cerrado con la puerta abierta deja de significar
   nada y la proxima vez no se mira.

   ABAJO Y NO ARRIBA -Oscar, 11/10/2026-: junto al foco, en la esquina
   superior, quedaba demasiado cerca de el y del titulo. La esquina inferior
   esta libre salvo por el final de `.hrm__d`, que ya reserva los 14px de la
   derecha para esto. */
.hrm__candado {
    position: absolute; bottom: 11px; right: 11px;
    font-size: 10px; color: var(--muted); cursor: help;
    padding: 2px; border-radius: 4px;
}
.hrm__candado:hover { color: var(--gold); }
body[data-cliente="puesto"] .hrm__candado { color: var(--bien); }
body[data-cliente="puesto"] .hrm__candado::before { content: "\f3c1"; }  /* candado abierto */

/* EL FOCO. Rojo mientras no hay cliente elegido -como el candado, pero
   visible sin acercarse a leer un icono de 10px-, verde en cuanto lo hay.
   Mismo halo que ya usa `.pest__nuevo` para que lea como una senal de estado
   y no como un adorno nuevo. */
.hrm__luz {
    position: absolute; top: 13px; right: 29px;
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--mal); box-shadow: 0 0 6px var(--mal);
}
body[data-cliente="puesto"] .hrm__luz {
    background: var(--bien); box-shadow: 0 0 6px var(--bien);
}

/* LA PESTAÑA DE ABAJO dice que, con RTSS elegido, hay una lista de
   aplicaciones justo debajo y que se puede plegar. Nace oculta: solo
   `.hrm.activa` la ensena, porque sin RTSS elegido no hay nada que anunciar.
   Gira 180deg al plegar la lista -`hrm--plegada`, que pone `irA()`- para que
   la misma pestaña diga "hay mas abajo" o "esto ya esta abierto". */
.hrm__flecha {
    display: none;
    position: absolute; left: 50%; bottom: -7px; transform: translateX(-50%);
    width: 20px; height: 13px; align-items: center; justify-content: center;
    font-size: 9px; color: var(--lat-activo-txt);
    background: var(--lat-activo); border: 1px solid rgba(255, 74, 94, .5);
    border-top: 0; border-radius: 0 0 7px 7px;
    transition: transform .2s var(--ease);
}
.hrm.activa .hrm__flecha { display: flex; }
.hrm.activa.hrm--plegada .hrm__flecha { transform: translateX(-50%) rotate(180deg); }

/* --------------------------- los grupos de la barra ---------------------
   El encabezado de cada seccion: tenue, pequeno y SIN icono. No es pulsable y
   no tiene por que serlo -solo dice de que es este tramo de la barra-, asi que
   tampoco lleva foco ni :hover. Antes la barra era una pila en la que las dos
   herramientas, la lista de aplicaciones y tres botones sueltos pesaban igual.
   Es la misma etiqueta para los dos grupos, Herramientas y Aplicaciones: dos
   estilos parecidos acabarian separandose. */
.lat-seccion {
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .24em;
    text-transform: uppercase; color: var(--muted); padding: 0 6px;
    margin: 0 0 2px;
}

/* ------------------------------- los clientes --------------------------- */
/* `overflow: hidden` para que la lista no se escape nunca de su contenedor,
   pase lo que pase con los minimos de dentro. Es la red de seguridad del mismo
   fallo de arriba. */
.lat-emp { display: flex; flex-direction: column; gap: 8px;
           flex: 1 1 auto; min-height: 0; overflow: hidden; }
.lat-emp__t {
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .24em;
    text-transform: uppercase; color: var(--muted); padding: 0 6px;
}
/* LA LISTA LLENA EL HUECO QUE QUEDA, no un alto fijo.
   Con `max-height: 46vh` cortaba una fila a media linea -su contador de
   auditorias quedaba medio tapado- y ademas desperdiciaba sitio en pantallas
   altas. Creciendo hasta donde empieza el pie, el corte cae donde de verdad se
   acaba la barra. El relleno de abajo deja ver que hay mas debajo del ultimo. */
.lat-lista {
    display: flex; flex-direction: column; gap: 4px;
    /* `min-height: 0` Y NO 120px. Un minimo en pixeles le gana al tope de
       `max-height: 40vh` del modo icono, asi que en una pantalla baja -o con
       zoom, que es lo mismo- la lista crecia por encima de su caja y el pie de
       cuenta se dibujaba encima de las ultimas filas. El `flex: 1 1 auto` ya le
       da todo el hueco que sobra; el minimo no estaba repartiendo nada, solo
       impedia encogerse. */
    flex: 1 1 auto; min-height: 0; overflow-y: auto;
    padding-right: 2px; padding-bottom: 4px;
    border-radius: 10px;
    scrollbar-gutter: stable;
}
/* Cuando se pulsa RTSS sin cliente, la lista es donde hay que mirar. */
.lat-lista--pide {
    outline: 1px dashed rgba(255, 74, 94, .6); outline-offset: 4px;
    animation: latido 1s ease-in-out 2;
}

.emp {
    display: grid; grid-template-columns: auto 1fr; gap: 0 10px;
    align-items: center; text-align: left; cursor: pointer;
    padding: 8px 10px 8px 8px; border-radius: 9px;
    border: 1px solid transparent; background: transparent;
    /* El filete de la izquierda nace transparente y con su sitio reservado:
       si apareciera al activarse, la fila se movería 3px al pulsarla. */
    border-left: 3px solid transparent;
    transition: background .2s var(--ease), border-color .2s var(--ease);
}
.emp:hover { background: var(--capa-hover); }
/* El monograma de la fila es el MISMO elemento que el de la tarjeta del
   selector -.mono, con su color derivado del slug- para que una aplicacion se
   reconozca igual en los dos sitios. Su tamano de aqui lo pone .mono--chico,
   en el bloque del selector. */
.emp__n {
    font-size: 12.5px; font-weight: 500; color: var(--bone-2); line-height: 1.3;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.emp__d {
    display: flex; align-items: center; gap: 6px;
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .06em;
    color: var(--muted); line-height: 1.4;
}
/* EL ESTADO Y EL CONTEO NO SON LO MISMO Y DEJAN DE PARECERLO.
   En la misma linea convivian "ejecutando" -lo que pasa ahora- y "1 auditoria"
   -cuantas hubo-, con la misma letra y el mismo color. Son dos preguntas
   distintas y el ojo las confundia. El estado va en mayusculas y con mas peso;
   el conteo se atenua. Cuando hay algo vivo, el estado gana. */
.emp__d--estado {
    text-transform: uppercase; letter-spacing: .12em; font-weight: 700;
    color: var(--bone-2);
}
.emp__d--conteo { opacity: .62; }
.emp__luz--huerfana {
    background: transparent; border: 2px solid var(--aviso);
    box-sizing: content-box; width: 5px; height: 5px; flex-basis: 5px;
}
/* En la tarjeta del selector, lo mismo: si ahi el estado se leyera como un
   conteo, elegir la aplicacion que ya tiene algo corriendo seria un accidente. */
.selt__aud--estado {
    text-transform: uppercase; letter-spacing: .1em; font-weight: 700;
    color: var(--bone-2);
}

/* LA FILA ACTIVA, con tres senales a la vez y no solo color: fondo, filete
   lateral y peso de la letra. Un filete de un pixel en rojo sobre fondo rojo
   oscuro no lo distingue nadie a las dos de la madrugada, y equivocarse de
   fila aqui es lanzar un pentest autorizado contra el objetivo de otro. */
.emp--activa {
    background: var(--lat-activo);
    border-color: rgba(255, 74, 94, .5);
    border-left-color: var(--gold);
}
.emp--activa .emp__n { color: var(--lat-activo-txt); font-weight: 700; }
/* El monograma de la fila activa se CERCA, no se repinta. Su color es como se
   reconoce la aplicacion; cambiarselo justo a la que esta elegida le quitaria
   esa senal al unico caso en el que importa confirmarla. */
.emp--activa .mono { box-shadow: 0 0 0 2px var(--gold); }
.emp--activa .emp__d { color: var(--bone); }

/* El punto de actividad. Cada aplicacion tiene su propio hueco de ejecucion,
   asi que puede haber varias corriendo a la vez y la lista tiene que dejarlo
   ver sin cambiar de aplicacion. */
.emp__luz { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 7px; }
.emp__luz--vivo { background: var(--bien); box-shadow: 0 0 8px var(--bien);
    animation: latido 1.6s ease-in-out infinite; }
.emp__luz--espera { background: var(--aviso); box-shadow: 0 0 8px var(--aviso);
    animation: latido 1s ease-in-out infinite; }
.emp__luz--pausa { background: var(--aviso); box-shadow: 0 0 8px var(--aviso); }
/* LOS TRES PUNTOS DE LO QUE YA ACABO, Y NINGUNO LATE. El latido de `--vivo`
   significa "ahora mismo"; una corrida terminada que parpadeara seguiria
   diciendo que pasa algo, que es el ruido del que viene huyendo esta pantalla.
   Solidos y quietos: el color dice como acabo y la quietud dice que acabo.

   Y EL VERDE DE `--hecho` ES EL MISMO `--bien` QUE EL DE `--vivo` a proposito.
   No son dos verdes: es el mismo "esto esta bien" en dos momentos, y un segundo
   verde obligaria a aprenderse cual es cual. */
.emp__luz--hecho { background: var(--bien); }
.emp__luz--cortada { background: var(--mal); }
.emp__luz--parada { background: var(--aviso); }

.lat-vacio { font-size: 11px; color: var(--muted); line-height: 1.5; padding: 6px; }
.lat-aviso {
    font-size: 11px; line-height: 1.55; color: var(--bone-2);
    padding: 9px 10px; border-radius: 8px;
    border: 1px solid rgba(255, 74, 94, .4); background: rgba(255, 74, 94, .09);
}
.lat-alta {
    display: flex; align-items: center; gap: 9px;
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em;
    text-transform: uppercase; color: var(--muted);
    background: transparent; border: 1px dashed var(--rule); border-radius: 9px;
    padding: 9px 11px; cursor: pointer;
    transition: color .25s var(--ease), border-color .25s var(--ease);
}
.lat-alta:hover { color: var(--bone); border-color: var(--gold); }
.lat-pie { margin-top: auto; }

/* =========================================================================
   LA BANDA
   Se queda aunque la barra nombre al cliente: entre 1000 y 1180 px la barra
   colapsa a iconos y ahi el nombre no cabe. El cliente activo tiene que estar
   visible SIEMPRE, en cualquier ancho.

   Igual que la barra, el SITIO se lo da cada cara al final de esta hoja: fila
   de arriba de la region de contenido en la ventana de Windows, Large Title
   dentro del scroll en el telefono.
   ========================================================================= */
.banda {
    position: fixed; top: 0; left: var(--lat-ancho); right: 0; z-index: 200;
    min-height: var(--banda-alto);
    display: flex; align-items: center; gap: clamp(10px, 2vw, 26px);
    padding: 0 var(--gutter);
    background: var(--chrome);
    border-bottom: 1px solid var(--rule);
    backdrop-filter: blur(14px);
}
.banda[data-estado="vacia"] {
    border-bottom-color: rgba(255, 74, 94, .55);
    box-shadow: inset 0 -2px 0 rgba(255, 74, 94, .35);
}
.banda[data-estado="puesta"] {
    border-bottom-color: rgba(76, 175, 125, .35);
    box-shadow: inset 0 -2px 0 rgba(76, 175, 125, .28);
}

.banda__cliente {
    flex: 1 1 auto; min-width: 0;
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
/* En Scan Regular el cliente elegido sigue a la vista, pero atenuado y con la
   nota de que esa herramienta no lo toca. Dejarlo igual que en RTSS haria
   creer que el escaneo se guarda en su expediente. */
.banda[data-herramienta="scan"] .banda__cliente { opacity: .55; }
.banda__nota {
    font-style: normal; font-family: var(--font-mono); font-size: 9px;
    letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
}
.banda__etiqueta {
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .26em;
    text-transform: uppercase; color: var(--muted); flex: 0 0 auto;
}
.banda__cliente strong {
    font-family: var(--font-serif); font-size: clamp(15px, 2vw, 22px);
    font-weight: 500; line-height: 1.1; color: var(--bone);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.banda[data-estado="vacia"] .banda__cliente strong { color: var(--bone); }
.banda__cliente code {
    font-family: var(--font-mono); font-size: 10.5px; color: var(--muted);
}

/* La derecha de la banda: los escaneos que quedan y el semaforo del servicio.
   En este orden -primero el numero, despues el estado- porque el estado es lo
   que cambia solo y lo que se mira de reojo, asi que va en el extremo, donde el
   ojo vuelve. */
.banda__sem { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; }

/* LOS ESCANEOS, Y SON DE LA CUENTA. El rotulo nombra al usuario a proposito: un
   numero pegado al nombre de una aplicacion se lee como "los escaneos de esta
   aplicacion", y el cupo se contrata una vez por cuenta y se gasta entre todos
   sus proyectos. */
.banda__cuota {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 5px 11px; border-radius: 999px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .3);
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.banda__cuota i { font-size: 11px; color: var(--gold-soft); }
.banda__cuota b {
    font-family: var(--font-sans); font-size: 11.5px; font-weight: 700;
    letter-spacing: 0; text-transform: none; color: var(--bone);
}
/* Sin cuota, la banda cuenta la MISMA historia que el formulario deshabilitado:
   si aqui saliera un numero tranquilo con los campos apagados, el operador
   buscaria el fallo en el sitio equivocado. */
.banda__cuota--off {
    border-color: rgba(255, 92, 110, .55); background: rgba(255, 92, 110, .12);
}
.banda__cuota--off i, .banda__cuota--off b { color: var(--mal); }

.sem {
    display: inline-flex; align-items: center; gap: 7px;
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .18em;
    text-transform: uppercase; color: var(--muted);
}
.sem__luz {
    width: 9px; height: 9px; border-radius: 50%; background: var(--muted);
    flex: 0 0 9px;
}
.sem.vivo .sem__luz { background: var(--bien); box-shadow: 0 0 12px var(--bien);
    animation: latido 1.6s ease-in-out infinite; }
.sem.vivo em { color: var(--bien); }
.sem.espera .sem__luz { background: var(--aviso); box-shadow: 0 0 12px var(--aviso);
    animation: latido 1s ease-in-out infinite; }
.sem.espera em { color: var(--aviso); }
.sem.parado .sem__luz { background: var(--mal); box-shadow: 0 0 12px var(--mal); }
.sem.parado em { color: var(--mal); }
/* HUERFANA: la solicitud dice ejecutando y no hay proceso vivo detras.
   Tiene su propio color -ambar con el punto hueco- y NO se parece al verde de
   "trabajando" ni al rojo de "parada": no es que vaya mal, es que no hay nadie
   trabajando aunque la pantalla diga que si. El punto no late, que es la mitad
   del mensaje: eso que parecia moverse no se mueve. */
.sem.huerfana .sem__luz {
    background: transparent; border: 2px solid var(--aviso);
    box-sizing: border-box; box-shadow: 0 0 10px rgba(245, 166, 35, .55);
}
.sem.huerfana em { color: var(--aviso); }
/* El tiempo que queda de una espera, al lado del estado. Tabular para que no
   baile al cambiar de cifra. */
.sem__reloj {
    font-family: var(--font-mono); font-size: 11px; font-weight: 700;
    letter-spacing: .04em; color: var(--bone);
    font-variant-numeric: tabular-nums;
}
@keyframes latido { 0%,100% { opacity: 1; } 50% { opacity: .25; } }

.lienzo {
    margin-left: var(--lat-ancho);
    padding-top: calc(var(--banda-alto) + 18px);
    padding-bottom: 60px;
}

/* ---------------------------------------------------------------- estrecho
   La barra fija se come la pantalla en un portatil pequeno. Colapsa a iconos:
   sigue estando entera -marca, herramientas y clientes- pero sin los textos
   largos. El nombre del cliente activo no se pierde, porque la banda lo lleva.
   Nada de menu de hamburguesa: esta familia de paginas se hizo sin el. */
@media (max-width: 1180px) and (min-width: 1000px) {
    :root { --lat-ancho: 68px; }
    .lateral { padding: 16px 8px; align-items: center; }
    .lat-marca { padding: 2px 0 12px; justify-content: center; }
    /* `.lateral .X` Y NO `.X` A SECAS, y es un arreglo del 05/10/2026 con su
       medicion: `.lat-yo__txt` se vuelve a declarar MAS ABAJO en esta hoja
       -linea ~2000, `display: flex`- con la misma especificidad 0-1-0, y un
       media query no suma ninguna, asi que ganaba el de abajo por orden. El
       nombre de la cuenta NUNCA se escondio a este ancho, y es el que hacia que
       el pie midiera 204 px dentro de una columna de 68 y se saliera por los dos
       lados. Se veia al hacer zoom, que es lo mismo que estrechar.

       Con `.lateral` delante son 0-2-0 y ganan estas, que son las que saben a
       que ancho estamos. */
    .lateral .lat-marca__t, .lateral .hrm__t, .lateral .hrm__d, .lateral .emp__n,
    .lateral .lat-seccion, .lateral .lat-emp__t, .lateral .lat-aviso,
    .lateral .lat-yo__txt, .lateral .lat-yo__flecha,
    .lateral .lat-menu__t, .lateral .lat-menu__b span,
    .lateral .lat-alta span { display: none; }

    /* La red de seguridad, para lo que no se haya pensado. `clip` y no
       `hidden`: en una columna de 68 px una barra de desplazamiento horizontal
       no sirve para nada y ademas se come 10 de esos 68. */
    .lateral { overflow-x: clip; }
    .lat-pie, .lat-yo, .lat-yo__b, .lat-alta { min-width: 0; max-width: 100%; }
    /* Del pie de cuenta queda el avatar con las iniciales, y su menu se queda en
       iconos: a 68px el nombre no cabe, y el avatar sigue diciendo que hay una
       cuenta detras -el nombre entero se lee en la banda y en el pie de la
       pagina-. Los dos iconos del menu son distintos y llevan su `title`, que es
       lo mismo que se hace con los demas botones de la barra a este ancho. */
    .lat-yo__b { justify-content: center; padding: 8px 0; }
    .lat-menu__b { justify-content: center; padding: 9px 0; }
    .lat-menu__b > i { margin-top: 0; flex: 0 0 auto; }
    /* El punto de actividad NO se va con el texto: sigue siendo la unica
       senal de que otro cliente tiene algo corriendo, y a este ancho es
       cuando mas falta hace, porque el nombre ya no se lee. Pasa a insignia
       sobre el monograma; el texto se queda sin cuerpo pero el punto no. */
    .emp { position: relative; }
    .emp__d { position: absolute; top: 1px; right: 7px; font-size: 0; gap: 0; }
    .emp__d .emp__luz { width: 9px; height: 9px; flex-basis: 9px;
                        border: 2px solid var(--chrome); box-sizing: content-box; }
    .hrm { grid-template-columns: 1fr; justify-items: center; padding: 11px 0; width: 100%; }
    .hrm > i:first-child { grid-row: auto; font-size: 17px; }
    .hrm__candado { top: auto; bottom: 5px; right: 5px; }
    /* Sin sitio para una segunda senal junto al icono solo: el candado ya
       cambia de color el mismo, y eso basta a este ancho. */
    .hrm__luz { display: none; }
    .emp { grid-template-columns: 1fr; justify-items: center; padding: 5px 0;
           border-left-width: 0; border-radius: 10px; }
    .emp .mono { grid-row: auto; width: 34px; height: 34px; flex-basis: 34px; }
    /* Sin sitio para el filete lateral, la fila activa se marca con el borde
       entero y el anillo del monograma: siguen siendo dos senales ademas del
       color. */
    .emp--activa { border-color: var(--gold); }
    .lat-alta { justify-content: center; padding: 9px 0; width: 100%; }
    .lat-lista { max-height: 40vh; }
}

/* ------------------------------------------------------------------ movil
   AQUI ESTABA LA BARRA EN HORIZONTAL, y se fue el 06/10/2026 con el rediseno.
   El umbral en el que esta pantalla dejaba de ser un escritorio era este;
   ahora es 999 px, donde empieza la cara de iPhone, y ahi la barra pasa a ser
   una lista agrupada dentro del scroll en vez de una fila encima del contenido.

   LO QUE SE QUEDA EN 760 px ES LO QUE VIVE FUERA DEL APARATO: las sub-ventanas.
   Un <dialog> no esta dentro de `.pantalla` -se dibuja en la capa superior del
   navegador- asi que no se encoge con el telefono y sigue viendo el viewport de
   verdad. Por debajo de 760 px un panel de 620 px con 16 px de margen a cada
   lado desperdicia el unico sitio que hay: pasa a ocupar la pantalla entera, que
   es lo que hace una hoja a pantalla completa en iOS. */
@media (max-width: 760px) {
    /* `[open]` NO ES ADORNO: sube la especificidad a dos clases para ganarle a
       `.dlg--ancha`, que se declara 1.300 lineas mas abajo con su ancho de 880
       px y, a igualdad de peso, ganaba por orden. Y es verdad ademas: estas
       reglas solo significan algo con la ventana abierta. */
    .dlg[open], .dlg--ancha[open] {
        width: 100vw; max-width: 100vw;
        max-height: 100vh; height: 100vh;
        border: 0; border-radius: 0;
        padding: 18px 16px calc(18px + env(safe-area-inset-bottom));
        overflow-y: auto;
    }
    /* La cabecera pegajosa de la ventana ancha ya existia; a pantalla completa
       hace mas falta todavia, porque el recorrido es mas largo. */
    .dlg--ancha[open] .dlg__cab { margin: -18px -16px 0; padding: 18px 16px 12px; }
    .dlg__x { flex: 0 0 auto; }
}

/* ========================= Tipografia de seccion ========================= */
/* LA PORTADA DE SCAN REGULAR, DE FONDO. Pedida el 18/10/2026, mismo criterio
   que la de la puerta de RTSS: la foto va detras con un degradado oscuro
   encima para que el texto -que aqui no tiene una caja opaca propia, como
   si la tiene `.console`- se siga leyendo. `background-attachment: fixed`
   y no `cover` a secas: esta pantalla tiene formulario, casillas, resultados
   y el aviso de uso autorizado, asi que es mas alta que una pantalla y una
   portada que se alargara con el contenido se veria estirada. Fija, la foto
   se queda del tamano del visor mientras el contenido pasa por encima. */
/* LOS NUMEROS DE ESTE BLOQUE SON LOS LITERALES DE `estilo.css` DE EMAIL
   BREACH MONITOR, UNO A UNO. Pedido el 20/10/2026: "que no se vean cambios
   al pasar de una herramienta a otra". Hasta aqui se habia igualado la
   fuente y el tamano del texto, pero la cabecera seguia siendo translucida
   (`rgba(10,8,9,.82)` encima de la foto) en vez de solida como `.cab`
   (`var(--ink-2)` a secas), el degradado de la foto usaba otro tinte
   (10,8,9 en vez de 23,19,20), y la tarjeta era mas angosta (640px de
   `--max` propio en vez de los 720px de `.lienzo`). Cada valor de aqui
   para abajo tiene su par exacto en el otro archivo -ver el comentario de
   cada regla-. */
#vista-scan {
    background: linear-gradient(180deg, rgba(23, 19, 20, .80), rgba(23, 19, 20, .93)),
                url('../img/scan-portada.jpg') center / cover no-repeat fixed;
    min-height: 100%;
    display: flex; flex-direction: column;
}
/* `.shell` ESTIRA PARA LLENAR EL HUECO ENTRE LA CABECERA Y EL PIE, asi el
   pie se queda abajo del todo incluso cuando el formulario -sin resultados
   todavia- no llena la pantalla. Con resultados mas largos que el visor,
   `flex:1` no estorba: el contenido simplemente crece y el pie baja con el,
   que es lo que ya pasa en cualquier pagina con scroll. */
#vista-scan > .shell--scan { flex: 1; }

/* LA CABECERA Y EL PIE DE MARCA. Mismo recurso que usa Email Breach Monitor
   en su propia pagina (`.cab`/`.pie`), reescrito aqui con nombre propio
   para no chocar con ninguna clase existente de esta hoja -pero con el
   MISMO fondo solido (`var(--ink-2)`, pinned a oscuro mas arriba) y el
   MISMO borde (`#332a2c`, el `--borde` de estilo.css -RTSS no tiene ese
   token con ese nombre, asi que se escribe literal-), no uno
   aproximado. */
.scan-cab, .scan-pie {
    display: flex; justify-content: space-between; align-items: center;
    padding: 14px 20px; flex: none;
    background: var(--ink-2);
}
.scan-cab { border-bottom: 1px solid #332a2c; }
.scan-pie { padding: 16px 20px; border-top: 1px solid #332a2c;
           font-size: 11.5px; color: rgba(247, 232, 234, .6); }
.scan-pie a { color: var(--gold-soft, #ff7e8d); text-decoration: none; }
.scan-pie a:hover { text-decoration: underline; }
.scan-cab__marca { font-weight: 600; letter-spacing: .3px; color: #f7e8ea; }
.scan-cab__marca em { color: #ff7e8d; font-style: normal; }
.scan-cab__pastilla {
    font-size: 11px; color: #ff7e8d; border: 1px solid #ff7e8d;
    border-radius: 999px; padding: 2px 10px; flex: none;
}

/* EL CONSENTIMIENTO, MISMA ESTRUCTURA QUE `.chk` DE EMAIL BREACH CHECKER
   (`estilo.css`): casilla + parrafo, no una opcion mas de las tres de
   arriba -por eso no reutiliza `.opt`, que lleva su propio fondo e icono-. */
.scan-chk {
    display: flex; gap: 10px; align-items: flex-start;
    font-size: 12.5px; color: var(--muted); margin-top: 16px;
}
.scan-chk input { margin-top: 3px; flex: none; }
.scan-chk a { color: var(--gold-soft); }

/* A PANTALLA ENTERA, SIN TIRAS BLANCAS. Pedido el 18/10/2026: la banda y el
   pie quedaban fuera de `#vista-scan` -son hermanos suyos, no hijos- asi que
   el degradado de arriba no los alcanzaba y se veian como dos franjas claras
   partiendo la foto. Mismo criterio que "LA PUERTA DE RTSS" mas abajo en esta
   hoja: se apagan los dos mientras se ve esta vista -tampoco aqui hay
   APLICACION ELEGIDA que anunciar, Scan Regular no la necesita- y el padding
   que `.lienzo` les reservaba se quita con ellos, para que la foto llegue a
   los dos bordes de verdad. */
body:has(#vista-scan:not([hidden])) #banda,
body:has(#vista-scan:not([hidden])) .foot { display: none; }
.lienzo:has(> #vista-scan:not([hidden])) {
    padding-top: 0; padding-bottom: 0;
}

/* SIEMPRE OSCURO, EN LOS DOS TEMAS -toda la vista, no solo el titulo.
   Encontrado el 20/10/2026 probando esto mismo en tema claro: la foto y su
   degradado de arriba no cambian con `[data-tema="claro"]` -son fijos,
   siempre oscuros-, pero la tarjeta (`.console--scan`, via `--panel`) SI
   cambiaba a blanco solido, y el titulo -ya fijado a hueso claro por la
   regla vieja que esto reemplaza- se volvia casi invisible: texto claro
   sobre tarjeta blanca.

   LA REGLA ANTERIOR SOLO ARREGLABA EL TITULO. `--bone`, `--gold-soft`,
   `--panel` y el resto de los tokens que intercambia `[data-tema="claro"]`
   siguen pintando cualquier otro texto o fondo de esta vista -la tarjeta,
   los campos, las casillas, el aviso-, y cada uno se habria roto igual con
   el tema claro puesto. En vez de perseguir elemento por elemento, se
   re-fijan aqui TODOS los tokens que el tema claro toca, a sus valores de
   `:root` (oscuro) -la misma lista completa de `[data-tema="claro"]", mas
   abajo en esta hoja-. Email Breach Monitor resuelve esto mismo siendo una
   pagina aparte sin selector de tema; aqui, que comparte consola con RTSS
   y Scan Regular NO es independiente del tema en ningun otro lado, el
   mismo resultado sale de fijar los tokens solo donde hace falta. */
#vista-scan {
    --ink: #171314; --ink-2: #201a1b; --ink-3: #2b2324;
    --ink-rgb: 23, 19, 20; --ink-3-rgb: 43, 35, 36;
    --bone: #f7e8ea; --bone-2: #e8c9cd; --bone-rgb: 246, 199, 206;
    --rule: rgba(var(--bone-rgb), 0.14);
    --gold: #ff4a5e; --gold-soft: #ff7e8d;
    --muted: rgba(247, 232, 234, 0.78); --tenue: rgba(247, 232, 234, .60);
    --sobre-acento: var(--ink);
    --hueco-rgb: 0, 0, 0;
    --capa-hover: rgba(255, 255, 255, .05); --capa-hover-2: rgba(255, 255, 255, .07);
    --chrome: rgba(10, 8, 9, .94); --chrome-alto: rgba(10, 8, 9, .97);
    --panel: linear-gradient(160deg, rgba(var(--ink-3-rgb), .5) 0%,
                                     rgba(var(--ink-rgb), .7) 100%);
    --panel-sombra: none;
    --bien: #4caf7d; --aviso: #f5a623; --mal: #ff5c6e;
    --sev-critica: #ff2d44; --sev-alta: #ff5c6e; --sev-media: #f5a623;
    --sev-baja: #4caf7d; --sev-informativo: #6f8fb0;
    --campo: #f6eef0; --campo-borde: rgba(41, 14, 16, .32);
    --lat-activo-txt: #fff;
}
/* SIN EL HUECO DE ARRIBA. Pedido el 20/10/2026: el `margin-top` de
   `.section-head` -hasta 64px- existe para separar el titulo de `#banda`,
   pero en esta vista `#banda` esta apagada (ver mas abajo, "A PANTALLA
   ENTERA"), asi que ese margen se quedaba como un hueco muerto encima de
   "Scan Regular" y nada mas. Mismo criterio que Email Breach Checker, que
   no tiene ese margen porque es una pagina aparte.

   ACTUALIZADO EL MISMO DIA: el titulo ahora vive DENTRO de `.console`
   -ver "TITULO Y FORMULARIO, EN UNA SOLA TARJETA" en app.html-, asi que el
   espacio de arriba ya lo da el padding de la tarjeta. Un margen aparte
   aqui encima solo duplicaria ese aire. */
#vista-scan .section-head { margin-top: 0; }

/* UNA SOLA TARJETA, ANGOSTA Y CENTRADA -A LOS MISMOS 720PX QUE
   `.lienzo` EN ESTILO.CSS, NI UN PIXEL MAS NI MENOS. Pedido el 20/10/2026,
   con Email Breach Checker como referencia explicita ("que no se vean
   cambios al pasar de una herramienta a otra"): `.shell` por omision mide
   hasta 1180px (`--max`) y su gutter lateral es un `clamp()` que crece con
   el viewport; alla el ancho y el gutter son numeros fijos (720px,
   16px). Angostar SOLO esta vista, sin tocar `--max` ni `--gutter` para el
   resto de la consola. */
#vista-scan .shell { max-width: 720px; padding-left: 16px; padding-right: 16px; }
/* El titulo y el formulario, juntos, en la misma tarjeta -mismo aspecto
   que la tarjeta unica de Email Breach Checker-. `.section-head` conserva
   su borde inferior como separador interno entre el titulo y los campos.

   CADA NUMERO, EL LITERAL DE `.tarjeta` EN ESTILO.CSS: margen superior
   28px (el `padding-top` de `.lienzo`, que es donde Email Breach Monitor
   separa su cabecera de la tarjeta), margen inferior 18px (el
   `margin-bottom` de `.tarjeta`), relleno 24px fijo (no el `clamp()` de
   `.console`), fondo solido `var(--ink-2)` -`--panel` en oscuro es un
   degradado con alfa, que dejaba la foto de fondo asomando A TRAVES de la
   tarjeta- y borde `#332a2c` -el `--borde` de estilo.css, no el `--rule`
   translucido de esta hoja-. */
#vista-scan .console--scan {
    margin-top: 28px; margin-bottom: 18px;
    padding: 24px; background: var(--ink-2); border-color: #332a2c;
}

/* MISMA FUENTE, MISMOS TAMANOS QUE EMAIL BREACH CHECKER. Pedido el
   20/10/2026: el titulo y el subtitulo de esta tarjeta usaban la
   tipografia editorial del resto de la consola (`--font-serif`, Space
   Grotesk, con su propio peso/interlineado/tracking), y la cabecera de
   marca no llevaba tamano propio -heredaba el de la consola-. Se igualan
   aqui a los valores literales de `estilo.css` en
   "Email Breach Monitor/web/assets/css/": la fuente del sistema
   (Segoe UI/Roboto/system-ui), el h1 a 24px/700 sin tracking negativo, el
   `.sub` a 14px, y la cabecera de marca sin tamano propio -mismo criterio
   que alla-, para que las dos pantallas lean como la misma familia
   tipografica letra por letra, no solo de paleta. */
#vista-scan .scan-cab__marca,
#vista-scan .section-head h2,
#vista-scan .section-head .sub {
    font-family: "Segoe UI", Roboto, system-ui, sans-serif;
}
#vista-scan .section-head h2 {
    font-weight: 700; font-size: 24px; line-height: normal; letter-spacing: normal;
}
/* "SCAN REGULAR" ENTERO EN NEGRITAS. Pedido el 20/10/2026. La regla
   compartida `.section-head h2 em` pone el segundo nombre en peso 400
   -normal, mas liviano que el titulo- para el resto de la consola; aqui se
   pisa SOLO para esta vista, asi "Regular" pesa lo mismo que "Scan" en vez
   de leerse mas delgado al lado. */
#vista-scan .section-head h2 em { font-weight: 700; }
#vista-scan .section-head .sub { font-size: 14px; line-height: normal; }

/* EL MENSAJE "Analizando..." NO SE VEIA EN TEMA CLARO -pedido el 20/10/2026
   con una captura-. `.ag-estado__fila` no fija su propio color en
   estilo.css -a diferencia de `.ag-falta`, que si lo hace-, asi que hereda
   el `color` que ya calculo `body` (oscuro en tema claro, sobre el fondo
   CLARO general de la consola) en vez de resolver `--ink`/`--bone` otra vez
   aqui abajo, donde `#vista-scan` ya los re-fijo a sus valores oscuros de
   siempre. El resultado era texto oscuro sobre el fondo oscuro fijo de esta
   vista. `#cajaEstado` (la misma clase en el flujo normal de RTSS) no
   necesita este arreglo porque ahi el fondo SI cambia con el tema. */
#vista-scan .ag-estado__fila { color: var(--bone); }

/* SIN TRANSPARENCIAS EN EL PANEL DE RESULTADO. Pedido el 20/10/2026 con una
   captura: la foto fija de esta vista (`scan-portada.jpg`) y el logo
   gigante que lleva encima asomaban A TRAVES del veredicto, de los chips y
   de cada tarjeta de hallazgo, porque esos fondos se mezclan con
   `transparent` (o no llevan fondo) y eso funciona bien sobre el degradado
   solido del resto de la consola, pero no sobre una foto grande detras.
   Mismo criterio que el bloque de arriba: se fija SOLO dentro de esta
   vista, mezclando cada color contra `--ink-2` (la misma base solida que
   ya usa `.console--scan`) en vez de contra transparente. */
#vista-scan .vd {
    background: color-mix(in srgb, var(--vd, var(--gold)) 16%, var(--ink-2));
}
#vista-scan .pg-chip,
#vista-scan .hz__f {
    background: var(--ink-2);
}
#vista-scan .ag-falta {
    background: color-mix(in srgb, var(--gold) 12%, var(--ink-2));
}
#vista-scan .caja__nota {
    background: var(--ink-2); border-radius: 9px; padding: 12px 14px;
    border: 1px solid var(--rule);
}

.section-head {
    margin: clamp(32px, 5vw, 64px) 0 clamp(20px, 3vw, 32px);
    padding-bottom: 20px; border-bottom: 1px solid var(--rule);
}
.section-head h2 {
    font-family: var(--font-serif); font-weight: 500;
    font-size: clamp(24px, 3.2vw, 44px); line-height: 1.0;
    letter-spacing: -0.02em; color: var(--bone);
}
.section-head h2 em { font-style: normal; color: var(--gold-soft); font-weight: 400; }
.section-head .sub {
    font-family: var(--font-serif); font-size: clamp(13px, 1.1vw, 17px);
    line-height: 1.5; color: var(--muted); margin-top: 11px; max-width: 760px;
}
.section-head code, .sub code {
    font-family: var(--font-mono); font-size: .86em; color: var(--bone-2);
}

/* ========================= LA MIGA DE PAN ===============================
   Encima del titulo: donde estas, en tres pasos. Nombra la APLICACION por
   tercera vez -banda, barra y aqui- y es a proposito: equivocarse de aplicacion
   es lanzar un pentest autorizado contra el objetivo de otro. */
.vcab__miga {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-top: clamp(26px, 4vw, 48px);
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .18em;
    text-transform: uppercase; color: var(--muted);
}
.vcab__miga i { font-size: 7px; opacity: .6; }
.vcab__miga b { color: var(--bone); font-weight: 700; }
/* EL NOMBRE DE LA APLICACION ES UN BOTON: es la puerta a lo que es SUYO -su
   alcance, sus expedientes, sus ajustes-. Que el camino salga de la propia
   aplicacion es lo que evita la pregunta "de que proyecto es esta lista
   blanca". Lo del usuario se llega por el pie de la barra, donde esta el
   usuario. */
.vcab__app {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 3px 9px; cursor: pointer;
    border: 1px solid var(--rule); border-radius: 999px;
    background: rgba(var(--hueco-rgb), .25); color: var(--bone-2);
    font-family: inherit; font-size: inherit; letter-spacing: inherit;
    text-transform: inherit;
    max-width: min(46ch, 50vw); overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap;
    transition: border-color .2s var(--ease), color .2s var(--ease);
}
.vcab__app i { font-size: 10px; opacity: .75; flex: 0 0 auto; }
.vcab__app:hover { border-color: var(--gold); color: var(--bone); }
.vcab__app:hover i { opacity: 1; color: var(--gold); }
/* Sin aplicacion elegida no hay nada suyo que ensenar. No se esconde -dejaria un
   hueco raro en mitad de la miga- sino que se atenua, y al pulsarla lleva a la
   lista en vez de no hacer nada. */
.vcab__app--off { opacity: .5; }
/* Con la miga encima, el titulo ya no necesita su propio aire de arriba: si lo
   mantuviera, entre la miga y el titulo quedaria un hueco de dos lineas. */
.vcab__miga + .section-head { margin-top: 12px; }

/* ============================= LAS PESTANAS =============================
   Tres en la vista de RTSS y cuatro en la sub-ventana del contexto, con la
   misma hoja: son el mismo control y dos estilos parecidos se separarian.

   La vista era una sola columna -formulario, progreso, hallazgos, aislamiento y
   un bloque enorme de contexto, uno debajo de otro- y lo que acababa de pasar
   quedaba a tres pantallazos de scroll. Con pestanas se ve UNA cosa a la vez.

   La activa se marca con TRES senales y no solo con color: fondo solido, filete
   inferior en rojo y letra en negrita. Es la misma regla que la fila de la barra
   lateral, y por el mismo motivo: un cambio de color de un pixel no lo distingue
   nadie a las dos de la madrugada. */
/* SE DESPLAZA, NO SE PARTE. Tenia `flex-wrap: wrap` y con cinco pestanas mas los
   dos botones de accion, al estrechar -o al hacer zoom, que es lo mismo- se
   partia en dos lineas y la segunda colgaba fuera de la caja, por debajo del
   filete inferior. Una barra de pestanas en dos filas deja ademas de leerse como
   una barra: pasa a leerse como una lista, y entonces ya no se entiende que son
   vistas de la misma cosa.

   LA BARRA DE DESPLAZAMIENTO SE ESCONDE pero el desplazamiento se queda: con
   rueda, con gesto tactil y con el teclado al tabular hacia una pestana que no
   se ve, que es como de verdad se llega a ella. Una barra visible de 10 px
   debajo de las pestanas, en una fila de 40, se lee como un error de
   maquetacion. */
.pest {
    display: flex; gap: 4px; flex-wrap: nowrap;
    /* `auto hidden` y no `overflow-x: auto` a secas: con el eje vertical sin
       declarar el navegador lo computa a `auto` igual, y entonces aparece una
       barra de desplazamiento vertical de un pixel en una fila de 40. Dicho
       explicito, se queda recortado y sin barra. */
    overflow: auto hidden;
    scrollbar-width: none;
    border-bottom: 1px solid var(--rule);
    margin-bottom: clamp(18px, 2.5vw, 26px);
}
.pest::-webkit-scrollbar { display: none; }
/* Sin esto una pestana se encoge hasta que su rotulo se parte en dos renglones,
   que es la otra forma de que esta fila deje de parecer una barra. */
.pest__b { flex: 0 0 auto; white-space: nowrap; }
.pest__b {
    position: relative;
    display: flex; align-items: center; gap: 8px;
    padding: 11px 15px; cursor: pointer;
    background: transparent; border: 1px solid transparent;
    border-radius: 10px 10px 0 0; border-bottom: 0;
    /* El filete de abajo nace transparente y con su sitio reservado: si
       apareciera al activarse, la pestana se moveria 2px al pulsarla y la fila
       entera daria un salto. */
    box-shadow: inset 0 -2px 0 transparent;
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
    transition: background .2s var(--ease), color .2s var(--ease),
                box-shadow .2s var(--ease), transform .08s var(--ease);
}
.pest__b i { font-size: 12px; }
.pest__b:hover:not(:disabled) { color: var(--bone); background: var(--capa-hover); }
/* AL PULSARLA, SE HUNDE. Oscar, 10/10/2026: la fila entera se leia plana. Una
   pestana no se convierte en un boton solido -el filete de abajo ya dice cual
   esta elegida, y una pestana no es una accion de una vez- pero SI tiene que
   sentirse pulsable: el mismo hundimiento de 1px que ya llevan los botones de
   verdad de esta consola, nada mas. */
.pest__b:active:not(:disabled) { transform: translateY(1px); }
/* EL FOCO SE VE, y sobre la pestana entera: de un tablist se entra con un solo
   tabulador y dentro se anda con las flechas, asi que si el foco no se viera no
   habria forma de saber en que pestana estan las flechas. */
/* `-2px` Y NO `2px`: desde que `.pest` desplaza en horizontal es un contenedor
   de recorte, y un anillo dibujado por fuera del boton se pierde en la primera
   pestana -por la izquierda y por arriba- y en la ultima al desplazar hasta el
   final. Hacia dentro siempre se ve, y es lo que ya hacen `.hzx__id` y
   `.hzx__re-b` en esta misma hoja. Medido por pixel el 05/10/2026. */
.pest__b:focus-visible { outline: 1px solid var(--gold); outline-offset: -2px; }
.pest__b--on, .pest__b[aria-selected="true"] {
    background: var(--lat-activo);
    border-color: rgba(255, 74, 94, .4);
    box-shadow: inset 0 -2px 0 var(--gold);
    color: var(--bone); font-weight: 700;
}
.pest__b--on i, .pest__b[aria-selected="true"] i { color: var(--gold); }
/* Una pestana apagada no ensena un panel vacio: sin aplicacion elegida no hay
   corrida ni hallazgos, y un panel en blanco se lee como una averia. */
.pest__b:disabled { opacity: .4; cursor: not-allowed; }

/* EL PUNTO DE NOVEDAD. Aparece en la pestana que NO esta activa cuando ahi pasa
   algo -un hallazgo nuevo, la bitacora que crece- y se apaga al entrar. Avisa y
   espera: no roba el foco, porque robarlo mientras alguien escribe unas
   credenciales es peor que no avisar. */
.pest__nuevo {
    width: 7px; height: 7px; border-radius: 50%; flex: 0 0 7px;
    background: var(--gold); box-shadow: 0 0 8px var(--gold);
    animation: latido 1.6s ease-in-out infinite;
}

/* El panel. El `hidden` es lo que lo esconde, como en todo el resto de la
   pantalla: la hoja le pone !important arriba y no se inventa aqui otra forma. */
.pest-panel:focus-visible { outline: 1px solid var(--gold); outline-offset: 4px; }

/* EL TEXTO LARGO, AL FINAL DEL PANEL. Esta herramienta explica por que hace cada
   cosa y eso se queda; lo que cambia es donde. Antes el porque iba delante y
   habia que leerlo para llegar a los controles. Aqui esta debajo, al alcance de
   quien lo busque y fuera del camino de quien ya lo sabe. */
.pnl-nota {
    margin-top: 16px; font-size: 11.5px; line-height: 1.65; color: var(--muted);
    max-width: 760px;
}
.pnl-nota b { color: var(--bone-2); }
.pnl-nota code { font-family: var(--font-mono); font-size: .9em; color: var(--bone-2); }

@media (max-width: 560px) {
    /* A ancho de movil las tres pestanas no caben en una fila con su texto
       entero. Se reparten a tercios y se aprieta la letra ANTES que esconderla:
       un icono solo no dice cual es "En curso" y cual "Hallazgos", y adivinar
       pestanas es justo lo que esto venia a arreglar. */
    .pest__b { flex: 1 1 0; justify-content: center;
               padding: 10px 5px; font-size: 9px; letter-spacing: .05em; }
    .pest__b i { font-size: 11px; }
    /* Las cuatro de la sub-ventana caben a mitades, no a cuartos. */
    .pest--dlg .pest__b { flex: 1 1 40%; }
}

/* ============================== Campos ==================================

   UNA RANURA HUNDIDA Y CLARA. Antes el campo era del mismo color que el fondo
   y con un filete de un pixel: no se distinguia de un rotulo y el operador no
   veia donde escribir.

   El hundido es `inset` de verdad -la sombra va dentro-, y el fondo claro
   arrastra los otros tres colores: lo escrito, el marcador de posicion y el
   cursor. Cambiar el fondo sin cambiarlos deja el texto en hueso sobre blanco,
   que es ilegible; por eso los cuatro viven juntos en :root con su contraste
   medido al lado.
   ======================================================================== */
input[type=text], input[type=password], select, textarea {
    width: 100%; padding: 13px 15px;
    border: 1px solid var(--campo-borde); border-radius: 6px;
    background: var(--campo);
    color: var(--campo-texto); font-family: var(--font-mono);
    font-size: 12.5px; letter-spacing: .02em;
    /* La ranura: sombra DENTRO por arriba, para que parezca rehundida en la
       pantalla, y una linea clara abajo que hace de canto iluminado. */
    box-shadow: inset 0 2px 5px rgba(41, 14, 16, .30),
                inset 0 -1px 0 rgba(255, 255, 255, .55);
    /* El cursor tambien: en hueso sobre blanco no se ve, y entonces no se sabe
       si el campo tiene el foco. */
    caret-color: var(--campo-texto);
    transition: border-color .25s var(--ease), box-shadow .25s var(--ease);
}
input::placeholder, textarea::placeholder {
    color: var(--campo-marca); letter-spacing: .04em; opacity: 1;
}
input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--gold);
    /* Al enfocar, el hundido se mantiene y se le anade un halo: si al enfocar
       se volviera plano, pareceria que el campo se apaga justo al usarlo. */
    box-shadow: inset 0 2px 5px rgba(41, 14, 16, .30),
                inset 0 -1px 0 rgba(255, 255, 255, .55),
                0 0 0 3px rgba(255, 74, 94, .28);
}
/* DESHABILITADO SIGUE PARECIENDO DESHABILITADO. Vuelve a oscuro, pierde el
   hundido y el borde se parte: un campo blanco y hundido que no acepta texto
   es peor que uno apagado, porque invita a escribir en el. */
input:disabled, select:disabled, textarea:disabled {
    cursor: not-allowed;
    background: rgba(var(--ink-rgb), .55);
    color: var(--muted); border-style: dashed;
    border-color: var(--rule); box-shadow: none;
}
input:disabled::placeholder { color: rgba(247, 232, 234, .30); }
select { cursor: pointer; }
select option { background: var(--campo); color: var(--campo-texto); }

/* BURBUJA CENTRADA, EN TODAS LAS INTERFACES. Pedido asi: las 31 etiquetas de
   campo del sitio -el escaneo, el alta, la cuenta, los ajustes- pasan de un
   rotulo plano alineado a la izquierda a una pastilla centrada sobre su campo.
   `display: table` y no `inline-block` + `text-align:center` en el padre: la
   etiqueta ya vive suelta dentro de bloques que no son flex ni tienen su
   propio text-align, y `table` es el unico display que SE ENCOGE a su
   contenido y a la vez acepta `margin: 0 auto` para centrarse solo, sin tener
   que tocar el contenedor de cada uno de los 31 sitios donde aparece. */
.field-label {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .28em;
    text-transform: uppercase; color: var(--muted);
    display: table; margin: 0 auto 10px; padding: 5px 16px;
    border-radius: 999px; border: 1px solid var(--rule);
    background: rgba(var(--hueco-rgb), .3);
}
/* BLANCO Y EN NEGRITA, PERO SOLO EN EL TEMA OSCURO -el de por defecto, sin
   [data-tema]-. Dentro de la pastilla el `--muted` oscuro (hueso atenuado al
   78%) se lee bien sobre el fondo liso de la pagina, pero sobre el propio
   fondo de la pastilla -un hueco mas claro todavia- pierde el contraste que
   tenia; blanco solido en negrita lo recupera. En el tema claro `--muted` ya
   es un gris oscuro que SI tiene contraste contra la pastilla clara, asi que
   ahi no se toca -ver [data-tema="claro"] mas abajo, donde se revierte-. */
.field-label { color: #ffffff; font-weight: 700; }
[data-tema="claro"] .field-label { color: var(--muted); font-weight: 600; }
/* El icono de ayuda viaja DENTRO de la pastilla pero no hereda su blanco: si
   se leyera igual que el rotulo no se distinguiria el texto del signo de
   interrogacion que lo explica. */
.campo-ayuda {
    position: relative;
    margin-left: 6px; font-size: 11px; cursor: help;
    color: var(--gold-soft, var(--gold));
}
.campo-ayuda:hover, .campo-ayuda:focus-visible { color: var(--gold); }

/* EL GLOBITO ES PROPIO, NO EL title= DEL NAVEGADOR. La primera version usaba
   title -el mismo patron que ya usa ".nc" en los hallazgos sin confirmar- pero
   en la practica Oscar reporto que al pasar el mouse no aparecia nada. La
   causa real no era el navegador: Font Awesome YA USA ::before en este mismo
   elemento para dibujar el glyph del icono -por eso es un <i> vacio, todo su
   contenido visible sale de ese pseudo-elemento-, y una primera version de
   este globito tambien ponia su "puntita" en ::before. La declaracion de aqui
   abajo, que carga despues en la hoja, ganaba la cascada y le borraba el
   contenido al icono -quedaba en `content: ""`, 0x0px, nada que recibiera el
   mouse-: no es que el tooltip no respondiera al hover, es que no habia icono
   sobre el que pasar el mouse. Por eso el globito entero vive en ::after -el
   unico pseudo-elemento que le quedaba libre al icono- y no lleva puntita: una
   puntita en una tercera capa necesitaria envolver el icono en un <span>
   propio, y no hacia falta para que el globito se vea y funcione. */
.campo-ayuda::after {
    content: attr(data-tip);
    position: absolute; z-index: 60;
    top: 100%; left: 50%; margin-top: 10px;
    transform: translateX(-50%) translateY(-4px);
    width: max-content; max-width: 260px;
    background: var(--ink-3); color: var(--bone);
    border: 1px solid var(--rule); border-radius: 8px;
    padding: 9px 11px;
    font-family: var(--font-mono); font-size: 11.5px; font-weight: 400;
    text-transform: none; letter-spacing: normal; line-height: 1.55;
    box-shadow: 0 10px 28px rgba(0, 0, 0, .4);
    opacity: 0; pointer-events: none;
    transition: opacity .15s var(--ease), transform .15s var(--ease);
}
.campo-ayuda:hover::after, .campo-ayuda:focus-visible::after {
    opacity: 1; transform: translateX(-50%) translateY(0);
}

/* SOLO PARA EL LECTOR DE PANTALLA. El globito de ".campo-ayuda" se dibuja con
   `content: attr(data-tip)` en un ::after, y el contenido generado por CSS en un
   pseudo-elemento NO se expone de forma fiable a las tecnologias de asistencia:
   lo que se ve con el mouse no existe para quien navega por voz.

   Donde eso solo cuesta una explicacion opcional no pasa nada. Donde el aviso es
   la unica senal de que un control no hace lo que parece -el desplegable de
   Ajustes, que administra un proyecto que puede NO ser el que se esta
   auditando- hace falta un texto de verdad en el arbol de accesibilidad, y este
   es el que lo lleva.

   No se usa `display:none` ni `visibility:hidden`: las dos lo sacan tambien del
   arbol de accesibilidad, que es justo lo contrario de lo que se busca. El
   patron es el de siempre: un recuadro de 1px, recortado y fuera de la vista,
   que el lector si anuncia. */
.solo-lector {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}
.url-wrap { position: relative; }
.url-wrap > i:first-child {
    position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
    /* Sobre la ranura clara el rojo de la marca se queda en 3:1 y se lee
       lavado: este es el mismo rojo, oscurecido hasta 5.1:1. */
    color: var(--campo-icono); font-size: 12px; pointer-events: none;
}
.url-wrap input { padding-left: 38px; }
.url-wrap--ojo input { padding-right: 44px; }
/* El ojito solo cambia el type del campo: el valor no se copia a ningun lado. */
.ojo {
    position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
    background: transparent; border: 0; cursor: pointer; padding: 8px 10px;
    /* Va DENTRO de la ranura clara, asi que su color es el del campo y no el
       del fondo oscuro de la pagina. */
    color: var(--campo-marca); font-size: 12px;
}
.ojo:hover { color: var(--campo-icono); }
.url-wrap--off { opacity: .55; }
.url-wrap--off input { cursor: not-allowed; }
/* Con el campo apagado, el icono y el ojito vuelven al color del fondo oscuro:
   quedarse en el del campo claro los dejaria ilegibles sobre el apagado. */
.url-wrap--off > i:first-child, .url-wrap--off .ojo { color: var(--muted); }

.fila { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.fila input { flex: 1 1 200px; }

/* =============================== Cajas ================================== */
.console {
    border: 1px solid var(--rule); border-radius: 10px;
    background: var(--panel);
    padding: clamp(16px, 2.2vw, 26px);
}
.console--agentico { border-color: rgba(255, 74, 94, 0.28); }

/* AQUI ESTABA .rejilla-cliente, la rejilla de tres columnas del contexto
   plegado: alcance, expedientes y alta, uno al lado del otro al final de la
   vista. Se fue con el bloque, porque dentro de la sub-ventana cada uno tiene su
   propia pestana y ya no hay nada que repartir en columnas. */
.caja {
    border: 1px solid var(--rule); border-radius: 10px;
    background: rgba(var(--hueco-rgb), .18); padding: 16px;
    display: flex; flex-direction: column; gap: 10px;
}
.caja__t {
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .2em;
    text-transform: uppercase; color: var(--bone);
}
.caja__t i { margin-right: 7px; }
.caja__nota { font-size: 11.5px; line-height: 1.6; color: var(--muted); }
.caja__nota code { font-family: var(--font-mono); color: var(--bone-2); }
.caja__nota.bien { color: var(--bien); }
.caja__nota.malo { color: var(--mal); }

/* Listas de alcance y de expedientes. Scroll propio: una lista blanca larga no
   puede empujar fuera de la vista el formulario que esta al lado. */
.alc { max-height: 190px; overflow-y: auto; }
.alc__l {
    display: flex; align-items: baseline; gap: 8px;
    font-family: var(--font-mono); font-size: 11.5px; line-height: 1.75;
    color: var(--bone-2); word-break: break-all;
}
.alc__l i { font-size: 9px; flex: 0 0 11px; }
.alc__l.si i { color: var(--bien); }
.alc__l.no i { color: var(--mal); }
.alc__l.no { color: var(--muted); text-decoration: line-through; }
.alc__l button {
    background: transparent; border: 0; color: var(--bone); cursor: pointer;
    font-family: var(--font-mono); font-size: 10px; padding: 0 4px;
}
.alc__t {
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .2em;
    text-transform: uppercase; color: var(--muted); margin: 8px 0 3px;
}
.alc__t:first-child { margin-top: 0; }
/* EN "GENERALES" LOS HOSTS NO SE PULSAN. Ahi es solo lista -ver el
   comentario de `alcAjustesCuerpo` en app.html, pulsar un host escribiria el
   objetivo de la corrida del proyecto elegido para auditar, que puede no ser
   el que se esta administrando-, asi que el cursor de mano que invita a
   pulsar se quita: un boton que no hace nada se nota, y el cursor es lo
   primero que lo delata. */
.alc--solo-lectura .alc__l button { cursor: default; }

/* ============================== Botones ================================= */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 12px;
    padding: 15px 24px; border-radius: 6px;
    font-family: var(--font-mono); font-size: 10.5px;
    letter-spacing: 0.22em; text-transform: uppercase;
    border: 1px solid transparent; cursor: pointer; white-space: nowrap;
    transition: background .3s var(--ease), color .3s var(--ease),
                border-color .3s var(--ease), opacity .3s var(--ease);
}
.btn-primary { background: var(--bone); color: var(--ink); border-color: var(--bone); }
.btn-primary:hover:not(:disabled) { background: var(--gold); border-color: var(--gold); color: var(--ink); }
.btn:disabled { opacity: .45; cursor: default; }
.btn i { font-size: 11px; }

.ag-mini {
    font-family: var(--font-mono); font-size: 11px; letter-spacing: .6px;
    color: var(--bone); background: rgba(var(--hueco-rgb), .28);
    border: 1px solid var(--rule); border-radius: 7px;
    padding: 9px 14px; cursor: pointer;
    transition: background .25s var(--ease), border-color .25s var(--ease);
}
.ag-mini:hover:not(:disabled) { background: rgba(var(--hueco-rgb), .5); border-color: var(--bone-2); }
.ag-mini:disabled { opacity: .45; cursor: default; }
/* SOLO EL HOVER ES ROJO, igual que .hzx__borrar: el boton en reposo no puede
   gritar que algo va a borrarse cuando lo que hace -archivar- es reversible. */
.ag-mini--peligro:hover:not(:disabled) {
    color: var(--mal); background: rgba(255, 92, 110, .12); border-color: var(--mal);
}
.ag-mini i { margin-right: 6px; }

/* Rejilla y no flex con wrap: con wrap, el boton que cae solo a la segunda
   linea se estira a todo el ancho y queda disparejo. */
.ag-botonera {
    display: grid; gap: 10px; margin-top: 16px; align-items: stretch;
    grid-template-columns: minmax(200px, 1fr) auto auto auto;
}
@media (max-width: 860px) {
    .ag-botonera { grid-template-columns: 1fr 1fr; }
    .ag-botonera .btn-primary { grid-column: 1 / -1; }
}

/* El freno no compite en color con el boton principal: es gris hasta que lo
   necesitas y solo entonces se pone rojo. Un boton de emergencia siempre
   encendido deja de leerse como emergencia. */
.btn-detener, .btn-2fa, .btn-cerrar {
    font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 1px;
    background: transparent; border: 1px solid var(--rule); border-radius: 10px;
    padding: 14px 18px; cursor: pointer; color: var(--muted);
    transition: color .25s var(--ease), border-color .25s var(--ease),
                background .25s var(--ease);
}
.btn-detener:hover:not(:disabled) { color: #fff; background: #d32f3f; border-color: #d32f3f; }
.btn-detener:disabled, .btn-2fa:disabled, .btn-cerrar:disabled { opacity: .5; cursor: default; }
.btn-detener i, .btn-2fa i, .btn-cerrar i { margin-right: 7px; }
/* El codigo del segundo factor caduca en minutos: el boton se distingue de sus
   vecinos para encontrarlo de un vistazo, sin competir con DETENER. */
.btn-2fa { color: var(--bone); border-color: var(--bone-2); }
.btn-2fa:hover:not(:disabled) { background: var(--capa-hover-2); }
.btn-cerrar:hover:not(:disabled) { color: var(--bone); border-color: var(--gold); }

/* ======================= EL SELECTOR DE APLICACION =======================

   AQUI VIVIA EL VELO: un panel oscuro con un `backdrop-filter` encima del
   formulario y el cartel "Elige primero la aplicacion". Funcionaba -nadie
   lanzaba nada sin aplicacion- pero era una pared que decia lo que NO se puede
   hacer.

   Lo que hay ahora ocupa el mismo sitio y dice lo que SI se puede: una tarjeta
   por aplicacion, con imagen y texto. La regla no cambio: el formulario sigue
   sin poder lanzarse sin aplicacion, los campos siguen deshabilitados y la
   cerradura de verdad sigue en el servidor.
   ======================================================================== */
.zona { position: relative; }

.sel {
    border: 1px solid rgba(255, 74, 94, .28); border-radius: 10px;
    background: var(--panel);
    padding: clamp(16px, 2.2vw, 26px);
    display: flex; flex-direction: column; gap: 16px;
}
.sel__cab { display: flex; gap: 14px; align-items: flex-start; }
.sel__cab > i { font-size: 20px; color: var(--gold); margin-top: 3px; }
.sel__cab b {
    display: block; font-family: var(--font-serif);
    font-size: clamp(16px, 2vw, 21px); font-weight: 500; color: var(--bone);
    line-height: 1.25;
}
.sel__cab span {
    display: block; font-size: 12.5px; color: var(--muted); line-height: 1.6;
    margin-top: 5px;
}
/* La vuelta de un pago. En ambar y no en rojo: no es un fallo, es algo que
   falta por hacer y que se hace eligiendo una tarjeta. */
/* AQUI VIVIA `.sel__off`, el marcador de "sin elegir una, el formulario de la
   auditoria sigue apagado". Se quito el 04/10/2026 junto con el parrafo largo
   que sustituia: el operador no quiere ninguna de las dos versiones. La regla
   no la sostenia este estilo sino `pintarFormulario()`, que ESCONDE el
   formulario entero y pone la tarjeta del selector en su sitio, asi que no hay
   campos a la vista que puedan parecer utilizables.

   La regla se borra de la hoja al borrar lo que la usaba, y no se deja
   huerfana: una clase que ya no escribe nadie es la siguiente que alguien copia
   creyendo que hace algo. */

.sel__vuelta {
    display: flex; gap: 9px; align-items: flex-start;
    font-size: 12.5px; line-height: 1.55; color: var(--bone-2);
    border: 1px solid rgba(245, 166, 35, .45);
    background: rgba(245, 166, 35, .09);
    border-radius: 9px; padding: 11px 13px;
}
.sel__rejilla {
    display: grid; gap: 12px;
    grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
}
.sel__alta { align-self: flex-start; }
.sel__vacio { font-size: 12.5px; color: var(--muted); line-height: 1.6; }

/* LA TARJETA. Es un <button> de verdad, asi que se recorre con el tabulador y
   se activa con Espacio o Enter sin que haya que programarlo. */
.selt {
    display: grid; grid-template-columns: auto 1fr; gap: 3px 13px;
    align-items: center; text-align: left; cursor: pointer;
    padding: 14px; border-radius: 11px;
    border: 1px solid var(--rule);
    background: linear-gradient(180deg, rgba(255, 255, 255, .05) 0%,
                                        rgba(0, 0, 0, .20) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10),
                0 1px 2px rgba(0, 0, 0, .28);
    transition: border-color .18s var(--ease), box-shadow .18s var(--ease),
                transform .08s var(--ease);
}
.selt:hover { border-color: var(--gold); }
.selt:active { transform: translateY(1px); }
.selt--activa {
    border-color: var(--gold);
    box-shadow: inset 0 3px 7px rgba(0, 0, 0, .45),
                inset 0 0 0 1px rgba(255, 74, 94, .25);
}
.selt__n {
    font-size: 14px; font-weight: 700; color: var(--bone); line-height: 1.25;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.selt__o {
    grid-column: 2; font-family: var(--font-mono); font-size: 10.5px;
    color: var(--bone-2); line-height: 1.4;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.selt__pie {
    grid-column: 2; display: flex; gap: 8px; flex-wrap: wrap;
    align-items: center; margin-top: 4px;
}
.selt__plan {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .08em;
    text-transform: uppercase; color: var(--bone);
    border: 1px solid rgba(255, 74, 94, .35); border-radius: 999px;
    padding: 2px 8px;
}
.selt__aud {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .06em;
    color: var(--muted);
}

/* EL MONOGRAMA. La imagen de la aplicacion cuando no hay logotipo: sus
   iniciales sobre un color derivado del slug, el mismo siempre. El operador la
   reconoce por forma y color sin llegar a leer el nombre, que es lo que evita
   el error que esta herramienta no se puede permitir: lanzar el pentest de una
   contra el objetivo de otra.

   El color llega en --mono desde el JS, porque sale del slug y aqui no hay
   manera de calcularlo. */
.mono {
    grid-row: 1 / span 3; width: 46px; height: 46px; flex: 0 0 46px;
    display: grid; place-items: center; border-radius: 11px; overflow: hidden;
    font-family: var(--font-mono); font-size: 15px; font-weight: 700;
    letter-spacing: .02em;
    color: #fff;
    background: var(--mono, rgba(var(--bone-rgb), .14));
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22);
}
.mono img { width: 100%; height: 100%; object-fit: cover; }
.mono--chico {
    grid-row: 1 / span 2; width: 28px; height: 28px; flex: 0 0 28px;
    border-radius: 8px; font-size: 10.5px;
}

/* ====================== SIN CUOTA, CON SALIDA ===========================

   El segundo motivo del velo era la cuota agotada, y tapaba el formulario con
   el motivo centrado. Ahora el motivo va EN LINEA, arriba del formulario y
   antes de cualquier campo, con el boton de comprar al lado: una negativa sin
   salida es la que hace que el operador cierre la herramienta.

   Los campos siguen deshabilitados mientras esto se vea. Lo que cambia es como
   se dice, no la regla.
   ======================================================================== */
.cuota-off {
    display: flex; gap: 13px; align-items: center; flex-wrap: wrap;
    border: 1px solid rgba(255, 92, 110, .5);
    background: rgba(255, 92, 110, .10);
    border-radius: 10px; padding: 13px 15px; margin-bottom: 16px;
}
.cuota-off > i { font-size: 18px; color: var(--mal); }
.cuota-off > div { flex: 1 1 260px; min-width: 0; }
.cuota-off b {
    display: block; font-family: var(--font-mono); font-size: 11px;
    letter-spacing: .16em; text-transform: uppercase; color: var(--mal);
}
.cuota-off span {
    display: block; font-size: 12.5px; color: var(--bone-2); line-height: 1.55;
    margin-top: 4px;
}

/* ===================== LA VENTANA DE COMPRA =============================
   Un <dialog> de verdad: el navegador atrapa el foco, cierra con Escape y
   deja el fondo inerte sin que haya que programarlo.
   ======================================================================== */
.dlg {
    width: min(620px, calc(100vw - 32px));
    /* El `margin: auto` que centra un <dialog> abierto lo pone el navegador, y
       el `* { margin: 0 }` de arriba se lo quita: sin esta linea la ventana
       sale pegada a la esquina de arriba a la izquierda. */
    margin: auto;
    border: 1px solid rgba(255, 74, 94, .35); border-radius: 14px;
    background: linear-gradient(160deg, var(--ink-3) 0%, var(--ink) 100%);
    color: var(--bone); padding: clamp(18px, 3vw, 26px);
    box-shadow: 0 30px 80px rgba(0, 0, 0, .6);
}
.dlg::backdrop { background: rgba(12, 3, 4, .72); backdrop-filter: blur(2px); }
.dlg__cab { display: flex; align-items: center; gap: 12px; }
.dlg__cab h3 {
    flex: 1 1 auto; font-family: var(--font-serif); font-weight: 500;
    font-size: clamp(17px, 2.2vw, 22px); color: var(--bone); line-height: 1.2;
}
.dlg__cab h3 i { color: var(--gold); font-size: .85em; margin-right: 7px; }
.dlg__x {
    background: transparent; border: 1px solid var(--rule); border-radius: 8px;
    color: var(--muted); cursor: pointer; padding: 7px 10px; font-size: 13px;
}
.dlg__x:hover { color: var(--bone); border-color: var(--gold); }
/* DE QUIEN ES LO QUE SE ESTA MIRANDO. En la ventana de compra es una linea
   suelta; en la del contexto cambia con la pestana, porque las cinco no son del
   mismo dueno: el plan y el alta son del USUARIO y el alcance, los expedientes y
   los ajustes son de la APLICACION. Sin esto, abrir "Alcance" obligaria a
   adivinar de que proyecto es la lista blanca que se esta leyendo. */
.dlg__app {
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--muted); margin-top: 8px;
}
.dlg__app--usuario, .dlg__app--app {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px;
    margin-top: 12px; padding: 9px 13px; border-radius: 10px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .25);
}
/* Dos colores, y la diferencia es el mensaje: el ambar es de la cuenta -lo que
   se comparte entre proyectos- y el rojo de la marca es de la aplicacion, lo que
   NO se comparte con ninguna otra. */
.dlg__app--usuario { border-color: rgba(245, 166, 35, .4); }
.dlg__app--usuario > i { color: var(--aviso); }
.dlg__app--app { border-color: rgba(255, 74, 94, .4); }
.dlg__app--app > i { color: var(--gold); }
.dlg__app b {
    font-family: var(--font-sans); font-size: 14px; font-weight: 700;
    letter-spacing: 0; text-transform: none; color: var(--bone);
}
.dlg__app em {
    flex: 1 1 100%; font-style: normal; font-family: var(--font-sans);
    font-size: 11.5px; letter-spacing: 0; text-transform: none;
    color: var(--muted); line-height: 1.5;
}
/* MAS VISIBLE, Y SOLO EN AJUSTES. Oscar, 24/10/2026: de las cinco pantallas
   que usan ".dlg__app" esta es la unica donde confundir "lo que se ve" con
   "lo que se esta editando" tiene un costo real -escribir en el perfil de un
   proyecto que no es el pensado-, asi que es la unica que sube de contraste;
   subirlo en las otras cuatro diluiria la jerarquia que esto crea. */
.dlg__app--destacada {
    padding: 13px 16px; border-width: 2px;
    border-color: rgba(255, 74, 94, .65);
    background: rgba(255, 74, 94, .1);
}
.dlg__app--destacada > i:first-child { font-size: 17px; }
.dlg__app--destacada b { font-size: 16px; }
.dlg__modo {
    display: flex; gap: 10px; align-items: flex-start;
    font-size: 12.5px; line-height: 1.6; color: var(--bone-2);
    border-radius: 10px; padding: 12px 14px; margin-top: 14px;
    border: 1px solid rgba(245, 166, 35, .45);
    background: rgba(245, 166, 35, .09);
}
.dlg__modo i { color: var(--aviso); font-size: 14px; margin-top: 3px; }
.dlg__modo--real { border-color: rgba(76, 175, 125, .4); background: rgba(76, 175, 125, .08); }
.dlg__modo--real i { color: var(--bien); }
.dlg__modo b { color: var(--bone); }
.dlg__modo code {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone);
}
.dlg__paq { display: grid; gap: 10px; margin-top: 16px; }

/* Cada paquete es un boton. El precio y el tamano los manda el servidor: un
   precio escrito en el navegador es una promesa duplicada. */
.paq {
    display: grid; grid-template-columns: 1fr auto; gap: 3px 14px;
    align-items: center; text-align: left; cursor: pointer;
    border: 1px solid var(--rule); border-radius: 10px; padding: 13px 15px;
    background: linear-gradient(180deg, rgba(255, 255, 255, .05) 0%,
                                        rgba(0, 0, 0, .20) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10),
                0 1px 2px rgba(0, 0, 0, .28);
    transition: border-color .18s var(--ease), transform .08s var(--ease);
}
.paq:hover:not(:disabled) { border-color: var(--gold); }
.paq:active:not(:disabled) { transform: translateY(1px); }
.paq:disabled { opacity: .5; cursor: default; }
/* LAS TRES CELDAS, EXPLICITAS Y NO POR AUTO-ACOMODO -14/10/2026-: el nombre
   y la descripcion a la IZQUIERDA -columna ancha, "1fr"-, el precio a la
   DERECHA -columna angosta, "auto"-, como un recibo. El auto-acomodo del
   grid (sin `grid-column` en ningun hijo) dependia de que el motor
   adivinara el orden correcto a partir del `grid-row` del precio, y Oscar
   lo encontro mal acomodado -el precio a la izquierda, pegado al borde-: de
   ahi que cada celda diga ahora, sin adivinar, donde va. */
.paq__n {
    grid-column: 1; grid-row: 1; text-align: left;
    font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em;
    text-transform: uppercase; color: var(--bone); font-weight: 700;
}
.paq__p {
    grid-column: 2; grid-row: 1 / span 2; text-align: right;
    font-family: var(--font-mono); font-size: 16px;
    font-weight: 700; color: var(--bone); white-space: nowrap;
}
.paq__d {
    grid-column: 1; grid-row: 2; text-align: left;
    font-size: 11.5px; color: var(--muted); line-height: 1.45;
}
/* LAS PESTANAS DE "COMPRAR ESCANEOS" -14/10/2026-, pedidas por Oscar para
   separar el escaneo del retesting como los dos productos que son, en vez
   de una lista unica con una etiqueta en el mas barato -que es como estaba
   antes de este cambio: ver el historial de .paq--retesting/.paq__etq si
   hace falta volver a eso-. */
.dlg__pestanas { display: flex; gap: 6px; margin: 14px 0 12px; }
.dlg__pestana {
    flex: 1 1 auto; cursor: pointer; text-align: center;
    padding: 9px 10px; border-radius: 9px 9px 0 0;
    border: 1px solid var(--rule); border-bottom: none;
    background: rgba(var(--bone-rgb), .04);
    font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em;
    text-transform: uppercase; color: var(--muted); font-weight: 600;
    transition: color .15s var(--ease), background .15s var(--ease);
}
.dlg__pestana:hover { color: var(--bone-2); }
.dlg__pestana--on {
    color: var(--bone); background: rgba(var(--hueco-rgb), .2);
    border-color: var(--gold);
}
.dlg__nota {
    font-size: 11.5px; color: var(--muted); line-height: 1.6; margin-top: 14px;
}
.dlg__nota.malo { color: var(--mal); }
.dlg__nota.bien { color: var(--bien); }

/* EL CONFIRMAR PROPIO, EN VEZ DE window.confirm(). Angosta a proposito -no es
   un formulario, es una pregunta de si/no- y los dos botones a la derecha,
   el orden que ya tienen los dialogos nativos del sistema: cancelar primero,
   la accion despues, para no entrenar al operador a pulsar siempre el de la
   derecha. */
#dlgConfirmar { width: min(440px, calc(100vw - 32px)); }
.dlg__confirmar-texto {
    font-size: 13px; line-height: 1.6; color: var(--bone-2);
    margin-top: 4px; white-space: pre-line;
}
.dlg__confirmar-acciones { justify-content: flex-end; margin-top: 20px; }
.dlg__confirmar-check {
    display: flex; align-items: flex-start; gap: 9px; margin-top: 16px;
    padding: 10px 12px; border-radius: 8px; cursor: pointer;
    border: 1px solid rgba(255, 92, 110, .35);
    background: rgba(255, 92, 110, .08);
    font-size: 12.5px; line-height: 1.5; color: var(--bone-2);
}
.dlg__confirmar-check input { margin-top: 2px; flex: 0 0 auto; }

/* LA LISTA DE "SIN CONFIRMAR". Nombres, severidad y categoria -nada mas-: es
   una ventana pequena para reconocer de que hallazgo se trata y abrir el
   expediente a mirarlo, no para leerlo entero aqui. */
.snc__nota {
    margin: 10px 0 0; font-size: 12px; line-height: 1.6; color: var(--muted);
}
.snc__lista {
    list-style: none; margin: 14px 0 0; padding: 0;
    display: grid; gap: 7px; max-height: min(50vh, 380px); overflow-y: auto;
}
.snc__it {
    display: flex; flex-direction: column; gap: 3px;
    padding: 9px 11px; border-radius: 8px;
    border: 1px solid var(--rule); border-left: 3px solid var(--sev, var(--aviso));
    background: rgba(var(--hueco-rgb), .2);
}
.snc__it[data-sev="Critica"] { --sev: var(--sev-critica); }
.snc__it[data-sev="Alta"] { --sev: var(--sev-alta); }
.snc__it[data-sev="Media"] { --sev: var(--sev-media); }
.snc__it[data-sev="Baja"] { --sev: var(--sev-baja); }
.snc__it[data-sev="Informativo"] { --sev: var(--sev-informativo); }
.snc__t { font-size: 13px; color: var(--bone); }
.snc__m {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .06em;
    color: var(--muted);
}
.snc__m b { color: var(--sev, var(--aviso)); }

@media (max-width: 560px) {
    .paq { grid-template-columns: 1fr; }
    /* CON UNA SOLA COLUMNA, `grid-column: 2` del precio -puesto explicito el
       14/10/2026- apuntaria a una columna que ya no existe: se vuelve a
       dejar en la 1, en su propio renglon y alineado a la izquierda como el
       resto, que es lo que tiene sentido cuando ya no hay dos columnas que
       enfrentar. */
    .paq__p { grid-column: 1; grid-row: auto; text-align: left; }
}

/* ============================ Modo y avisos ============================= */
.ag-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; margin-bottom: 18px;
}
.ag-tag {
    font-family: var(--font-mono); font-size: 12px; letter-spacing: 1.5px;
    text-transform: uppercase; color: var(--bone);
}
.ag-tag i { margin-right: 6px; }
.ag-2fa {
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .5px;
    color: var(--muted); border: 1px solid var(--rule);
    border-radius: 999px; padding: 4px 12px;
}

/* Tres casillas que se comportan como botones de radio. No son <radio> porque
   cada una lleva su descripcion y el radio nativo no deja componer eso; el
   comportamiento excluyente se mantiene en el JS y el servidor lo vuelve a
   comprobar por su cuenta. */
/* ===================== LOS CONTROLES, COMO TECLAS =======================

   Antes esto eran casillas: un cuadradito con una marca dentro de un recuadro
   grande. Parecia que se podian marcar varias, y la unica senal de cual estaba
   puesto era la marca.

   Ahora cada opcion es una TECLA. La puesta se ve HUNDIDA, como una tecla
   pulsada, y la que no, en relieve.

   TRES COSAS QUE NO SE PUEDEN PERDER AL HACER ESTO:

   1. POR DENTRO SIGUEN SIENDO CONTROLES DE VERDAD. La tecla es el <label> y
      dentro va el <input type=checkbox> que ya estaba, con la logica que ya
      tenia. No hay un solo div con onclick: con divs se pierden el tabulador,
      el foco y los lectores de pantalla.
   2. EL HUNDIDO NO ES LA UNICA SENAL. Una sombra interior se pierde con el
      brillo bajo o con mucha luz alrededor, asi que la puesta lleva ademas
      borde dorado, letra en negrita y el indicador relleno con su marca. Es la
      misma razon por la que la fila activa de la barra lateral lleva tres
      senales y no una.
   3. EL FOCO SE VE. El <input> queda debajo de la tecla y el anillo se pinta
      sobre el <label> con :has(:focus-visible), asi que al tabular se ve la
      tecla entera enmarcada y no un punto escondido.

   El indicador es el propio <input> con appearance:none. Sigue siendo el
   control -recibe el foco, responde a Espacio- y de paso es el indicador que
   pide la senal numero 2.
   ======================================================================== */

/* La base de las dos familias de teclas: los modos y las opciones. */
.ag-modo, .opt {
    position: relative;
    border: 1px solid var(--rule); border-radius: 10px;
    background: linear-gradient(180deg, rgba(255, 255, 255, .05) 0%,
                                        rgba(0, 0, 0, .18) 100%);
    /* En relieve: la luz viene de arriba, asi que la linea clara va arriba y la
       sombra fuera y abajo. */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10),
                0 1px 2px rgba(0, 0, 0, .28);
    cursor: pointer;
    transition: border-color .18s var(--ease), box-shadow .18s var(--ease),
                background .18s var(--ease), transform .08s var(--ease);
}
.ag-modo:hover, .opt:hover { border-color: rgba(255, 74, 94, .40); }
/* Mientras se mantiene pulsada, se hunde: la tecla responde al dedo. */
.ag-modo:active, .opt:active { transform: translateY(1px); }

/* EL FOCO, sobre la tecla entera. */
.ag-modo:has(:focus-visible), .opt:has(:focus-visible) {
    outline: 2px solid var(--gold); outline-offset: 2px;
}

/* PUESTA: hundida, con borde dorado y letra en negrita. La sombra va DENTRO y
   el relieve de arriba desaparece, que es lo que hace que se lea como pulsada
   y no como coloreada. */
.ag-modo--on, .ag-modo:has(input:checked),
.opt--on, .opt:has(input:checked) {
    border-color: var(--gold);
    background: rgba(255, 74, 94, .13);
    box-shadow: inset 0 3px 7px rgba(0, 0, 0, .45),
                inset 0 0 0 1px rgba(255, 74, 94, .25);
}

/* EL INDICADOR. Es el <input> de verdad, repintado. */
.ag-modo input, .opt input {
    appearance: none; -webkit-appearance: none;
    width: 16px; height: 16px; flex: 0 0 16px;
    margin: 0; border-radius: 5px; cursor: pointer;
    border: 1px solid rgba(var(--bone-rgb), .38);
    background: rgba(var(--hueco-rgb), .34);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, .5);
    display: grid; place-items: center;
    transition: background .18s var(--ease), border-color .18s var(--ease);
}
.ag-modo input:checked, .opt input:checked {
    background: var(--gold); border-color: var(--gold);
    box-shadow: none;
}
/* La marca se dibuja con dos filetes girados y no con una tipografia: asi no
   depende de que Font Awesome haya cargado. */
.ag-modo input:checked::after, .opt input:checked::after {
    content: ""; width: 4px; height: 8px; margin-top: -2px;
    border: solid var(--ink); border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.ag-modo input:disabled, .opt input:disabled { cursor: not-allowed; opacity: .45; }

/* -------------------------------- los modos ---------------------------- */
.ag-modos { display: flex; gap: 10px; flex-wrap: wrap; }
.ag-modo {
    flex: 1 1 210px; min-width: 190px;
    display: grid; grid-template-columns: auto 1fr; gap: 4px 10px;
    align-items: center; padding: 12px 14px;
}
.ag-modo__t {
    font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .08em;
    text-transform: uppercase; color: var(--bone); font-weight: 500;
}
.ag-modo__d { grid-column: 2; font-size: 11.5px; color: var(--muted); line-height: 1.4; }
/* Era `--gold-soft` por una medicion de contraste del 06/10/2026 (ver
   historial si hace falta el numero). Oscar pidio el 15/10/2026 que ningun
   texto de la plataforma quede en tono rojo/dorado en modo claro -que sea
   negro- ni en modo oscuro -que sea blanco-, asi que ahora es `--bone` como
   el resto: lo elegido ya se distingue por el fondo de la tecla, no necesita
   tambien el color del rotulo. */
.ag-modo--on .ag-modo__t, .ag-modo:has(input:checked) .ag-modo__t {
    color: var(--bone); font-weight: 700;
}

/* Un modo que no se puede elegir -no hay aplicacion, o no queda cuota- se
   apaga de verdad: ni mano, ni relieve, ni invitacion a pulsarlo. */
.ag-modo:has(input:disabled), .opt:has(input:disabled) {
    opacity: .5; cursor: not-allowed; box-shadow: none;
    border-style: dashed; transform: none;
}

.ag-nota-campo { margin: 6px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.ag-nota-campo.malo { color: var(--mal); }
.ag-nota-campo.bien { color: var(--bien); }

/* ============ LOS HOSTS AUTORIZADOS, DEBAJO DEL CAMPO ==================
   Esta funcion existia solo dentro de la ventana del alcance, a dos clics y un
   cambio de contexto. El parrafo que explicaba por que existe se quito al
   aligerar la pantalla, asi que lo que queda es que no haga falta explicarla:
   los hosts estan aqui, pegados al campo, y se ponen con un clic. Teclear el
   objetivo a mano es la via por la que se cuela el sistema de otro cliente.
   ======================================================================== */
.hosts { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.hosts__t {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
}
.hosts__t i { color: var(--bien); margin-right: 5px; }
.hosts button {
    font-family: var(--font-mono); font-size: 10.5px; cursor: pointer;
    padding: 4px 10px; border-radius: 999px; color: var(--bone);
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .28);
    transition: border-color .15s var(--ease), color .15s var(--ease);
}
.hosts button:hover { border-color: var(--gold); color: var(--bone); }
.hosts button:disabled { opacity: .45; cursor: not-allowed; border-style: dashed; }

.ag-aviso-cred, .warn {
    display: flex; gap: 12px; align-items: flex-start;
    margin-top: 14px; padding: 12px 14px;
    border: 1px solid rgba(245, 166, 35, .34); border-radius: 10px;
    background: rgba(245, 166, 35, .07);
    font-size: 11.5px; line-height: 1.65; color: var(--muted);
}
.ag-aviso-cred i, .warn i { color: var(--aviso); font-size: 14px; margin-top: 2px; flex-shrink: 0; }
.ag-aviso-cred b, .warn b, .warn strong { color: var(--bone-2); }

/* ============================ Estado y pasos ============================ */
.ag-estado {
    margin-top: 18px; padding: 16px; border-radius: 10px;
    border: 1px solid var(--rule); background: rgba(255, 74, 94, 0.05);
}
.ag-estado__fila { display: flex; align-items: center; gap: 12px; font-size: 13.5px; }
/* El giro solo se anima mientras hay espera; al terminar se le quita la clase. */
.ag-spinner {
    width: 16px; height: 16px; flex: 0 0 16px; border-radius: 50%;
    border: 2px solid var(--rule); border-top-color: var(--gold);
}
.ag-spinner.girando { animation: gira .8s linear infinite; }
@keyframes gira { to { transform: rotate(360deg); } }

/* LA CUENTA ATRAS DEL CUPO. Va dentro de `.ag-estado`, debajo de la fila del
   mensaje, porque es el mismo sitio donde esta pantalla ya cuenta lo que esta
   pasando. No es una alarma: el cupo agotado no es un error, es un turno que
   todavia no llega, asi que no se pinta en rojo. El reloj va en monoespaciada
   para que los digitos no bailen de ancho al cambiar cada segundo. */
.ag-cupo {
    display: flex; align-items: center; gap: 10px;
    margin-top: 12px; padding-top: 12px;
    border-top: 1px solid var(--rule);
    font-size: 13px; color: var(--muted);
}
.ag-cupo b {
    font-family: var(--font-mono); font-size: 16px;
    letter-spacing: .5px; color: var(--bone);
    font-variant-numeric: tabular-nums;
}

.ag-pasos { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.ag-paso {
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .5px;
    padding: 5px 10px; border-radius: 6px;
    border: 1px solid var(--rule); color: var(--muted); opacity: .5;
}
/* ACTIVO es "esto esta pasando ahora mismo": pulso vivo, para que se note sin
   leer la letra. HECHO es "esto ya paso": verde fijo y sin pulso, con un
   check delante. Antes los dos compartian el mismo borde dorado estatico y
   no habia forma de distinguir, con el ojo, una corrida en curso de una ya
   terminada -ver TEXTO_PASO en app.js, que es la otra mitad de este arreglo. */
.ag-paso.activo {
    opacity: 1; color: var(--bone); border-color: var(--gold);
    background: rgba(255, 74, 94, .12);
    animation: ag-paso-pulso 1.6s ease-in-out infinite;
}
.ag-paso.hecho { opacity: 1; color: var(--bien); border-color: var(--bien); }
.ag-paso.hecho::before { content: "\2713\0020"; }
.ag-paso.falla { opacity: 1; color: var(--mal); border-color: var(--mal); }

@keyframes ag-paso-pulso {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 74, 94, .4); }
    50% { box-shadow: 0 0 0 4px rgba(255, 74, 94, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .ag-paso.activo { animation: none; }
}

/* ============ LO QUE PASA DESPUES DE PULSAR "SOLICITAR" =================
   Este aviso vivia debajo del boton que lanza, en la pestana de configuracion.
   Se quito de alli al aligerarla, y aterrizo aqui: pegado a los tres pasos, que
   es donde se espera y donde el paso 2 -"Aprobada por el operador"- se queda sin
   marcar hasta que contesta el correo. Lo que no puede pasar es que el operador
   pulse, llegue a esta pestana y crea que la corrida ya arranco.
   ======================================================================== */
.ag-aprob {
    display: flex; align-items: flex-start; gap: 10px; margin: 14px 0 0;
    padding: 10px 12px; border-radius: 9px;
    border: 1px solid rgba(245, 166, 35, .40);
    background: rgba(245, 166, 35, .07);
    font-size: 12px; line-height: 1.6; color: var(--bone-2);
}
.ag-aprob > i { color: var(--aviso); font-size: 14px; margin-top: 2px; flex-shrink: 0; }
.ag-aprob b { color: var(--bone); }
.ag-aprob strong { color: var(--aviso); }

/* El codigo del correo se teclea aqui, pegado al aviso. Seis digitos grandes y
   espaciados para que se lean de un vistazo contra el correo. */
.ag-codigo { margin: 10px 0 0; }
.ag-codigo__fila { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 6px; }
.ag-codigo input.ag-codigo__in {
    width: 10.5em; max-width: 100%; padding: 8px 10px; text-align: center;
    font-family: var(--font-mono); font-size: 20px; letter-spacing: .35em;
}
.ag-codigo__msg { min-height: 1.4em; margin: 8px 0 0; font-size: 12.5px; color: var(--aviso); }

/* La solicitud caduca a los 10 min. Sin reloj la espera se vive como un limbo:
   no se sabe si quedan veinte minutos o veinte segundos. */
.ag-reloj {
    display: inline-flex; align-items: center; gap: 9px; margin-top: 14px;
    padding: 8px 14px; border-radius: 999px;
    border: 1px solid var(--rule); background: rgba(var(--ink-3-rgb), .45);
    font-size: 12px; color: var(--muted);
    transition: border-color .4s var(--ease), color .4s var(--ease);
}
.ag-reloj b {
    font-family: var(--font-mono); font-size: 15px; font-weight: 700;
    color: var(--bone); font-variant-numeric: tabular-nums;
}
.ag-reloj.poco { border-color: rgba(245, 166, 35, .45); background: rgba(245, 166, 35, .08); }
.ag-reloj.poco b, .ag-reloj.poco i { color: var(--aviso); }
.ag-reloj.agotado { border-color: rgba(255, 92, 110, .5); background: rgba(255, 92, 110, .09); }
.ag-reloj.agotado b, .ag-reloj.agotado i { color: var(--mal); }

/* ========================= Entrega del expediente ======================= */
.ag-ok, .ag-falta {
    display: flex; align-items: flex-start; gap: 10px;
    font-size: 13px; font-weight: 500; line-height: 1.45;
    padding: 11px 14px; border-radius: 8px; margin-top: 12px;
}
.ag-ok { color: var(--bien); background: rgba(76, 175, 125, 0.10); border: 1px solid rgba(76, 175, 125, 0.30); }
.ag-falta { color: var(--bone); background: rgba(255, 74, 94, 0.09); border: 1px solid rgba(255, 74, 94, 0.30); }
.ag-ruta { margin-top: 12px; display: flex; flex-direction: column; gap: 4px; }
.ag-ruta span {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 1.2px;
    color: var(--bone); text-transform: uppercase;
}
.ag-ruta code {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone-2);
    background: rgba(var(--hueco-rgb), 0.3); border: 1px solid var(--rule);
    border-radius: 6px; padding: 8px 10px; word-break: break-all; line-height: 1.5;
}
.ag-acciones { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.ag-texto {
    margin-top: 12px; padding: 12px; border-radius: 8px;
    background: rgba(var(--hueco-rgb), 0.35); border: 1px solid var(--rule);
    font-family: var(--font-mono); font-size: 11px; line-height: 1.65;
    color: var(--bone-2); white-space: pre-wrap; word-break: break-word;
    max-height: 340px; overflow-y: auto;
}

/* ====================== Panel del segundo factor =========================
   Aparece cuando el agente deja la senal, y tambien a mano desde el boton de
   la botonera. El codigo va del campo al archivo que el agente lee: no se
   guarda en el navegador, no se manda al correo y no queda en el expediente. */
.ag-pausa {
    margin: 0 0 14px; padding: 13px 15px; border-radius: 11px;
    border: 1px solid rgba(245, 166, 35, .45); background: rgba(245, 166, 35, .07);
}
.ag-pausa__cab { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 4px; }
.ag-pausa__t {
    font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 1.1px;
    text-transform: uppercase; color: var(--aviso); font-weight: 700;
}
.ag-pausa__d { font-size: 12px; color: var(--bone-2); margin-bottom: 10px; }
/* La aclaracion de cual de las dos cuentas pide el codigo: tiene que leerse,
   pero no competir con la frase que dice que hay que hacer. */
.ag-pausa__d--sutil { font-size: 11.5px; color: var(--muted); }

/* CUANTO LE QUEDA AL CODIGO, pegado al campo donde se pega. Va ENCIMA del
   campo y no debajo: es lo que decide si merece la pena pegarlo. El 08/10/2026
   se pegaron codigos ya caducados porque la pantalla no decia nada de su vida,
   y con tres correos en la bandeja se pego el de uno viejo. */
.ag-2fa-vida {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin: 0 0 10px;
}
.ag-2fa-reloj {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 5px 11px; border-radius: 999px;
    border: 1px solid var(--rule); background: rgba(var(--ink-3-rgb), .45);
    font-size: 11px; color: var(--muted);
    transition: border-color .4s var(--ease), color .4s var(--ease);
}
.ag-2fa-reloj b {
    font-family: var(--font-mono); font-size: 14px; font-weight: 700;
    color: var(--bone); font-variant-numeric: tabular-nums;
}
/* Los dos ultimos minutos cambian de tono: a partir de ahi ya no da tiempo a
   ir a buscar el correo, hay que pegar el que se tenga o pedir otro. */
.ag-2fa-reloj.poco { border-color: rgba(245, 166, 35, .45); background: rgba(245, 166, 35, .08); }
.ag-2fa-reloj.poco b, .ag-2fa-reloj.poco i { color: var(--aviso); }
.ag-2fa-reloj.agotado { border-color: rgba(255, 92, 110, .5); background: rgba(255, 92, 110, .09); }
.ag-2fa-reloj.agotado b, .ag-2fa-reloj.agotado i, .ag-2fa-reloj.agotado span { color: var(--mal); }
/* La hora a la que se pidio el codigo: es lo unico que distingue un correo de
   otro cuando hay varios seguidos en la bandeja. */
.ag-2fa-emitido { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); line-height: 1.6; }

.ag-pausa__fila { display: grid; gap: 8px; grid-template-columns: minmax(160px, 1fr) auto; }
@media (max-width: 560px) {
    .ag-pausa__fila { grid-template-columns: 1fr; }
}
/* El campo del codigo va con la MISMA familia que los demas: una ranura clara
   y hundida. Una sola familia de controles para toda la aplicacion; dos
   familias es lo que hace que un campo parezca roto por ser distinto. */
.ag-pausa input {
    min-width: 0; font-family: var(--font-mono); font-size: 16px;
    letter-spacing: .5em; text-align: center;
    color: var(--campo-texto); background: var(--campo);
    caret-color: var(--campo-texto);
    border: 1px solid var(--campo-borde); border-radius: 8px;
    box-shadow: inset 0 2px 5px rgba(41, 14, 16, .30),
                inset 0 -1px 0 rgba(255, 255, 255, .55);
    padding: 10px 12px; outline: none;
}
.ag-pausa input::placeholder { color: var(--campo-marca); }
.ag-pausa input:focus { border-color: var(--aviso);
    box-shadow: inset 0 2px 5px rgba(41, 14, 16, .30),
                inset 0 -1px 0 rgba(255, 255, 255, .55),
                0 0 0 3px rgba(245, 166, 35, .30); }
.ag-pausa__nota { font-family: var(--font-mono); font-size: 10.5px; margin-top: 9px; color: var(--muted); line-height: 1.6; }
.ag-pausa__nota.bien { color: var(--bien); }
.ag-pausa__nota.malo { color: var(--mal); }
.ag-pausa--cerrando { border-color: rgba(255, 74, 94, .4); background: rgba(255, 74, 94, .07); }
.ag-pausa--cerrando .ag-pausa__t { color: var(--bone); }

/* =============================== El plan ===============================
   Lo que el cliente compro, y cuanto le queda. La cifra de la cuota se pinta
   grande porque es el unico dato de esta seccion que cambia solo y que puede
   impedir trabajar: si hay que verlo antes de rellenar el formulario, tiene
   que leerse sin buscarlo. */
.pl { display: grid; gap: 14px; }
.pl__cab { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.pl__n {
    font-family: var(--font-serif); font-size: clamp(20px, 2.6vw, 30px);
    font-weight: 500; color: var(--bone); line-height: 1;
}
.pl__d { font-size: 12.5px; color: var(--muted); line-height: 1.5; }

.pl__cuota {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    padding: 14px 16px; border-radius: 10px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .2);
}
.pl__cuota--agotada { border-color: rgba(255, 92, 110, .45); background: rgba(255, 92, 110, .08); }
.pl__cifra {
    font-family: var(--font-mono); font-size: clamp(24px, 3.4vw, 38px);
    font-weight: 700; color: var(--bone); line-height: 1;
    font-variant-numeric: tabular-nums; flex: 0 0 auto;
}
.pl__cifra em { font-style: normal; font-size: .5em; color: var(--muted); }
.pl__cuota--agotada .pl__cifra { color: var(--mal); }
.pl__txt { flex: 1 1 220px; min-width: 0; }
.pl__txt b {
    display: block; font-family: var(--font-mono); font-size: 10px;
    letter-spacing: .22em; text-transform: uppercase; color: var(--muted); font-weight: 400;
}
.pl__txt span { display: block; font-size: 12px; color: var(--bone-2); margin-top: 4px; line-height: 1.5; }
.pl__txt span strong { color: var(--bone); font-weight: 700; }
.pl__barra {
    margin-top: 9px; height: 5px; border-radius: 999px;
    background: rgba(var(--bone-rgb), .12); overflow: hidden;
}
.pl__barra i { display: block; height: 100%; background: var(--gold); border-radius: 999px; }
/* La parte de la barra que se esta pagando con creditos comprados va en otro
   color: con un solo color, "3 de 2" se lee como un error de la herramienta. */
.pl__barra em { display: block; height: 100%; background: var(--bien); border-radius: 999px; }

/* LOS CREDITOS COMPRADOS. Solo se pintan cuando hay alguno: una linea que
   dice "0 comprados" ocupa sitio para no decir nada. */
.pl__cred {
    display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
    border: 1px solid rgba(76, 175, 125, .35);
    background: rgba(76, 175, 125, .08);
    border-radius: 9px; padding: 10px 13px;
}
.pl__cred i { color: var(--bien); font-size: 13px; }
.pl__cred b {
    font-family: var(--font-mono); font-size: 13px; color: var(--bien);
}
.pl__cred span { flex: 1 1 200px; font-size: 11.5px; color: var(--bone-2); line-height: 1.5; }
.pl__pie { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.pl__cuota--agotada .pl__barra i { background: var(--mal); }

/* ========================= Progreso de la corrida ======================= */
.pg-obj {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--rule);
}
.pg-obj span {
    font-family: var(--font-mono); font-size: 9px; letter-spacing: 1.5px;
    color: var(--bone); border: 1px solid rgba(255, 74, 94, .4);
    border-radius: 999px; padding: 3px 9px; text-transform: uppercase;
}
.pg-obj code {
    font-family: var(--font-mono); font-size: 12px; font-weight: 700;
    color: var(--bone); word-break: break-all;
}
.pg-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.pg-chip {
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .4px;
    color: var(--muted); border: 1px solid var(--rule);
    border-radius: 999px; padding: 4px 11px;
}
.pg-chip b { color: var(--bone); margin-left: 3px; }
.pg-chip--aviso { border-color: rgba(245, 166, 35, .45); color: var(--aviso); }
.pg-chip--aviso b { color: var(--aviso); }
.pg-chip--vacia { border-color: rgba(255, 92, 110, .4); color: var(--mal); }
.pg-chip--vacia b { color: var(--mal); }
.pg-chip i { margin-right: 5px; opacity: .7; }
/* ===========================================================================
   BORRADOR v2 — El panel de contadores de EN CURSO.  RED SIGMA.

   ESTO NO ESTA EN EL PRODUCTO. Va pegado en `web/assets/css/app.css`, detras
   del bloque "Progreso de la corrida" (hoy alrededor de la linea 1750). No
   sustituye a `.pg-chip`: esa clase la usan otras cuatro pantallas -el plan,
   la cabecera de hallazgos, el resumen y el scan- y tocarla las moveria todas.

   ====================== POR QUE HAY UNA v2 ==============================
   La v1 eran tres cajas en tres columnas y SE MIDIO EN EL NAVEGADOR. No
   pasaba, y no por pocos pixeles: en los seis anchos probados ocupaba mas
   que el panel de hoy, hasta +118px a 560.

   Lo que ensena la medida no es "recorta un poco", es que los dos disenos
   estaban en REGIMENES DISTINTOS:

       ancho    hoy   v1
        420     201   268
        560     133   251
        700     133   142
        860      99   124
       1000      66   124
       1100      66   124

   El panel de hoy ocupa lo que le deja el ancho -de 201 a 66- porque es una
   fila de pastillas que envuelve. La v1 era PLANA en 124 de 700 a 1100: tres
   cajas con alto propio no se benefician del espacio horizontal. Por eso
   perdia por mas cuanto mas ancha era la pantalla, que es justo al reves de
   lo que uno espera.

   ESTA v2 VUELVE AL REGIMEN DE HOY: una sola caja cuyo contenido envuelve.
   Gana jerarquia -cifra grande arriba, etiqueta debajo, que es lo que pidio
   Oscar al senalar la tarjeta de criticidad- sin volver a apilar cajas.

   Y COMO LA JERARQUIA CUESTA ALTO POR DEFINICION -una cifra de 21px con su
   etiqueta ocupa mas que una pastilla de 10.5px, siempre-, el panel SE PUEDE
   PLEGAR. Nace abierto. El operador que quiera leer la bitacora lo cierra y
   recupera el panel entero en una linea. Hoy no puede: hoy le ocupa 99px
   siempre, quiera o no.
   =========================================================================== */

.pgx {
    position: relative;
    margin-top: 12px;
    padding: 9px 34px 9px 12px;   /* el hueco de la derecha es para el tirador */
    border: 1px solid var(--rule);
    border-radius: 10px;
    background: rgba(var(--hueco-rgb), .22);
}

/* LA FILA. Envuelve, como las pastillas de hoy: en pantalla ancha las tres
   zonas caben en una linea y en estrecho se reparten solas, sin un punto de
   corte propio que mantener. */
.pgx__fila {
    display: flex;
    align-items: center;
    gap: 10px 20px;
    flex-wrap: wrap;
}

/* El separador entre zonas. Una linea fina en vez de tres cajas: delimita
   igual y no anade ni padding ni borde ni fondo, que es de donde salia el
   alto de la v1. */
.pgx__sep {
    width: 1px;
    align-self: stretch;
    min-height: 30px;
    background: var(--rule);
}

.pgx__z { display: flex; align-items: center; gap: 16px; min-width: 0; }

.pgx__c { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.pgx__c b {
    font-family: var(--font-mono);
    font-size: 20px;
    font-weight: 700;
    line-height: 1.15;
    color: var(--bone);
    /* Tabular: sin esto, un contador que pasa de 519 a 520 cambia de ancho y
       empuja lo que tiene al lado. En un numero que se actualiza cada pocos
       segundos, ese temblor se nota mas que el propio dato. */
    font-variant-numeric: tabular-nums;
}
.pgx__c span {
    font-family: var(--font-mono);
    font-size: 8.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--tenue);
    white-space: nowrap;
}

/* La barra de la ventana de uso, debajo de su cifra y del ancho de la zona.
   Reutiliza el criterio de `.rs__barra`: el color lo pone el contenedor segun
   la banda, no la propia barra. */
.pgx__cuota { min-width: 76px; }
.pgx__barra {
    margin-top: 3px;
    height: 4px;
    border-radius: 3px;
    background: rgba(var(--hueco-rgb), .5);
    overflow: hidden;
    color: var(--bien);
}
.pgx__barra span { display: block; height: 100%; background: currentColor; }
.pgx[data-banda="media"] .pgx__barra { color: var(--aviso); }
.pgx[data-banda="alta"] .pgx__barra { color: var(--mal); }
.pgx[data-banda="media"] .pgx__cuota b { color: var(--aviso); }
.pgx[data-banda="alta"] .pgx__cuota b { color: var(--mal); }

/* LAS SIETE CARPETAS, EN TILES. Es la pieza que Oscar senalo de la tarjeta de
   criticidad: cifra grande arriba, etiqueta corta debajo.

   `flex` y no rejilla fija, al reves que en `.rs__rej--sev`: alli son cinco
   severidades que siempre son cinco, y aqui el numero de carpetas lo decide el
   servidor. Con una rejilla de siete columnas, una carpeta nueva rompe el
   reparto; envolviendo, se coloca sola. */
.pgx__tiles { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.pgx__tile {
    padding: 3px 7px;
    border-radius: 6px;
    background: rgba(var(--hueco-rgb), .3);
    text-align: center;
    min-width: 46px;
}
.pgx__tile b {
    display: block;
    font-family: var(--font-mono);
    font-size: 14px;
    font-weight: 700;
    line-height: 1.15;
    color: var(--bone);
    font-variant-numeric: tabular-nums;
}
.pgx__tile span {
    display: block;
    font-size: 8px;
    letter-spacing: .02em;
    color: var(--tenue);
    white-space: nowrap;
}

/* ===================== EL CERO, Y ESTE ES EL ARREGLO QUE MAS IMPORTA ========
   Hoy CUALQUIER carpeta con cero se pinta con el rojo de severidad -la clase
   `pg-chip--vacia`, `color: var(--mal)`-. En una herramienta de seguridad el
   rojo significa "mira esto", y gastarlo en "todavia no, y es normal a esta
   altura del trabajo" lo devalua para cuando de verdad haga falta: un
   entregable vacio a mitad de auditoria es lo esperado.

   PERO UN CERO NO SIEMPRE ES INOCENTE, y por eso no basta con apagarlo. El
   color depende del ESTADO DE LA CORRIDA y no solo del numero:

     corrida viva      + carpeta vacia -> apagado. Todavia no toca.
     corrida TERMINADA + carpeta vacia -> aviso.   Eso si hay que verlo.

   El estado ya viene en el mismo objeto de la respuesta, asi que distinguir
   los dos casos no cuesta ni una peticion mas. */
.pgx__tile--cero b { color: var(--tenue); }
.pgx__tile--cero span { opacity: .7; }
.pgx__tile--pendiente {
    background: rgba(245, 166, 35, .12);
    box-shadow: inset 0 0 0 1px rgba(245, 166, 35, .4);
}
.pgx__tile--pendiente b { color: var(--aviso); }
.pgx__tile--pendiente span { color: var(--aviso); opacity: .9; }

/* LAS HERRAMIENTAS, EN UNA LINEA DE TEXTO Y NO EN PASTILLAS. Seis pastillas
   identicas piden seis lecturas; una linea se lee de una pasada. Y van en
   ORDEN FIJO, no por uso: hoy se ordenan por cuantas veces se usaron y se
   cortan a las seis primeras, asi que mientras el operador mira, los chips se
   cambian de sitio entre si y uno puede desaparecer porque otro lo adelanto.
   La mitad de la sensacion de "amontonado" es que el contenido no se esta
   quieto. */
.pgx__herr {
    margin: 7px 0 0;
    font-family: var(--font-mono);
    font-size: 10px;
    line-height: 1.5;
    color: var(--muted);
}
.pgx__herr b { color: var(--bone-2); font-weight: 700; font-variant-numeric: tabular-nums; }
.pgx__herr em { font-style: normal; color: var(--tenue); margin: 0 4px; }

/* El aviso de freno. Ocupa su propia linea porque no es un contador: es lo
   unico que puede detener el trabajo. */
.pgx__freno {
    display: flex; align-items: center; gap: 8px;
    margin-top: 7px; padding: 6px 10px; border-radius: 7px;
    background: rgba(245, 166, 35, .12);
    border-left: 3px solid var(--aviso);
    font-size: 11.5px; color: var(--aviso);
}

/* ======================= EL TIRADOR Y EL PLEGADO ===========================
   VA POSICIONADO Y NO EN EL FLUJO, a proposito: un `summary` propio -como el
   del indice del manual- anade su propia linea al alto, y aqui el alto es
   justo lo que estamos peleando. Asi el control no cuesta ni un pixel de los
   que queremos ahorrar.

   NACE ABIERTO. Un panel que nace cerrado es un panel que la mitad de los
   operadores no sabe que tiene datos dentro. */
.pgx__tirador {
    position: absolute;
    top: 6px; right: 6px;
    width: 22px; height: 22px;
    display: grid; place-items: center;
    border: 0; border-radius: 6px;
    background: transparent;
    color: var(--tenue);
    cursor: pointer;
    line-height: 1;
}
.pgx__tirador:hover { background: var(--capa-hover, rgba(255,255,255,.05)); color: var(--bone); }
.pgx__tirador::after {
    content: '';
    width: 6px; height: 6px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: translateY(-2px) rotate(-135deg);
}
.pgx[data-plegado="si"] .pgx__tirador::after { transform: translateY(-2px) rotate(45deg); }

/* PLEGADO: el panel no desaparece, se reduce a UNA LINEA con lo mismo que
   decia, en texto. Esconder los contadores del todo obligaria a desplegar
   para saber si algo se movio, que es peor que tenerlos. */
.pgx[data-plegado="si"] .pgx__fila,
.pgx[data-plegado="si"] .pgx__herr { display: none; }
.pgx__minimo { display: none; }
.pgx[data-plegado="si"] .pgx__minimo {
    display: block;
    font-family: var(--font-mono);
    font-size: 10.5px;
    line-height: 1.5;
    color: var(--muted);
}
.pgx__minimo b { color: var(--bone-2); font-variant-numeric: tabular-nums; }
.pgx__minimo em { font-style: normal; color: var(--tenue); margin: 0 5px; }

/* ---------------------------------------------------------------- estrecho
   A 860 LAS CARPETAS DEJAN DE SER TILES Y PASAN A TEXTO. Es el mismo
   contenido en otra disposicion -la regla de la casa-, y es lo que arregla el
   peor caso medido: a 560 los tiles envolvian en dos filas y el panel se iba
   a 251px. En texto son dos renglones.

   Se pierde la estetica de tiles por debajo de 860, y se asume: esa estetica
   es para la pantalla en la que se vigila una corrida, que es ancha. Un tile
   de 46px repetido siete veces en un telefono no es jerarquia, es ruido. */
@media (max-width: 860px) {
    .pgx__sep { display: none; }
    .pgx__fila { gap: 8px 16px; }
    .pgx__tiles {
        display: block;
        font-family: var(--font-mono);
        font-size: 10px;
        line-height: 1.5;
        color: var(--muted);
    }
    .pgx__tile {
        display: inline;
        padding: 0;
        background: none;
        box-shadow: none;
        min-width: 0;
    }
    .pgx__tile::after { content: '·'; color: var(--tenue); margin: 0 4px; }
    .pgx__tile:last-child::after { content: ''; }
    .pgx__tile b, .pgx__tile span { display: inline; font-size: 10px; }
    .pgx__tile span { letter-spacing: 0; text-transform: none; }
    .pgx__tile b { margin-left: 3px; }
    /* El tile pendiente sigue avisando en texto: pierde el fondo, no el aviso. */
    .pgx__tile--pendiente b, .pgx__tile--pendiente span { color: var(--aviso); }
}

.pg-dice {
    margin-top: 12px; padding: 10px 12px; border-radius: 8px;
    background: rgba(255, 74, 94, .07); border-left: 2px solid var(--gold);
    font-size: 12.5px; line-height: 1.55; color: var(--bone-2);
}
.pg-dice i { color: var(--gold); margin-right: 7px; opacity: .6; font-size: 10px; }
.pg-lista { list-style: none; margin: 14px 0 0; padding: 0; max-height: 420px; overflow-y: auto; }
.pg-lista li {
    display: flex; gap: 10px; align-items: flex-start;
    padding: 7px 0; border-top: 1px solid var(--rule);
    font-size: 12px; line-height: 1.5;
}
.pg-lista li:first-child { border-top: 0; }
.pg-lista i { color: var(--gold); opacity: .75; font-size: 11px; margin-top: 3px; flex: 0 0 14px; }
.pg-lista b { color: var(--bone); font-weight: 500; }
.pg-lista code { font-family: var(--font-mono); font-size: 11px; color: var(--muted); word-break: break-all; }
.pg-lista .nota span { color: var(--bone-2); font-style: italic; }

/* ============================= Hallazgos ================================ */
.hz { display: grid; gap: 10px; }
.hz__cab { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 4px; }
.hz__f {
    border: 1px solid var(--rule); border-left-width: 3px; border-radius: 9px;
    background: rgba(var(--hueco-rgb), .2); padding: 12px 14px;
}
.hz__f[data-sev="Critica"] { border-left-color: var(--sev-critica); }
.hz__f[data-sev="Alta"] { border-left-color: var(--sev-alta); }
.hz__f[data-sev="Media"] { border-left-color: var(--sev-media); }
.hz__f[data-sev="Baja"] { border-left-color: var(--sev-baja); }
.hz__t { font-size: 14px; font-weight: 500; color: var(--bone); line-height: 1.35; }
.hz__m { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 8px; }
.hz__m span {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--muted);
    border: 1px solid var(--rule); border-radius: 999px; padding: 3px 9px;
}
.hz__m span.sev { color: var(--bone); border-color: currentColor; }
/* LA MARCA DE "SIN CONFIRMAR". Aqui habia un parrafo al final de la pestana
   que explicaba que existe; se quito, y la marca tiene que decirlo sola. Ambar
   con fondo y con icono, no solo un borde de otro color: lo que no puede pasar
   es que un hallazgo que el agente no reprodujo se lea como uno confirmado y
   acabe en un entregable. La explicacion larga vive en su `title`. */
.hz__m span.nc {
    color: var(--aviso); border-color: rgba(245, 166, 35, .55);
    background: rgba(245, 166, 35, .12); font-weight: 700; cursor: help;
}
.hz__m span.nc i { font-size: 9px; margin-right: 4px; }

/* LA MARCA DE REINCIDENCIA: el mismo CWE ya salio en otra auditoria de esta
   aplicacion. Hereda la pildora de .hz__m span y solo cambia el color, porque
   es un dato de CONTEXTO y no una alarma: compite por la atencion con la
   severidad y con "sin confirmar", que si lo son.
   La variante --baila SI sube a ambar, y es la que importa: el mismo defecto
   puntuado distinto en corridas distintas es lo que resta credibilidad al
   informe delante del cliente. */
.hz__m span.rei { cursor: help; }
.hz__m span.rei i { font-size: 9px; margin-right: 4px; }
.hz__m span.rei--baila {
    color: var(--aviso); border-color: rgba(245, 166, 35, .45);
}

/* El recuento en la cabecera de la carpeta: las carpetas nacen plegadas menos
   la ultima, asi que la marca de dentro no se ve hasta que alguien abre. */
.hzx__nc {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .08em;
    text-transform: uppercase; font-style: normal; cursor: help;
    padding: 3px 8px; border-radius: 999px;
    color: var(--aviso); border: 1px solid rgba(245, 166, 35, .55);
    background: rgba(245, 166, 35, .12);
}
.hzx__nc i { font-size: 9px; margin-right: 4px; }
.hz__d { font-size: 12.5px; line-height: 1.65; color: var(--muted); margin-top: 9px; }

/* El color de la severidad tambien en el contador, no solo en el filete de la
   tarjeta: la fila de contadores es lo primero que se mira de un expediente y
   "Critica 3" en el mismo gris que "Baja 3" no dice cual duele. */
/* LOS CHIPS DE SEVERIDAD VAN EN SOLIDO desde el 06/10/2026, a peticion de
   Oscar. Antes eran un contorno de color sobre el fondo del panel: a 10,5 px y
   con el borde de 1 px, las cinco severidades se distinguian por un matiz de
   rojo o verde que en una pantalla con brillo bajo no se separa. En solido, el
   ojo las ordena sin leerlas.

   EL TEXTO VA EN `--ink`, el fondo del panel, y no en blanco: sobre el ambar de
   `--sev-media` y el verde de `--sev-baja` un texto claro no tiene contraste
   suficiente, y esas dos son justo las mas numerosas.

   LA FORMA TAMBIEN CAMBIA: de pastilla redonda a esquina suave. Una pastilla
   dice "etiqueta"; un bloque dice "cantidad", que es lo que esto es. */
/* LA BASE LLEVA FONDO PROPIO, y no es decoracion: hay un SEXTO valor de
   `data-sev` que no estaba previsto. `servidor.py` devuelve "Sin severidad"
   cuando un hallazgo no declara ninguna de las cinco de la escala, y al quitar
   el borde de `.pg-chip` para pintar las otras en solido esa casilla se quedaba
   sin fondo Y sin borde: texto gris flotando junto a cinco bloques, con el
   separador de su `<b>` -casi negro- invisible sobre el panel. Antes al menos
   se leia como chip. Con fondo en la base, cualquier valor que llegue se ve. */
.hz-sev {
    border-radius: 6px; padding: 5px 10px; border: none;
    font-weight: 600; letter-spacing: .5px;
    background: var(--ink-3); color: var(--bone-2);
}
.hz-sev b {
    margin-left: 7px; padding-left: 7px;
    border-left: 1px solid rgba(var(--ink-rgb), .35);
    font-weight: 700;
}
/* El separador del `<b>` se aclara en la casilla de fondo oscuro, donde el
   negro translucido no se ve. */
.hz-sev:not([data-sev="Critica"]):not([data-sev="Alta"]):not([data-sev="Media"]):not([data-sev="Baja"]):not([data-sev="Informativo"]) b {
    border-left-color: var(--rule); color: var(--bone);
}
.hz-sev[data-sev="Critica"] { background: var(--sev-critica); color: var(--ink); }
.hz-sev[data-sev="Critica"] b { color: var(--ink); }
.hz-sev[data-sev="Alta"] { background: var(--sev-alta); color: var(--ink); }
.hz-sev[data-sev="Alta"] b { color: var(--ink); }
.hz-sev[data-sev="Media"] { background: var(--sev-media); color: var(--ink); }
.hz-sev[data-sev="Media"] b { color: var(--ink); }
.hz-sev[data-sev="Baja"] { background: var(--sev-baja); color: var(--ink); }
.hz-sev[data-sev="Baja"] b { color: var(--ink); }
.hz-sev[data-sev="Informativo"] { background: var(--sev-informativo); color: var(--ink); }
.hz-sev[data-sev="Informativo"] b { color: var(--ink); }

/* =================== LOS EXPEDIENTES, COMO CARPETAS =====================
   Esta pestana pintaba solo la corrida en curso, asi que de cero estaba en
   blanco. Ahora es el acumulado: una carpeta por corrida, la mas reciente
   abierta y las demas cerradas.

   POR QUE PLEGABLES Y NO UNA LISTA LARGA. Con quince corridas y sus hallazgos
   desplegados, esto es otra pared de texto, que es justo de lo que esta
   pantalla viene huyendo. Cerradas, cada carpeta cabe en una linea y dice lo
   que hace falta para decidir si se abre: cuando fue, como acabo y cuanto
   encontro.

   LA CABECERA ES UN <button> DE VERDAD con aria-expanded, no un div: asi se
   alcanza con el tabulador, se abre con Espacio y un lector de pantalla dice si
   esta abierta. El icono cambia de carpeta cerrada a abierta y el galon gira:
   dos senales, no una, igual que la fila activa de la barra.
   ======================================================================== */
/* MAS AIRE ENTRE TARJETAS. Oscar, 24/10/2026: a 8px, con el color de cada
   tarjeta tan cerca del de la pagina, una lista de varios escaneos se leia
   como un solo bloque continuo en vez de tarjetas separadas. */
.hzx { display: grid; gap: 14px; margin-top: 4px; }
.hzx__c {
    border: 1px solid rgba(var(--bone-rgb), .18); border-radius: 10px;
    background: rgba(var(--hueco-rgb), .16); overflow: hidden;
    /* La sombra separa la tarjeta del FONDO DE LA PAGINA -no de la de al
       lado, para eso ya esta el gap de arriba-: sin ella, el borde de 1px
       era la unica senal de "aqui empieza otra tarjeta" y se perdia en
       pantallas con el brillo bajo. */
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
/* Un expediente que no dejo hallazgos NO se esconde -eso seria mentir sobre lo
   que ha pasado- pero tampoco pesa igual: borde discontinuo y un punto menos de
   presencia. Se distingue del que si tiene sin tener que leerlo. */
.hzx__c--vacia { border-style: dashed; background: rgba(var(--hueco-rgb), .10); }
.hzx__fila { display: flex; align-items: stretch; gap: 0; flex-wrap: wrap; }
.hzx__cab {
    flex: 1 1 260px; min-width: 0; display: flex; align-items: center;
    gap: 10px; flex-wrap: wrap; text-align: left; cursor: pointer;
    padding: 11px 13px; border: 0; background: transparent;
    color: var(--bone); font-family: inherit;
    transition: background .15s var(--ease);
}
.hzx__cab:hover { background: rgba(255, 74, 94, .07); }
.hzx__cab:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.hzx__v {
    font-size: 10px; color: var(--gold); opacity: .8; flex: 0 0 10px;
    transition: transform .18s var(--ease);
}
.hzx__cab[aria-expanded="true"] .hzx__v { transform: rotate(90deg); }
.hzx__ico { font-size: 13px; color: var(--gold); flex: 0 0 15px; }
.hzx__n {
    font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .04em;
    color: var(--bone); font-weight: 500; min-width: 0;
}
.hzx__cab[aria-expanded="true"] .hzx__n { color: var(--bone); font-weight: 700; }
.hzx__m { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.hzx__e, .hzx__t {
    font-style: normal; font-family: var(--font-mono); font-size: 10px;
    letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
    padding: 2px 7px; border-radius: 999px; border: 1px solid var(--rule);
}
.hzx__t { color: var(--bone-2); }
.hzx__t--cero { color: var(--muted); border-style: dashed; }

/* EL ID, COPIABLE. Es lo que se pega en una incidencia y transcribirlo a ojo es
   como se pega el de la corrida de al lado. Va FUERA del boton de la carpeta: un
   boton dentro de otro no es HTML valido. */
.hzx__id {
    display: flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 11px 13px; border: 0; border-left: 1px solid var(--rule);
    background: rgba(var(--hueco-rgb), .18); color: var(--muted);
    transition: color .15s var(--ease), background .15s var(--ease);
}
.hzx__id:hover { color: var(--bone); background: rgba(255, 74, 94, .08); }
.hzx__id:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.hzx__id code { font-family: var(--font-mono); font-size: 10.5px; color: inherit; }

/* EL BOTON SIN EL ID A LA VISTA. El id sigue en `data-copiar` y en el `title`:
   lo que se quita es la cadena de 24 caracteres que nadie lee y que empujaba la
   fila. Se le deja ancho de objetivo tactil -el icono solo mide 13 px- porque
   un boton de 13x13 no se acierta en un telefono. */
.hzx__id--mudo { padding-left: 10px; padding-right: 10px; }
.hzx__id--mudo code { display: none; }
.hzx__id i { font-size: 11px; opacity: .75; }
.hzx__eco {
    font-style: normal; font-family: var(--font-mono); font-size: 9.5px;
    letter-spacing: .1em; text-transform: uppercase; max-width: 0;
    overflow: hidden; white-space: nowrap; transition: max-width .2s var(--ease);
}
.hzx__eco--on { max-width: 140px; }
.hzx__eco.bien { color: var(--bien); }
.hzx__eco.malo { color: var(--aviso); }

.hzx__cuerpo { padding: 2px 13px 13px; border-top: 1px solid var(--rule); }
.hzx__obj {
    margin: 11px 0 11px; font-family: var(--font-mono); font-size: 10.5px;
    color: var(--muted); word-break: break-all;
}
.hzx__obj i { color: var(--gold); opacity: .7; margin-right: 6px; }
.hzx__cuerpo .hz { margin-top: 11px; }
.hzx__cuerpo .caja__nota { margin-top: 11px; }

@media (max-width: 640px) {
    /* El id baja a su propia linea: en movil, cabecera e id en la misma fila
       dejan las dos ilegibles. */
    .hzx__id { flex: 1 1 100%; border-left: 0; border-top: 1px solid var(--rule); }
    .hzx__m { margin-left: 0; }

    /* PERO EL MUDO NO: esa regla existe para que quepan 24 caracteres de id, y
       el mudo no ensena ninguno. Una franja a todo lo ancho para un icono de
       copiar es un renglon regalado en la pantalla donde menos sobra. */
    .hzx__id--mudo { flex: 0 0 auto; border-left: 1px solid var(--rule); border-top: 0; }
}

/* ===================== EL AVISO DEL AISLAMIENTO =========================
   AQUI VIVIA UNA SECCION ENTERA, con dos botones -"Verificar el aislamiento" y
   "Verificar y dejarlo en el acta"- y un cartel verde de "Corrida limpia" que se
   ensenaba siempre. Se fue: un control interno que funciona no es noticia para
   quien lee la pantalla, y ocupaba sitio para decir que todo iba bien.

   La verificacion no se quito, la hace el servidor al terminar la corrida y
   escribe su veredicto en el acta. Lo que queda aqui es SOLO el caso malo, y por
   eso no hay variante limpia en esta hoja: si algo se ve, es que hay un
   problema. No se puede cerrar ni plegar, y es el unico elemento de la pantalla
   en rojo pleno: una corrida que nombro a otro cliente no se entrega. */
.aisl-aviso {
    margin-bottom: 18px; padding: 16px 18px; border-radius: 12px;
    border: 1px solid var(--mal); border-left: 4px solid var(--mal);
    background: rgba(255, 92, 110, .12);
    font-size: 13px; line-height: 1.6;
}
.aisl-aviso__t {
    display: flex; align-items: center; gap: 10px;
    font-family: var(--font-mono); font-size: 12px; letter-spacing: .1em;
    text-transform: uppercase; font-weight: 700; color: var(--mal);
}
.aisl-aviso__t i { font-size: 15px; }
.aisl-aviso__d { margin-top: 10px; color: var(--bone-2); font-size: 12.5px; line-height: 1.65; }
.aisl-aviso__d b { color: var(--bone); }
.aisl-aviso__d code {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone);
    word-break: break-all;
}
.aisl-aviso .pg-chips { margin-top: 12px; }
/* Cada linea dice en que archivo esta: es lo que permite ir a mirarlo. Se
   parten por donde haga falta porque son rutas y no se pueden cortar con
   elipsis sin perder justo el final, que es el nombre del archivo. */
.aisl-aviso__l {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone-2);
    padding: 6px 0; border-top: 1px solid rgba(255, 92, 110, .28);
    word-break: break-all; line-height: 1.6;
}

/* ========================== Scan Regular =============================== */
.console-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.console-row .url-wrap { flex: 1 1 260px; }
@media (max-width: 640px) {
    .console-row { flex-direction: column; align-items: stretch; }
    .console-row .btn { width: 100%; }
}

.opciones {
    display: grid; gap: 8px; margin-top: 16px;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
/* Scan Regular tiene TRES casillas desde que el escaneo de puertos salio del
   alcance. Con el auto-fit de arriba, tres caben en dos columnas a anchos
   medios y la tercera se queda sola con un hueco al lado: la rejilla parecia
   un cuarto recuadro que falta justo donde habia uno. Tres columnas iguales
   mientras quepan y una sola cuando no. El 2+1 no se da en ningun ancho. */
.opciones--tres { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 860px) {
    .opciones--tres { grid-template-columns: 1fr; }
}
/* .opt es la MISMA tecla que .ag-modo -el relieve, el hundido y el indicador
   estan arriba, en el bloque que comparten-; aqui solo va su reparto. Una sola
   familia de controles para toda la aplicacion: los de Scan Regular, el del
   autenticador y el de BOLA se ven y se comportan igual que los modos. */
.opt {
    display: grid; grid-template-columns: auto 1fr; gap: 10px;
    align-items: start; padding: 11px 13px;
}
.opt input { margin-top: 1px; }
.opt span {
    font-family: var(--font-mono); font-size: 11px; letter-spacing: .4px;
    color: var(--bone); text-transform: uppercase;
}
.opt--on > span, .opt:has(input:checked) > span { color: var(--bone); font-weight: 700; }
.opt em {
    display: block; font-style: normal; font-family: var(--font-sans);
    font-size: 11.5px; letter-spacing: 0; text-transform: none;
    color: var(--muted); line-height: 1.4; margin-top: 3px;
}
/* Una sola casilla a lo ancho, fuera de la rejilla de opciones. La usa la
   casilla del autenticador, que no es una opcion entre varias sino una
   afirmacion sobre la cuenta. */
.opt--linea { display: grid; grid-template-columns: auto 1fr; gap: 10px; }

/* ================== LAS TECLAS PEQUENAS, EN FILA =======================
   Las dos opciones del bloque de credenciales -el autenticador y BOLA- eran
   dos recuadros a lo ancho, uno debajo de otro, y cada uno con su parrafo de
   cuatro lineas debajo. Entre las dos ocupaban media pantalla para decir algo
   que casi siempre se deja como esta.

   Ahora son teclas PEQUENAS y van EN FILA, alineadas entre si: son dos opciones
   del mismo rango y ponerlas al mismo tamano y a la misma altura lo dice sin
   escribirlo. Sus campos no existen en pantalla hasta que se activan, y la
   explicacion larga aparece ahi, cuando ya significa algo. Lo que haria falta
   leer ANTES de activarla vive en su `title`, que no ocupa sitio.

   Siguen siendo la MISMA tecla que .ag-modo y que las de Scan Regular -el
   relieve, el hundido y el indicador salen del bloque que comparten- y por
   dentro siguen siendo <label> con <input type=checkbox>: lo unico que cambia
   es el reparto y el tamano.
   ======================================================================== */
.opt-fila { display: flex; flex-wrap: wrap; gap: 8px; align-items: stretch; }
.opt--chip {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 12px; flex: 0 1 auto; max-width: 100%;
}
.opt--chip > span {
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .06em;
    text-transform: uppercase; color: var(--bone-2); line-height: 1.35;
}
.opt--chip input { flex: 0 0 14px; width: 14px; height: 14px; margin-top: 0; }
/* El mismo caso que `.ag-modo--on .ag-modo__t`, y el mismo arreglo. */
.opt--chip--on > span, .opt--chip:has(input:checked) > span { color: var(--bone); }
@media (max-width: 640px) {
    /* A ancho de telefono, dos teclas en una fila dejan las dos cortadas a
       media palabra: cada una a su linea y a todo el ancho. */
    .opt--chip { flex: 1 1 100%; }
}

/* El veredicto. El color lo pone el propio veredicto en --vd, para que la
   pantalla y el informe no puedan discrepar sobre de que color es un objetivo. */
.vd {
    display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
    padding: 16px 18px; border-radius: 12px;
    border: 1px solid var(--vd, var(--gold));
    background: color-mix(in srgb, var(--vd, var(--gold)) 10%, transparent);
}
.vd__cifra {
    font-family: var(--font-mono); font-size: clamp(32px, 5vw, 52px);
    font-weight: 700; line-height: 1; color: var(--vd, var(--gold));
    font-variant-numeric: tabular-nums; flex: 0 0 auto;
}
.vd__cifra em { font-style: normal; font-size: .45em; opacity: .7; }
.vd__txt { flex: 1 1 260px; min-width: 0; }
.vd__txt b {
    display: block; font-family: var(--font-serif); font-size: clamp(17px, 2.2vw, 23px);
    font-weight: 500; color: var(--bone); line-height: 1.15;
}
.vd__txt i {
    display: block; font-style: normal; font-family: var(--font-mono);
    font-size: 10px; letter-spacing: .2em; text-transform: uppercase;
    color: var(--vd, var(--gold)); margin-top: 5px;
}
.vd__txt span { display: block; font-size: 12.5px; color: var(--muted); line-height: 1.6; margin-top: 8px; }

/* El boton de descargar el PDF de un Scan Regular -pedido el 20/10/2026-. */
.scan-descarga { margin-top: 16px; }

/* ============ Contexto de la aplicacion, en su sub-ventana =============
   AQUI VIVIA EL BLOQUE PLEGADO: un <details> al final de la vista de RTSS con
   el plan, el alcance, los expedientes y el alta, uno debajo de otro. Cuatro
   asuntos distintos en una pila, debajo de la herramienta, y buena parte de la
   pared de texto de la que se quejaba el operador.

   Ahora es un <dialog> -el mismo patron que la ventana de compra- con cuatro
   pestanas propias. Lo unico que hace falta vestir aqui es que sea mas ancha
   que la de compra, porque el panel del plan lleva una tabla, y que pueda
   desplazarse por dentro cuando no quepa: sin esto, la lista de expedientes de
   una aplicacion con muchas corridas empuja la ventana fuera de la pantalla y
   el boton de cerrar deja de alcanzarse. */
.dlg--ancha {
    width: min(880px, calc(100vw - 32px));
    max-height: calc(100vh - 48px);
    overflow-y: auto;
}
/* LA CABECERA SE QUEDA mientras el contenido se desplaza. Sin esto, en una
   pantalla baja el titulo y la X se iban por arriba al bajar por el panel del
   plan o por la lista de expedientes, y la unica salida que quedaba era Escape
   -que funciona, pero hay que saberlo-. El fondo es el del arranque del
   degradado de la ventana, que es justo donde se pega. */
.dlg--ancha .dlg__cab {
    position: sticky; top: 0; z-index: 2;
    margin: -6px 0 0; padding: 6px 0 10px;
    background: var(--ink-3);
}
/* Dentro de la ventana la lista respira mas que en la columna estrecha de
   antes, pero sigue con su scroll propio: una lista blanca larga no puede
   empujar lo que tiene debajo. */
.alc--dlg { max-height: min(46vh, 340px); }
/* Las pestanas de la sub-ventana van pegadas a su cabecera, no sueltas en medio
   de la pagina como las de la vista. */
.pest--dlg { margin-top: 16px; }

/* UN DATO QUE SE VE Y NO SE TOCA: el slug del proyecto en la pestana de ajustes.
   NO es un campo deshabilitado, y la diferencia importa. Un campo gris invita a
   intentar escribir en el y no dice por que no deja; esto tiene la forma de un
   dato -no de una ranura- y lleva el motivo escrito al lado. El operador lo
   necesita a la vista para pegarlo en una incidencia. */
.fijo {
    display: flex; flex-direction: column; gap: 7px;
    border: 1px solid var(--rule); border-radius: 10px;
    background: rgba(var(--hueco-rgb), .22); padding: 13px 15px;
}
.fijo__t {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .2em;
    text-transform: uppercase; color: var(--muted);
}
.fijo__t i { color: var(--gold); margin-right: 6px; }
.fijo > code {
    font-family: var(--font-mono); font-size: 13px; color: var(--bone);
    word-break: break-all;
}

/* ============ EL SELECTOR DE PROYECTO DE LOS AJUSTES ====================
   Este panel editaba SIEMPRE la aplicacion elegida en la barra: para arreglarle
   el nombre a otra habia que cambiarse a ella -lo que vacia la pantalla entera
   y tira la corrida que se estuviera siguiendo-, arreglarlo y volver.

   Y AQUI ESTA LA LINEA QUE NO SE PUEDE CRUZAR. Administrar un proyecto no es
   elegir el objetivo de una auditoria. Por eso este control NO se parece al
   selector de aplicacion ni a la fila de la barra: es un desplegable de los de
   formulario, con dos flechas para recorrer, y lleva su nota al lado diciendo
   que la aplicacion elegida para auditar no se toca. Si se pareciera al otro,
   alguien lo usaria para cambiar de objetivo.
   ======================================================================== */
.ajp {
    padding: 12px 13px; border-radius: 10px; margin-bottom: 14px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .18);
}
.ajp .field-label { margin-top: 0; }
.ajp__fila { display: flex; gap: 8px; align-items: center; }
.ajp__fila select { flex: 1 1 auto; min-width: 0; align-self: stretch; }
/* MAS CHICAS, para dejarle sitio al logotipo sin ensanchar la fila entera.
   Oscar, 24/10/2026: a 38px cuadradas competian con el logotipo por espacio;
   a 30px siguen siendo comodas para el dedo/el clic y caben junto a el. */
.ajp__flecha {
    flex: 0 0 30px; align-self: stretch; cursor: pointer; border-radius: 8px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .3);
    color: var(--bone-2); font-size: 11px;
    transition: border-color .15s var(--ease), color .15s var(--ease);
}
/* EL LOGOTIPO DEL PROYECTO EN EL DESPLEGABLE. `.mono--chico` ya resuelve el
   circulo/imagen/monograma -es la misma clase de la barra y las tarjetas-,
   asi que aqui solo hace falta que no se encoja en la fila flex. */
.ajp__logo { flex: 0 0 auto; }
.ajp__logo:empty { display: none; }
.ajp__flecha:hover { border-color: var(--gold); color: var(--bone); }
.ajp__flecha:disabled { opacity: .4; cursor: not-allowed; border-style: dashed; }
.ajp__verarch {
    display: flex; align-items: center; gap: 7px; margin-top: 10px;
    font-size: 12.5px; color: var(--muted); cursor: pointer;
}

/* DOS CAMPOS POR FILA EN VEZ DE UNO. La pestana "Generales" con un campo por
   fila medía el doble de alto de lo que la ventana -ya ancha, 880px por
   `.dlg--ancha`- de verdad necesitaba: sobraba la mitad derecha en blanco
   mientras la izquierda obligaba a bajar con scroll hasta Archivar o
   Eliminar. Cada columna es su propio <div> con su etiqueta, su campo y su
   nota -no basta con poner dos <input> seguidos sueltos-, porque sin ese
   contenedor el grid no sabe que la nota de la izquierda pertenece al campo
   de la izquierda. En pantallas angostas cae a una columna: dos campos
   apretados en menos de 640px son menos legibles que uno, no mas. */
.ed-grid2 {
    display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px;
    /* SEPARACION ENTRE FILAS. Sin esto, tres `.ed-grid2` seguidos quedaban a
       0px de distancia -el ultimo elemento de una fila no trae margen de
       abajo y la siguiente no traia margen de arriba-, y de lejos se leia
       como si una fila invadiera la de encima. Oscar, 24/10/2026. */
    margin-top: 18px;
}
.ed-grid2 .field-label { margin-top: 0; }
@media (max-width: 640px) {
    .ed-grid2 { grid-template-columns: 1fr; gap: 0; }
    .ed-grid2 > div:first-child { margin-bottom: 14px; }
}

/* ESTA VENTANA EN PARTICULAR SE LEE MAS PEQUENA DE LO QUE DEBERIA: el operador
   reporto tener que acercar el zoom del navegador para leerla. El tamano base
   de toda la pagina (12.5px en los campos, 10px en las etiquetas) se queda
   igual en el resto de la app -cambiarlo ahi es un rediseno aparte, no lo que
   se pidio-; aqui, en "Ajustes generales", se sube solo dentro de `#dlgApp`. */
#dlgApp input[type=text], #dlgApp input[type=password],
#dlgApp select, #dlgApp textarea { font-size: 14.5px; }
#dlgApp .field-label { font-size: 11.5px; }
#dlgApp .caja__nota { font-size: 13px; }

/* Cuando lo que se administra NO es la aplicacion elegida para auditar, la
   cabecera de la ventana cambia de color: es la unica pantalla que escribe en el
   perfil de un proyecto que no es el de la banda, y eso tiene que verse. */
.dlg__app--otra { border-color: rgba(245, 166, 35, .5); }
.dlg__app--otra > i { color: var(--aviso); }
.dlg__app--otra em { color: var(--aviso); }
/* Las notas solo crecen hacia abajo: a lo ancho empujarian la sub-ventana fuera
   de la pantalla y el boton de cerrar dejaria de alcanzarse. */
textarea { resize: vertical; min-height: 72px; }

/* ================================ Pie ================================== */
.foot {
    border-top: 1px solid var(--rule); margin-top: 48px;
    padding: 24px 0 8px;
    display: flex; justify-content: space-between; align-items: center;
    gap: 16px; flex-wrap: wrap;
    font-family: var(--font-mono); font-size: 9.5px;
    letter-spacing: .2em; text-transform: uppercase; color: var(--muted); opacity: .7;
}

/* ===================================================================
   DE QUIEN SON LOS PROYECTOS
   ===================================================================
   Un proyecto es de un USUARIO: quien contrata y quien paga. Con una
   sola cuenta basta una linea discreta encima de la lista; con dos o
   mas, un encabezado por grupo. Lo que no puede pasar es que con dos
   cuentas dadas de alta la pantalla no diga en cual estas, porque
   equivocarse de cuenta es trabajar sobre el cliente de otro.
   =================================================================== */

/* EL PIE DE CUENTA. Estaba arriba, dentro del bloque de aplicaciones, y ahi se
   leia como una fila mas de la lista: mismo tamano, mismo sitio y justo encima
   de las filas que si son pulsables. Al fondo de la barra es donde se le busca,
   y deja el bloque de aplicaciones para las aplicaciones.

   NO es un boton: no hay nada que elegir aqui. Con una sola cuenta elegir entre
   uno no es elegir, y con varias se cambia eligiendo el proyecto, que es lo que
   de verdad decide sobre que se trabaja. */
.lat-yo { display: flex; flex-direction: column; margin-bottom: 8px; min-width: 0; }
/* El pie es un DESPLEGABLE: de el cuelga lo que es del usuario -su plan, su
   cuota y dar de alta un proyecto suyo-, que antes eran dos botones sueltos
   ocupando dos filas que le hacian falta a la lista de aplicaciones. */
.lat-yo__b {
    display: flex; align-items: center; gap: 9px; width: 100%;
    padding: 9px 10px; cursor: pointer; text-align: left;
    border: 1px solid var(--rule); border-radius: 10px;
    background: rgba(var(--hueco-rgb), .25); min-width: 0;
    transition: border-color .2s var(--ease), background .2s var(--ease);
}
.lat-yo__b:hover { border-color: var(--gold); background: rgba(var(--hueco-rgb), .4); }
.lat-yo__flecha {
    margin-left: auto; flex: 0 0 auto; font-size: 10px; color: var(--muted);
    transition: transform .25s var(--ease);
}
/* La flecha apunta hacia donde se va a abrir, y el menu se abre HACIA ARRIBA
   porque esto vive al fondo de la barra. Cerrado apunta arriba; abierto gira. */
.lat-yo__b[aria-expanded="true"] { border-color: var(--gold); }
.lat-yo__b[aria-expanded="true"] .lat-yo__flecha { transform: rotate(180deg); }

.lat-menu {
    display: flex; flex-direction: column; gap: 3px;
    margin-bottom: 7px; padding: 7px;
    border: 1px solid rgba(255, 74, 94, .4); border-radius: 10px;
    background: var(--chrome-alto);
    box-shadow: 0 -10px 30px rgba(0, 0, 0, .5);
}
.lat-menu__t {
    font-family: var(--font-mono); font-size: 8.5px; letter-spacing: .2em;
    text-transform: uppercase; color: var(--muted); padding: 2px 6px 5px;
}
.lat-menu__b {
    display: flex; align-items: flex-start; gap: 9px; text-align: left;
    padding: 8px 9px; border-radius: 8px; cursor: pointer;
    border: 1px solid transparent; background: transparent;
    color: var(--bone);
}
.lat-menu__b:hover { background: var(--lat-activo); border-color: rgba(255, 74, 94, .4); }
.lat-menu__b > i { font-size: 12px; color: var(--gold); margin-top: 2px; flex: 0 0 14px; }
.lat-menu__b span {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
    text-transform: uppercase; line-height: 1.4; min-width: 0;
}
/* El avatar: las MISMAS iniciales que distinguen una aplicacion, aqui para la
   cuenta. Redondo y no cuadrado a proposito: el cuadrado es de las aplicaciones
   y confundir la cuenta con un proyecto es justo el error que esto evita. */
.lat-yo__av {
    display: grid; place-items: center; flex: 0 0 28px;
    width: 28px; height: 28px; border-radius: 50%;
    border: 1px solid var(--rule); background: rgba(var(--ink-3-rgb), .9);
    font-family: var(--font-mono); font-size: 10px; font-weight: 700;
    letter-spacing: .04em; color: var(--bone-2);
}
/* LA FOTO OCUPA EXACTAMENTE EL SITIO DEL MONOGRAMA: mismo diametro, mismo
   borde y mismo `flex`, porque los dos caen en la misma ranura y el pie no puede
   moverse segun si la cuenta tiene foto o no. `object-fit: cover` porque la
   subida no obliga a un cuadrado y una foto apaisada estirada a circulo deforma
   la cara. */
.lat-yo__foto {
    flex: 0 0 28px; width: 28px; height: 28px; border-radius: 50%;
    border: 1px solid var(--rule); object-fit: cover; display: block;
}
.lat-yo__txt { min-width: 0; display: flex; flex-direction: column; }
/* El nombre se CORTA con elipsis en vez de romper la barra: un correo largo
   ensanchaba el pie y descuadraba la columna entera. */
.lat-cuenta {
    font-family: var(--font-sans); font-size: 11.5px; font-weight: 600;
    color: var(--bone); line-height: 1.25;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lat-yo__txt em {
    font-style: normal; font-family: var(--font-mono); font-size: 8.5px;
    letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* El encabezado de cada grupo, cuando hay mas de una cuenta. Pegajoso:
   con varias cuentas y muchos proyectos, al bajar la lista hay que
   seguir viendo de quien es la fila que se esta mirando. */
.lat-grupo {
    position: sticky; top: 0; z-index: 1;
    display: flex; align-items: center; gap: 6px;
    margin-top: 6px; padding: 5px 6px 4px;
    background: var(--chrome-alto);
    border-bottom: 1px solid var(--rule);
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
}
.lat-grupo:first-child { margin-top: 0; }
.lat-grupo b {
    font-family: var(--font-sans); font-size: 11px; font-weight: 600;
    letter-spacing: 0; text-transform: none; color: var(--bone);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lat-grupo span { margin-left: auto; opacity: .85; }

/* En la banda, al lado del nombre del proyecto. Solo cuando hay mas de
   una cuenta: lo que siempre esta deja de leerse. */
.banda__cuenta {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 2px 8px; flex: 0 0 auto;
    border: 1px solid var(--rule); border-radius: 999px;
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .12em;
    text-transform: uppercase; color: var(--muted);
}
.banda__cuenta b {
    font-family: var(--font-sans); font-size: 11px; letter-spacing: 0;
    text-transform: none; color: var(--bone-2);
}

/* El encabezado de cada grupo de tarjetas del selector. */
.sel__grupo {
    grid-column: 1 / -1;
    display: flex; align-items: baseline; gap: 8px;
    margin: 6px 0 -2px;
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
}
.sel__grupo b {
    font-family: var(--font-serif); font-size: 14px; font-weight: 500;
    letter-spacing: 0; text-transform: none; color: var(--bone);
}

/* EL DESGLOSE DE LA CUOTA POR PROYECTO, en el panel del plan. Con
   varios proyectos, un total sin desglose no responde a la pregunta que
   se hace el operador cuando se le acaba el cupo: donde se fue. */
.pl__reparto { margin: 10px 0 0; }
.pl__reparto table { width: 100%; border-collapse: collapse; font-size: 11px; }
.pl__reparto th {
    text-align: left; padding: 0 0 4px;
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
    border-bottom: 1px solid var(--rule);
}
.pl__reparto td {
    padding: 4px 0; color: var(--bone-2);
    border-bottom: 1px solid rgba(var(--bone-rgb), .07);
}
/* NO SOLO EL ULTIMO: desde el 14/10/2026 hay DOS columnas de numero
   -escaneos y retesting-, no una, asi que las dos se alinean a la derecha y
   no solo la final. */
.pl__reparto th:not(:first-child), .pl__reparto td:not(:first-child) {
    text-align: right;
}
.pl__reparto tr.pl__reparto--esta td { color: var(--bone); font-weight: 600; }
/* LA BARRA DEL DESGLOSE. Pedida por Oscar el 14/10/2026: un numero suelto no
   dice de un vistazo quien se esta comiendo el cupo; la barra, escalada
   contra el proyecto que mas gasto EN ESA MISMA COLUMNA, si. El escaneo usa
   el mismo color que la barra principal del plan -var(--gold)-; el retesting
   lleva el verde de su paquete en "Comprar escaneos" -var(--bien)-, para que
   las dos lean como la misma medida que ya se vio ahi. */
.pl__reparto-fila { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.pl__reparto-barra {
    flex: 1 1 auto; max-width: 44px; height: 5px; border-radius: 999px;
    background: rgba(var(--bone-rgb), .12); overflow: hidden;
}
.pl__reparto-barra i { display: block; height: 100%; background: var(--gold); border-radius: 999px; }
.pl__reparto td:last-child .pl__reparto-barra i { background: var(--bien); }
.pl__reparto-fila b {
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    min-width: 12px; text-align: right;
}
.pl__reparto tr.pl__reparto--esta .pl__reparto-barra i { background: var(--bien); }

/* ===================================================================
   EL ALTA: EL PASO QUE FALTA DESPUES DE CREAR
   ===================================================================
   Crear un proyecto con una URL no autoriza esa URL. Este aviso es el
   paso siguiente y explicito: el host a la vista y un boton para
   anadirlo. Se parece a un aviso y no a una confirmacion de exito,
   porque lo que dice es que todavia falta algo.
   =================================================================== */

.alta-alcance {
    margin-top: 10px; padding: 10px 11px; border-radius: 8px;
    border: 1px solid rgba(245, 166, 35, .42);
    background: rgba(245, 166, 35, .08);
    font-size: 11px; line-height: 1.55; color: var(--bone-2);
}
.alta-alcance b { color: var(--bone); }
.alta-alcance code {
    font-family: var(--font-mono); font-size: 11px;
    padding: 1px 5px; border-radius: 4px;
    background: rgba(var(--ink-3-rgb), .55); color: var(--bone);
}
.alta-alcance .fila { margin-top: 9px; }
.alta-alcance--hecho {
    border-color: rgba(76, 175, 125, .42);
    background: rgba(76, 175, 125, .08);
}

/* Las sugerencias de nombre cuando lo que se escribio parece una URL.
   Son BOTONES: lo que se propone se acepta con un clic, porque un aviso
   que solo dice "eso esta mal" deja al operador escribiendolo otra vez
   a mano. */
.alta-sug {
    display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px;
}
.alta-sug button {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .06em;
    padding: 4px 9px; border-radius: 999px; cursor: pointer;
    border: 1px solid var(--rule); background: rgba(var(--ink-3-rgb), .5);
    color: var(--bone); transition: border-color .15s var(--ease);
}
.alta-sug button:hover { border-color: var(--gold); }

/* La miniatura de la imagen elegida, antes de subirla: lo que se ve es
   lo que se sube. */
.alta-img {
    display: flex; align-items: center; gap: 9px; margin-top: 7px;
}
.alta-img img {
    width: 40px; height: 40px; border-radius: 8px; object-fit: contain;
    border: 1px solid var(--rule); background: rgba(var(--ink-rgb), .6);
}
.alta-img span { font-size: 11px; color: var(--muted); }


/* ==========================================================================
   LA FILA DE PESTANAS CON EL BOTON DE LIMPIAR AL FINAL
   ==========================================================================

   El tablist se queda como estaba y la fila es lo que lo envuelve: el boton de
   borrar NO es una pestana y no puede estar dentro del role="tablist" -se
   recorreria con las flechas como si fuera un paso mas del trabajo-. El filete
   inferior se muda del tablist a la fila para que la linea siga siendo continua
   de un extremo al otro; el margen de abajo, igual, porque si se quedaran los
   dos la separacion se contaria dos veces. */
.pest-fila {
    display: flex; align-items: flex-end; gap: 10px;
    border-bottom: 1px solid var(--rule);
    margin-bottom: clamp(18px, 2.5vw, 26px);
}
.pest-fila .pest {
    flex: 1 1 auto; min-width: 0;
    border-bottom: 0; margin-bottom: 0;
}

/* LIMPIAR. Mismo tamano y misma tipografia que una pestana para que la fila no
   se descuadre, y distinto a la vista para que no se pulse por inercia: sin
   fondo, con el borde y la letra apagados, y solo al pasar por encima se tine
   de rojo. Un boton de borrar que se parece a la pestana de al lado es un boton
   de borrar que se pulsa queriendo entrar en Hallazgos. */
/* BOTON DE VERDAD, NO UN BORDE SUELTO. Mismo idioma que `.hz-inf__b` y
   `.rt__lanzar .btn`: bisel con degradado, sombra que lo levanta del fondo y
   hundimiento al pulsar. Diagnostico y Limpiar son acciones, no pestanas -por
   eso viven FUERA del tablist-, y tienen que sentirse como tal. */
.pest__fin {
    display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
    margin-bottom: 6px; padding: 9px 14px; cursor: pointer;
    border: 1px solid var(--rule); border-radius: 8px;
    background: linear-gradient(180deg, rgba(255, 255, 255, .05) 0%,
                                        rgba(0, 0, 0, .15) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07),
                0 1px 2px rgba(0, 0, 0, .25);
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
    transition: background .2s var(--ease), border-color .2s var(--ease),
                color .2s var(--ease), box-shadow .15s var(--ease),
                transform .08s var(--ease);
}
.pest__fin i { font-size: 12px; }
.pest__fin:hover:not(:disabled) {
    color: var(--bone); border-color: var(--mal);
    background: linear-gradient(180deg, rgba(255, 92, 110, .2) 0%,
                                        rgba(255, 92, 110, .1) 100%);
}
.pest__fin:active:not(:disabled) {
    transform: translateY(1px);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, .35);
}
.pest__fin:focus-visible { outline: 1px solid var(--gold); outline-offset: 2px; }
/* Sin aplicacion elegida esta apagado de verdad: ver el HTML. */
.pest__fin:disabled { opacity: .35; cursor: not-allowed; }

/* ==========================================================================
   LA VENTANA DE BORRADO
   ==========================================================================

   Tres puertas en orden -aviso y casilla, palabra, lista- y cada una abre la
   siguiente. Los dos pasos de abajo nacen con `hidden`, que es lo que gobierna
   lo que se ve en toda esta pantalla; aqui no se inventa otra forma de esconder
   cosas. */
.lmp__aviso {
    margin-top: 14px; padding: 13px 15px; border-radius: 10px;
    border: 1px solid rgba(255, 92, 110, .45);
    background: rgba(255, 92, 110, .10);
    font-size: 12.5px; line-height: 1.6; color: var(--bone);
}
.lmp__aviso p { margin: 0; }
.lmp__aviso p + p { margin-top: 8px; color: var(--muted); }

.lmp__casilla {
    display: flex; align-items: flex-start; gap: 10px;
    margin-top: 14px; padding: 11px 13px; border-radius: 9px;
    border: 1px solid var(--rule); background: rgba(var(--ink-3-rgb), .45);
    font-size: 12.5px; line-height: 1.5; color: var(--bone); cursor: pointer;
}
.lmp__casilla input { margin-top: 2px; flex: 0 0 auto; accent-color: var(--gold); }

.lmp__paso { margin-top: 16px; }
.lmp__et {
    display: block; font-size: 12.5px; line-height: 1.6; color: var(--muted);
}
.lmp__et b { color: var(--bone); }

/* LA PALABRA NO SE PUEDE SELECCIONAR. Es el unico sitio de la pantalla donde se
   impide, y tiene motivo: si se puede copiar y pegar, la puerta mide si sabes
   usar el porta papeles en vez de obligarte a leer de que aplicacion son los
   expedientes que vas a borrar, que es TODO lo que esta puerta existe para
   comprobar. No estorba a un lector de pantalla: `user-select` no toca el arbol
   de accesibilidad y la palabra se sigue anunciando. */
.lmp__palabra {
    -webkit-user-select: none; user-select: none;
    font-family: var(--font-mono); font-size: 12px; font-weight: 700;
    letter-spacing: .08em; color: var(--bone);
    padding: 2px 7px; border-radius: 6px;
    border: 1px solid rgba(255, 74, 94, .35);
    background: rgba(255, 74, 94, .10);
}
#lmpPalabra {
    width: 100%; margin-top: 9px; padding: 11px 13px;
    border-radius: 9px; border: 1px solid var(--campo-borde);
    background: var(--campo); color: var(--campo-texto);
    font-family: var(--font-mono); font-size: 13px; letter-spacing: .04em;
}
#lmpPalabra:focus-visible { outline: 1px solid var(--gold); outline-offset: 2px; }

.lmp__nota { margin: 8px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.lmp__nota.malo { color: var(--mal); }
.lmp__nota.bien { color: var(--bien); }

.lmp__barra {
    display: flex; flex-wrap: wrap; gap: 10px;
    align-items: center; justify-content: space-between;
}
.lmp__cuenta {
    font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em;
    color: var(--bone);
}
.lmp__acciones { display: flex; gap: 7px; flex-wrap: wrap; }
.lmp__acciones .ag-mini { padding: 6px 11px; font-size: 10px; }

.lmp__respaldo {
    margin: 10px 0 0; font-size: 11.5px; line-height: 1.55; color: var(--muted);
}
.lmp__respaldo code {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone-2);
}

/* La lista tiene tope de alto y se desplaza: con treinta expedientes, una
   ventana que crece hasta no caber deja el boton de borrar fuera de la pantalla
   y lo que se pulsaria a ciegas es justo el boton que no se puede pulsar a
   ciegas. */
.lmp__lista {
    margin-top: 12px; max-height: min(46vh, 420px); overflow-y: auto;
    display: flex; flex-direction: column; gap: 7px;
    padding-right: 4px;
}

.lmp__f {
    display: flex; align-items: flex-start; gap: 11px;
    padding: 11px 13px; border-radius: 9px;
    border: 1px solid var(--rule); background: rgba(var(--ink-3-rgb), .4);
}
.lmp__f input { margin-top: 3px; flex: 0 0 auto; accent-color: var(--gold); }
.lmp__f input:disabled { cursor: not-allowed; }

/* EL QUE CONTIENE TRABAJO NO SE VE IGUAL QUE UN INTENTO. Es la regla de esta
   ventana: en esta instalacion 31 de 32 expedientes eran intentos de 2 a 6
   archivos y uno tenia 233 archivos y 19 hallazgos. Una lista donde los 32 se
   ven iguales es una trampa, asi que este lleva filete lateral, fondo propio y
   una etiqueta que lo dice con palabras. */
.lmp__f--trabajo {
    border-color: rgba(245, 166, 35, .55);
    background: rgba(245, 166, 35, .09);
    box-shadow: inset 3px 0 0 var(--aviso);
}
/* Y el que no se puede borrar -corrida viva o en pausa- se ve apagado: la
   casilla esta deshabilitada y la fila tiene que decir por que sin que haya que
   intentarlo. */
.lmp__f--viva { opacity: .62; border-style: dashed; }

.lmp__d { min-width: 0; flex: 1 1 auto; }
.lmp__t {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
    font-size: 13px; color: var(--bone);
}
.lmp__t code {
    font-family: var(--font-mono); font-size: 10.5px; color: var(--muted);
}
.lmp__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.lmp__chip {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em;
    text-transform: uppercase; padding: 3px 8px; border-radius: 999px;
    border: 1px solid var(--rule); background: rgba(var(--ink-rgb), .5);
    color: var(--muted);
}
.lmp__chip b { color: var(--bone); margin-left: 5px; font-weight: 700; }
.lmp__chip--trabajo {
    border-color: rgba(245, 166, 35, .6); color: var(--aviso);
    background: rgba(245, 166, 35, .12);
}
.lmp__chip--cobrado {
    border-color: rgba(255, 92, 110, .5); color: var(--mal);
    background: rgba(255, 92, 110, .10);
}
.lmp__chip--bien {
    border-color: rgba(76, 175, 125, .5); color: var(--bien);
    background: rgba(76, 175, 125, .10);
}
.lmp__por {
    margin: 7px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--muted);
}
.lmp__por.malo { color: var(--mal); }

.lmp__pie {
    margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--rule);
    display: flex; flex-wrap: wrap; gap: 12px;
    align-items: center; justify-content: space-between;
}
.lmp__pie .lmp__nota { margin: 0; flex: 1 1 240px; }
.lmp__botones { display: flex; gap: 9px; flex-wrap: wrap; }

/* ===================== LA VENTANA DEL DIAGNOSTICO ========================

   LA JERARQUIA ES EL TRABAJO DE ESTE PANEL, igual que en Retesting. Lo que se
   puede aceptar lleva casilla y se lee como una decision; lo que NO tiene
   explicacion va en rojo y SIN casilla, porque no hay nada que decidir ahi: se
   queda. Si las dos cosas se parecieran, el panel se leeria como una lista de
   avisos que se pueden quitar, que es exactamente lo que no es.
   ======================================================================== */
.dg__cuantos { margin: 0 0 12px; font-size: 12.2px; color: var(--muted); }
.dg__cuantos b { color: var(--bone-2); font-family: var(--font-mono); }
.dg__cargando { margin: 10px 0; font-size: 12.5px; color: var(--muted); }
.dg__t {
    margin: 16px 0 8px; font-family: var(--font-mono); font-size: 10px;
    letter-spacing: .14em; text-transform: uppercase; color: var(--bone);
}
.dg__t em { font-style: normal; text-transform: none; letter-spacing: .02em;
    color: var(--muted); }
.dg__t--mal { color: var(--sev-alta); }

/* LA PROPUESTA ES UN <label> CON SU CASILLA DENTRO: se marca pulsando en
   cualquier parte del bloque y no solo en el cuadradito de 14px. */
.dg__p {
    display: flex; gap: 11px; align-items: flex-start; cursor: pointer;
    padding: 12px 13px; margin-bottom: 9px; border-radius: 10px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .2);
}
.dg__p:hover { background: var(--capa-hover-2); }
.dg__p input { margin-top: 3px; flex: 0 0 14px; width: 14px; height: 14px;
    accent-color: var(--gold); }
.dg__c { display: grid; gap: 6px; min-width: 0; }
.dg__c b { font-size: 13.5px; color: var(--bone); font-weight: 500; }
.dg__exp { font-style: normal; font-size: 12.2px; line-height: 1.6;
    color: var(--bone-2); max-width: 78ch; }
/* La causa de raiz y el efecto son NOTAS AL PIE de la propuesta, no segundos
   titulares: dicen lo que pasa despues y lo que se escribe, y si compitieran
   con la explicacion nadie leeria ninguna de las tres. */
.dg__raiz, .dg__efecto {
    font-style: normal; font-size: 11.4px; line-height: 1.55;
    color: var(--muted); max-width: 78ch;
}
.dg__raiz i, .dg__efecto i { color: var(--gold); opacity: .7; margin-right: 7px; }

/* SIN CASILLA Y EN ROJO. Esto no se puede aceptar: se queda. */
.dg__sin {
    margin: 0 0 8px; padding: 11px 13px; border-radius: 9px;
    border: 1px solid rgba(255, 92, 110, .35); border-left: 3px solid var(--sev-alta);
    background: rgba(255, 92, 110, .07);
    font-size: 12.2px; line-height: 1.6; color: var(--bone-2); max-width: 86ch;
}
.dg__sin b { display: block; font-family: var(--font-mono); font-size: 11.5px;
    color: var(--bone); margin-bottom: 4px; }
.dg__ley { display: block; margin-top: 6px; font-style: normal; font-size: 11.4px;
    color: var(--sev-alta); }

.dg__viva {
    margin: 0 0 8px; padding: 10px 13px; border-radius: 9px;
    border: 1px solid var(--rule); border-left: 3px solid var(--bien);
    background: rgba(var(--hueco-rgb), .18);
    font-size: 12.2px; line-height: 1.6; color: var(--muted);
}
.dg__viva b { font-family: var(--font-mono); font-size: 11.5px; color: var(--bone-2);
    margin-right: 9px; }

.dg__bien, .dg__ok {
    margin: 10px 0 0; padding: 12px 14px; border-radius: 9px;
    border: 1px solid rgba(76, 175, 125, .4); background: rgba(76, 175, 125, .08);
    font-size: 12.5px; line-height: 1.6; color: var(--bone-2); max-width: 86ch;
}
.dg__bien i, .dg__ok i { color: var(--bien); margin-right: 9px; }
.dg__ok { margin: 0 0 8px; }
.dg__mal {
    margin: 10px 0 0; padding: 12px 14px; border-radius: 9px;
    border: 1px solid rgba(255, 92, 110, .45); background: rgba(255, 92, 110, .08);
    font-size: 12.5px; line-height: 1.6; color: var(--bone-2); max-width: 86ch;
}
.dg__botones { display: flex; gap: 9px; flex-wrap: wrap; margin-top: 18px; }

/* El lanzador de retesting, que se mudo aqui desde la fila de pestanas. Separado
   de la lista por una regla: pedir uno nuevo y leer los que hay son dos cosas. */
.rt__lanzar {
    display: flex; margin-bottom: 14px; padding-bottom: 14px;
    border-bottom: 1px solid var(--rule);
}

/* BOTON DE VERDAD, NO UN RECTANGULO CON BORDE. Oscar, 10/10/2026: el mismo
   pedido que ya se le hizo a `.hz-inf__b` -bisel con degradado, sombra que lo
   levanta y hundimiento al pulsar-, aplicado aqui y no a `.btn` en general:
   ese se comparte con botones de otras pantallas -entrar, 2FA, diagnostico-
   que nadie pidio tocar. */
.rt__lanzar .btn {
    color: var(--bone-2);
    background: linear-gradient(180deg, rgba(255, 255, 255, .06) 0%,
                                        rgba(0, 0, 0, .18) 100%);
    border-color: var(--rule);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08),
                0 1px 2px rgba(0, 0, 0, .3);
    transition: color .15s var(--ease), background .15s var(--ease),
                border-color .15s var(--ease), box-shadow .15s var(--ease),
                transform .08s var(--ease);
}
.rt__lanzar .btn:hover:not(:disabled) {
    color: var(--bone); border-color: var(--gold);
    background: linear-gradient(180deg, rgba(255, 94, 108, .2) 0%,
                                        rgba(255, 74, 94, .1) 100%);
}
.rt__lanzar .btn:active:not(:disabled) {
    transform: translateY(1px);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, .4);
}

/* EL BOTON DE EJECUTAR NACE DESHABILITADO y solo se enciende con las tres
   condiciones cumplidas: casilla, palabra exacta y al menos un expediente
   marcado. Apagado se ve apagado -no hay hover ni cursor de mano-, porque un
   boton que parece pulsable y no lo es manda a buscar el fallo donde no esta. */
.lmp__ir {
    display: flex; align-items: center; gap: 8px;
    font-family: var(--font-mono); font-size: 11px; letter-spacing: .6px;
    padding: 10px 16px; border-radius: 7px; cursor: pointer;
    color: var(--bone); background: rgba(255, 92, 110, .18);
    border: 1px solid var(--mal);
    transition: background .2s var(--ease), border-color .2s var(--ease);
}
.lmp__ir:hover:not(:disabled) { background: rgba(255, 92, 110, .34); }
.lmp__ir:focus-visible { outline: 1px solid var(--gold); outline-offset: 2px; }
.lmp__ir:disabled {
    opacity: .4; cursor: not-allowed;
    background: transparent; border-color: var(--rule); color: var(--muted);
}

/* EL PANEL DE REINICIAR, en la caja de estado de la corrida. Reusa `ag-pausa`
   -que es la caja de la pausa y la del segundo factor- y solo le cambia el
   color del filete: es el mismo sitio de la pantalla y la misma forma, asi que
   no hace falta una caja nueva. */
.ag-pausa--falla { border-color: rgba(255, 92, 110, .5); }
.rei__datos { display: flex; flex-wrap: wrap; gap: 6px; margin: 9px 0 0; }


/* ==========================================================================
   BORRAR UN EXPEDIENTE DESDE SU PROPIA FILA
   ==========================================================================

   El caso de todos los dias no es "limpio la aplicacion entera", es "esta
   corrida murio sin arrancar, fuera". El boton va al final de la fila, pegado
   al del id, con la misma altura y el mismo filete lateral: es la tercera
   columna de la fila, no un adorno flotando encima.

   Y LA DIFERENCIA SE VE ANTES DE PULSARLO, que es lo que hace que un boton por
   fila no sea peligroso: borrar una corrida vacia y borrar una auditoria de 19
   hallazgos no pueden parecer la misma accion. El de un expediente con trabajo
   va en rojo, con escudo y con puntos suspensivos -"Borrar..."- porque NO
   borra: abre la ventana con la confirmacion completa. El de un intento vacio
   va apagado y dice "Borrar" a secas, porque eso es lo que hace. */
.hzx__borrar {
    display: flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 11px 13px; border: 0; border-left: 1px solid var(--rule);
    background: rgba(var(--hueco-rgb), .18); color: var(--muted);
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em;
    text-transform: uppercase;
    transition: color .15s var(--ease), background .15s var(--ease);
}
.hzx__borrar i { font-size: 11px; opacity: .8; }
.hzx__borrar:hover:not(:disabled) {
    color: var(--mal); background: rgba(255, 92, 110, .12);
}
.hzx__borrar:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.hzx__borrar:disabled { opacity: .45; cursor: default; }

/* EL QUE TIENE TRABAJO DENTRO NO SE PARECE AL OTRO. Rojo desde el principio,
   no solo al pasar por encima: lo que distingue tiene que verse barriendo la
   lista, no pasando el raton fila por fila. */
.hzx__borrar--trabajo {
    color: var(--mal); background: rgba(255, 92, 110, .10);
}
.hzx__borrar--trabajo:hover:not(:disabled) {
    background: rgba(255, 92, 110, .24); color: var(--bone);
}

/* UNA CORRIDA VIVA NO TIENE BOTON. En su sitio, un candado con el motivo en el
   `title`. No es lo mismo que un boton apagado: un boton apagado dice "ahora
   no", y esto dice "aqui no se borra, hay un agente escribiendo dentro". */
.hzx__viva {
    display: flex; align-items: center; justify-content: center;
    padding: 11px 15px; border-left: 1px solid var(--rule);
    background: rgba(var(--hueco-rgb), .18); color: var(--aviso); cursor: help;
}
.hzx__viva i { font-size: 11px; }

/* ==========================================================================
   EL TEXTO DE UN HALLAZGO, REPARTIDO
   ==========================================================================

   La descripcion de un hallazgo real trae entre 1.200 y 2.700 caracteres y de
   los 76 que hay en disco, 66 vienen en UN bloque sin ninguna linea en blanco.
   Se volcaba en un div a ancho completo del panel: un muro.

   NO SE RECORTA NADA. El md5 del cuerpo, los tamanos en bytes, la URL exacta
   con la que se reproduce y el analisis de por que importa en ESTE activo son
   justo lo que un pentester quiere leer. Lo que se arregla es la forma.

   AJUSTE DEL 07/10/2026, A PETICION DIRECTA DE OSCAR SOBRE CAPTURA: el ancho de
   74ch dejaba un hueco grande a la derecha del panel -marcado en rojo en
   `10-descripcion-hallazgo.png`- y el texto se veia pequeno. Se cambian DOS de
   las cuatro cosas de abajo y se dejan DOS:
     1. ANCHO DE LINEA: de 74ch a 90% DEL PANEL, que es la cifra que se pidio.
        Con el tamano de letra que sigue, una linea al 90% de un panel tipico de
        esta consola (~860px) ronda los 100-110 caracteres: mas larga de lo
        ideal para lectura corrida, pero es lo que se pidio y el salto de
        parrafo (ver mas abajo) sigue partiendo el texto en trozos cortos, que es
        lo que de verdad evita perder el renglon.
     1b. TAMANO DE LETRA: de 12.8px a 14.5px, tambien pedido en la captura.
     2. AIRE ENTRE PARRAFOS. Se mantiene -ahora 13px, un poco mas por la letra
        mayor- y sigue siendo lo que hace que se lean como parrafos.
     3. INTERLINEADO. Se mantiene en 1.7 y se sube el JUSTIFICADO pedido en la
        captura: `text-align: justify` mas `hyphens: auto` -con `lang="es-MX"`
        ya puesto en el `<html>`- para que el justificado no abra "rios" de
        espacio feos en una columna que ya no es estrecha pero tampoco es ancha
        de sobra.
     4. VINETAS. Se mantienen con su bolo rojo y su sangria, y su ancho sube
        igual a 90% para que no desentonen con el parrafo de al lado.

   EL SALTO DE PARRAFO POR TEMA YA EXISTIA Y NO SE TOCA: lo hace
   `bloquesDeTexto()` en app.js, partiendo por las lineas en blanco que el
   agente ya deja en `hallazgos.json` entre un asunto y el siguiente -ver la
   captura de referencia, que ya los ensena separados-. No hacia falta inventar
   donde cortar.

   CONTRASTE, RECALCULADO el 07/10/2026 sobre los tokens de esta hoja (formula
   de luminancia relativa WCAG, CALCULADO sobre los valores de :root y NO
   muestreado de un render en vivo -no habia navegador a mano-): --muted sobre
   el fondo compuesto de `.hz__f` (rgba(var(--hueco-rgb), .2) sobre el panel)
   da aprox. 9.9:1 en tema oscuro y aprox. 6.7:1 en tema claro. Las dos pasan
   AA (4.5:1) con margen; subir el tamano de fuente no cambia la razon de
   contraste -es independiente del tamano-, asi que el numero es el mismo antes
   y despues de este cambio. */
.hz__p {
    margin: 0; max-width: 90%;
    font-size: var(--lectura-tam, 14.5px); line-height: 1.7; color: var(--muted);
    text-align: justify; hyphens: auto;
}
.hz__p + .hz__p { margin-top: 13px; }
.hz__d {
    font-size: var(--lectura-tam, 14.5px); line-height: 1.7; color: var(--muted);
    margin-top: 13px; max-width: 90%; text-align: justify; hyphens: auto;
}

/* MODO LECTURA, ESTILO EPUB. Pedido el 18/10/2026: el texto largo de un
   veredicto -que se intento, que contesto, en que se diferencia- es el mas
   denso de toda la pantalla, y hasta hoy no se podia hacer nada con el salvo
   entrecerrar los ojos. Dos controles, los mismos que trae cualquier lector:
   tamano de letra y fondo de lectura. VIVEN EN `<html>`, no en cada tarjeta,
   porque es una preferencia de ESTA persona leyendo, no de este hallazgo: se
   pone una vez y sigue en el siguiente que se abra. */
html[data-lectura-tam="grande"] { --lectura-tam: 17px; }
html[data-lectura-tam="muy-grande"] { --lectura-tam: 20px; }
html[data-lectura-fondo="sepia"] { --lectura-fondo: #f4ecd8; --lectura-texto: #3a2f22; }
html[data-lectura-fondo="papel"] { --lectura-fondo: #fafafa; --lectura-texto: #1a1a1a; }
html[data-lectura-fondo] .hz__s {
    background: var(--lectura-fondo); color: var(--lectura-texto);
    padding: 13px 15px; border-radius: 9px; margin-top: 15px; padding-top: 12px;
    border-top: none;
}
html[data-lectura-fondo] .hz__s + .hz__s { margin-top: 10px; }
html[data-lectura-fondo] .hz__sr, html[data-lectura-fondo] .hz__p,
html[data-lectura-fondo] .hz__d { color: var(--lectura-texto); opacity: .85; }
html[data-lectura-fondo] .hz__sr { opacity: 1; }

.lect__ctrl {
    display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
    padding-bottom: 10px; border-bottom: 1px dashed var(--rule);
}
.lect__ctrl span {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--muted); margin-right: 2px;
}
.lect__b {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em;
    padding: 4px 10px; border-radius: 999px; border: 1px solid var(--rule);
    background: rgba(var(--hueco-rgb), .2); color: var(--bone); cursor: pointer;
    display: flex; align-items: center; gap: 5px;
}
.lect__b:hover { border-color: var(--gold); }
.lect__b i { font-size: 10px; }

/* EL ROTULO QUE EL AGENTE PUSO EN MAYUSCULAS -"ESTADO:"- abre parrafo y se ve.
   Lo escribio el para senalar un cambio de asunto, asi que aqui se respeta. */
.hz__rot {
    color: var(--bone); font-weight: 700; letter-spacing: .04em;
    margin-right: 5px;
}

/* LO QUE EL AGENTE ESCRIBE COMO CODIGO. Monoespaciada y partible: un nombre de
   endpoint largo en texto normal desborda la caja a la derecha. NO es un
   enlace, ni cuando es una URL: un clic desde aqui saldria contra el objetivo
   de un cliente sin que nadie lo haya autorizado. */
.hz__cod {
    font-family: var(--font-mono); font-size: 11.5px;
    color: var(--bone-2); background: rgba(var(--hueco-rgb), .3);
    border-radius: 4px; padding: 1px 5px;
    overflow-wrap: break-word; word-break: break-word;
}

.hz__ul {
    /* Mismo 90% que .hz__p del 07/10/2026: para que una vineta y el parrafo de
       al lado no corten en sitios distintos. */
    list-style: none; margin: 11px 0 0; padding: 0;
    max-width: 90%; display: grid; gap: 8px;
}
.hz__ul li {
    position: relative; padding-left: 17px;
    font-size: 12.8px; line-height: 1.65; color: var(--muted);
}
.hz__ul li::before {
    content: "\2022"; position: absolute; left: 3px; top: -1px;
    color: var(--gold); font-size: 14px;
}

/* ===== EL ACCESO REQUERIDO, CON SITIO PROPIO Y ARRIBA =====================
   Es lo que separa un hallazgo grave de uno teorico: el mismo defecto con
   "cualquiera, el registro es publico" delante y con "el administrador de la
   organizacion" delante no son el mismo hallazgo. El encargo lo declara
   obligatorio con el argumento de que el privilegio requerido SE MIDE, NO SE
   SUPONE, y enterrado en medio de 1.900 caracteres nadie lo mide: lo supone.

   Caja con filete propio y rotulo en linea. NO lleva titulillo de seccion:
   los titulillos son los del PDF y este campo no es una de sus secciones. */
.hz__acc {
    margin-top: 11px; padding: 10px 12px; border-radius: 8px;
    border: 1px solid var(--rule); border-left: 2px solid var(--gold-soft);
    background: rgba(var(--hueco-rgb), .18);
}
.hz__acc-r {
    display: inline-block; margin-bottom: 6px;
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--bone); font-weight: 700;
}
.hz__acc-c .hz__p { font-size: 12.4px; color: var(--bone-2); }

/* ===== LAS SECCIONES SON LAS DEL INFORME COMPLETO Y EN SU ORDEN ===========
   analisis de riesgo, evidencia, impacto y recomendacion, con los mismos
   titulillos en mayusculas pequenas que el PDF: asi la misma auditoria se lee
   igual en la pantalla y en el documento. */
.hz__s { margin-top: 15px; padding-top: 12px; border-top: 1px solid var(--rule); }
.hz__sr {
    margin: 0 0 8px; display: flex; align-items: center; gap: 9px;
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .16em;
    text-transform: uppercase; color: var(--bone-2); font-weight: 700;
}
.hz__sr em {
    font-style: normal; letter-spacing: .04em; text-transform: none;
    color: var(--muted); font-weight: 400;
}

/* LA EVIDENCIA, COMO UNA VENTANA DE CONSOLA. Es el mismo recuadro que dibuja
   `bloque_evidencia()` en el PDF, con sus tres bolitas: lo que se vio tiene
   que parecer lo que se vio. Solo sale en los hallazgos CONFIRMADOS, igual que
   alli, y por lo mismo. */
.hz__ev {
    border-radius: 8px; overflow: hidden;
    border: 1px solid rgba(var(--bone-rgb), .2); background: rgba(var(--hueco-rgb), .42);
}
.hz__ev-b {
    display: flex; align-items: center; gap: 6px;
    padding: 7px 11px; border-bottom: 1px solid rgba(var(--bone-rgb), .14);
    background: rgba(var(--hueco-rgb), .3);
}
.hz__ev-b span { width: 7px; height: 7px; border-radius: 50%; }
.hz__ev-b span:nth-child(1) { background: var(--sev-alta); }
.hz__ev-b span:nth-child(2) { background: var(--sev-media); }
.hz__ev-b span:nth-child(3) { background: var(--sev-baja); }
.hz__ev-b em {
    font-style: normal; margin-left: 6px;
    font-family: var(--font-mono); font-size: 10px; color: var(--muted);
}
/* pre-wrap y no overflow: una linea larga se parte en vez de abrir una barra
   horizontal. Lo que se copia sale con los mismos saltos que escribio el
   agente. */
.hz__ev-l {
    margin: 0; padding: 11px 13px;
    font-family: var(--font-mono); font-size: 11.5px; line-height: 1.6;
    color: var(--bone-2); white-space: pre-wrap; overflow-wrap: break-word;
    word-break: break-word;
}
.hz__ev-g { margin-top: 9px; font-size: 12px; font-style: italic; }

/* LA LINEA DEL PDF, UNA POR CARPETA Y NO UNA POR HALLAZGO. Dice que el informe
   no va a salir con IMPACTO y RECOMENDACION en blanco: el generador los pone
   por la categoria. Repetida en diez tarjetas seria el ruido que esta pestana
   viene a quitar. */
.hzx__pdf {
    margin: 13px 0 0; padding: 9px 12px; border-radius: 8px;
    border: 1px dashed var(--rule); background: rgba(var(--hueco-rgb), .14);
    font-size: 11.8px; line-height: 1.55; color: var(--muted);
}
.hzx__pdf i { color: var(--gold); opacity: .65; margin-right: 8px; }
.hzx__pdf b { color: var(--bone-2); }

/* EL AVISO DE UNA FILA. Sustituye al window.alert del boton de borrar: un
   cuadro del navegador tapa justo la fila de la que habla, y por ahi salia un
   TypeError crudo a la cara del operador. Es role="status", asi que un lector
   de pantalla lo lee sin que nadie tenga que cerrar nada. */
.hzx__aviso {
    margin: 0; padding: 9px 13px; border-top: 1px solid var(--rule);
    background: rgba(var(--hueco-rgb), .22);
    font-size: 11.8px; line-height: 1.55; color: var(--bone-2);
}
.hzx__aviso.malo { color: var(--mal); background: rgba(255, 92, 110, .1); }
.hzx__aviso.bien { color: var(--bien); }

/* ===== LOS DOS BOTONES DEL INFORME =======================================
   Dos y no uno con desplegable: el ejecutivo RESERVA el detalle de los
   criticos y los altos y el completo lo entrega entero. Un solo boton invita a
   mandar el que no era, y despues del envio ya no se puede distinguir. */
/* UNA BANDEJA PEGADA A LA TARJETA, NO UNA PASTILLA FLOTANDO DENTRO DE ELLA.
   Oscar, 24/10/2026, backtesting: con su propio borde completo y redondeado
   Y un margen de 13px antes del fondo de la tarjeta, esta fila se leia como
   una caja metida dentro de otra caja -ni pegada a la cabecera de arriba ni
   pegada al borde de la tarjeta-, y esa tierra de nadie es justo lo que hacia
   dificil saber donde terminaba un escaneo y empezaba el siguiente. Ahora es
   plana y a lo ancho, como una bandeja de acciones colgada de la cabecera:
   solo lleva un filete ARRIBA -la frontera real, entre lo que informa
   (cabecera) y lo que ejecuta (estos botones)- y ni margen ni radio propio,
   asi que el `overflow: hidden` y el radio de `.hzx__c` la redondean solos
   cuando le toca ser el ultimo tramo visible de la tarjeta. */
.hz-inf {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    margin: 0; padding: 11px 13px;
    border-top: 1px solid rgba(var(--bone-rgb), .14);
    background: rgba(var(--hueco-rgb), .3);
}
.hz-inf__r {
    display: flex; align-items: center; gap: 7px;
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted);
}
.hz-inf__r i { color: var(--gold); opacity: .75; font-size: 11px; }
/* BOTON DE VERDAD, NO UN RECTANGULO CON BORDE. Oscar, 10/10/2026: tiene que
   leerse como un boton de aplicacion de escritorio, no como una etiqueta
   superficial. Mismo idioma que ya usa `.selt` -la tarjeta de aplicacion del
   alta-: un degradado sutil de luz arriba a sombra abajo da el bisel, un
   `inset` claro en el canto superior mas una sombra exterior lo levanta del
   fondo, y al pulsarlo SE HUNDE -1px de traslado y la sombra pasa a ser
   interior- que es la fisica que le falta a un boton plano. Esta es la
   plantilla a copiar la proxima vez que haga falta un boton nuevo: no un
   borde suelto con color al pasar el raton. */
.hz-inf__b {
    display: flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 7px 12px; border-radius: 7px;
    border: 1px solid var(--rule); color: var(--bone-2);
    background: linear-gradient(180deg, rgba(255, 255, 255, .06) 0%,
                                        rgba(0, 0, 0, .18) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08),
                0 1px 2px rgba(0, 0, 0, .3);
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
    text-transform: uppercase;
    transition: color .15s var(--ease), background .15s var(--ease),
                border-color .15s var(--ease), box-shadow .15s var(--ease),
                transform .08s var(--ease);
}
.hz-inf__b i { font-size: 11px; opacity: .8; }
.hz-inf__b:hover:not(:disabled) {
    color: var(--bone); border-color: var(--gold);
    background: linear-gradient(180deg, rgba(255, 94, 108, .2) 0%,
                                        rgba(255, 74, 94, .1) 100%);
}
.hz-inf__b:active:not(:disabled) {
    transform: translateY(1px);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, .4);
}
.hz-inf__b:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* APAGADO DE VERDAD, no gris decorativo: una corrida viva da un PDF a medias
   que PARECE entero, y sin hallazgos no hay informe. El motivo va en el
   `title` y en la nota de al lado. */
.hz-inf__b:disabled { opacity: .4; cursor: not-allowed; }
/* QUE SE VEA QUE TRABAJA: tarda, y sin senal el operador vuelve a pulsar. Los
   dos botones se apagan mientras uno va. */
.hz-inf__b--va { color: var(--bone); border-color: var(--gold); }
.hz-inf__b--va i { animation: giro 1s linear infinite; }

/* Y QUE SE VEA QUE BAJA. La segunda espera es otra: el PDF ya esta hecho y
   lo que falta es que llegue al equipo del operador. Flecha que cae en vez
   de rueda que gira, porque son dos cosas distintas y el rotulo del boton
   tambien cambia ("Generando" -> "Descargando"). */
.hz-inf__b--baja { color: var(--bone); border-color: var(--gold); }
.hz-inf__b--baja i { animation: cae .9s var(--ease) infinite; }

/* CIFRAR / DESCIFRAR. Mismo boton de verdad que los de informe -mismo
   bisel, mismo hundimiento al pulsar-, pero en el tono neutro de un candado
   y no en el rojo de una descarga: no hacen lo mismo y no deberian leerse
   igual. Sin funcionalidad todavia -pendiente 13 de PENDIENTES.md-, asi que
   el hover no promete mas de lo que el boton hace hoy. */
.hz-inf__b--cifrar:hover:not(:disabled) {
    color: var(--bone); border-color: var(--muted);
    background: linear-gradient(180deg, rgba(255, 255, 255, .09) 0%,
                                        rgba(0, 0, 0, .18) 100%);
}

@keyframes cae {
    0%   { transform: translateY(-3px); opacity: .35; }
    55%  { transform: translateY(3px);  opacity: 1; }
    100% { transform: translateY(-3px); opacity: .35; }
}
.hz-inf__n {
    font-style: normal; flex: 1 1 220px; min-width: 0;
    font-size: 11.5px; line-height: 1.5; color: var(--muted);
}
.hz-inf__n.malo { color: var(--mal); }
.hz-inf__n.bien { color: var(--bien); }

@keyframes giro { to { transform: rotate(360deg); } }

@media (max-width: 640px) {
    .hz-inf__n { flex: 1 1 100%; }
    /* En movil el 90% sigue dejando un margen que no hace falta: la caja ya es
       estrecha de por si. */
    .hz__p, .hz__ul, .hz__d { max-width: 100%; }
}

/* ==========================================================================
   RETESTING
   ==========================================================================

   LA JERARQUIA VISUAL ES EL TRABAJO DE ESTE PANEL. Un retesting existe para
   responder "de lo que me encontraste, que sigue vivo?", asi que lo que sigue
   vivo SALTA A LA VISTA y lo remediado va discreto. Un retesting donde todo
   pesa igual no responde la pregunta que lo motivo.

   Las carpetas reutilizan el galon y el icono de las de Hallazgos -.hzx__v,
   .hzx__ico, .hzx__n, .hzx__m, .hzx__id- para que se reconozcan como lo mismo.
   ========================================================================== */
.rtx { display: grid; gap: 8px; margin-top: 4px; }
.rtx__c {
    border: 1px solid var(--rule); border-radius: 10px;
    background: rgba(var(--hueco-rgb), .16); overflow: hidden;
}
/* CON ALGO VIVO DENTRO, LA CARPETA LO DICE CERRADA. Es lo que hay que ver
   barriendo la lista, sin abrir nada. */
.rtx__c--vivo { border-left: 3px solid var(--mal); }
.rtx__fila { display: flex; align-items: stretch; flex-wrap: wrap; }
.rtx__cab {
    flex: 1 1 260px; min-width: 0; display: flex; align-items: center;
    gap: 10px; flex-wrap: wrap; text-align: left; cursor: pointer;
    padding: 11px 13px; border: 0; background: transparent;
    color: var(--bone); font-family: inherit;
    transition: background .15s var(--ease);
}
.rtx__cab:hover { background: rgba(255, 74, 94, .07); }
.rtx__cab:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.rtx__cab[aria-expanded="true"] .hzx__v { transform: rotate(90deg); }
.rtx__cab[aria-expanded="true"] .hzx__n { color: var(--bone); font-weight: 700; }
.rtx__cuerpo { padding: 2px 13px 14px; border-top: 1px solid var(--rule); }

/* EL ANILLO DE RESUMEN. Mismos cuatro colores que los chips de abajo -rojo
   vivo, ambar bajo de nivel, verde remediado, apagado sin veredicto/no
   comprobable-, para que de un vistazo se vea como va el retesting sin
   sumar los numeros de la fila. El numero del centro es SOLO remediados
   sobre el total: es el que responde "cuanto se arreglo", que es la
   pregunta mas corta que se le puede hacer a esta pantalla. */
.rtx__anillo {
    position: relative; flex: 0 0 auto;
    width: 40px; height: 40px;
    display: inline-flex; align-items: center; justify-content: center;
}
.rtx__anillo svg { width: 100%; height: 100%; }
.rtx__anillo svg circle { transition: stroke-dasharray .25s var(--ease); }
.rtx__anillo-n {
    position: absolute; font-family: var(--font-mono); font-weight: 700;
    font-size: 10.5px; color: var(--bone); letter-spacing: 0;
}
.rtx__anillo-n em {
    font-style: normal; font-weight: 400; font-size: 8.5px; color: var(--muted);
}
@media (max-width: 640px) { .rtx__anillo { width: 34px; height: 34px; } }
/* LA VERSION GRANDE, PARA EL RESUMEN EJECUTIVO. Mismo componente, mismo
   lenguaje de color, solo mas grande porque ahi es el resumen de TODA la
   aplicacion, no de una fila entre otras. */
.rtx__anillo--grande { width: 76px; height: 76px; }
.rtx__anillo--grande .rtx__anillo-n { font-size: 19px; }
.rtx__anillo--grande .rtx__anillo-n em { font-size: 13px; }

/* LOS TRES RECUENTOS DE LA CABECERA. "Vivos" lleva fondo y peso; "remediados"
   es un borde apagado. La diferencia se ve sin leer los numeros. */
.rtx__p {
    font-style: normal; font-family: var(--font-mono); font-size: 10px;
    letter-spacing: .08em; text-transform: uppercase;
    padding: 3px 9px; border-radius: 999px; border: 1px solid var(--rule);
    color: var(--muted);
}
.rtx__p--vivo {
    color: var(--mal); border-color: rgba(255, 92, 110, .55);
    background: rgba(255, 92, 110, .14); font-weight: 700;
}
.rtx__p--bajo {
    color: var(--aviso); border-color: rgba(245, 166, 35, .5);
    background: rgba(245, 166, 35, .1);
}
.rtx__p--ok { color: var(--bien); border-color: rgba(76, 175, 125, .4); }

/* EL AMARRE AL ESCANEO DE ORIGEN, CON LAS DOS FECHAS. Sin el par no se puede
   escribir "esto estaba mal el dia 3 y el dia 5 ya no", que es la unica frase
   que un retesting existe para poder decir. */
.rtx__orig {
    margin: 12px 0 0; padding: 9px 12px; border-radius: 8px;
    background: rgba(var(--hueco-rgb), .22); border: 1px dashed var(--rule);
    font-size: 11.8px; line-height: 1.6; color: var(--muted);
}
.rtx__orig i { color: var(--gold); opacity: .7; margin-right: 8px; }
.rtx__orig code {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone-2);
    word-break: break-all;
}
.rtx__orig em { font-style: normal; color: var(--bone-2); }

/* LOS TRES BLOQUES. El de vivos con filete rojo y fondo, el de bajados ambar y
   el de remediados sin fondo y mas chico: la jerarquia es la respuesta. */
.rtb { margin-top: 15px; padding: 12px 14px; border-radius: 9px; }
.rtb--vivo {
    border: 1px solid rgba(255, 92, 110, .45); border-left: 3px solid var(--mal);
    background: rgba(255, 92, 110, .07);
}
.rtb--bajo {
    border: 1px solid rgba(245, 166, 35, .38); border-left: 3px solid var(--aviso);
    background: rgba(245, 166, 35, .05);
}
.rtb--ok { border: 1px dashed var(--rule); background: rgba(var(--hueco-rgb), .12); }
.rtb__t {
    margin: 0; display: flex; align-items: center; gap: 10px;
    font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em;
    text-transform: uppercase; color: var(--bone);
}
.rtb__t em {
    font-style: normal; padding: 2px 8px; border-radius: 999px;
    border: 1px solid currentColor; font-size: 10px;
}
.rtb--vivo .rtb__t { color: var(--mal); font-weight: 700; font-size: 12px; }
.rtb--bajo .rtb__t { color: var(--aviso); }
.rtb--ok .rtb__t { color: var(--muted); font-size: 10px; }
.rtb__d {
    margin: 8px 0 0; max-width: 74ch;
    font-size: 11.8px; line-height: 1.6; color: var(--muted);
}
.rtb__f { margin-top: 12px; }

/* DE QUE SEVERIDAD A QUE SEVERIDAD. "Bajo de nivel" sin los dos extremos
   obliga a abrir el escaneo viejo para saber de donde venia. */
.rtb__salto {
    display: flex; align-items: center; gap: 9px; margin: 0 0 8px;
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
    text-transform: uppercase;
}
.rtb__salto span {
    padding: 3px 9px; border-radius: 999px; border: 1px solid currentColor;
    color: var(--muted);
}
.rtb__salto i { color: var(--aviso); font-size: 10px; }
.rtb__salto span[data-sev="Critica"] { color: var(--sev-critica); }
.rtb__salto span[data-sev="Alta"] { color: var(--sev-alta); }
.rtb__salto span[data-sev="Media"] { color: var(--sev-media); }
.rtb__salto span[data-sev="Baja"] { color: var(--sev-baja); }

/* LO REMEDIADO EN UNA LISTA, NO EN TARJETAS. De un hallazgo cerrado lo que
   hace falta es su nombre y de que severidad era. Es la buena noticia: no es
   lo que hay que decidir hoy. */
.rtb__ok { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px; }
.rtb__ok li {
    display: flex; align-items: baseline; gap: 9px;
    font-size: 12.2px; line-height: 1.5; color: var(--muted);
}
.rtb__ok i { color: var(--bien); font-size: 10px; flex: 0 0 12px; }
.rtb__ok li > span { flex: 1 1 auto; min-width: 0; }
.rtb__ok em {
    font-style: normal; flex: 0 0 auto;
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--muted);
    border: 1px solid var(--rule); border-radius: 999px; padding: 2px 8px;
}
.rtb__ok em[data-sev="Critica"] { color: var(--sev-critica); }
.rtb__ok em[data-sev="Alta"] { color: var(--sev-alta); }
.rtb__ok em[data-sev="Media"] { color: var(--sev-media); }
.rtb__ok em[data-sev="Baja"] { color: var(--sev-baja); }

/* EL BOTON QUE LANZA UNO NUEVO. En la fila de pestanas, junto a Hallazgos, y
   FUERA del tablist igual que LIMPIAR. Se tine de rojo Red Sigma y no de rojo
   de borrar: lanza trabajo, no lo destruye. */
.pest__fin--re:hover:not(:disabled) {
    color: var(--bone); border-color: var(--gold);
    background: linear-gradient(180deg, rgba(255, 94, 108, .22) 0%,
                                        rgba(255, 74, 94, .12) 100%);
}

/* ===== LA VENTANA DEL RETESTING ========================================== */
.rt__aviso {
    margin-top: 14px; padding: 12px 15px; border-radius: 10px;
    border: 1px solid var(--rule); border-left: 2px solid var(--gold);
    background: rgba(255, 74, 94, .07);
    font-size: 12.5px; line-height: 1.6; color: var(--bone-2);
}
.rt__aviso p { margin: 0; }
.rt__aviso p + p { margin-top: 7px; }
.rt__aviso b { color: var(--bone); }

.rt__paso {
    margin: 16px 0 0; padding: 13px 15px;
    border: 1px solid var(--rule); border-radius: 10px;
    background: rgba(var(--ink-3-rgb), .35);
}
.rt__leg {
    padding: 0 8px; font-family: var(--font-mono); font-size: 10px;
    letter-spacing: .16em; text-transform: uppercase; color: var(--bone);
}
.rt__nota { margin: 10px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.rt__casilla {
    display: flex; align-items: flex-start; gap: 10px;
    margin-top: 13px; padding: 10px 12px; border-radius: 9px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .18);
    font-size: 12.2px; line-height: 1.5; color: var(--bone-2); cursor: pointer;
}
.rt__casilla input { margin-top: 2px; flex: 0 0 auto; accent-color: var(--gold); }

/* CADA OPCION DICE CUANTOS HALLAZGOS Y DE QUE SEVERIDAD, antes de elegir: es
   la unica diferencia que importa entre dos escaneos de la misma aplicacion, y
   lanzar contra el equivocado gasta un escaneo del plan revalidando lo que ya
   estaba arreglado. */
.rt__orig { display: grid; gap: 8px; }
.rt__op {
    display: flex; align-items: flex-start; gap: 11px;
    padding: 11px 13px; border-radius: 9px; cursor: pointer;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .2);
    transition: border-color .15s var(--ease), background .15s var(--ease);
}
.rt__op:hover { border-color: var(--gold-soft); }
.rt__op input { margin-top: 3px; flex: 0 0 auto; accent-color: var(--gold); }
.rt__op:focus-within { outline: 2px solid var(--gold); outline-offset: 2px; }
.rt__op--on { border-color: var(--gold); background: rgba(255, 74, 94, .12); }
/* Un escaneo que no sirve de punto de partida SALE EN LA LISTA, apagado y con
   el motivo: no salir no distingue "no se puede" de "no existe". */
.rt__op--off { opacity: .5; cursor: not-allowed; }
.rt__op--off:hover { border-color: var(--rule); }
.rt__op-c { display: grid; gap: 5px; min-width: 0; }
.rt__op-c b { font-size: 12.8px; color: var(--bone); font-weight: 500; }
.rt__op-c code {
    font-family: var(--font-mono); font-size: 10.5px; color: var(--muted);
    word-break: break-all;
}
.rt__op-s {
    display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .08em;
    text-transform: uppercase; color: var(--bone-2);
}
.rt__op-m {
    font-style: normal; font-size: 11.5px; line-height: 1.5; color: var(--aviso);
}
.lmp__ir--re { border-color: var(--gold); }

/* ==========================================================================
   RESUMEN
   ==========================================================================

   La bandera de criticidad de la aplicacion, cuantas veces se la ha escaneado
   y su logotipo. La criticidad la calcula el servidor con
   `veredicto.calcular_riesgo()` y aqui solo se pinta: dos escalas de riesgo
   para el mismo hallazgo acabarian diciendo cosas distintas en la pantalla y
   en el PDF, que es el precio que este proyecto ya pago con las severidades.

   ES UNA ESCALA DE RIESGO: MAS ALTO ES PEOR. La barra se llena hacia el rojo,
   no hacia el verde, y la leyenda lo dice con palabras al lado del numero.
   ========================================================================== */
.rs { display: grid; gap: 16px; }
.rs__cab { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.rs__quien { display: grid; gap: 3px; min-width: 0; }
.rs__quien b { font-size: 17px; color: var(--bone); font-weight: 500; }
.rs__quien code {
    font-family: var(--font-mono); font-size: 10.5px; color: var(--muted);
}
.rs__quien em {
    font-style: normal; font-family: var(--font-mono); font-size: 11px;
    color: var(--bone-2); word-break: break-all;
}

.rs__flag {
    display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
    padding: 18px 20px; border-radius: 12px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .24);
}
/* El filete lo elige la BANDA que dijo el veredicto, con los mismos hex que el
   PDF: --sev-alta, --sev-media y --sev-baja son los colores de _banda(). */
.rs__flag[data-banda="roja"] { border-left: 4px solid var(--sev-alta); }
.rs__flag[data-banda="ambar"] { border-left: 4px solid var(--sev-media); }
.rs__flag[data-banda="verde"] { border-left: 4px solid var(--sev-baja); }
.rs__sello { width: 96px; height: auto; flex: 0 0 96px; }
.rs__flag-c { flex: 1 1 280px; min-width: 0; display: grid; gap: 9px; }
.rs__t {
    font-family: var(--font-serif); font-size: 21px; letter-spacing: .01em;
    color: var(--bone);
}
.rs__barra {
    height: 9px; border-radius: 999px; overflow: hidden;
    background: rgba(var(--hueco-rgb), .45); border: 1px solid var(--rule);
}
.rs__barra span { display: block; height: 100%; background: currentColor; }
.rs__flag[data-banda="roja"] .rs__barra { color: var(--sev-alta); }
.rs__flag[data-banda="ambar"] .rs__barra { color: var(--sev-media); }
.rs__flag[data-banda="verde"] .rs__barra { color: var(--sev-baja); }
.rs__pct { margin: 0; font-size: 13px; color: var(--bone-2); }
.rs__pct b { font-family: var(--font-mono); font-size: 16px; color: var(--bone); }
/* LA ESCALA SE DICE EN LA PROPIA BANDERA. Un porcentaje suelto se lee como una
   nota de examen, y aqui 90 es lo peor que hay. */
.rs__esc {
    margin: 0; font-family: var(--font-mono); font-size: 10px;
    letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.rs__esc b { color: var(--bone); }
/* EL DINERO, EN LA MISMA BANDERA QUE LOS HALLAZGOS. Mismo cuerpo que la escala
   de al lado para que no compita con la severidad, que es lo que manda aqui: la
   cifra informa, no grita. */
.rs__gasto {
    margin: 2px 0 0; font-family: var(--font-mono); font-size: 10px;
    letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.rs__gasto b { font-size: 14px; color: var(--bone); letter-spacing: 0; }
.rs__exp { margin: 0; max-width: 74ch; font-size: 12.2px; line-height: 1.65; color: var(--muted); }

/* SIN DATOS NO ES UN 0. Con escala de riesgo el 0 es la mejor nota que existe,
   y hay expedientes a 0 porque la corrida ni arranco. NO MIRAR NO ES ESTAR
   LIMPIO: se dice con palabras y sin ningun numero al lado. */
.rs__sin {
    display: flex; align-items: flex-start; gap: 14px;
    padding: 16px 18px; border-radius: 12px;
    border: 1px dashed rgba(245, 166, 35, .5); background: rgba(245, 166, 35, .07);
}
.rs__sin > i { color: var(--aviso); font-size: 20px; margin-top: 2px; }
.rs__sin b { color: var(--bone); font-size: 14px; }
.rs__sin p { margin: 7px 0 0; max-width: 74ch; font-size: 12.4px; line-height: 1.65; color: var(--bone-2); }
.rs__sin code { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.rs__sin--fallo { border-color: var(--rule); background: rgba(var(--hueco-rgb), .2); }
.rs__sin--fallo > i { color: var(--muted); }
.rs__cargando { margin: 0; padding: 16px 18px; font-size: 12.5px; color: var(--muted); }
.rs__cargando code { font-family: var(--font-mono); font-size: 11px; }

/* UNA CORRIDA VIVA SE MARCA PROVISIONAL y no se parece a una terminada: a
   mitad de la auditoria faltan hallazgos por escribir, asi que el riesgo solo
   puede subir. */
.rs__prov {
    margin: 0; padding: 12px 14px; border-radius: 9px;
    border: 1px solid rgba(245, 166, 35, .5); border-left: 3px solid var(--aviso);
    background: rgba(245, 166, 35, .1);
    max-width: 90ch; font-size: 12.4px; line-height: 1.65; color: var(--bone-2);
}
.rs__prov i { color: var(--aviso); margin-right: 9px; }
.rs__prov b { color: var(--aviso); letter-spacing: .06em; }

.rs__rej { display: flex; gap: 10px; flex-wrap: wrap; }
.rs__fi {
    flex: 1 1 180px; min-width: 0; padding: 12px 14px; border-radius: 10px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .2);
    display: grid; gap: 4px;
}
.rs__fi b { font-family: var(--font-mono); font-size: 22px; color: var(--bone); }
.rs__fi span {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em;
    text-transform: uppercase; color: var(--bone);
}
.rs__fi em { font-style: normal; font-size: 11.3px; line-height: 1.5; color: var(--muted); }
.rs__fi--aviso { border-color: rgba(245, 166, 35, .45); }
.rs__fi--aviso b, .rs__fi--aviso span { color: var(--aviso); }

/* LA FICHA QUE ES BOTON. "Sin confirmar" abre la lista de nombres, y tiene
   que SENTIRSE pulsable antes de que nadie lea la letra pequena. Mismo
   idioma que `.hz-inf__b` y `.selt`: un degradado de luz arriba a sombra
   abajo da el bisel, y al pulsarla SE HUNDE -1px de traslado y la sombra
   exterior se invierte a interior- que es la fisica que le falta a una
   ficha plana. Sin eso no se distingue de las otras tres, que no hacen nada. */
.rs__fi--boton {
    cursor: pointer; font: inherit; text-align: left;
    background: linear-gradient(180deg, rgba(255, 255, 255, .05) 0%,
                                        rgba(0, 0, 0, .15) 100%),
                rgba(var(--hueco-rgb), .2);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06),
                0 1px 2px rgba(0, 0, 0, .25);
    transition: transform .08s ease, box-shadow .08s ease,
                border-color .15s ease, background .15s ease;
}
.rs__fi--boton:hover { border-color: var(--aviso); }
.rs__fi--boton:active {
    transform: translateY(1px);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, .35);
    background: linear-gradient(180deg, rgba(0, 0, 0, .1) 0%,
                                        rgba(0, 0, 0, .05) 100%),
                color-mix(in srgb, var(--aviso) 16%, transparent);
}
.rs__fi--boton:focus-visible { outline: 2px solid var(--aviso); outline-offset: 2px; }

/* EL DESPLEGABLE DE LAS EXPLICACIONES. Recoge lo que antes eran siete bloques
   de prosa sueltos por la pantalla —tres avisos y cuatro pies de ficha—
   compitiendo entre si y con el parrafo que la tarjeta de criticidad ya trae.

   NACE CERRADO, y es la unica cosa de este manual que lo hace: lo que contiene
   es metodo permanente, se lee una vez y no cambia nunca. Lo que SI cambia
   -que una corrida este viva y la pantalla sea provisional- se quedo fuera y
   arriba del todo. */
.rs__guia {
    margin: 0; padding: 10px 13px; border-radius: 9px;
    border: 1px solid var(--rule); background: rgba(var(--hueco-rgb), .18);
    max-width: 90ch;
}
.rs__guia > summary {
    cursor: pointer; list-style: none;
    font-family: var(--font-mono); font-size: 10px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--bone);
}
.rs__guia > summary::-webkit-details-marker { display: none; }
.rs__guia > summary::after {
    content: ''; display: inline-block; margin-left: 8px;
    width: 5px; height: 5px; vertical-align: 2px;
    border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg);
}
.rs__guia[open] > summary::after { transform: rotate(-135deg); }
.rs__guia[open] > summary { margin-bottom: 9px; }
.rs__guia p {
    margin: 0 0 8px; font-size: 12.2px; line-height: 1.65; color: var(--muted);
}
.rs__guia p:last-child { margin-bottom: 0; }
.rs__guia b { color: var(--bone-2); }


/* ====== LA MISMA BANDERA, PARA EL ACUMULADO DE LA PESTANA HALLAZGOS ========

   Esa cabecera era una fila de chips pequenos y Oscar la tacho entera el
   07/10/2026: un renglon de etiquetas de colores del mismo tamano no dice QUE
   DE GRAVE es la cosa. Asi que reusa esta bandera -misma tarjeta, misma barra,
   mismas fichas- en lugar de una maqueta nueva.

   LO QUE NO REUSA ES EL PORCENTAJE DE RIESGO. `/api/veredicto` exige `id` y
   puntua por CORRIDA a proposito; el acumulado de una aplicacion no tiene
   veredicto y promediar los de sus corridas no significa nada. El porque largo
   esta en `banderaDelAcumulado()` en app.js. De ahi los tres modificadores:

     `data-peor`  el filete lo elige la peor severidad PRESENTE, que es un
                  hecho contable. NO se reusa `data-banda` precisamente para
                  que nadie lea una banda de riesgo donde hay un recuento.
     `.rs__dona`  la composicion por severidad, que NO es un medidor: un
                  anillo repartido en vez de una barra que se llena hacia el
                  rojo. El porque de la forma esta en `donaDeSeveridad()`.
     `[data-sev]` la ficha tenida de su severidad.
   ========================================================================= */
.rs__flag[data-peor="Critica"] { border-left: 4px solid var(--sev-critica); }
.rs__flag[data-peor="Alta"] { border-left: 4px solid var(--sev-alta); }
.rs__flag[data-peor="Media"] { border-left: 4px solid var(--sev-media); }
.rs__flag[data-peor="Baja"] { border-left: 4px solid var(--sev-baja); }
.rs__flag[data-peor="Informativo"] { border-left: 4px solid var(--sev-informativo); }
/* LA MISMA BANDERA, EN RETESTING: aqui no hay severidad que leer -el filete
   lo decide si queda algo vivo, no de que gravedad es-. */
.rs__flag[data-peor="vivo"] { border-left: 4px solid var(--mal); }

/* LA DONA OCUPA LA RANURA DEL SELLO, que esta bandera deja vacia porque aqui
   no hay banda de riesgo que sellar. Mismo ancho: la tarjeta no cambia de
   reparto y la bandera de Resumen y esta siguen pareciendose.

   El grosor del anillo lo pone el JS segmento a segmento -el de la peor
   severidad va mas gordo- y por eso no esta aqui: es dato, no estilo.

   LA CIFRA DEL AGUJERO es `--bone` a 25px en negrita -texto grande para WCAG,
   umbral 3:1- sobre el fondo de `.rs__flag`, que es negro al 24% sobre el
   panel. Medido el 07/10/2026 sobre ese fondo compuesto: 14.34:1 en el peor
   caso oscuro y 14.94:1 en claro. Los colores del anillo no son texto y no
   tienen umbral; quien los traduce a numero son las fichas de abajo. */
.rs__dona { flex: 0 0 116px; width: 116px; height: 116px; }
.rs__dona text {
    font-family: var(--font-mono); font-size: 25px; font-weight: 700;
    fill: var(--bone);
}

/* LA FICHA, TENIDA DE SU SEVERIDAD. Mismo patron que `.vd`: el tono entra por
   una variable y el fondo es ese mismo tono al 10%, asi que el tema claro lo
   intercambia solo -`--sev-*` existe en los dos- y no hay un segundo juego de
   colores que mantener.

   LA CIFRA VA EN EL COLOR Y LA ETIQUETA NO. El verde de `--sev-baja` y el ambar
   de `--sev-media` como texto pequeno son el problema que ya documenta el
   bloque de `.hz-sev`. La cifra son 22px en negrita -texto grande para WCAG,
   umbral 3:1- y la etiqueta se queda en `--gold-soft`, que ya estaba medido.
   Calculado el 07/10/2026 sobre el fondo COMPUESTO (el tono al 10% sobre el
   fondo del panel, porque los huecos de esta hoja se apilan), el peor caso de
   los diez es Critica en oscuro sobre `--ink-3`: 3.80:1 la cifra y 5.74:1 la
   etiqueta. Las otras nueve cifras van de 3.97:1 a 7.68:1. */
.rs__fi[data-sev] {
    border-color: var(--sev); border-left-width: 3px;
    background: color-mix(in srgb, var(--sev) 10%, transparent);
}
.rs__fi[data-sev] b { color: var(--sev); }
.rs__fi[data-sev="Critica"] { --sev: var(--sev-critica); }
.rs__fi[data-sev="Alta"] { --sev: var(--sev-alta); }
.rs__fi[data-sev="Media"] { --sev: var(--sev-media); }
.rs__fi[data-sev="Baja"] { --sev: var(--sev-baja); }
.rs__fi[data-sev="Informativo"] { --sev: var(--sev-informativo); }

/* LAS CINCO EN REJILLA, NO EN FILA FLEXIBLE. Con `flex: 1 1 180px` las cinco no
   cabian y la quinta -INFORMATIVO, la menos grave- caia sola a una segunda fila
   ESTIRADA A TODO EL ANCHO: el bloque mas grande de la pantalla para el dato
   menos importante, y con pinta de error. En rejilla, una celda que sobra
   conserva el ancho de su columna en vez de estirarse, asi que el huerfano no
   puede volver a pasar ni cuando las columnas bajan a tres. */
.rs__rej--sev {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px;
}
@media (max-width: 860px) {
    .rs__rej--sev { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
    .rs__rej--sev { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.rs__cob, .rs__nc {
    margin: 0; max-width: 90ch; font-size: 12px; line-height: 1.6; color: var(--muted);
}
.rs__cob i, .rs__nc i { color: var(--gold); opacity: .7; margin-right: 8px; }
.rs__cob b { color: var(--bone-2); }
/* EN CAJA, Y NO TEXTO SUELTO. Como texto corrido justo debajo de los chips se
   leia amontonado contra ellos. Mismo tratamiento que `.rs__prov`: filete y
   fondo en el ambar de aviso, para que se note que esto pide una accion -
   confirmar a mano- y no es una glosa mas. */
.rs__nc {
    display: flex; align-items: flex-start; gap: 9px;
    margin: 10px 0 0; padding: 11px 13px; border-radius: 9px;
    border: 1px solid rgba(245, 166, 35, .45); border-left: 3px solid var(--aviso);
    background: rgba(245, 166, 35, .1);
    max-width: 90ch; font-size: 12px; line-height: 1.6; color: var(--bone-2);
}
.rs__nc b { color: var(--aviso); }
.rs__nc i { margin-top: 2px; opacity: 1; flex: 0 0 auto; }

/* EL AVANCE DE REMEDIACION, bajo la barra. Es la unica zona que responde "y
   hoy, cuanto se arreglo y cuanto queda abierto": la bandera da el riesgo y
   el historico da el trabajo hecho, pero ninguno de los dos cuenta esto.
   Mismo anillo que en la pestana Retesting -grande-, con el porcentaje al
   lado y las tres cifras que lo componen debajo. Rojo mientras algo siga
   vivo; en cuanto el ultimo retesting da cero vivos, pasa a verde: es la
   misma firma que ya usaba .rs__vivos--cero. */
.rs__avance {
    display: flex; align-items: center; gap: 16px;
    margin-top: 10px; padding: 12px 16px; border-radius: 10px;
    background: rgba(255, 74, 94, .08);
    border-left: 3px solid var(--sev-critica);
}
.rs__avance--cero { background: rgba(76, 175, 125, .08); border-left-color: var(--sev-baja); }
.rs__avance-d { min-width: 0; }
.rs__avance-pct {
    margin: 0; display: flex; align-items: baseline; gap: 8px;
}
.rs__avance-pct b {
    font-family: var(--font-mono); font-size: 22px; line-height: 1; color: var(--bone);
}
.rs__avance-pct span { font-size: 12px; color: var(--bone-2); }
.rs__avance-cifras {
    display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px;
}
.rs__avance-c {
    font-style: normal; font-size: 11px; color: var(--muted);
    display: flex; align-items: center; gap: 4px;
}
.rs__avance-c b { font-family: var(--font-mono); font-size: 13px; color: inherit; }
.rs__avance-c--vivo { color: var(--mal); }
.rs__avance-c--bajo { color: var(--aviso); }
.rs__avance-c--ok { color: var(--bien); }
.rs__avance-d small {
    display: block; margin-top: 6px; font-size: 10.5px; color: var(--muted);
}
@media (max-width: 480px) { .rs__avance { flex-wrap: wrap; } }

/* EL DELTA DE UN RETESTING: cuanto habia antes, al lado de cuanto hay ahora. */
.rtx__d {
    font-style: normal; font-size: 9.5px; letter-spacing: .3px;
    margin-left: 6px; opacity: .75;
}
/* EL AVISO DEL VEREDICTO VA COMPLETO. Es el que dice que un resultado bajo con
   cobertura incompleta no equivale a un objetivo seguro. */
.rs__aviso {
    margin: 0; padding: 12px 14px; border-radius: 9px;
    border: 1px solid rgba(255, 92, 110, .45); border-left: 3px solid var(--mal);
    background: rgba(255, 92, 110, .09);
    max-width: 90ch; font-size: 12.3px; line-height: 1.65; color: var(--bone-2);
}
.rs__aviso i { color: var(--mal); margin-right: 9px; }

@media (max-width: 640px) {
    .rs__sello { width: 68px; flex-basis: 68px; }
    .rs__flag { gap: 14px; padding: 14px 15px; }
    .rs__fi { flex: 1 1 100%; }
    .rs__cual, .rs__prov, .rs__aviso, .rs__exp, .rs__sin p { max-width: 100%; }
    .rtb__d { max-width: 100%; }
}

/* ===== RETESTEAR ESTE ESCANEO, DESDE SU PROPIA FILA =======================

   El boton de arriba obliga a abrir la ventana y buscar de que escaneo se
   quiere el retesting. El de la fila YA SABE CUAL ES.

   VA SEPARADO DEL BORRADO Y NO SE PARECE A EL, y las dos cosas importan: en
   esta fila conviven tres acciones y una de ellas borra un expediente de 19
   hallazgos. El id copiable queda EN MEDIO de los dos -ver el orden en el que
   los escribe carpetaDeExpediente()-. El texto y el icono eran el rojo de
   marca para distinguirse del rojo de peligro de la papelera; desde el barrido
   de colores del 15/10/2026 el texto es `--bone` como el resto de la
   plataforma, y lo que sigue distinguiendo este boton del de borrar es el
   fondo tenido que conserva. */
.hzx__re-b {
    display: flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 11px 14px; border: 0; border-left: 1px solid var(--rule);
    background: rgba(255, 74, 94, .07); color: var(--bone);
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .1em;
    text-transform: uppercase;
    transition: color .15s var(--ease), background .15s var(--ease);
}
.hzx__re-b i { font-size: 11px; opacity: .85; }
.hzx__re-b:hover:not(:disabled) {
    color: var(--bone); background: rgba(255, 74, 94, .2);
}
.hzx__re-b:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
/* APAGADO Y DICIENDO POR QUE, no escondido: un hueco no distingue "aqui no se
   puede" de "esto todavia no existe". El motivo va en el `title`. */
.hzx__re-b:disabled { opacity: .35; cursor: not-allowed; }

/* SI ESE ESCANEO YA SE REVALIDO, EN LA CABECERA Y CON LA FECHA. Es la pregunta
   inmediata al mirar la lista -"esto ya lo revalide?"- y sin esto habria que
   irse a la otra pestana a averiguarlo. */
.hzx__re {
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .06em;
    text-transform: uppercase; font-style: normal; cursor: help;
    padding: 3px 8px; border-radius: 999px;
    color: var(--bone); border: 1px solid rgba(255, 126, 141, .45);
    background: rgba(255, 74, 94, .1);
}
.hzx__re i { font-size: 9px; margin-right: 4px; }

/* EL ORIGEN PUESTO NO SE PUEDE CAMBIAR: no es un control, es lo que se eligio
   al pulsar Retestear en una fila. Sin radio y con la chincheta. */
.rt__op--fijo { cursor: default; }
.rt__op--fijo > i { color: var(--gold); font-size: 13px; margin-top: 3px; }
.rt__op--fijo:hover { border-color: var(--gold); }

@media (max-width: 640px) {
    /* En movil las tres acciones de la fila bajan a su propia linea: apretadas
       en una fila estrecha, una de ellas borra un expediente. */
    .hzx__re-b {
        flex: 1 1 100%; justify-content: center;
        border-left: 0; border-top: 1px solid var(--rule);
    }
}

/* LA CONSTANCIA DE LO QUE SE ACABA DE BORRAR, en la pestana donde se borro.
   La fila desaparece -eso ya se ve- pero DONDE QUEDA APUNTADO no, y eso se
   escribia en la caja de estado, que vive en otra pestana. Un borrado
   irreversible del que la pantalla no dice donde quedo constancia es el hueco
   que no puede tener. Se pinta una vez y se olvida: es una noticia, no un
   cartel. */
.hzx__hecho {
    margin: 0 0 14px; padding: 11px 14px; border-radius: 9px;
    border: 1px solid rgba(76, 175, 125, .45); border-left: 3px solid var(--bien);
    background: rgba(76, 175, 125, .09);
    font-size: 12.4px; line-height: 1.6; color: var(--bone-2);
}
.hzx__hecho i { color: var(--bien); margin-right: 9px; }
.hzx__hecho b { color: var(--bone); }
.hzx__hecho code {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone);
    word-break: break-all;
}

/* ===== LOS DOS GRUPOS QUE FALTABAN DEL RETESTING ==========================

   `no_comprobable` NO ES UNA BUENA NOTICIA y no se pinta como tal: el hallazgo
   puede seguir vivo y lo que falto fue poder medirlo. Y "sin revisar" -los
   hallazgos del escaneo original que el retesting no menciona- es el fallo que
   de verdad importa: nueve veredictos impecables de trece hallazgos se leen
   como un retesting completo si nadie cuenta los cuatro que faltan. */
.rtb--duda {
    border: 1px solid rgba(245, 166, 35, .38); border-left: 3px solid var(--aviso);
    background: rgba(245, 166, 35, .05);
}
.rtb--duda .rtb__t { color: var(--aviso); }
.rtb--falta {
    border: 1px solid rgba(255, 92, 110, .45); border-left: 3px solid var(--mal);
    background: rgba(255, 92, 110, .07);
}
.rtb--falta .rtb__t { color: var(--mal); font-weight: 700; font-size: 12px; }
.rtb--falta .rtb__ok i, .rtb--duda .rtb__ok i { color: var(--aviso); }
.rtb__d code {
    font-family: var(--font-mono); font-size: 11px; color: var(--bone-2);
    word-break: break-all;
}

/* Las casillas de la cabecera llevan el recuento dentro, como las de severidad. */
.rtx__p b { margin-left: 4px; }
.rtx__p--duda {
    color: var(--aviso); border-color: rgba(245, 166, 35, .5);
    background: rgba(245, 166, 35, .08);
}
.rtx__p--falta {
    color: var(--mal); border-color: rgba(255, 92, 110, .6);
    background: rgba(255, 92, 110, .16); font-weight: 700; cursor: help;
}
.rtx__p--falta i { font-size: 9px; margin-right: 4px; }

/* EL VINCULO SOBREVIVE AL EXPEDIENTE. Cuando el escaneo original ya no esta en
   disco, la fila lo dice ahi mismo en vez de ensenar un id que no lleva a
   ningun sitio. */
.rtx__ido { color: var(--aviso); font-weight: 400; }

/* La tarjeta de un veredicto reusa la del hallazgo -mismo filete de severidad,
   mismos titulillos- para que las dos pestanas se lean igual. */
.rtb__f .hz__f { background: rgba(var(--hueco-rgb), .26); }
.rtb__f .caja__nota { margin-top: 12px; }

/* ======================= LA PUERTA DE RTSS ==============================

   La caja de acceso. Ocupa el sitio de la vista de RTSS -no se pone encima-,
   asi que se centra en el hueco que queda bajo la banda y no en la pantalla
   entera: la barra lateral sigue ahi, que es lo que dice que esto es la
   misma herramienta y no otra pagina.

   LA BANDA Y EL PIE, EN CAMBIO, SE APAGAN AQUI. Hasta el 18/10/2026 se
   dejaban puestos con el mismo argumento de la barra lateral, pero los dos
   hablan de LA APLICACION ELEGIDA -"SIN APLICACION ELEGIDA", "INACTIVO", el
   pie con "sin aplicacion"-, y esa pregunta no existe todavia: nadie eligio
   nada, porque nadie ha entrado. Enseñarla antes de la sesion es responder
   una pregunta que no se puede hacer hasta pasar la puerta. */
body:has(#vista-acceso:not([hidden])) #banda,
body:has(#vista-acceso:not([hidden])) .foot { display: none; }

/* LA PORTADA USA TODO ESE HUECO, DE BORDE A BORDE. Pedido el 18/10/2026: el
   `.shell` que trae el gutter horizontal y el `.lienzo` que reserva espacio
   abajo son los mismos de cualquier otra pantalla, y aqui se anulan los dos
   -solo para ESTA vista, con `:has()`, sin tocar el resto-: la foto es el
   fondo de la puerta, no una tarjeta mas dentro de ella.

   POR QUE NO BASTA CON `100vh`. De 1000px para arriba la app vive dentro de
   `.aparato` -la ventana simulada de Win11/macOS, `height: 100vh` y
   `overflow: hidden`- y `.lienzo` es la UNICA pieza de ahi dentro que hace
   scroll por su cuenta (`overflow-y: auto`, con su propio alto ya acotado
   por la rejilla de `.cuerpo`). `100vh` ahi mide la ventana REAL del
   navegador, no el hueco que le queda a `.lienzo` -que es mas bajo, por el
   title bar y la banda-, asi que forzarlo habria reproducido el scroll de
   mas que el comentario viejo de esta regla ya documentaba y arreglaba.
   Por eso esto no mide en vh: ESTIRA por flex hasta donde `.lienzo` de
   verdad llega, cualquiera que sea esa cifra. */
#vista-acceso .shell { max-width: none; margin: 0; padding: 0; }
.lienzo:has(> #vista-acceso:not([hidden])) {
    /* El padding-top tambien era SOLO para la banda -le dejaba su hueco
       encima del titulo-; con la banda apagada aqui, ese hueco se queda
       vacio si no se quita tambien. */
    padding-top: 0; padding-bottom: 0;
}
#vista-acceso:not([hidden]) {
    min-height: 100%; display: flex; flex-direction: column;
}
#vista-acceso .shell { flex: 1; display: flex; flex-direction: column; }
#vista-acceso .acc { flex: 1; }
.acc {
    display: grid; place-items: center;
    min-height: calc(100vh - var(--banda-alto) - 150px);
    position: relative;
    /* LA PORTADA, DETRAS. Pedida el 18/10/2026 "al frente" el login: por eso
       la imagen va de fondo de ESTE contenedor y no de la pantalla entera
       -asi sigue valiendo el comentario de arriba, "no se pone encima"-, y
       el degradado oscuro encima de la foto es lo que deja el formulario
       legible sin depender solo de que su propia caja sea opaca. */
    background: linear-gradient(180deg, rgba(10, 8, 9, .35), rgba(10, 8, 9, .72)),
                url('../img/acc-portada.jpg') center / cover no-repeat;
}
.acc__caja {
    width: min(100%, 440px);
    display: flex; flex-direction: column; gap: 16px;
    border: 1px solid rgba(255, 74, 94, 0.28); border-radius: 12px;
    background: var(--panel);
    padding: clamp(20px, 3.4vw, 30px);
    /* AL FRENTE DE VERDAD: sombra propia para que se note que esta flotando
       sobre la portada y no pegada a ella. */
    box-shadow: 0 20px 60px rgba(0, 0, 0, .55);
}
.acc__cab { display: flex; gap: 14px; align-items: flex-start; }
.acc__cab > i { font-size: 20px; color: var(--gold); margin-top: 4px; }
.acc__cab h2 {
    font-family: var(--font-serif); font-size: clamp(20px, 2.6vw, 25px);
    color: var(--bone); margin: 0 0 6px; line-height: 1.2;
}
.acc__cab h2 em { font-style: normal; color: var(--gold-soft); }
.acc__cab p { margin: 0; font-size: 13px; line-height: 1.5; color: var(--muted); }

.acc__campo { display: flex; flex-direction: column; gap: 6px; }
.acc__campo > span {
    font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .18em;
    text-transform: uppercase; color: var(--bone);
}
.acc__campo input { width: 100%; }
/* La ranura con el ojito dentro, como las del token y el secreto TOTP. */
.acc__conojo { position: relative; display: block; }
.acc__conojo input { padding-right: 44px; }

.acc__b { width: 100%; justify-content: center; margin-top: 2px; }

/* EL AVISO. Nace oculto y solo aparece con algo que decir: una caja de aviso
   vacia reservando su alto hace saltar el boton al aparecer el texto, justo
   cuando se va a pulsar. */
.acc__aviso {
    margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted);
    border-left: 2px solid var(--rule); padding-left: 10px;
}
.acc__aviso[hidden] { display: none; }
.acc__aviso--mal { color: var(--mal); border-left-color: var(--mal); }
.acc__aviso--aviso { color: var(--aviso); border-left-color: var(--aviso); }

/* "Entrar no autoriza nada": lo que esta puerta NO es. Va dentro de la caja y
   no en letra chica al pie de la pagina, porque es lo que impide leer el login
   como el unico control de la herramienta. */
.acc__pie {
    margin-top: 4px; padding-top: 14px; border-top: 1px solid var(--rule);
    display: flex; flex-direction: column; gap: 8px;
}
.acc__pie p { margin: 0; font-size: 11.5px; line-height: 1.6; color: var(--muted); }
.acc__pie b { color: var(--bone-2); }

/* SALIR, en el menu del pie de la barra. Se distingue del resto del menu por el
   color del icono: las otras entradas abren cosas y esta cierra la sesion, y en
   una lista de botones iguales se pulsa la de al lado. */
.lat-menu__b--salir { border-top: 1px solid var(--rule); border-radius: 0 0 8px 8px; }
.lat-menu__b--salir > i { color: var(--aviso); }
.lat-menu__b--salir:hover {
    background: rgba(245, 166, 35, .12); border-color: rgba(245, 166, 35, .45);
}

/* =========================================================================
   LA BARRA LATERAL, PLEGADA A UNA BARRITA

   Pedido por Oscar el 05/10/2026: "cuando hacemos zoom se descuadra horrible".
   La barra mide 244 px FIJOS y el lienzo se aparta con `margin-left`. Al subir
   el zoom el viewport en pixeles CSS se encoge, asi que esos 244 px pasan a ser
   una fraccion cada vez mayor de la pantalla y al lienzo no le queda sitio. El
   modo icono de 68 px no salva el caso porque lo dispara el ANCHO DEL VIEWPORT,
   y al 150 % en una pantalla grande el viewport sigue siendo ancho.

   UN MANDO Y NO OTRO UMBRAL: un cuarto punto de corte seria adivinar otra vez a
   que zoom molesta, y el zoom que a uno le sobra a otro le falta.

   SE PLIEGA ENTERA, no a modo icono. A medio esconder sigue robando ancho, que
   es justo lo que se queria recuperar.

   LA CLASE VA EN <html> Y NO EN <body> NI EN LA BARRA: `--lat-ancho` se declara
   en `:root` y lo leen la barra, la banda y el lienzo. Puesta mas abajo, el
   valor nuevo no llegaria a quien lo lee desde arriba.
   ========================================================================= */
.lat-tirador {
    position: absolute;
    top: 10px; right: 6px;
    z-index: 2;
    width: 22px; height: 30px;
    display: grid; place-items: center;
    padding: 0;
    border: 1px solid var(--rule);
    border-radius: 7px;
    background: rgba(var(--ink-rgb), .9);
    color: var(--muted);
    cursor: pointer;
    transition: color .16s ease, border-color .16s ease;
}
.lat-tirador:hover { color: var(--bone); border-color: var(--gold); }
.lat-tirador > i { font-size: 11px; transition: transform .18s ease; }

/* EN MODO ICONO SE VA AL PIE. A 68 px de ancho el tirador caia justo encima del
   logotipo de la marca y le robaba los clics: el enlace de volver al sitio
   dejaba de poder pulsarse. Abajo y centrado no hay nada, y sigue estando a la
   vista, que es lo unico que necesita. */
@media (max-width: 1180px) and (min-width: 1000px) {
    .lat-tirador {
        top: auto; bottom: 10px;
        right: 50%;
        transform: translateX(50%);
    }
}
/* AQUI HABIA UN `.lateral { position: fixed }`, Y SE BORRO EL 05/10/2026 el
   mismo dia que se escribio. Se puso "para que la barra sea el bloque de
   referencia del tirador", que ya lo era: la regla base de arriba lo declara
   desde siempre. Lo que si hacia era anular el `position: static` del bloque de
   760 px -misma especificidad y mas abajo en la hoja-, y con eso la pagina
   entera se dibujaba DEBAJO de la barra en movil. Medido: 690x749 px de solape
   sobre el lienzo a 700 px de ancho.

   Se deja escrito porque el error es facil de repetir: cualquier regla suelta
   de `.lateral` al final de esta hoja pisa a los dos media queries. Si hace
   falta tocar la barra, se toca en su bloque. */

html.lat-plegada { --lat-ancho: 20px; }
html.lat-plegada .lateral {
    padding: 0;
    gap: 0;
    overflow: visible;        /* el tirador asoma del canto, 20 px no lo contienen */
    background: var(--chrome);
}
/* TODO MENOS EL TIRADOR. `> *` y no una lista de clases: el dia que entre un
   bloque nuevo en la barra, se pliega con los demas sin que nadie se acuerde. */
html.lat-plegada .lateral > *:not(.lat-tirador) { display: none; }
html.lat-plegada .lat-tirador { right: -1px; border-radius: 0 7px 7px 0; }
html.lat-plegada .lat-tirador > i { transform: rotate(180deg); }

/* EL PLIEGUE ES DE LA CARA DE WINDOWS Y SOLO DE ELLA. Nacio para recuperar
   ancho cuando el zoom alto deja al lienzo sin sitio, y eso solo pasa con la
   barra en una columna fija a la izquierda. En la cara de iPhone la barra ya no
   es una columna: es una lista agrupada dentro del mismo scroll que el resto, y
   plegarla seria esconder la lista de aplicaciones -el estado HUERFANA incluido-
   detras de un tirador que ahi no significa nada. Se apaga en el bloque de 999
   px, junto con el tirador. */

/* Quien pidio que nada se mueva tampoco ve girar la flecha. */
@media (prefers-reduced-motion: reduce) {
    .lat-tirador, .lat-tirador > i { transition: none; }
}

/* =========================================================================
   MI CUENTA: LA FOTO DE PERFIL
   El monograma debajo de la foto es el RESPALDO, no un hueco: sin foto se ven
   las iniciales, igual que en la lista de proyectos cuando una aplicacion no
   tiene logotipo. Distinguen igual de bien y no hay que conseguirlas de nadie.
   ========================================================================= */
.usr { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 16px; }
.usr__foto {
    position: relative;
    width: 72px; height: 72px; flex: 0 0 72px;
    border-radius: 16px;
    border: 1px solid var(--rule);
    background: rgba(var(--ink-rgb), .55);
    overflow: hidden;
    display: grid; place-items: center;
}
.usr__foto img { width: 100%; height: 100%; object-fit: cover; }
.usr__mono {
    font-family: var(--font-mono); font-size: 24px; font-weight: 700;
    letter-spacing: .04em; color: var(--bone);
}
.usr__acc { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; min-width: 0; }
/* El `<label>` que abre el selector de archivos se pinta como los botones de su
   lado: un rotulo que abre un dialogo tiene que parecer pulsable. */
.usr__acc label.ag-mini { cursor: pointer; }
.usr__acc .caja__nota { margin: 0; max-width: 46ch; }

/* El logotipo de la caja "Entra a RTSS". Sustituye al icono de candado de la
   biblioteca: ese decia "aqui se entra" -que ya lo dicen el titulo, los campos y
   el boton- y no decia A DONDE. Esta es la unica pantalla que se ve antes de
   entrar, asi que es donde la marca hace falta.

   `.acc__sigma` es el respaldo del `onerror`, el mismo patron que `.lat-marca`:
   si el archivo falta, queda la sigma y no el aspa del navegador. */
.acc__logo { width: 40px; height: 40px; flex: 0 0 40px; object-fit: contain; margin-top: 2px; }
.acc__sigma {
    display: grid; place-items: center;
    width: 40px; height: 40px; flex: 0 0 40px; margin-top: 2px;
    border: 1px solid var(--rule); border-radius: 10px;
    font-family: var(--font-mono); font-size: 21px; color: var(--gold);
}

/* =========================================================================
   LA BANDERA DE UN VEREDICTO DE RETESTING

   Antes cada hallazgo escupia sus cuatro bloques de texto ABIERTOS. Un
   retesting de nueve dejaba una pared de varias pantallas donde un "sigue
   vivo" critico pesaba lo mismo que un informativo: todo igual, y habia que
   leerlo entero para saber que mirar primero.

   AHORA LO QUE SE VE SIN PULSAR ES: el filete del color de la severidad que
   manda HOY -la nueva, si cambio-, el nombre de esa severidad con su numero, el
   salto de una a otra cuando lo hubo, y una linea de adelanto. El texto entero
   sigue estando, detras del boton, sin recortar una palabra.

   EL NUMERO LLEVA SU "aprox." Y NO ES DECORACION: el resultado de un retesting
   no trae vector CVSS, asi que esa cifra es el centro de la banda de su
   severidad. Sin la marca, acaba citada en un correo como si alguien la hubiera
   medido.
   ========================================================================= */
.hz__f--plegable { padding: 0; }
.hzp__cab { display: grid; gap: 9px; padding: 14px 16px; }

.hzp__t { font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--bone); }

.hzp__m { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }

/* La pastilla de severidad: palabra, numero y la marca de que es aproximado.
   El color sale del mismo `data-sev` que ya usan las demas, para que no haya
   dos escalas de color en la misma pantalla. */
.hzp__sev {
    display: inline-flex; align-items: baseline; gap: 7px;
    padding: 4px 11px; border-radius: 999px;
    border: 1px solid currentColor;
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em;
    text-transform: uppercase; font-weight: 700;
}
.hzp__sev b { font-family: var(--font-sans); font-size: 15px; letter-spacing: 0; }
.hzp__sev i {
    font-style: normal; font-size: 8.5px; letter-spacing: .06em;
    opacity: .7; text-transform: none;
}
.hzp__sev[data-sev="Critica"] { color: var(--sev-critica); }
.hzp__sev[data-sev="Alta"] { color: var(--sev-alta); }
.hzp__sev[data-sev="Media"] { color: var(--sev-media); }
.hzp__sev[data-sev="Baja"] { color: var(--sev-baja); }
.hzp__sev[data-sev="Informativo"] { color: var(--muted); }

.hzp__salto { display: inline-flex; align-items: center; gap: 6px; }
.hzp__salto em {
    font-style: normal;
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .1em;
    text-transform: uppercase;
    padding: 3px 8px; border-radius: 999px; border: 1px solid currentColor;
}
.hzp__salto em[data-sev="Critica"] { color: var(--sev-critica); }
.hzp__salto em[data-sev="Alta"] { color: var(--sev-alta); }
.hzp__salto em[data-sev="Media"] { color: var(--sev-media); }
.hzp__salto em[data-sev="Baja"] { color: var(--sev-baja); }
.hzp__salto em[data-sev="Informativo"] { color: var(--muted); }
.hzp__salto i { font-size: 9px; color: var(--muted); }

.hzp__cat, .hzp__falta {
    font-family: var(--font-mono); font-size: 9px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--muted);
    padding: 3px 9px; border-radius: 999px; border: 1px solid var(--rule);
}
.hzp__falta { color: var(--aviso); border-color: var(--aviso); }

/* El adelanto. Dos lineas como mucho: es un anticipo, no el contenido, y si
   crece deja de distinguirse del detalle que hay detras del boton. */
.hzp__ade {
    font-size: 13px; line-height: 1.6; color: var(--muted);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}

.hzp__b {
    justify-self: start;
    display: inline-flex; align-items: center; gap: 8px;
    padding: 7px 13px; cursor: pointer;
    background: transparent; border: 1px solid var(--rule); border-radius: 8px;
    font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em;
    text-transform: uppercase; color: var(--muted);
    transition: color .18s var(--ease), border-color .18s var(--ease);
}
.hzp__b:hover { color: var(--bone); border-color: var(--gold); }
.hzp__b:focus-visible { outline: 1px solid var(--gold); outline-offset: -2px; }
.hzp__b > i { font-size: 10px; transition: transform .18s var(--ease); }
.hzp__b[aria-expanded="true"] > i { transform: rotate(180deg); }

.hzp__cuerpo { padding: 0 16px 14px; border-top: 1px solid var(--rule); }
.hzp__cuerpo > *:first-child { margin-top: 12px; }

@media (prefers-reduced-motion: reduce) {
    .hzp__b, .hzp__b > i { transition: none; }
}


/* ===========================================================================
   LAS DOS CARAS DEL APARATO
   ===========================================================================

   La consola se dibuja como una APLICACION, no como una pagina: ventana de
   Windows 11 en escritorio y aplicacion de iPhone al estrecharse. Es el mismo
   marcado en los dos casos -el de arriba, sin tocar- repartido distinto con
   `grid-template-areas`. No hay dos arboles que se oculten entre si: lo que
   cambia entre un escritorio y un telefono es la DISPOSICION, no los datos, y
   duplicar el contenido seria garantizar que un dia digan cosas distintas.

   `display: none` solo se usa para el CHROME -controles de ventana, Dynamic
   Island, barra de estado, indicador de inicio-: son piezas del aparato, no
   dicen nada que el usuario de la otra cara necesite leer. Ningun dato de la
   auditoria se apaga en ninguna de las dos.

   EL REPARTO:
     1. BASE Y APARATO
     2. CARA WINDOWS   (min-width: 1000px)
     3. CARA iOS       (max-width:  999px)
     4. TELEFONO ESTRECHO (max-width: 439px)
   =========================================================================== */


/* --- 1. BASE Y APARATO ---------------------------------------------------- */

.escena { display: flex; justify-content: center; }

/* La pantalla es el bloque contenedor de las dos caras. Lo que tiene que
   quedarse quieto mientras el contenido se desplaza -la barra de pestanas de
   iOS, el boton de tema, el indicador de inicio- se posiciona contra ella; el
   scroll vive por dentro. */
.pantalla { position: relative; }

/* Piezas que solo existen en una de las dos caras. */
.chrome-win, .chrome-ios, .indicador { display: none; }

/* Las dos variantes de marca conviven en el DOM y el tema decide cual se ve: es
   lo que hace un Asset Catalog con una imagen "Any/Dark". Se pregunta por
   `:not([data-tema="claro"])` y no por `[data-tema="oscuro"]` a proposito: si el
   JS no llegara a escribir el atributo, el estado sin atributo tiene que seguir
   siendo el oscuro y no los dos logotipos a la vez. */
html:not([data-tema="claro"]) .solo-claro,
html[data-tema="claro"] .solo-oscuro { display: none; }

/* El conmutador de tema es el MISMO boton en las dos caras: solo cambia de
   forma y de sitio. Su glifo se define una vez aqui. El sol va en trazo y la
   luna en relleno porque es como los dibujan los dos sistemas. Siempre se ve el
   DESTINO y no el estado actual: un boton que ensena donde estas no dice a
   donde lleva. */
.btn-tema svg {
    width: 16px; height: 16px; flex: 0 0 auto;
    fill: none; stroke: currentColor; stroke-width: 1.3; stroke-linecap: round;
}
.btn-tema .ico-luna { fill: currentColor; stroke: none; }
html:not([data-tema="claro"]) .ico-luna { display: none; }
html[data-tema="claro"] .ico-sol { display: none; }


/* --- 2. CARA WINDOWS ------------------------------------------------------
   Ventana flotante, NavigationView lateral y lenguaje Fluent. A partir de
   1000 px hay sitio para que la barra de aplicaciones viva permanentemente a la
   vista, que es lo que pide un escritorio: el objeto sobre el que se opera no se
   esconde detras de un toque. */
@media (min-width: 1000px) {

    body { padding: 0; min-height: 100vh; }

    /* El gutter deja de seguir al viewport y pasa a ser el de una pagina de
       Win11. */
    :root { --gutter: 22px; }

    /* Antes era una ventana flotante con esquinas, sombra y margen de
       escritorio alrededor. Ahora ocupa la pantalla entera: sin bisel que
       enseñar, igual que ya hacia el telefono estrecho por debajo de 440 px. */
    .aparato {
        width: 100%;
        height: 100vh;
        min-height: 620px;
        display: flex;
        background: var(--mica);
        border: 0;
        box-shadow: none;
        overflow: hidden;
    }
    .pantalla { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

    /* 2.1 LA BARRA DE TITULO. Las apps modernas de Win11 extienden su contenido
       al title bar y solo reservan la zona de los caption buttons. Icono y
       titulo a la izquierda, los tres controles a la derecha, en ese orden y
       nunca al reves. */
    .chrome-win {
        display: flex; flex: 0 0 auto;
        height: 40px;
        align-items: center; justify-content: space-between;
        padding-left: 12px;
        user-select: none;
    }
    .cw-ident { display: flex; align-items: center; gap: 9px; min-width: 0; }
    .cw-icono { width: 16px; height: 16px; object-fit: contain; }
    /* 12 px es el tamano de Caption en la escala de Win11, y en peso normal:
       destacar el titulo de la ventana competiria con el contenido. */
    .cw-titulo {
        font-size: 12px; color: var(--muted);
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }

    /* 2.2 EL BOTON DE TEMA. Vive en el title bar, a la derecha, ya que no hay
       caption buttons de los que apartarse. */
    .btn-tema {
        position: absolute;
        top: 4px; right: 12px;
        height: 32px;
        display: inline-flex; align-items: center; gap: 7px;
        padding: 0 11px;
        border: 1px solid var(--rule); border-radius: 4px;
        background: transparent;
        color: var(--bone);
        font-family: var(--font-sans); font-size: 12px;
        cursor: pointer;
        z-index: 10;
    }
    .btn-tema:hover { background: var(--capa-hover); }

    /* 2.3 EL ESQUELETO. NavigationView a la izquierda y region de contenido a la
       derecha: el esqueleto de Configuracion, el Explorador y la Microsoft
       Store. La barra deja de ser `fixed` -ya no hay pagina que desplazarse
       por debajo de ella- y pasa a ser una celda de la rejilla; el unico que
       se desplaza es el lienzo.

       LA BANDA YA NO TIENE FILA PROPIA AQUI. Oscar, 10/10/2026, senalando el
       hueco vacio de `.chrome-win`: "usar este espacio para subir las
       laterales que apuntan las flechas y reducir espacio". La rejilla baja
       de dos filas a una -`apps lienzo`- y la banda se superpone encima de
       la barra de titulo por su cuenta, mas abajo en esta hoja; ver ese
       bloque para el porque de que siga sin moverse del HTML. */
    .cuerpo {
        flex: 1 1 auto; min-height: 0;
        display: grid;
        grid-template-columns: var(--lat-ancho) minmax(0, 1fr);
        grid-template-rows: minmax(0, 1fr);
        grid-template-areas: "apps lienzo";
        overflow: hidden;
    }
    .lateral {
        grid-area: apps;
        position: relative; inset: auto; z-index: auto;
        width: auto; min-width: 0;
    }
    .lienzo {
        grid-area: lienzo; min-width: 0;
        margin-left: 0;
        padding: 0 0 24px;
        background: var(--ink);
        border-left: 1px solid var(--rule);
        overflow-y: auto; overflow-x: hidden;
    }

    /* 2.4 LA BANDA, SUPERPUESTA EN LA BARRA DE TITULO. Pedido por Oscar el
       10/10/2026, senalando el hueco vacio de `.chrome-win` entre el titulo
       y el conmutador de tema: "usar este espacio... y reducir espacio". La
       aplicacion elegida y el semaforo del servicio ya no tienen fila
       propia -56px enteros solo para eso-: se superponen en los mismos 40px
       de la barra de titulo, en el hueco que quedaba vacio entre el titulo
       y el conmutador de tema. `position: fixed` y no `absolute`: banda
       vive fuera de `.chrome-win` en el HTML -ver el porque en el comentario
       de donde se borro su fila de la rejilla, mas arriba-, asi que no tiene
       un ancestro mas cercano que la pantalla entera para anclarse. */
    .banda {
        position: fixed;
        top: 0; left: 230px; right: 150px; bottom: auto;
        z-index: 15;
        height: 40px; min-height: 0;
        padding: 0; gap: clamp(8px, 1.5vw, 18px);
        background: transparent;
        border-bottom: 0;
        backdrop-filter: none;
    }
    .banda[data-estado="vacia"], .banda[data-estado="puesta"] { box-shadow: none; }
    .banda__cliente strong { font-size: 13px; }
    .banda__etiqueta { display: none; }
    /* La puerta de acceso se centra en el hueco que le queda al lienzo, no en la
       pantalla entera: `100vh` aqui son los 900 px del navegador y el lienzo
       mide 700, asi que la caja empujaba un scroll que no hacia falta. */
    .acc { min-height: 0; }

    /* Barra de desplazamiento fina y sin pista visible, como la overlay
       scrollbar de Fluent: solo pesa cuando se usa. */
    .lienzo::-webkit-scrollbar, .lat-lista::-webkit-scrollbar { width: 12px; }
    .lienzo::-webkit-scrollbar-track, .lat-lista::-webkit-scrollbar-track { background: transparent; }
    .lienzo::-webkit-scrollbar-thumb, .lat-lista::-webkit-scrollbar-thumb {
        background: var(--rule);
        border: 4px solid transparent;
        border-radius: 8px;
        background-clip: padding-box;
    }

    /* 2.4 LA BARRA DE APLICACIONES, EN FLUENT. Se deja sobre el material Mica de
       la ventana, como el pane de un NavigationView: es el contenido el que se
       levanta encima, no la barra. Lo que cambia respecto de antes es el
       acabado, no la estructura ni las senales: la fila elegida se sigue
       marcando con fondo solido, filete lateral y peso de letra, que es lo que
       impide lanzar un pentest contra el objetivo de otro cliente. */
    .lateral {
        padding: 4px 8px 10px;
        gap: 0;
        border-right: 1px solid var(--rule);
    }
    .lat-marca { padding: 8px 4px 14px; border-bottom: 0; }
    .lat-nav { gap: 2px; padding-bottom: 4px; }
    .lat-seccion, .lat-emp__t { padding: 12px 10px 6px; margin: 0; }
    .lat-emp { gap: 4px; }
    .lat-lista { gap: 2px; }

    /* NavigationViewItem con plantilla de dos lineas: 10 px de radio, el item
       entero es la superficie pulsable y el hover le superpone un velo en lugar
       de cambiarle el color. */
    .hrm, .emp { border-radius: 10px; }
    /* `:not(.activa)` NO SOBRA: este bloque va al final de la hoja y `.hrm:hover`
       tiene la misma especificidad que `.hrm.activa`, asi que sin la exclusion
       el velo del hover le ganaba por orden y la fila elegida perdia su fondo
       solido justo al pasarle el raton por encima, que es cuando mas se mira. */
    .hrm:hover:not(.activa) { background: var(--capa-hover); border-color: var(--rule); }
    .emp { padding: 8px 11px 8px 9px; }
    .emp:hover:not(.emp--activa) { background: var(--capa-hover); border-color: var(--rule); }

    /* El pane reserva su base para destinos secundarios -Ajustes en el sistema-
       y aqui para la cuenta, que es de quien es el proyecto que se audita. */
    .lat-pie { padding-top: 10px; border-top: 1px solid var(--rule); }

    /* 2.5 CABECERA DE PAGINA. Win11 pone el nombre de la pagina arriba a la
       izquierda y sus comandos a la derecha: navegar a un lado, ejecutar al
       otro, que es el reparto de un CommandBar. */
    .banda { padding: 0 var(--gutter); }

    /* 2.6 EL PIVOT. Win11 marca la pestana activa con una barra inferior CORTA y
       centrada en el acento, no con un filete de lado a lado. Se queda el fondo
       solido y el peso de la letra: son las otras dos senales de las tres, y
       bajar a una sola era el error que esta hoja ya evito una vez en la barra
       lateral. */
    .pest-fila { padding-top: 14px; }
    .pest__b { border-radius: 6px 6px 0 0; box-shadow: none; }
    .pest__b--on, .pest__b[aria-selected="true"] { box-shadow: none; }
    .pest__b--on::after, .pest__b[aria-selected="true"]::after {
        content: "";
        position: absolute;
        left: 14px; right: 14px; bottom: 2px;
        height: 3px; border-radius: 2px;
        background: var(--gold);
    }

    /* 2.7 EL FOCO EN WIN11 ES UN ANILLO DOBLE -trazo oscuro interior, claro
       exterior- para sobrevivir sobre cualquier fondo. */
    .btn:focus-visible, .btn-tema:focus-visible, .hrm:focus-visible,
    .emp:focus-visible, .lat-yo__b:focus-visible,
    .lat-tirador:focus-visible {
        outline: none;
        box-shadow: 0 0 0 2px var(--ink), 0 0 0 4px var(--bone);
    }
}


/* --- 3. CARA iOS ----------------------------------------------------------
   iPhone, Large Title, listas agrupadas y tab bar translucida.

   POR QUE LA BARRA DE APLICACIONES SE CONVIERTE EN UNA LISTA AGRUPADA Y NO EN
   UNA FILA PLEGADA CON CHEVRON. Las dos son patrones legitimos de iOS, pero
   contestan preguntas distintas: la fila con chevron es para un selector cuyo
   valor se consulta de vez en cuando -empuja otra pantalla y esconde a los
   hermanos-, y la lista agrupada es para elegir entre pocas opciones cuando la
   eleccion tiene consecuencias. Aqui la tiene: equivocarse de aplicacion es
   lanzar un pentest autorizado contra el objetivo de otro cliente. Y, sobre
   todo, una fila puede llevar el estado HUERFANA, que es una alarma -una
   corrida cuyo proceso sobrevivio al servidor-; detras de un chevron esa alarma
   solo se ve si a alguien se le ocurre tocar. Asi que la barra se queda entera y
   al principio del scroll.
   -------------------------------------------------------------------------- */
@media (max-width: 999px) {

    .escena { padding: 0; }

    /* El margen de la pagina es el de iOS -16 px- y deja de seguir al viewport:
       `3.5vw` se median contra la ventana del navegador y no contra el telefono,
       asi que a 999 px el contenido de un aparato de 393 px arrancaba con 35 px
       de sangria a cada lado. */
    :root { --gutter: 16px; }

    /* Sin chasis de iPhone ni barra de estado falsa: la pantalla ocupa el
       aparato entero, igual que en la cara de escritorio. */
    .aparato {
        width: 100%;
        background: var(--ink);
    }
    .pantalla {
        width: 100%;
        height: 100vh;
        min-height: 560px;
        overflow: hidden;
        background: var(--ink);
        isolation: isolate;
    }

    /* 3.1 NAV BAR. La cabecera va absoluta sobre el scroll para que el blur
       tenga contenido detras: en iOS el material no es un color, es el fondo
       desenfocado. */
    .chrome-ios {
        display: block;
        position: absolute;
        top: 0; left: 0; right: 0;
        z-index: 20;
        background: var(--material);
        -webkit-backdrop-filter: blur(20px) saturate(180%);
        backdrop-filter: blur(20px) saturate(180%);
        border-bottom: .5px solid var(--rule);
    }

    .navbar { position: relative; height: 44px; display: flex; align-items: center; padding: 0 10px 0 16px; }
    .nb-logo { height: 26px; width: auto; object-fit: contain; }

    /* Boton circular de barra, a la derecha de la nav bar: el sitio del boton de
       accion en iOS, igual que el del title bar en Windows. Es el MISMO elemento
       en las dos caras, solo cambia de forma y de sitio. */
    .btn-tema {
        position: absolute;
        top: 5px; right: 10px;
        width: 34px; height: 34px;
        display: grid; place-items: center;
        border: 0; border-radius: 50%;
        background: var(--relleno);
        color: var(--gold);
        cursor: pointer;
        z-index: 25;
    }
    .btn-tema:active { transform: scale(.94); }
    .btn-tema__t { display: none; }

    /* Indicador de inicio: el gesto de Home, siempre sobre el contenido. */
    .indicador {
        display: block;
        position: absolute;
        bottom: 8px; left: 50%;
        transform: translateX(-50%);
        width: 140px; height: 5px;
        border-radius: 3px;
        background: var(--bone);
        opacity: .85;
        z-index: 30;
    }

    /* 3.2 EL SCROLL. Una sola columna y un solo desplazamiento, con hueco arriba
       para la cabecera y abajo para la tab bar, que es lo que en iOS son las
       safe areas.

       `position: static` NO ES DECORATIVO: la tab bar de abajo se posiciona
       contra `.pantalla` y no contra el scroll, que es lo que la deja quieta
       mientras el contenido corre. Si este contenedor se posicionara, pasaria a
       ser SU bloque contenedor y la barra se iria con el scroll. */
    .cuerpo {
        position: static;
        height: 100%;
        overflow-y: auto; overflow-x: hidden;
        overscroll-behavior: contain;
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        /* `max-content` Y NO `auto`, Y SE PAGO CARO AVERIGUARLO. Con filas
           `auto` y un contenedor de alto definido, cuando la suma de las filas
           no cabe el navegador reparte el hueco desde la base de cada una, y la
           base de una fila `auto` es el MINIMO del item, no su contenido. La
           banda declaraba `min-height: 0` -venia de quitarle los 56 px de la
           cara de escritorio- asi que su base era 0: la fila se quedaba en 18 px
           -solo el relleno- y el Large Title se dibujaba ENCIMA de la lista de
           herramientas. Con `max-content` la base ya es el contenido y la fila
           no puede encogerse por debajo de el. */
        grid-template-rows: max-content max-content max-content;
        grid-template-areas: "banda" "apps" "lienzo";
        align-content: start;
        padding: 44px 0 100px;
        scrollbar-width: none;
    }
    .cuerpo::-webkit-scrollbar { width: 0; }

    /* 3.3 LARGE TITLE. El nombre de la aplicacion elegida ES el titulo de esta
       pantalla -no hay otro mas importante- y vive DENTRO del scroll, que es por
       lo que se colapsa al subir: 34 px, peso 700, alineado a la izquierda y con
       el tracking apretado. */
    .banda {
        grid-area: banda;
        position: static;
        min-height: auto;
        display: block;
        padding: 8px 16px 10px;
        background: transparent;
        border-bottom: 0;
        box-shadow: none;
        backdrop-filter: none;
    }
    .banda[data-estado="vacia"], .banda[data-estado="puesta"] {
        border-bottom: 0;
        box-shadow: none;
    }
    .banda__cliente { display: block; }
    .banda__etiqueta { display: block; margin-bottom: 2px; }
    .banda__cliente strong {
        display: block;
        font-size: 30px; font-weight: 700; line-height: 1.1;
        letter-spacing: -.5px;
        white-space: normal;
    }
    .banda__sem { margin-top: 10px; flex-wrap: wrap; }

    /* 3.4 LA BARRA DE APLICACIONES COMO LISTAS AGRUPADAS. El patron que define
       iOS: filas agrupadas en tarjetas de 10 px de radio, 16 px de margen
       lateral, y un encabezado en mayusculas pequenas alineado con el TEXTO de
       las filas. */
    .lateral {
        grid-area: apps;
        position: relative; inset: auto; z-index: auto;
        display: block;
        width: auto; min-width: 0;
        padding: 0;
        gap: 0;
        background: transparent;
        border-right: 0;
        backdrop-filter: none;
        overflow: visible;
    }

    /* La cabecera de marca se va, y es la unica pieza de la barra que lo hace:
       el isotipo ya esta en la nav bar y "RTSS · v2" en el pie de la pagina, asi
       que repetirlo aqui seria la tercera copia. Es chrome, no dato. */
    .lat-marca { display: none; }

    /* EL PLIEGUE SE APAGA AQUI. Nacio para recuperar ancho con el zoom alto y
       una columna fija a la izquierda; sin esa columna, plegar seria esconder la
       lista de aplicaciones -con su estado HUERFANA- detras de un tirador que ya
       no pliega nada. */
    .lat-tirador { display: none; }
    html.lat-plegada .lateral { padding: 0; gap: 0; }
    /* Se deshace el pliegue por si se venia de la cara ancha con la barra
       recogida: la clase vive en <html> y sobrevive al cambio de ancho. La
       cabecera de marca queda FUERA de la exclusion -si no, volveria a
       aparecer- y es la pieza que esta cara no quiere repetida. */
    html.lat-plegada .lateral > *:not(.lat-tirador):not(.lat-marca) { display: block; }

    .lat-seccion, .lat-emp__t {
        display: block;
        margin: 0;
        padding: 22px 32px 7px;
        font-family: var(--font-sans);
        font-size: 13px; letter-spacing: .06em;
    }
    .lat-nav, .lat-emp { display: block; overflow: visible; min-height: 0; }

    /* LA TARJETA DEL GRUPO DE APLICACIONES ES `.lat-lista`, que ya es un
       elemento propio y deja al encabezado fuera, que es donde lo pone iOS. */
    .lat-lista {
        margin: 0 16px;
        background: var(--ink-2);
        border-radius: var(--r-ios);
        overflow: hidden;
        max-height: none; min-height: 0;
        padding: 0;
        box-shadow: var(--panel-sombra);
    }

    /* 44 px es el objetivo tactil minimo de las HIG, y es el alto que gobierna
       toda la lista; con dos lineas de texto crece, nunca encoge. */
    .hrm, .emp {
        position: relative;
        width: 100%;
        min-height: 44px;
        padding: 11px 16px;
        border: 0; border-radius: 0;
        border-left: 0;
        background: transparent;
        gap: 2px 12px;
    }
    /* Separador que NO llega al borde izquierdo: arranca alineado con el texto.
       Es el detalle mas reconocible de una lista de iOS, y el que la distingue
       de una tabla cualquiera. */
    .hrm:not(:last-child)::after, .emp:not(:last-child)::after {
        content: '';
        position: absolute;
        left: 56px; right: 0; bottom: 0;
        height: .5px;
        background: var(--rule);
    }
    .hrm:hover, .emp:hover { background: transparent; border-color: transparent; }
    /* El pulsado de una fila de lista: un velo translucido ENCIMA del fondo de
       la tarjeta, que es lo que hace iOS. Sobre `.lat-lista` basta con poner el
       velo, porque la tarjeta esta debajo en el contenedor. */
    .emp:active { background: var(--relleno); }

    /* EL GRUPO DE HERRAMIENTAS NO TIENE UN `.lat-lista`: su encabezado y sus dos
       filas son hermanos dentro de `.lat-nav`. La tarjeta se monta entonces
       sobre las FILAS -fondo propio y esquinas redondeadas solo en la primera y
       la ultima-, no sobre el contenedor. Se intento al reves, con la tarjeta en
       `.lat-nav` y el encabezado sacado con un margen negativo, y el
       `overflow: hidden` que redondea las esquinas se lo comia: el rotulo
       HERRAMIENTAS desaparecia.

       VA DESPUES DE LAS REGLAS GENERICAS DE LA FILA, no antes: `.hrm` y
       `.lat-nav .hrm` empatan en especificidad para el navegador -las clases
       cuentan, el descendiente no- asi que gana la ultima, y puesta arriba el
       `background: transparent` de la fila generica borraba la tarjeta entera. */
    .lat-nav { margin: 0 16px; background: transparent; }
    .lat-nav .lat-seccion { padding: 22px 16px 7px; }
    .lat-nav .hrm, .lat-nav .hrm:hover { background: var(--ink-2); }
    .lat-nav .hrm:first-of-type {
        border-top-left-radius: var(--r-ios);
        border-top-right-radius: var(--r-ios);
    }
    .lat-nav .hrm:last-of-type {
        border-bottom-left-radius: var(--r-ios);
        border-bottom-right-radius: var(--r-ios);
    }
    /* Y aqui el velo tiene que ir en una capa propia: debajo no hay tarjeta que
       lo sostenga, asi que un color translucido a secas dejaria ver el fondo de
       grupo a traves de la fila. */
    .lat-nav .hrm:active {
        background: linear-gradient(var(--relleno), var(--relleno)) var(--ink-2);
    }

    .hrm__t, .emp__n {
        font-family: var(--font-sans); font-size: 16px; font-weight: 600;
        letter-spacing: .01em; text-transform: none; color: var(--bone);
    }
    .hrm__d { font-size: 13px; padding-right: 0; }
    .hrm > i:first-child { font-size: 20px; width: 26px; text-align: center; color: var(--gold); }
    .hrm__candado { top: 14px; right: 14px; font-size: 13px; }
    .hrm__luz { top: 17px; right: 36px; }
    /* Aqui las dos herramientas son filas seguidas de una lista, sin aire
       entre ellas: una pestaña que sobresale por abajo -como en la barra de
       escritorio- se superpondria con la fila de aplicaciones de debajo en
       vez de anunciarla. La lista ya nace justo bajo RTSS y se ve sola. */
    .hrm__flecha { display: none; }
    .emp .mono { width: 44px; height: 44px; flex-basis: 44px; border-radius: 11px; font-size: 14px; }
    .emp__d { font-size: 12px; }

    /* SELECCION EXCLUSIVA EN LISTA: nombre en el color de acento y sin tenir la
       fila. iOS no pinta el fondo de la fila elegida -eso lo hace Windows con su
       filete-, y aqui ademas conviene, porque es lo que deja tenir el nombre:
       sobre la tarjeta limpia el acento da 5.22:1 en oscuro y 5.71:1 en claro,
       y sobre el tinte de --lat-activo se cae a 4.19:1 y 4.69:1. Siguen siendo
       tres senales -color del nombre, anillo del monograma y la palomita-, que
       es lo que esta hoja exige donde equivocarse de fila cuesta un pentest
       contra el objetivo de otro. */
    .emp--activa {
        background: transparent;
        border-color: transparent;
        border-left-color: transparent;
    }
    /* La fila de herramienta activa pierde el TINTE pero no la tarjeta: aqui la
       tarjeta del grupo la llevan las propias filas -no hay un `.lat-lista` que
       la sostenga- asi que dejarla transparente abria un hueco gris en medio del
       grupo y se comia el separador de arriba. */
    .hrm.activa {
        background: var(--ink-2);
        border-color: transparent;
        border-left-color: transparent;
    }
    .hrm.activa .hrm__t, .emp--activa .emp__n { color: var(--bone); }
    .hrm.activa::before, .emp--activa::before {
        content: '';
        position: absolute;
        right: 18px; top: 50%;
        width: 6px; height: 12px;
        margin-top: -8px;
        border-right: 2.2px solid var(--gold);
        border-bottom: 2.2px solid var(--gold);
        border-radius: 1px;
        transform: rotate(45deg);
    }
    .hrm.activa .hrm__t, .hrm.activa .hrm__d,
    .emp--activa .emp__n, .emp--activa .emp__d { padding-right: 22px; }

    /* El pie de cuenta es otro grupo mas: en iOS "de quien es esta sesion" se
       contesta al final de la lista de ajustes, que es donde se le busca. */
    .lat-pie {
        margin: 22px 16px 0;
        background: var(--ink-2);
        border-radius: var(--r-ios);
        overflow: hidden;
        box-shadow: var(--panel-sombra);
    }
    .lat-yo { margin-bottom: 0; }
    .lat-yo__b {
        min-height: 44px;
        padding: 11px 16px;
        border: 0; border-radius: 0;
        background: transparent;
    }
    .lat-yo__b:hover { background: transparent; border-color: transparent; }
    .lat-yo__av { width: 32px; height: 32px; flex-basis: 32px; font-size: 12px; }
    .lat-menu { margin: 0; border: 0; border-radius: 0; box-shadow: none; background: var(--relleno); }
    .lat-aviso { margin: 10px 16px 0; }

    /* 3.5 LA TAB BAR. Cinco destinos de primer nivel siempre visibles: icono
       arriba, etiqueta debajo, la activa en el color de acento, y el mismo
       material translucido que la nav bar. Es la MISMA lista de pestanas que en
       escritorio se dibuja como pivot: una sola, no dos, y la gobierna el mismo
       JS sin enterarse de que cambio de sitio.

       `.pest-fila > .pest` Y NO `.pest` A SECAS: la sub-ventana de ajustes tiene
       su propia fila de pestanas con la misma clase, y mandarla al pie de la
       pantalla la sacaria de su ventana. */
    .pest-fila > .pest {
        position: absolute;
        bottom: 0; left: 0; right: 0;
        z-index: 20;
        height: 83px;
        padding: 7px 4px 26px;
        margin: 0;
        display: flex;
        gap: 0;
        overflow: visible;
        background: var(--material);
        -webkit-backdrop-filter: blur(20px) saturate(180%);
        backdrop-filter: blur(20px) saturate(180%);
        border-top: .5px solid var(--rule);
        border-bottom: 0;
    }
    .pest-fila > .pest .pest__b {
        flex: 1 1 0; min-width: 0;
        flex-direction: column;
        align-items: center; justify-content: center;
        gap: 3px;
        padding: 0 2px;
        border: 0; border-radius: 0;
        background: transparent;
        box-shadow: none;
        color: var(--tenue);
        /* La etiqueta de una tab bar de iOS va en caja de frase, no en
           versales: las versales son un 15% mas anchas y "Configuracion" no cabe
           en la quinta parte de un iPhone. */
        font-family: var(--font-sans); font-size: 9.5px; font-weight: 600;
        letter-spacing: 0; text-transform: none;
    }
    .pest-fila > .pest .pest__b::after { content: none; }
    .pest-fila > .pest .pest__b i { font-size: 20px; }
    .pest-fila > .pest .pest__t {
        max-width: 100%;
        text-align: center; line-height: 1.1;
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .pest-fila > .pest .pest__b--on,
    .pest-fila > .pest .pest__b[aria-selected="true"] {
        background: transparent;
        color: var(--bone);
        font-weight: 700;
    }
    .pest-fila > .pest .pest__b--on i,
    .pest-fila > .pest .pest__b[aria-selected="true"] i { color: var(--gold); }
    /* El punto de novedad se monta sobre el icono, que es donde lo pone iOS. */
    .pest-fila > .pest .pest__nuevo {
        position: absolute;
        top: 2px; left: 50%;
        margin-left: 6px;
    }

    /* Lo que queda de la fila son las dos ACCIONES -lanzar un retesting y
       limpiar-, que nunca fueron pestanas. En iOS una accion secundaria de
       pantalla es un boton de texto en el color de acento, sin fondo. */
    .pest-fila {
        display: flex;
        justify-content: flex-start;
        gap: 20px;
        padding: 2px 16px 0;
        border-bottom: 0;
        margin-bottom: 14px;
    }
    .pest__fin {
        margin-bottom: 0;
        padding: 6px 0;
        border: 0;
        background: transparent;
        color: var(--bone);
        font-family: var(--font-sans); font-size: 15px; font-weight: 600;
        letter-spacing: .01em; text-transform: none;
    }
    .pest__fin span { display: inline; }
    .pest__fin:hover:not(:disabled) { background: transparent; border-color: transparent; color: var(--bone); }
    .pest__fin:active:not(:disabled) { opacity: .45; }

    /* 3.6 EL CONTENIDO, EN FORMA DE iOS. Mismas tarjetas, otro acabado: 10 px de
       radio, sin borde -la elevacion la da el blanco contra el fondo de grupo,
       no una linea- y 16 px de margen. */
    .lienzo {
        grid-area: lienzo; min-width: 0;
        margin-left: 0;
        padding: 0 0 4px;
        background: transparent;
    }
    .shell { padding: 0; }
    .section-head { margin: 18px 16px 16px; padding-bottom: 14px; }
    .section-head h2 { font-size: 26px; line-height: 1.15; }
    .vcab__miga { margin: 0 16px; }
    .console, .caja, .sel, .acc__caja, .zona > .ag-estado {
        border-radius: var(--r-ios);
        box-shadow: var(--panel-sombra);
    }
    .console { margin: 0 16px; padding: 16px; }
    .sel { margin: 0 16px; padding: 16px; }
    .acc { min-height: 0; padding: 16px; }
    .foot { margin: 0 16px; }

    :focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
}


/* --- 4. TELEFONO ESTRECHO -------------------------------------------------
   Por debajo de 440 px el navegador ES el telefono: dibujar un bisel de iPhone
   dentro de una ventana del ancho de un iPhone roba 22 px de contenido para
   ensenar un marco que el usuario ya tiene en la mano. Se quita el chasis y la
   pantalla ocupa el alto entero, que es lo que hace una app instalada. La isla,
   la barra de estado y la tab bar se quedan: eso no es el aparato, es la app.
   -------------------------------------------------------------------------- */
@media (max-width: 439px) {
    .escena { padding: 0; }
    .aparato {
        width: 100%;
        padding: 0;
        border: 0; border-radius: 0;
        box-shadow: none;
    }
    .pantalla { height: 100vh; min-height: 560px; border-radius: 0; }
}

/* ------------------------------------------------ descargas del retesting
   La barra del informe va ARRIBA DEL TODO del cuerpo, antes de los veredictos:
   es la accion de la carpeta entera, y puesta al final habria que recorrer
   quince hallazgos para encontrarla. El anexo de evidencia, en cambio, va
   dentro de su veredicto, porque es de ese veredicto y de ningun otro. */
.rtx__acc { display: flex; justify-content: flex-end; margin: 0 0 14px; }
.hz-inf__b--ev { margin-top: 6px; }

/* --------------------------------------------- Email Breach Checker (iframe)
   Mismo patron que #vista-acceso: pantalla completa, sin el padding de
   `.lienzo` ni el ancho maximo de `.shell`, porque lo que vive aqui dentro
   -el Email Breach Monitor independiente- pinta su propia cabecera y su
   propio pie; envolverlo en los de esta consola seria duplicarlos.

   LA BANDA Y EL PIE DE RTSS, APAGADOS AQUI TAMBIEN. Pedido el 20/10/2026:
   se veian "SIN APLICACION ELEGIDA" / "INACTIVO" encima del iframe, y esta
   herramienta -como Scan Regular- no tiene aplicacion que elegir: es
   freemium, sin sesion. Mismo criterio y misma regla que ya usa
   `#vista-scan` mas arriba en esta hoja. */
body:has(#vista-breach:not([hidden])) #banda,
body:has(#vista-breach:not([hidden])) .foot { display: none; }
.lienzo:has(> #vista-breach:not([hidden])) { padding: 0; }
#vista-breach:not([hidden]) { min-height: 100%; display: flex; }
#vista-breach .shell--iframe {
    max-width: none; margin: 0; padding: 0; flex: 1; display: flex;
}
.iframe-breach { flex: 1; width: 100%; border: 0; background: var(--ink, #171314); }
.rtx__nota { flex-basis: 100%; margin: 8px 0 0; text-align: left; }

/* =====================================================================
   AVISO DE CORREO SIN CONFIRMAR. Solo lo enciende el servidor publico, y
   solo con sesion -ver avisoCorreo en app.html y app.js-. Sticky arriba del
   todo, igual que la banda: el servidor ya rechaza con 403 un analisis sin
   correo confirmado, asi que esto tiene que verse antes de que alguien lo
   descubra por un error de 403 sin contexto.
   ===================================================================== */
.aviso-correo {
    position: sticky; top: 0; z-index: 60;
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
    padding: 10px 16px;
    background: var(--acc-soft, #2a1417);
    border-bottom: 1px solid var(--aviso, #f0b429);
    color: var(--bone, #e7e9ec);
    font: 400 13px/1.4 var(--font-sans);
}
.aviso-correo__t { font-weight: 600; display: flex; align-items: center; gap: 8px; }
.aviso-correo__t i { color: var(--aviso, #f0b429); }
.aviso-correo__form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.aviso-correo__form input {
    background: var(--campo, #0d0e11); color: var(--campo-texto, #e7e9ec);
    border: 1px solid var(--campo-borde, #6f7783); border-radius: 8px;
    padding: 6px 10px; width: 150px; font: inherit; letter-spacing: 2px;
}
.aviso-correo__form input:focus-visible {
    outline: 2px solid var(--anillo, #ff8a8c); outline-offset: 1px;
}
.aviso-correo__msg { flex-basis: 100%; margin: 0; font-size: 12px; }
.aviso-correo__msg--bien { color: var(--bien, #3ccf8e); }
.aviso-correo__msg--mal { color: var(--mal, #ff6b6e); }
