/*
 * Estilos del contenedor de la aplicación: menú lateral, barra superior y
 * componentes comunes (tarjetas, tablas, formularios, pestañas).
 *
 * Se apoya en los tokens de theme.css, que traen la identidad de QORVEX.
 * Vocabulario de clases en español, el mismo que ya tenía el proyecto. No se
 * usa ningún framework de utilidades.
 *
 * REGLA QUE SOSTIENE LOS DOS TEMAS: aquí NO hay colores.
 * El tema claro se implementa reasignando las variables de theme.css, así que
 * un color escrito a mano en este archivo es un píxel que no se enterará de
 * que cambió el tema, y se descubre como texto blanco sobre blanco. La única
 * excepción es el bloque de impresión del final, y está justificada allí.
 */

/* ── Base global ────────────────────────────────────────────────────── */

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

html {
	background: var(--color-bg);
}

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

h1,
h2,
h3 {
	text-wrap: balance;
	margin: 0;
}

/* Display en Space Grotesk, bold y con tracking +0.04em (§3 del manual). Solo
   el H1: los H2/H3 siguen en Inter para que la jerarquía la marque el tamaño y
   no un cambio de familia en cada tarjeta. */
h1 {
	font-family: var(--font-display);
	font-weight: 700;
	letter-spacing: 0.04em;
	line-height: 1.15;
}

p {
	text-wrap: pretty;
}

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

a:hover {
	text-decoration: underline;
}

/* «Enlaces y botones deben proyectar un contorno nítido de 2 px en Cyan Vector
   al recibir navegación por teclado» (§4). En Cyan, no en el color de marca:
   el foco tiene que verse igual sobre el cromo oscuro y sobre el contenido. */
:focus-visible {
	outline: 2px solid var(--color-vector);
	outline-offset: 2px;
}

svg {
	flex: none;
}

/* Todo dato de red —IP, MAC, uptime, tráfico, cifras— va en cifra tabular:
   sin esto, un contador que se refresca cambia de ancho a cada segundo y la
   columna entera baila. */
.mono,
.kpi-valor,
.dato {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-feature-settings: 'tnum' 1;
}

/* ── Marca ────────────────────────────────────────────────────────────
 * No existe logotipo de producto para QHOTSPOT. Hasta que QORVEX entregue uno,
 * la forma admitida es el isotipo con el nombre en TEXTO, en Space Grotesk.
 * Fabricarlo redibujando la tipografía está prohibido (§7).
 */

.marca {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	min-width: 0;
}

.marca__logo {
	flex: 0 0 auto;
}

.marca__texto {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.marca__nombre {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.95rem;
	letter-spacing: 0.04em;
	color: var(--color-text);

	/* En el teléfono el nombre no debe partirse en dos líneas y empujar el
	   resto de la barra: antes se corta. */
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.marca__sub {
	font-size: 0.7rem;
	color: var(--color-muted);
	white-space: nowrap;
}
.app {
	min-height: 100vh;
	background: var(--color-bg);
}

/* ── Menú lateral ─────────────────────────────────────────────────────
 * Es un panel desplegable que se superpone al contenido en CUALQUIER tamaño de
 * pantalla, no una columna fija: el editor del portal y las tablas de sesiones
 * aprovechan todo el ancho disponible, y reservarle 280 px permanentes se los
 * quitaría incluso cuando nadie está navegando.
 *
 * La 012 probó la columna fija a partir de 1280 px y se retiró el 9 oct 2026
 * (013): el menú se comporta como el de la familia de marca.
 */

.menu {
	position: fixed;
	top: 0;
	left: 0;
	bottom: 0;
	z-index: 60;
	width: 280px;
	max-width: 86vw;
	display: flex;
	flex-direction: column;
	background: var(--menu-bg);
	color: var(--menu-texto);
	overflow-y: auto;
	transform: translateX(-100%);
	transition: transform 0.22s ease;
	box-shadow: 0 0 40px rgb(4 12 26 / 55%);
}

.menu--abierto {
	transform: translateX(0);
}

.menu__marca {
	display: flex;
	align-items: flex-start;
	gap: 0.7rem;
	padding: 1rem 1rem 0.95rem;
	border-bottom: 1px solid var(--menu-borde);
}

/* La marca y, debajo, quién opera la red. El producto es QHOTSPOT; la entidad
   es el cliente, y por eso va en segundo plano y no al revés. */
.menu__identidad {
	display: flex;
	align-items: center;
	gap: 0.55rem;
}

.menu__entidad {
	margin: 0.4rem 0 0;
	font-size: 0.6875rem;
	color: var(--menu-texto-suave);
}

/* El escudo conserva su plaqueta clara. No es adorno: es un blasón a todo
   color y sobre un fondo casi negro se vuelve una mancha ilegible. */
/* SIN fondo blanco. Lo llevaba cuando el logotipo era el de INNOLAB, que es
   oscuro sobre claro; el isotipo de QORVEX es la «Q» BLANCA con su vector cian
   sobre transparente, y sobre un cuadro blanco desaparecería la mitad. */
.menu__logo {
	flex: 0 0 auto;
}

.menu__marca-texto {
	flex: 1;
	min-width: 0;
}

.menu__titulo {
	font-family: var(--font-display);
	font-size: 1.0625rem;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.01em;
	color: var(--menu-texto);
}

.menu__cerrar {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 30px;
	height: 30px;
	border-radius: 8px;
	border: 0;
	background: transparent;
	color: var(--menu-texto-suave);
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

.menu__cerrar:hover {
	background: var(--menu-hover);
	color: var(--menu-texto);
}

.menu__nav {
	flex: 1;
	padding: 0.7rem 0.55rem;
	display: flex;
	flex-direction: column;
	gap: 0.12rem;
}

.menu__seccion {
	padding: 0.75rem 0.7rem 0.3rem;
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--menu-texto-suave);
	opacity: 0.75;
}

.menu__enlace {
	position: relative;
	display: flex;
	align-items: center;
	gap: 0.72rem;
	width: 100%;
	padding: 0.6rem 0.7rem;
	border-radius: 10px;
	color: var(--menu-texto-suave);
	text-decoration: none;
	font: inherit;
	font-size: 0.9rem;
	font-weight: 500;
	background: transparent;
	border: 0;
	text-align: left;
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

/* El rótulo se trunca: un nombre largo no debe empujar al galón del grupo
   fuera del panel ni partir la fila en dos líneas. */
.menu__rotulo {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.menu__enlace:hover {
	background: var(--menu-hover);
	color: var(--menu-texto);
	text-decoration: none;
}

/* El elemento activo se distingue por fondo y por una barra amarilla, no solo
   por color: quien no distingue bien los colores igual lo identifica.
   La barra va como pseudoelemento y no como `inset box-shadow` para poder
   redondearla y dejarla más corta que la fila. */
.menu__enlace[aria-current='page'] {
	background: var(--menu-activo);
	color: var(--menu-texto);
	font-weight: 600;
}

.menu__enlace[aria-current='page']::before {
	content: '';
	position: absolute;
	left: 0;
	top: 50%;
	transform: translateY(-50%);
	width: 3px;
	height: 55%;
	border-radius: 0 3px 3px 0;
	background: var(--color-highlight);
}

.menu__pie {
	padding: 0.85rem;
	border-top: 1px solid var(--menu-borde);
}

.menu__usuario {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	margin-bottom: 0.7rem;
}

.menu__avatar {
	width: 38px;
	height: 38px;
	border-radius: 50%;
	background: var(--menu-avatar);
	color: var(--menu-texto);
	display: grid;
	place-items: center;
	font-weight: 600;
	font-size: 0.82rem;
	flex: 0 0 auto;
}

.menu__usuario-datos {
	min-width: 0;
}

.menu__usuario-nombre {
	font-weight: 600;
	font-size: 0.88rem;
	line-height: 1.25;
	overflow-wrap: anywhere;
}

.menu__usuario-rol {
	display: flex;
	align-items: center;
	gap: 0.35rem;
	color: var(--menu-texto-suave);
	font-size: 0.76rem;
}

.menu__punto {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--color-success);
	flex: 0 0 auto;
}

.menu__boton {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	padding: 0.62rem;
	border-radius: 10px;
	border: 1px solid var(--menu-borde-fuerte);
	background: transparent;
	color: var(--menu-texto);
	font: inherit;
	font-size: 0.85rem;
	font-weight: 500;
	cursor: pointer;
	transition: background 0.15s ease;
}

.menu__boton + .menu__boton {
	margin-top: 0.45rem;
}

.menu__boton:hover {
	background: var(--menu-hover);
}

/* Con el menú abierto, la página de detrás no se desplaza: en el móvil, al
   arrastrar dentro del panel se movía el contenido y uno acababa en otro
   punto de la pantalla al cerrarlo. */
body.menu-abierto {
	overflow: hidden;
}

.velo {
	position: fixed;
	inset: 0;
	background: rgb(6 20 40 / 55%);
	backdrop-filter: blur(2px);
	z-index: 55;
	border: 0;
	padding: 0;
	cursor: pointer;
}

/* ── Grupos plegables ──────────────────────────────────────────────────
 *
 * Un grupo es un BOTÓN, no un rótulo: se pliega, lleva icono y galón, y no
 * enlaza a ninguna parte porque no es una pantalla. Antes eran versalitas
 * decorativas, que no decían que hubiera nada debajo que abrir.
 */

.menu__grupo {
	display: flex;
	align-items: center;
	gap: 0.72rem;
	width: 100%;
	padding: 0.6rem 0.7rem;
	border: 0;
	border-radius: 10px;
	background: transparent;
	color: var(--menu-texto-suave);
	font: inherit;
	font-size: 0.9rem;
	font-weight: 500;
	text-align: left;
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

.menu__grupo:hover {
	background: var(--menu-hover);
	color: var(--menu-texto);
}

/* El galón apunta a la derecha plegado y gira 90° al abrirse. Es la única
   señal de que ahí dentro hay algo, así que no se puede quitar. */
.menu__galon {
	margin-left: auto;
	flex: 0 0 auto;
	opacity: 0.6;
	transition: transform 0.18s ease;
}

.menu__grupo[aria-expanded='true'] .menu__galon {
	transform: rotate(90deg);
}

/* Los hijos, indentados tras un filete: sin él, al plegar el grupo de arriba
   no se sabe de cuál cuelga cada uno. */
.menu__hijos {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	margin: 0.15rem 0 0.4rem 1.25rem;
	padding-left: 0.5rem;
	border-left: 1px solid var(--menu-borde-fuerte);
}

.menu__enlace--hijo {
	padding: 0.45rem 0.6rem;
	font-size: 0.8125rem;
}

/* ── Tema: tres opciones ───────────────────────────────────────────────
 *
 * Un grupo de radios, no tres botones sueltos: se recorre con las flechas y
 * solo el elegido entra en el orden de tabulación. Antes era un botón que
 * rotaba en la barra, que obligaba a pulsarlo para saber en qué estado estaba.
 */

.menu__tema {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	padding: 0.75rem 1rem;
	border-top: 1px solid var(--menu-borde);
}

.menu__tema-rotulo {
	font-size: 0.875rem;
	font-weight: 500;
	color: var(--menu-texto);
}

.tema {
	display: flex;
	gap: 0.25rem;
	padding: 0.25rem;
	border: 1px solid var(--menu-borde-fuerte);
	border-radius: 12px;
	background: var(--menu-hover);
}

.tema__opcion {
	display: grid;
	place-items: center;
	width: 40px;
	height: 32px;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: var(--color-primary);
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}

.tema__opcion:hover {
	background: var(--menu-borde-fuerte);
	color: var(--menu-texto);
}

.tema__opcion--activa {
	background: var(--color-primary-fuerte);
	color: #ffffff;
}

/* La versión en uso. En mono porque es un identificador que se copia y se
   pega en un reporte, no una frase. */
.menu__version {
	margin: 0.6rem 0 0;
	text-align: center;
	font-size: 0.625rem;
	color: var(--menu-texto-suave);
	opacity: 0.8;
}

/* ── Contenido ────────────────────────────────────────────────────────── */

.app,
.contenido {
	--alto-barra: 3.8rem;
}

.contenido {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	min-width: 0;

	/* Abajo, la barra de gestos de Android y la raya del iPhone. */
	padding-bottom: env(safe-area-inset-bottom);
}

/*
 * La barra superior manda sobre todo lo que se desplaza. Se queda por debajo
 * del menú lateral (60) y de su velo (55), que sí deben taparla al abrirse.
 */
.barra {
	position: sticky;
	top: 0;
	z-index: 40;

	--alto-barra: 3.8rem;
	min-height: var(--alto-barra);
	display: flex;
	align-items: center;
	gap: 0.55rem;

	/* El FONDO llega de lado a lado —la barra es el marco de la aplicación—,
	   pero su contenido se alinea con el de la página: el logotipo cae a plomo
	   sobre la primera tarjeta. Se consigue con el mismo `max()` del
	   contenedor, sin envolver nada en un div extra.

	   `env()` entra en la cuenta porque con `viewport-fit=cover` la aplicación
	   llega al borde físico, y en un móvil con muesca el logotipo quedaba
	   debajo de la cámara. Vale cero donde no hay recortes. */
	padding-top: calc(0.7rem + env(safe-area-inset-top));
	padding-bottom: 0.7rem;
	padding-left: max(var(--margen-lateral), env(safe-area-inset-left), calc((100% - var(--ancho-pagina)) / 2));
	padding-right: max(var(--margen-lateral), env(safe-area-inset-right), calc((100% - var(--ancho-pagina)) / 2));
	background: var(--color-surface);
	border-bottom: 1px solid var(--color-border);
}

.barra__escudo {
	display: block;
	flex: 0 0 auto;
	height: 28px;
	width: auto;
}

.barra:focus {
	outline: none;
}

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

/* Este botón es la única forma de llegar al resto del sistema, así que está
   presente en todos los tamaños de pantalla, no solo en móvil. */
.barra__menu-btn {
	display: grid;
	place-items: center;
	margin-right: 0.3rem;
	width: 38px;
	height: 38px;
	flex: 0 0 auto;
	background: transparent;
	border: 1px solid var(--color-border-strong);
	border-radius: 9px;
	cursor: pointer;
	color: var(--color-text);
}

.barra__menu-btn:hover {
	background: var(--color-surface-alt);
	border-color: var(--color-primary);
	color: var(--color-primary);
}

/* Acciones del extremo derecho de la barra (tema). */
.barra__acciones {
	display: flex;
	align-items: center;
	gap: 0.3rem;
	flex: 0 0 auto;
	margin-left: auto;
}

.barra__accion {
	display: grid;
	place-items: center;
	width: 38px;
	height: 38px;
	border: 1px solid transparent;
	border-radius: 9px;
	background: transparent;
	color: var(--color-muted);
	cursor: pointer;
}

.barra__accion:hover {
	background: var(--color-surface-alt);
	color: var(--color-primary);
}

/* La miga se queda con el hueco que sobra. */
.miga {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: center;
	gap: 0.45rem;
	font-size: 0.95rem;
}

.miga__raiz {
	color: var(--color-muted);
	font-weight: 500;
	white-space: nowrap;
}

.miga__sep {
	color: var(--color-border-strong);
}

/* El grupo: presente pero en segundo plano. Es contexto, no destino. */
.miga__grupo {
	color: var(--color-muted);
	white-space: nowrap;
	flex: none;
}

@media (max-width: 640px) {
	.miga__grupo,
	.miga__grupo + .miga__sep {
		display: none;
	}
}

.miga__actual {
	color: var(--color-text);
	font-weight: 700;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
}

@media (max-width: 600px) {
	.miga__raiz,
	.miga__raiz + .miga__sep {
		display: none;
	}
}

/*
 * El contenedor de contenido: márgenes laterales fluidos y medida máxima.
 *
 * No lleva `max-width` + `margin-inline: auto` sino un relleno calculado. Con
 * `max-width` el fondo se cortaría con el contenido; así el área sigue siendo
 * de lado a lado y lo que se centra es lo de dentro. Es lo mismo que hace la
 * barra, y por eso las dos cosas quedan alineadas.
 *
 * Cuando la ventana es más estrecha que `--ancho-pagina`, `(100% - ancho)/2`
 * sale negativo y gana `--margen-lateral`.
 */
.pagina {
	padding-top: 1.25rem;
	padding-bottom: 1.25rem;
	padding-left: max(var(--margen-lateral), env(safe-area-inset-left), calc((100% - var(--ancho-pagina)) / 2));
	padding-right: max(var(--margen-lateral), env(safe-area-inset-right), calc((100% - var(--ancho-pagina)) / 2));
	flex: 1;
	min-width: 0;

	/*
	 * Red de seguridad contra el desbordamiento horizontal: basta una MAC larga
	 * o una tabla ancha para que TODA la página quede recortada por la derecha
	 * en un teléfono. Se usa `clip` y no `hidden` porque `hidden` crearía un
	 * contenedor de desplazamiento y rompería el `sticky` de la barra.
	 */
	overflow-x: clip;
}

.pagina--sin-relleno {
	padding: 0;
}

@media (prefers-reduced-motion: reduce) {
	.menu {
		transition: none;
	}
}

/* Ver / ocultar la contraseña: en un móvil, a pleno sol, se agradece. */
.campo--con-boton {
	position: relative;
}

.campo--con-boton .campo__control {
	padding-right: 4.2rem;
}

.campo__boton {
	position: absolute;
	right: 0.3rem;
	bottom: 0.28rem;
	padding: 0.3rem 0.5rem;
	border: 0;
	border-radius: 6px;
	background: transparent;
	color: var(--color-primary);
	font: inherit;
	font-size: 0.78rem;
	font-weight: 600;
	cursor: pointer;
}

.campo__boton:hover {
	background: var(--color-surface-alt);
}

/* ── Cabecera de página ───────────────────────────────────────────────── */

.pagina__cabecera {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 0.9rem;
	flex-wrap: wrap;
	margin-bottom: 1.25rem;
}

.pagina__titulo {
	font-size: var(--fs-xl);
	font-weight: 700;
	letter-spacing: -0.015em;
}

.pagina__nota {
	margin: 0.2rem 0 0;
	font-size: 0.85rem;
	color: var(--color-muted);
}

/* ── Acción principal de la vista ─────────────────────────────────────
 * «Una acción principal por vista», con el degradado Cyan→Cobalt y texto
 * Obsidian (§4 del manual).
 *
 * Se resuelve por POSICIÓN y no con una clase nueva: el botón sólido de la
 * cabecera de página ES la acción principal —«Nuevo router», «Nuevo
 * administrador»— y hay como mucho uno. Así no hay que recordar ponerle una
 * clase en cada vista, y es imposible que aparezcan dos por descuido.
 *
 * `--color-sobre-vector` y no blanco: blanco sobre Cyan da 1,4:1.
 */
.pagina__acciones .boton:not(.boton--suave):not(.boton--fantasma):not(.boton--peligro):not(.boton--peligro-suave) {
	background: var(--gradient-brand);
	color: var(--color-sobre-vector);

	/* Único sitio con brillo, y acotado a 8 px: el manual prohíbe más. */
	box-shadow: var(--shadow-glow);
}

.pagina__acciones .boton:not(.boton--suave):not(.boton--fantasma):not(.boton--peligro):not(.boton--peligro-suave):hover:not(:disabled) {
	background: var(--gradient-brand);
	filter: brightness(1.08);
}

.pagina__acciones {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-wrap: wrap;
}

/* ── Componentes comunes ──────────────────────────────────────────────── */

.tarjeta {
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: var(--radius);
	padding: 1.1rem;
}

.tarjeta + .tarjeta {
	margin-top: 1rem;
}

.tarjeta--plana {
	padding: 0;
	overflow: hidden;
}

.tarjeta__titulo {
	display: flex;
	align-items: center;
	gap: 0.45rem;
	margin: 0 0 0.2rem;
	font-size: 1rem;
	font-weight: 700;
	color: var(--color-text);
}

.tarjeta__titulo svg {
	color: var(--color-primary);
}

.tarjeta__nota {
	margin: 0 0 0.9rem;
	font-size: 0.83rem;
	color: var(--color-muted);
}

.tarjeta__cabecera {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	flex-wrap: wrap;
	padding: 0.8rem 1rem;
	border-bottom: 1px solid var(--color-border);
}

.rejilla {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.rejilla-2 {
	display: grid;
	gap: 0 1rem;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.pestanas {
	display: flex;
	gap: 0.35rem;
	border-bottom: 2px solid var(--color-border);
	margin-bottom: 1.25rem;
	flex-wrap: wrap;
}

.pestana {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	appearance: none;
	background: transparent;
	border: 0;
	border-bottom: 3px solid transparent;
	margin-bottom: -2px;
	padding: 0.65rem 0.9rem;
	font: inherit;
	font-size: 0.9rem;
	font-weight: 600;
	color: var(--color-muted);
	cursor: pointer;
}

.pestana:hover {
	color: var(--color-text);
}

.pestana[aria-selected='true'] {
	color: var(--color-primary);
	border-bottom-color: var(--color-primary);
}

/* ── Tablas ───────────────────────────────────────────────────────────── */

.tabla-envoltura {
	overflow-x: auto;
	border: 1px solid var(--color-border);
	border-radius: var(--radius);
	background: var(--color-surface);
}

.tabla {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.875rem;
	min-width: 640px;
}

.tabla th,
.tabla td {
	padding: 0.7rem 0.85rem;
	text-align: left;
	border-bottom: 1px solid var(--color-border);
}

.tabla th {
	background: var(--color-surface-alt);
	font-size: 0.74rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--color-muted);
	white-space: nowrap;
}

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

.tabla__principal {
	font-weight: 600;
}

.tabla__secundario {
	font-size: 0.78rem;
	color: var(--color-muted);
	margin-top: 1px;
}

.tabla__acciones {
	display: flex;
	gap: 0.3rem;
	justify-content: flex-end;
}

/* La columna de acciones va a la derecha, cabecera incluida: alinear solo los
   botones deja el título flotando al otro extremo de la columna. */
.tabla th.tabla__col-acciones,
.tabla td.tabla__col-acciones {
	text-align: right;
}

/*
 * En el teléfono, una tabla de siete columnas se lee de lado y obliga a
 * arrastrar. `.tabla--fichas` la convierte en una ficha por fila, con la
 * cabecera de cada columna delante del dato (`data-etiqueta`).
 *
 * Es una extensión propia de este panel, no del sistema de referencia: allí
 * las tablas se desplazan en horizontal. Aquí la mitad de las consultas se
 * hacen de pie y con el móvil, así que compensa.
 */
@media (max-width: 640px) {
	.tabla--fichas {
		min-width: 0;
	}

	.tabla--fichas thead {
		display: none;
	}

	.tabla--fichas tbody tr {
		display: block;
		padding: 0.75rem 0.85rem;
		border-bottom: 1px solid var(--color-border);
	}

	.tabla--fichas tbody tr:last-child {
		border-bottom: 0;
	}

	.tabla--fichas tbody td {
		display: flex;
		align-items: baseline;
		justify-content: space-between;
		gap: 1rem;
		padding: 0.2rem 0;
		border: 0;
		text-align: right;
	}

	.tabla--fichas tbody td::before {
		content: attr(data-etiqueta);
		flex: 0 0 auto;
		text-align: left;
		font-size: 0.68rem;
		font-weight: 700;
		letter-spacing: 0.05em;
		text-transform: uppercase;
		color: var(--color-muted);
	}

	/* La primera celda es el título de la ficha: ocupa la fila entera. */
	.tabla--fichas tbody td:first-child {
		display: block;
		text-align: left;
		padding-bottom: 0.5rem;
	}

	.tabla--fichas tbody td:first-child::before {
		display: none;
	}

	.tabla--fichas .tabla__acciones {
		justify-content: flex-end;
		padding-top: 0.5rem;
	}
}

/* ── Etiquetas y estado ───────────────────────────────────────────────── */

.etiqueta {
	display: inline-block;
	padding: 0.2rem 0.55rem;
	border-radius: var(--radius-full);
	font-size: 0.72rem;
	font-weight: 700;
	white-space: nowrap;
}

.etiqueta--admin {
	background: var(--color-info-bg);
	color: var(--color-primary);
}

.etiqueta--gestor,
.etiqueta--activo {
	background: var(--color-success-bg);
	color: var(--color-success);
}

.etiqueta--inspector {
	background: var(--color-warning-bg);
	color: var(--color-warning);
}

.etiqueta--visor,
.etiqueta--neutro {
	background: var(--color-surface-alt);
	color: var(--color-muted);
}

.etiqueta--inactivo {
	background: var(--color-danger-bg);
	color: var(--color-danger);
}

/*
 * Estado de un equipo o de una sesión. Lleva un punto delante además del
 * color de fondo: el color solo no basta para quien no lo distingue, y en una
 * tabla de veinte filas el punto es lo que se localiza de un vistazo.
 */
.estado {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.2rem 0.6rem 0.2rem 0.45rem;
	border-radius: var(--radius-full);
	font-size: 0.72rem;
	font-weight: 700;
	white-space: nowrap;
}

.estado::before {
	content: '';
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: currentColor;
	flex: none;
}

.estado--ok {
	background: var(--color-success-bg);
	color: var(--color-success);
}

.estado--error {
	background: var(--color-danger-bg);
	color: var(--color-danger);
}

.estado--alerta {
	background: var(--color-warning-bg);
	color: var(--color-warning);
}

.estado--apagado {
	background: var(--color-surface-alt);
	color: var(--color-muted);
}

/* Sesión viva: el punto late despacio. */
.estado--vivo::before {
	animation: latir 2.2s ease-in-out infinite;
}

@keyframes latir {
	0%,
	100% {
		box-shadow: 0 0 0 0 currentColor;
		opacity: 1;
	}
	50% {
		box-shadow: 0 0 0 3px transparent;
		opacity: 0.55;
	}
}

@media (prefers-reduced-motion: reduce) {
	.estado--vivo::before {
		animation: none;
	}
}

/* ── Botones ──────────────────────────────────────────────────────────── */

.boton {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	padding: 0.5rem 0.9rem;
	border-radius: var(--radius-sm);
	border: 1px solid transparent;

	/* El RELLENO no es `--color-primary`: ese es el color de TEXTO de marca.
	   Cobalt Deep con texto blanco de 12 px da 2,8:1; el relleno es su variante
	   oscura, que da 5,9:1 y cumple AA. */
	background: var(--relleno-primary);
	color: var(--color-sobre-relleno);
	font: inherit;
	font-size: 0.85rem;
	font-weight: 600;
	cursor: pointer;
	white-space: nowrap;
}

.boton:hover:not(:disabled) {
	background: var(--relleno-primary-hover);
	text-decoration: none;
}

.boton:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

.boton--suave {
	background: var(--color-surface);
	color: var(--color-text);
	border-color: var(--color-border-strong);
}

.boton--suave:hover:not(:disabled) {
	background: var(--color-surface-alt);
}

.boton--peligro {
	background: var(--color-danger);
}

.boton--peligro:hover:not(:disabled) {
	background: var(--color-danger-fuerte);
}

/* Peligro en versión discreta: para el icono de eliminar dentro de una fila,
   donde un botón rojo macizo por fila convierte la tabla en un semáforo. */
.boton--peligro-suave {
	background: var(--color-surface);
	color: var(--color-danger);
	border-color: color-mix(in srgb, var(--color-danger) 35%, transparent);
}

.boton--peligro-suave:hover:not(:disabled) {
	background: var(--color-danger-bg);
	border-color: var(--color-danger);
}

.boton--fantasma {
	background: transparent;
	color: var(--color-muted);
	border-color: transparent;
}

.boton--fantasma:hover:not(:disabled) {
	background: var(--color-surface-alt);
	color: var(--color-text);
}

.boton--pequeno {
	padding: 0.35rem 0.6rem;
	font-size: 0.78rem;
}

/* Solo icono: cuadrado, con el mismo alto que el botón que acompaña. */
.boton--icono {
	padding: 0.35rem;
	width: 30px;
	height: 30px;
}

.boton--bloque {
	width: 100%;
}

/* ── Formularios ──────────────────────────────────────────────────────── */

.campo {
	display: block;
	margin-bottom: 0.9rem;
}

.campo__etiqueta {
	display: block;
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--color-text);
	margin-bottom: 0.3rem;
}

.campo__control {
	width: 100%;
	padding: 0.55rem 0.7rem;
	border: 1px solid var(--color-border-strong);
	border-radius: var(--radius-sm);
	font: inherit;
	font-size: 0.9rem;
	color: var(--color-text);
	background: var(--color-surface);
}

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

.campo__control:disabled {
	background: var(--color-surface-alt);
	color: var(--color-muted);
	cursor: not-allowed;
}

textarea.campo__control {
	min-height: 90px;
	resize: vertical;
	line-height: 1.5;
}

input[type='color'].campo__control {
	height: 38px;
	padding: 3px;
	cursor: pointer;
}

.campo__ayuda {
	display: block;
	margin-top: 0.25rem;
	font-size: 0.78rem;
	color: var(--color-muted);
	font-weight: 400;
}

.campo__error {
	display: block;
	margin-top: 0.25rem;
	font-size: 0.78rem;
	color: var(--color-danger);
}

.campo--invalido .campo__control {
	border-color: var(--color-danger);
	border-width: 2px;
}

/* Casilla de verificación con su etiqueta. El área de toque llega a 44 px
   aunque la caja se vea de 18: es el mínimo cómodo para el pulgar. */
.casilla {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin-bottom: 0.8rem;
	cursor: pointer;
}

.casilla input {
	position: relative;
	width: 1.1rem;
	height: 1.1rem;
	accent-color: var(--color-primary);
	flex: none;
	cursor: pointer;
}

.casilla input::after {
	content: '';
	position: absolute;
	inset: -13px;
}

.casilla span {
	font-size: 0.88rem;
}

/* Buscador con lupa incrustada. */
.buscador {
	position: relative;
	display: flex;
	align-items: center;
	flex: 1 1 240px;
	min-width: 0;
	max-width: 340px;
}

.buscador svg {
	position: absolute;
	left: 0.6rem;
	color: var(--color-muted);
	pointer-events: none;
}

.buscador .campo__control {
	padding-left: 2rem;
}

/* Barra de filtros sobre una tabla. */
.filtros {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-wrap: wrap;
	margin-bottom: 0.9rem;
}

/* ── Avisos ───────────────────────────────────────────────────────────── */

.aviso {
	display: flex;
	align-items: flex-start;
	gap: 0.55rem;
	padding: 0.7rem 0.9rem;
	border-radius: var(--radius-sm);
	font-size: 0.85rem;
	margin-bottom: 1rem;
	border: 1px solid transparent;
	line-height: 1.5;
}

.aviso svg {
	margin-top: 1px;
}

.aviso--error {
	background: var(--color-danger-bg);
	color: var(--aviso-error-texto);
	border-color: var(--aviso-error-borde);
}

.aviso--ok {
	background: var(--color-success-bg);
	color: var(--aviso-ok-texto);
	border-color: var(--aviso-ok-borde);
}

.aviso--info {
	background: var(--color-info-bg);
	color: var(--aviso-info-texto);
	border-color: var(--aviso-info-borde);
}

/* Algo que hay que saber pero que no impide seguir. */
.aviso--alerta {
	background: var(--aviso-alerta-fondo);
	color: var(--aviso-alerta-texto);
	border-color: var(--aviso-alerta-borde);
}

/* ── Estados ──────────────────────────────────────────────────────────── */

.vacio {
	text-align: center;
	padding: 2.5rem 1rem;
	color: var(--color-muted);
	font-size: 0.9rem;
}

.vacio__icono {
	display: flex;
	justify-content: center;
	margin-bottom: 0.7rem;
	color: var(--color-border-strong);
}

.vacio__titulo {
	font-size: 0.95rem;
	font-weight: 700;
	color: var(--color-text);
	margin-bottom: 0.25rem;
}

.vacio p {
	margin: 0 auto;
	max-width: 42ch;
	line-height: 1.55;
}

.vacio .boton {
	margin-top: 1rem;
}

.cargando {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.6rem;
	padding: 2.5rem;
	color: var(--color-muted);
	font-size: 0.9rem;
}

.girando {
	width: 20px;
	height: 20px;
	border: 2px solid var(--color-border);
	border-top-color: var(--color-primary);
	border-radius: 50%;
	animation: girar 1s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
	.girando {
		animation: none;
	}
}

/* Esqueleto: la página no salta cuando llegan los datos. */
.esqueleto {
	background: linear-gradient(
		90deg,
		var(--color-surface-alt),
		var(--color-border),
		var(--color-surface-alt)
	);
	background-size: 200% 100%;
	border-radius: var(--radius-sm);
	animation: brillar 1.3s linear infinite;
}

@keyframes brillar {
	to {
		background-position: -200% 0;
	}
}

/* ── Modal ────────────────────────────────────────────────────────────── */

.modal-fondo {
	position: fixed;
	inset: 0;
	background: rgb(6 20 40 / 55%);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1rem;
	z-index: 80;
}

/*
 * En el teléfono `vh` se refiere a la pantalla con la barra del navegador
 * escondida, aunque esté a la vista: un modal de 90vh puede ser más alto que
 * lo que de verdad se ve, y lo primero que se pierde son los botones de
 * Guardar y Cancelar. `dvh` mide lo que hay en cada momento.
 */
@supports (height: 100dvh) {
	.modal-fondo {
		height: 100dvh;
	}
}

.modal {
	background: var(--color-surface);
	border-radius: 14px;
	width: min(520px, 100%);
	max-height: 90vh;
	overflow-y: auto;

	/* Sin esto, al llegar al final del modal el desplazamiento sigue en la
	   página de detrás y uno acaba en otro punto de la pantalla. */
	overscroll-behavior: contain;

	padding: 1.35rem;
	box-shadow: 0 18px 50px rgb(10 30 60 / 28%);
}

.modal--ancho {
	width: min(820px, 100%);
}

@supports (max-height: 90dvh) {
	.modal {
		max-height: 90dvh;
	}
}

.modal__titulo {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	margin: 0 0 1rem;
	font-size: 1.1rem;
	font-weight: 700;
	overflow-wrap: anywhere;
}

.modal__acciones {
	display: flex;
	gap: 0.55rem;
	justify-content: flex-end;
	margin-top: 1.2rem;
	flex-wrap: wrap;
}

/* En pantalla estrecha los botones ocupan el ancho y se apilan, en vez de
   quedar apretados en una esquina donde es fácil pulsar el que no es. */
@media (max-width: 480px) {
	.modal {
		padding: 1.1rem;
	}

	.modal__acciones {
		flex-direction: column-reverse;
		gap: 0.5rem;
	}

	.modal__acciones .boton {
		width: 100%;
	}
}

/* ── Notificaciones ───────────────────────────────────────────────────── */

.notificaciones {
	position: fixed;
	right: 1rem;
	bottom: calc(1rem + env(safe-area-inset-bottom));
	z-index: 100;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	max-width: calc(100vw - 2rem);
}

.notificacion {
	display: flex;
	align-items: flex-start;
	gap: 0.55rem;
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-left: 3px solid var(--color-primary);
	border-radius: var(--radius-sm);
	padding: 0.7rem 0.9rem;
	min-width: 240px;
	max-width: 380px;
	font-size: 0.85rem;
	line-height: 1.45;
	box-shadow: var(--shadow-lg);
	animation: entrar 0.2s ease;
}

.notificacion--ok {
	border-left-color: var(--color-success);
}

.notificacion--error {
	border-left-color: var(--color-danger);
}

@keyframes entrar {
	from {
		opacity: 0;
		transform: translateX(14px);
	}
}

@media (max-width: 480px) {
	.notificaciones {
		left: 1rem;
		right: 1rem;
	}

	.notificacion {
		max-width: none;
	}
}

/* ── Utilidades ───────────────────────────────────────────────────────── */

.apagado {
	color: var(--color-muted);
}

.fila {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.fila--separada {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.65rem;
	flex-wrap: wrap;
}

.seccion-titulo {
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--color-muted);
	margin: 1.5rem 0 0.65rem;
}

.seccion-titulo:first-child {
	margin-top: 0;
}

/* Texto que solo existe para quien navega con lector de pantalla. No se usa
   `display:none` porque eso también lo esconde del lector, que es justo para
   quien está. */
.visualmente-oculto {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Bloque de código: el script .rsc y el login.html del router. */
.codigo {
	font-family: var(--font-mono);
	font-size: 0.75rem;
	line-height: 1.6;
	background: var(--color-surface-alt);
	color: var(--color-text);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	padding: 0.85rem;
	margin: 0;
	max-height: 420px;
	overflow: auto;
	white-space: pre;
	tab-size: 4;
}

/* ── Impresión ────────────────────────────────────────────────────────── */

/* Los dos colores de este bloque son la excepción admitida a la regla de la
   cabecera: el papel es blanco pase lo que pase con el tema de la pantalla, así
   que aquí un literal es lo correcto y un token sería el error. */
@media print {
	.menu,
	.velo,
	.barra,
	.pagina__acciones,
	.tabla__acciones,
	.notificaciones,
	.filtros {
		display: none !important;
	}

	body {
		background: #fff;
	}

	.tabla-envoltura {
		border-color: #bbb;
		overflow: visible;
	}
}

/* ── Ficha del ciudadano y textos legales ────────────────────────────── */

/*
 * Lista de pares dato/valor de la ficha. En el teléfono se apila, porque dos
 * columnas a 390 px parten el correo por la mitad.
 */
.ficha {
	display: grid;
	grid-template-columns: max-content 1fr;
	gap: 8px 18px;
	margin: 0 0 22px;
	font-size: 14px;
}

.ficha dt {
	color: var(--color-muted);
}

.ficha dd {
	margin: 0;
	color: var(--color-text);
}

.ficha__titulo {
	margin: 24px 0 10px;
	font-size: 14px;
	font-weight: 600;
	color: var(--color-text);
}

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

	.ficha dt {
		margin-top: 10px;
		font-size: 12px;
	}
}

/*
 * Vista previa de un texto legal. Va en <pre> a propósito: son documentos
 * jurídicos y los saltos de línea del original importan. Se limita la altura
 * porque la Política pasa de las ocho mil letras.
 */
.legal-previo {
	max-height: 260px;
	overflow: auto;
	margin: 12px 0 16px;
	padding: 14px;
	border: 1px solid var(--color-border);
	border-radius: var(--radius);
	background: var(--color-surface-alt);
	color: var(--color-muted);
	font-family: var(--font-mono);
	font-size: 12.5px;
	line-height: 1.6;
	white-space: pre-wrap;
	word-break: break-word;
}

.historial {
	margin-top: 14px;
}

.historial summary {
	cursor: pointer;
	font-size: 13px;
	color: var(--color-muted);
}

/* ── Informe de beneficiarios ────────────────────────────────────────── */

/*
 * La cifra que el proyecto de inversión reporta es «beneficiarios», no
 * «conexiones». Se destaca visualmente porque las cuatro van juntas a
 * propósito —para que la comparación sea inevitable— y sin jerarquía se
 * leería la primera que caiga.
 */
.kpi-tile--destacado {
	border-color: var(--color-primary);
	background: color-mix(in srgb, var(--color-primary) 8%, var(--color-surface));
}

.kpi-tile--destacado .kpi-valor {
	color: var(--color-primary);
}

.par-columnas {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 16px;
}

@media (max-width: 860px) {
	.par-columnas {
		grid-template-columns: 1fr;
	}
}

/* Barra proporcional dentro de una celda: da la forma de la distribución
   sin cargar una librería de gráficas, que no cabe en un proyecto sin
   paso de construcción. */
.barra-dato {
	min-width: 70px;
	height: 6px;
	border-radius: 3px;
	background: var(--color-surface-alt);
	overflow: hidden;
}

.barra-dato__relleno {
	height: 100%;
	border-radius: 3px;
	background: var(--color-primary);
}

/* Una zona sin coordenadas no se puede situar en el informe, y eso es justo
   lo que el proyecto tiene que reportar: se marca, no se deja en blanco. */
.aviso-inline {
	font-size: 12px;
	color: var(--color-warning);
}

.campo--enlinea {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
}

.campo--enlinea > span {
	font-size: 13px;
	color: var(--color-muted);
	white-space: nowrap;
}

.campo--enlinea .campo__control {
	width: auto;
	min-width: 140px;
}

/* ── Comprobación de la zona ─────────────────────────────────────────── */

.check-lista {
	display: flex;
	flex-direction: column;
	gap: 2px;
	margin-top: 14px;
}

.check-fila {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding: 11px 12px;
	border-radius: var(--radius-sm);
	border-left: 3px solid transparent;
}

.check-fila--ok {
	border-left-color: var(--color-success);
	color: var(--color-muted);
}

.check-fila--aviso {
	border-left-color: var(--color-warning);
	background: color-mix(in srgb, var(--color-warning) 7%, transparent);
}

.check-fila--error {
	border-left-color: var(--color-danger);
	background: color-mix(in srgb, var(--color-danger) 7%, transparent);
}

.check-fila svg {
	flex: none;
	margin-top: 1px;
}

.check-fila--ok svg { color: var(--color-success); }
.check-fila--aviso svg { color: var(--color-warning); }
.check-fila--error svg { color: var(--color-danger); }

.check-titulo {
	font-size: 14px;
	color: var(--color-text);
}

.check-detalle {
	margin-top: 2px;
	font-size: 12.5px;
	color: var(--color-muted);
	word-break: break-word;
}

/* Qué hacer. Es la mitad útil del hallazgo, así que no se esconde. */
.check-accion {
	margin-top: 5px;
	font-size: 13px;
	line-height: 1.5;
	color: var(--color-text);
}

/* ── Informe de beneficiarios (012) ───────────────────────────────────────
 *
 * Tres piezas: la cabecera de sección con icono, la rejilla de filtros y las
 * listas de distribución que sustituyen a las tablas de edad y sexo.
 */

.seccion-informe__titulo {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	margin: 0 0 0.9rem;
	font-family: var(--font-display);
	font-size: 1rem;
	font-weight: 650;
	letter-spacing: -0.01em;
	color: var(--color-text);
}

.seccion-informe__icono {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	border-radius: 8px;
	background: var(--color-surface-alt);
	border: 1px solid var(--color-border);
	color: var(--color-primary);
}

/* Las etiquetas de los filtros llevan icono: el `> span` heredado solo fijaba
   tipografía, y con un hijo dentro hay que alinear. */
.filtros--informe .campo--enlinea > span {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
}

/*
 * Rejilla en lugar de `flex-wrap`. Con dos fechas, un selector y dos botones el
 * ajuste automático repartía el bloque en cinco líneas de anchuras distintas a
 * 390 px. Emparejadas las dos fechas —que es como se leen— el bloque cae en
 * tres líneas previsibles, y en escritorio vuelve a ser una sola.
 */
.filtros--informe {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.6rem;
	align-items: end;
}

.filtros--informe .campo--ancho {
	grid-column: 1 / -1;
}

.filtros--informe .campo--enlinea .campo__control {
	flex: 1;
	min-width: 0;
}

/*
 * A 390 px, con el rótulo al lado el campo de fecha se recortaba: un
 * `input[type=date]` no baja de su anchura intrínseca por mucho `min-width: 0`
 * que lleve, porque el control nativo no es un bloque de texto que se pueda
 * estrechar. La solución es darle la celda entera y poner el rótulo encima.
 */
@media (max-width: 560px) {
	.filtros--informe .campo--enlinea {
		display: flex;
		flex-direction: column;
		align-items: stretch;
		gap: 0.25rem;
	}

	.filtros--informe .campo--enlinea > span {
		white-space: normal;
	}

	.filtros--informe .campo--enlinea .campo__control {
		width: 100%;
		min-width: 0;
	}
}

.filtros__acciones {
	grid-column: 1 / -1;
	display: flex;
	gap: 0.5rem;
}

.filtros__acciones .boton {
	flex: 1;
}

@media (min-width: 760px) {
	.filtros--informe {
		grid-template-columns: auto auto 1fr auto;
	}

	.filtros--informe .campo--ancho,
	.filtros__acciones {
		grid-column: auto;
	}

	.filtros__acciones .boton {
		flex: 0 0 auto;
	}
}

/* ── Listas de distribución ──────────────────────────────────────────────
 *
 * Para una distribución de seis filas, una tabla de cuatro columnas era más
 * marco que dato: tres de sus columnas se leían como una sola idea —cuánta
 * gente, de cuánta—. El punto de color acompaña al rótulo y a la barra, y
 * NUNCA porta información por sí solo: el rótulo y la cifra van siempre.
 */

.dist {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
}

.dist__fila {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
}

/* «Prefirió no decirlo» y «no se le preguntó» no son rasgos de nadie: se
   separan del resto para que no se lean como un grupo demográfico más. */
.dist__fila--aparte {
	margin-top: 0.35rem;
	padding-top: 0.7rem;
	border-top: 1px dashed var(--color-border);
}

.dist__cabecera {
	display: flex;
	align-items: center;
	gap: 0.45rem;
	font-size: 0.85rem;
}

.dist__punto {
	flex: 0 0 auto;
	width: 9px;
	height: 9px;
	border-radius: 3px;
}

.dist__rotulo {
	flex: 1;
	min-width: 0;
	color: var(--color-text);
}

.dist__cifras {
	flex: 0 0 auto;
	display: flex;
	align-items: baseline;
	gap: 0.45rem;
}

.dist__pct {
	color: var(--color-muted);
	font-size: 0.78rem;
}

.dist__reservado {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	color: var(--color-muted);
}

.dist__pista {
	height: 7px;
	border-radius: 999px;
	background: var(--color-surface-alt);
	border: 1px solid var(--color-border);
	overflow: hidden;
}

.dist__relleno {
	height: 100%;
	border-radius: 999px;
	transition: width 0.25s ease;
}

.dist__punto--a { background: var(--serie-a); }
.dist__punto--b { background: var(--serie-b); }
.dist__punto--c { background: var(--serie-c); }
.dist__punto--d { background: var(--serie-d); }
.dist__punto--e { background: var(--serie-e); }

.dist__relleno--a { background: var(--serie-a); }
.dist__relleno--b { background: var(--serie-b); }
.dist__relleno--c { background: var(--serie-c); }
.dist__relleno--d { background: var(--serie-d); }
.dist__relleno--e { background: var(--serie-e); }

/* Segunda línea de un aviso: era `style="margin-top:6px;font-size:12.5px"` en
   el JS, donde no se habría enterado de un cambio de escala tipográfica. */
.aviso__detalle {
	margin-top: 0.4rem;
	font-size: 0.79rem;
	color: var(--color-muted);
}

@media (prefers-reduced-motion: reduce) {
	.dist__relleno {
		transition: none;
	}
}

/* ── ¿Puede llegar el correo? (015) ───────────────────────────────────────
 *
 * Lista de comprobaciones del DNS del remitente. El estado va por icono Y por
 * color de borde, nunca solo por color: quien no distinga el rojo del verde
 * tiene que poder leerlo igual.
 */

.entrega__remitente {
	margin: 0 0 0.9rem;
	font-size: 0.875rem;
}

.entrega {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.entrega__punto {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
	padding: 0.7rem 0.85rem;
	border: 1px solid var(--color-border);
	border-left-width: 3px;
	border-radius: var(--radius);
	background: var(--color-surface-alt);
}

.entrega__punto--ok    { border-left-color: var(--color-success); }
.entrega__punto--mal   { border-left-color: var(--color-danger); }
.entrega__punto--aviso { border-left-color: var(--color-warning); }

.entrega__icono {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	margin-top: 1px;
}

.entrega__punto--ok    .entrega__icono { color: var(--color-success); }
.entrega__punto--mal   .entrega__icono { color: var(--color-danger); }
.entrega__punto--aviso .entrega__icono { color: var(--color-warning); }

.entrega__titulo {
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--color-text);
}

.entrega__detalle {
	margin-top: 0.15rem;
	font-size: 0.8rem;
	line-height: 1.5;
	color: var(--color-muted);
}
