:root {
  --amarillo: #EFC85F;
  --amarillo-suave: #FFF8DC;
  --negro: #1E1E1E;
  --gris-oscuro: #2D2D2D;
  --gris-medio: #555;
  --gris-suave: #f5f5f5;
  --blanco: #fff;
  --borde: #e8e8e8;
  --sombra: 0 2px 8px rgba(0, 0, 0, .07);
  --radio: 14px;
  --error: #c0392b;
  --exito: #16a34a;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  background: var(--gris-suave);
  color: var(--negro);
  min-height: 100vh;
}

/* ARMAZÓN FIJO — la cabecera y la barra de abajo no se mueven al desplazar.
   La clase la pone header.js, así que solo la llevan las páginas internas; el login y
   las pantallas sueltas de acceso siguen siendo páginas normales que se desplazan
   enteras.

   Antes la cabecera era `sticky` y la barra de abajo `fixed`. Sobre el papel eso las
   deja quietas, pero en el móvil no: al desplazar, el navegador esconde y saca su
   propia barra de direcciones, la altura visible de la ventana cambia a mitad del gesto
   y los dos elementos dan un salto. Por eso solo pasaba en las pantallas con contenido
   largo — las cortas no llegan a desplazarse y nunca se notaba.

   La solución es que el documento NO se desplace en absoluto: la ventana se reparte en
   tres, y lo único que se mueve es el contenido de en medio. Así el navegador no tiene
   motivo para esconder su barra, y las nuestras no pueden moverse porque no están
   flotando sobre nada: están en su sitio.

   El precio es que la barra de direcciones del móvil ya no se recoge al bajar, así que
   se ve un poco menos de contenido. Merece la pena: unas barras que bailan hacen fallar
   los toques, y eso es peor que perder unos píxeles. */
html {
  height: 100%;
}

body.app-fija {
  height: 100%;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Solo hay tres hijos en el reparto. Todo lo demás que cuelga del <body> —el botón
   flotante, los modales, la barra de selección, la hoja de impresión— va en `position:
   fixed` o escondido, así que no entra aquí. */
body.app-fija > .header,
body.app-fija > .bottom-nav {
  position: relative;
  flex: 0 0 auto;
}

body.app-fija > .contenido {
  flex: 1 1 auto;
  /* Imprescindible: `.contenido` lleva `margin: 0 auto` para centrarse, y dentro de una
     columna flexible un margen automático hace que el elemento se encoja hasta el tamaño
     de su contenido en vez de ocupar el ancho entero. Con el ancho fijado al 100%, el
     `max-width` sigue limitándolo y los márgenes siguen centrándolo, igual que antes. */
  width: 100%;
  overflow-y: auto;
  /* Al llegar al final, que no arrastre la página de detrás ni dispare el "recargar
     tirando hacia abajo" del navegador en mitad de una lista. */
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  /* El hueco de abajo se mantiene aunque la barra ya no flote sobre el contenido: el
     botón redondo de "+" sí sigue flotando, y sin este hueco la última tarjeta de la
     lista quedaría debajo de él justo al llegar al final. */
  padding-bottom: 90px;
}

button {
  cursor: pointer;
  font-family: inherit;
}

/* Botón desactivado mientras algo está en curso (ej. "Enviando…") — sin esto, el cambio de
   texto era la única pista de que ya se había pulsado, y era fácil pulsar otra vez de más. */
button:disabled {
  opacity: 0.6;
  cursor: default;
}

/* SELECT — estilo base para cualquier <select> suelto de la app (fuera de un .field, que
   ya tiene su propio estilo en calendario.css). Sin esto, un <select> hereda el aspecto
   plano del sistema operativo, desentonando con el resto del sistema de diseño. */
select {
  width: 100%;
  border: 1.5px solid var(--borde);
  border-radius: 10px;
  padding: 12px 34px 12px 14px;
  font-size: 15px;
  font-family: inherit;
  background: var(--blanco) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23555" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>') no-repeat right 10px center;
  background-size: 18px;
  color: var(--negro);
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  cursor: pointer;
  transition: border-color .15s;
}

select:focus {
  border-color: var(--amarillo);
}

/* HEADER — barra superior con el logo, compartida por todas las páginas internas
   (no se usa en la pantalla de login, que tiene su propio logo centrado a pantalla completa). */
.header {
  background: var(--negro);
  color: var(--blanco);
  padding: 16px 20px;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .3);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.header .logo {
  display: flex;
  align-items: center;
  gap: 8px;
}

.header .logo-titulo {
  font-size: 16px;
  font-weight: 800;
  color: var(--blanco);
}

.header .btn-volver {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--amarillo);
  padding: 4px;
  margin-right: 4px;
}

.header .btn-volver svg {
  width: 20px;
  height: 20px;
}

.header .logo-text {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 2px;
  color: rgba(255, 255, 255, .5);
  text-transform: uppercase;
}

.header .logo-tres {
  font-size: 22px;
  font-weight: 800;
  color: var(--amarillo);
  letter-spacing: -0.5px;
}

.header .logo-dots {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-left: 2px;
}

.header .logo-dot1 {
  width: 8px;
  height: 8px;
  background: var(--amarillo);
  border-radius: 50%;
}

.header .logo-dot2 {
  width: 6px;
  height: 6px;
  background: var(--amarillo);
  border-radius: 50%;
  opacity: .7;
}

.header .usuario {
  display: flex;
  align-items: center;
  gap: 10px;
}

.header .rol-badge {
  background: rgba(239, 200, 95, .15);
  color: var(--amarillo);
  padding: 4px 12px;
  border-radius: 20px;
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
}

/* Icono de apagado en vez de la palabra "Salir": ocupa menos y se entiende igual. */
.header .btn-salir {
  background: rgba(255, 255, 255, .1);
  color: var(--blanco);
  border: none;
  border-radius: 50%;
  width: 34px;
  height: 34px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.header .btn-salir svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.header .btn-salir:active {
  background: rgba(255, 255, 255, .2);
}

/* BOTTOM NAV — barra de navegación inferior fija, compartida por todas las páginas
   internas. Cada página marca su propio botón como .active vía el atributo data-pagina
   en el <body> (ver base.js). */
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--negro);
  border-top: 2px solid var(--amarillo);
  display: flex;
  z-index: 100;
  padding: 6px 0 10px;
}

.nav-btn {
  flex: 1;
  padding: 6px 4px;
  border: none;
  background: none;
  font-size: 10px;
  color: rgba(255, 255, 255, .35);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  font-weight: 600;
  letter-spacing: .3px;
  text-transform: uppercase;
  text-decoration: none;
  transition: color .15s;
}

.nav-btn svg {
  width: 22px;
  height: 22px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nav-btn.active {
  color: var(--amarillo);
}

/* Un apartado que solo ven algunos (Ruta, en la barra del trabajador) nace con [hidden] y se
   enciende al saber quién es. HACE FALTA ESTA REGLA: `[hidden]{display:none}` del navegador
   tiene la misma especificidad que `.nav-btn`, y como esta se declara después, GANA — el
   botón se vería igual con el atributo puesto. Es la sexta vez que pasa en este proyecto. */
.nav-btn[hidden] { display: none; }

/* CONTENIDO — envoltorio central de cada página, con espacio reservado abajo para
   que el bottom-nav fijo no tape el final del contenido. */
.contenido {
  max-width: 960px;
  margin: 0 auto;
  padding: 20px 16px;
  padding-bottom: 90px;
}

/* ANIMACIÓN DE CARGA "ESCOBA" — sustituye al texto "Cargando…"/spinner circular.
   Inspirada en la referencia visual del usuario (organizador-trabajos): una escoba
   empuja una bolita creciente hasta un recogedor, en bucle, mientras se ondulan las
   cerdas. Ver public/escoba.js para la lógica de animación — se auto-inicializa sola
   en cualquier .esc-track que aparezca en el DOM, no hace falta llamarla a mano. */
/* La escoba mide 102 px y el carril solo 50, con overflow visible: el palo asoma unos 57 px
   por encima. Con 30 px de hueco arriba se salía del recuadro y se plantaba encima de la
   barra de búsqueda de la pantalla que estuviera cargando. El hueco tiene que dar para el
   palo entero. */
.esc-track-wrap {
  display: flex;
  justify-content: center;
  padding: 62px 10px 8px;
}

.esc-track {
  position: relative;
  height: 50px;
  width: 66%;
  max-width: 230px;
  overflow: visible;
}

.esc-linea-base {
  position: absolute;
  bottom: 6px;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: linear-gradient(90deg, transparent, #e2e2e2 12%, #e2e2e2 88%, transparent);
  z-index: 1;
}

.esc-bolita {
  position: absolute;
  bottom: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  z-index: 3;
  background: radial-gradient(circle at 35% 30%, #f6dc93, #EFC85F 60%, #c79f2e 100%);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
  transition: left 0.7s cubic-bezier(.65, 0, .35, 1), width 0.7s cubic-bezier(.65, 0, .35, 1), height 0.7s cubic-bezier(.65, 0, .35, 1);
}

.esc-recogedor {
  position: absolute;
  bottom: 0;
  right: 2px;
  width: 36px;
  height: 34px;
  z-index: 6;
  transform-origin: 75% 95%;
  transition: transform .18s ease;
}

.esc-recogedor.recibiendo {
  animation: escRecWobble .3s ease;
}

@keyframes escRecWobble {
  0% { transform: rotate(0deg); }
  30% { transform: rotate(-4deg); }
  60% { transform: rotate(3deg); }
  100% { transform: rotate(0deg); }
}

.esc-escoba {
  position: absolute;
  bottom: 5px;
  width: 46px;
  height: 102px;
  z-index: 5;
  transform-origin: bottom center;
  filter: drop-shadow(0 3px 3px rgba(0, 0, 0, .13));
  transition: left 0.7s cubic-bezier(.65, 0, .35, 1);
}

.esc-cerda {
  transform-origin: 50% 0%;
}

.esc-texto {
  font-size: 12px;
  color: #aaa;
  margin-top: 10px;
  letter-spacing: .2px;
  text-align: center;
}

/* BOTONES */
.btn-primary {
  width: 100%;
  padding: 15px;
  background: var(--negro);
  color: var(--amarillo);
  border: none;
  border-radius: 12px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .3px;
  transition: opacity .15s, transform .1s;
}

.btn-primary:active {
  opacity: .85;
  transform: scale(.98);
}

.btn-primary:disabled {
  opacity: .5;
  cursor: not-allowed;
}

/* ALERTAS */
.alert {
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 12px;
  display: none;
}

/* LOS AVISOS FLOTAN POR ENCIMA DE TODO (03/09/2026).
 *
 * Antes eran un bloque más del principio de la página, sin posición ni z-index. Y eso tenía
 * una consecuencia que no se veía leyendo el CSS: **cuando algo falla dentro de un modal, el
 * aviso se pinta DETRÁS del modal**, arriba del todo, donde nadie lo ve. Desde fuera se
 * traduce en «le doy a Responder, no pasa nada y el cuadro no se va» — que es exactamente lo
 * que se reportó. El fallo estaba contado; simplemente no se podía leer.
 *
 * Así que se sacan a flotar, centrados arriba y por encima de los modales (que van a 3000).
 * Son mensajes que se van solos a los pocos segundos, así que un cartel flotante es además lo
 * que les corresponde: ocupando sitio en el flujo empujaban la página hacia abajo al aparecer
 * y la subían de golpe al irse.
 *
 * Solo afecta a `.alert.show`, que es la clase que se enciende y se apaga. Un aviso
 * permanente de una pantalla usa su propia clase (`.recl-aviso`, `.aviso-migracion`) y se
 * queda donde está. */
.alert.show {
  display: block;
  position: fixed;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4000;
  width: calc(100% - 24px);
  max-width: 520px;
  margin: 0;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .18);
}

/* UN AVISO QUE VIVE EN LA PÁGINA, NO FLOTANDO (05/09/2026).

   Hay avisos que no son una notificación de algo que acaba de pasar, sino parte de la
   pantalla: «faltan cuentas por clasificar» en PyG está ahí siempre, y flotando sobre el
   contenido tapaba lo que se venía a leer.

   Antes se apañaba con un `style="position:static"` a mano en cada sitio, y eso ESTABA MAL:
   quitaba el `position` pero NO el `transform: translateX(-50%)`, que se sigue aplicando a un
   elemento estático. El aviso salía desplazado media anchura hacia la izquierda y se veía
   cortado — que es exactamente como se reportó.

   Con una clase se apagan las cinco cosas a la vez, y no hay que acordarse de ninguna. */
.alert.show.alert-en-linea {
  position: static;
  transform: none;
  left: auto;
  width: auto;
  max-width: none;
  margin-bottom: 12px;
  box-shadow: none;
}

.alert-ok {
  background: #eafaf0;
  color: #116636;
}

.alert-err {
  background: #fdecec;
  color: #8a1f1f;
}

/* Aviso informativo (ni error ni confirmación): algo que conviene mirar, pero que no
   impide seguir. Ej. el consumo disparado de un vehículo en Repostajes. */
.alert-aviso {
  background: #fff7e6;
  color: #8a5a00;
}

/* Aviso con varias cosas dentro (p. ej. un vehículo por línea en Repostajes): el titular
   arriba y debajo un renglón por cada una, en vez de todo seguido en un párrafo. */
.aviso-titulo {
  font-weight: 700;
  margin-bottom: 6px;
}

/* El .alert lo pone todo en negrita; aquí solo debe destacar el nombre del vehículo. */
.aviso-linea {
  padding: 4px 0;
  line-height: 1.4;
  font-weight: 500;
}

.aviso-linea + .aviso-linea {
  border-top: 1px solid rgba(138, 90, 0, .15);
}

/* EXPORTAR — barra de Excel/PDF encima de un listado (ver compartido/exportar.js). */
.exportar-barra {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-bottom: 10px;
}

.exportar-btn {
  border: 1.5px solid var(--borde);
  background: var(--blanco);
  border-radius: 10px;
  padding: 7px 12px;
  font-size: 12px;
  font-weight: 700;
  color: var(--negro);
}

.exportar-btn:active {
  background: var(--amarillo);
}

/* FILA DE ACCIONES — dos o tres acciones principales en una sola línea y, al final, un
   menú de tres puntos con las secundarias (PDF, Excel…). Mismo criterio que las tarjetas
   con menú: lo que se usa mucho se ve, lo demás se guarda para no llenar la pantalla. */
.acciones-fila {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 12px;
}

.acciones-fila .accion-btn {
  flex: 1;
  min-width: 0;
  border: 1.5px solid var(--borde);
  background: var(--gris-suave);
  border-radius: 10px;
  padding: 10px 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--negro);
  text-align: center;
  text-decoration: none;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
}

.acciones-fila .accion-btn:active {
  background: var(--amarillo);
}

.acciones-menu {
  position: relative;
  flex-shrink: 0;
}

.acciones-menu > .menu-btn {
  width: 40px;
  height: 100%;
  border: 1.5px solid var(--borde);
  background: var(--blanco);
  border-radius: 10px;
  font-size: 18px;
  line-height: 1;
  color: var(--gris-medio);
}

.acciones-menu > .menu-btn:active {
  background: var(--gris-suave);
}

.acciones-menu .menu-lista {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 10;
  min-width: 170px;
  background: var(--blanco);
  border: 1.5px solid var(--borde);
  border-radius: 12px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .14);
  overflow: hidden;
}

.acciones-menu .menu-lista.abierto {
  display: block;
}

.acciones-menu .menu-lista button {
  display: block;
  width: 100%;
  border: none;
  border-bottom: 1px solid var(--borde);
  background: none;
  padding: 11px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--negro);
  text-align: left;
}

.acciones-menu .menu-lista button:last-child {
  border-bottom: none;
}

.acciones-menu .menu-lista button:active {
  background: var(--gris-suave);
}

/* Título de sección con una acción a la derecha, en la misma línea (el ⋮ de exportar
   sobre un listado, por ejemplo). El h3 pierde su margen inferior porque el subrayado lo
   pone la propia fila. */
.seccion-titulo-fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 14px;
  padding-bottom: 8px;
  border-bottom: 1.5px solid var(--borde);
}

/* Con el selector corto no basta: .form-section h3 (calendario.css) tiene la misma fuerza
   y se carga después, así que el título se quedaba con su propio subrayado y salían dos
   líneas grises, una bajo el texto y otra bajo la fila. */
.seccion-titulo-fila h3,
.form-section .seccion-titulo-fila h3 {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: none;
}

/* Buscador (o desplegable) con el menú de tres puntos al lado, para no gastar una línea
   entera en dos botones que se usan de uvas a peras. */
.buscador-fila {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 12px;
}

.buscador-fila > .buscador-input,
.buscador-fila > select {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
}

/* Pestañas con un botón de acción al lado (p. ej. el PDF de Semana/Zonas/Mes): así el
   botón no se come una línea entera para él solo. El margen inferior lo lleva la fila,
   no las pestañas, para que ambos queden a la misma altura. */
/* LAS PESTAÑAS. Aquí, y no en la hoja de un módulo (31/08/2026).
 *
 * Vivían en rrhh.css, que solo cargan las pantallas de RRHH — pero las usan DIECISÉIS
 * pantallas: propuestas, calidad, contratos, alta de cliente, albaranes, compras, facturación,
 * la ficha de proveedor, Sistema, trabajos sueltos… En las quince que no cargaban esa hoja las
 * pestañas salían como los botones grises que pinta el navegador cuando no hay estilo, que es
 * lo que se veía en el ordenador («se ven un cuadrado con el texto»).
 *
 * En el móvil llamaba menos la atención porque ocupan el ancho entero de la pantalla y parecen
 * una barra; en un monitor ancho quedan sueltos y se ve que son botones sin vestir. */
.tabs {
  display: flex;
  background: var(--gris-suave);
  border-radius: 12px;
  padding: 3px;
  margin-bottom: 12px;
}

/* Sin esto, un <div class="tabs" hidden> SE SIGUE VIENDO: el `display:flex` de arriba es una
   regla de autor y gana al `display:none` que el navegador aplica a [hidden], que es de su
   hoja por defecto.
   Pasaba en Semana y Mes, donde los botones se mandaron al menú de tres puntos y se dejaron
   escondidos para que el menú los pulsara por dentro — y seguían ocupando su línea entera
   encima del selector de fecha, que era justo el espacio que se quería ganar. */
.tabs[hidden] {
  display: none;
}

.tab-btn {
  flex: 1;
  padding: 9px;
  border: none;
  background: none;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  color: #888;
  transition: all .15s;
}

.tab-btn.active {
  background: var(--blanco);
  color: var(--negro);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .1);
}

.tabs-con-accion {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.tabs-con-accion .tabs {
  flex: 1;
  margin-bottom: 0;
}

.tabs-con-accion .exportar-btn {
  flex-shrink: 0;
  padding: 9px 14px;
}

/* HOJA DE IMPRESIÓN — se ve primero en pantalla (previsualización) y de ahí se manda a
   imprimir o a guardar como PDF. Se monta dentro de la propia página, no en una ventana
   nueva, que los navegadores móviles bloquean. Ver compartido/exportar.js. */
#zonaImpresion {
  display: none;
}

body.previsualizando {
  overflow: hidden;
}

body.previsualizando #zonaImpresion {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 3000;
  background: var(--gris-suave);
  overflow: auto;
}

.imp-barra {
  position: sticky;
  top: 0;
  display: flex;
  gap: 8px;
  justify-content: space-between;
  align-items: center;
  background: var(--negro);
  padding: 10px 12px;
}

.imp-barra button {
  border: none;
  border-radius: 10px;
  padding: 9px 14px;
  font-size: 13px;
  font-weight: 700;
}

.imp-barra .imp-cerrar {
  background: var(--gris-oscuro);
  color: var(--blanco);
}

.imp-barra .imp-imprimir {
  background: var(--amarillo);
  color: var(--negro);
}

/* La hoja en sí: en pantalla se ve como un folio blanco; al imprimir ocupa la página. */
.imp-hoja {
  background: var(--blanco);
  color: #000;
  max-width: 1000px;
  margin: 12px auto 40px;
  padding: 16px;
  box-shadow: var(--sombra);
  overflow-x: auto;
}

.imp-cabecera {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: 2px solid #000;
  padding-bottom: 6px;
}

/* El logo de verdad en la cabecera de cualquier listado impreso (09/09/2026). La altura
   manda y el ancho se calcula solo, para no deformarlo si algún día cambia el fichero. */
.imp-logo-img { height: 42px; width: auto; display: block; }

.imp-logo {
  font-size: 15px;
  font-weight: 300;
}

.imp-logo b {
  font-weight: 800;
}

.imp-fecha {
  font-size: 11px;
  color: #444;
}

.imp-titulo {
  font-size: 19px;
  margin: 14px 0 2px;
}

.imp-subtitulo {
  font-size: 12px;
  color: #444;
  margin-bottom: 10px;
}

.imp-tabla {
  width: 100%;
  border-collapse: collapse;
  margin-top: 8px;
  font-size: 12px;
}

.imp-tabla th,
.imp-tabla td {
  border: 1px solid #999;
  padding: 4px 6px;
  text-align: left;
  vertical-align: top;
}

.imp-tabla th {
  background: #eee;
}

.imp-tabla tbody tr:nth-child(even) {
  background: #f6f6f6;
}

.imp-tabla .num {
  text-align: right;
  white-space: nowrap;
}

.imp-totales {
  margin-top: 10px;
  font-weight: 800;
}

.imp-pie {
  margin-top: 4px;
  font-size: 11px;
  color: #444;
}

@media print {
  /* SOLO CUANDO HAY UNA PREVISUALIZACIÓN DELANTE (corregido el 02/09/2026).
     ------------------------------------------------------------------------
     Esta regla escondía TODO lo que no fuera la hoja de previsualización, en cualquier
     pantalla. Y hay pantallas que imprimen su propio contenido sin pasar por esa hoja: el
     informe de una reclamación, el albarán firmado y el recibo de kilometraje. En esas, la
     hoja no existe, así que se escondía la página entera y salía UN FOLIO EN BLANCO — que
     es como se reportó: «sale una página sin texto alguno, tanto en imprimir como en
     guardar».
     Con la clase delante, solo tapa lo de detrás cuando de verdad hay algo delante. */
  body.previsualizando > *:not(#zonaImpresion) {
    display: none !important;
  }

  /* Y lo que no debe salir en papel NUNCA, imprima la pantalla lo suyo o una hoja de
     previsualización: la cabecera, la barra de abajo, los avisos y los botones. Antes esto
     vivía solo en `albaranes.css`, así que una pantalla que no lo cargara imprimía el menú. */
  .app-header,
  .bottom-nav,
  .alert,
  .fab-anadir,
  .no-imprimir,
  #avisoErrorJs,
  #deshacerBanner {
    display: none !important;
  }

  /* Al imprimir deja de ser una capa flotante y vuelve al flujo normal: un elemento fijo
     se repetiría o se cortaría al pasar de página. */
  #zonaImpresion {
    display: block !important;
    position: static !important;
    overflow: visible !important;
    background: none !important;
    font-size: 10pt;
    /* Sin esto, el navegador quita los fondos al imprimir y se pierden tanto la fila de
       títulos como el rayado que hace legible una tabla larga. */
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .imp-barra {
    display: none !important;
  }

  .imp-hoja {
    max-width: none;
    margin: 0;
    padding: 0;
    box-shadow: none;
    overflow: visible;
  }

  /* EL ALBARÁN CABE EN UNA HOJA, y hay que ayudarle a caber.
     Lo que le sacaba a una segunda página era el apaisado —que la impresión de esta
     aplicación fuerza para los listados anchos— y ya se corrige inyectando `@page` vertical
     al abrirlo. Esto es lo otro: que no se parta por dentro. Un albarán partido entre dos
     hojas, con la firma en la segunda, no vale como justificante.
     Si las observaciones son largas, pasará a dos páginas: eso es correcto y es lo único que
     debería hacerlo. */
  .imp-hoja-albaran table,
  .imp-hoja-albaran tr {
    page-break-inside: avoid;
  }

  .imp-hoja-albaran .alb-firmas,
  .imp-hoja-albaran .alb-firma,
  .imp-hoja-albaran .alb-cliente,
  .imp-hoja-albaran .alb-nota-legal {
    page-break-inside: avoid;
  }

  /* EL APAISADO YA NO VIVE AQUÍ (02/09/2026).
     ------------------------------------------------------------------------
     Los listados anchos —Facturas son nueve columnas— sí lo necesitan. Pero `@page` no se
     puede escoger por clase: puesto aquí, valía para TODA la aplicación, y un informe de
     reclamación o un recibo salían tumbados. Se resolvía al revés —el albarán inyectaba
     `@page portrait` para deshacerlo—, lo que obliga a acordarse en cada documento nuevo.
     Ahora lo inyecta quien abre la hoja de previsualización (`compartido/exportar.js`),
     mientras dura. Lo demás sale vertical, que es lo que hace un navegador si nadie le
     dice otra cosa. */

  .imp-logo { font-size: 13pt; }
  .imp-fecha { font-size: 8pt; }
  .imp-titulo { font-size: 15pt; }
  .imp-subtitulo { font-size: 9pt; }
  .imp-tabla { font-size: 9pt; }
  .imp-totales { font-size: 10pt; }
  .imp-pie { font-size: 8pt; }

  /* Que la fila de títulos se repita en cada página del PDF. */
  .imp-tabla thead {
    display: table-header-group;
  }

  .imp-tabla tr {
    page-break-inside: avoid;
  }
}

/* Texto secundario, para líneas de detalle bajo un dato principal. Vive aquí y no en
   pendientes.css (de donde viene el nombre) porque lo usa media app. */
.pend-sub {
  font-size: 12px;
  color: var(--gris-medio);
}

/* BOTÓN FLOTANTE + — compartido por todas las pantallas que dan de alta algo (Clientes,
   Facturas, Ofertas, Caja...). Vive aquí, no en clientes.css, porque base.css es la única
   hoja que cargan absolutamente todas las páginas. */
.fab-anadir {
  position: fixed;
  bottom: 90px;
  right: 20px;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--negro);
  color: var(--amarillo);
  border: none;
  font-size: 28px;
  font-weight: 700;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .3);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 90;
}

/* Y la que hace que `hidden` funcione en el botón. `display: flex` va por clase y gana al
   `display: none` que el navegador aplica a [hidden]: sin esto, esconderlo desde el JS no lo
   esconde. Mismo tropiezo anotado ya en .tabs, .ind-detalle, .aviso-inline, .btn-campana,
   .campana-panel, #visorPdf y .fp-aprendido. */
.fab-anadir[hidden] { display: none; }

.fab-anadir:active {
  opacity: .85;
}

/* Campos que se guardan en mayúsculas (nombres, direcciones): se escriben ya en
   mayúsculas para que se vea desde el principio cómo va a quedar guardado. */
.mayus {
  text-transform: uppercase;
}

/* Aviso de error de la propia app (ver compartido/avisarError.js): va fijo abajo, encima
   de la barra de navegación, y se quita tocándolo. Solo aparece cuando algo falla. */
#avisoErrorJs {
  display: none;
  position: fixed;
  left: 10px;
  right: 10px;
  bottom: 78px;
  z-index: 200;
  background: #fef2f2;
  color: #c0392b;
  border: 1.5px solid #c0392b;
  border-radius: 12px;
  padding: 10px 14px;
  font-size: 12px;
  font-weight: 600;
  max-height: 40vh;
  overflow-y: auto;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .2);
}

/* INDICADORES PLEGABLES — ver compartido/indicadores.js. Plegados ocupan una línea en vez
   de media pantalla, y esa línea ya dice lo único que puede obligar a hacer algo hoy. */
.indicadores {
  margin-bottom: 12px;
}

.ind-linea {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  background: var(--blanco);
  border: none;
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  color: var(--gris-medio);
  text-align: left;
}

/* Cuando hay algo vencido o sin resolver, la línea deja de ser gris. Es lo que hace que
   valga la pena plegarlos: si no hay nada, no llama; si lo hay, se ve sin desplegar.
   Fondo en vez de borde lateral: con las esquinas redondeadas, un borde de 4px se curva
   y queda como un paréntesis rojo suelto. El fondo es además el mismo que ya usan los
   demás avisos de la aplicación. */
.ind-linea.ind-alerta {
  color: #c0392b;
  background: #fdecea;
}

.ind-flecha {
  flex: 0 0 auto;
  font-weight: 400;
}

.ind-detalle {
  margin-top: 8px;
}

/* Hace falta decirlo explícitamente: `.ind-detalle` lleva también la clase `.stat-grid`,
   que fija `display: grid`, y una regla de clase gana al `display: none` que el navegador
   aplica por el atributo `hidden`. Sin esto, plegarlos no plegaría nada. */
.ind-detalle[hidden] {
  display: none;
}

/* MENÚ DE TRES PUNTOS — grupos de opciones dentro del menú (ver compartido/exportar.js).
   Sirve para meter dentro un desplegable que no da para una línea entera, como el año. */
.menu-lista .menu-grupo + .menu-grupo {
  border-top: 1px solid var(--borde);
  margin-top: 4px;
  padding-top: 4px;
}

.menu-lista .menu-grupo-titulo {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--gris-medio);
  padding: 4px 12px 2px;
}

/* La opción elegida lleva una marca a la izquierda. El hueco se reserva en todas las
   opciones para que al cambiar de una a otra no se muevan de sitio.
   Solo en las opciones, no en PDF/Excel: esos botones ya existían en cinco pantallas y
   sangrarlos les cambiaría el aspecto sin motivo. */
.menu-lista button[data-valor]::before {
  content: '';
  display: inline-block;
  width: 14px;
}

.menu-lista button[data-valor].elegida {
  font-weight: 700;
}

.menu-lista button[data-valor].elegida::before {
  content: '✓';
  color: var(--amarillo);
}

/* Desplegable estrecho dentro de una fila de buscador: comparte línea con el campo de
   texto y con el menú de tres puntos. Se recorta el texto antes que empujar al resto —
   "Pendientes" cortado sigue leyéndose, y una fila que no cabe rompe la pantalla. */
.buscador-fila > .filtro-corto {
  flex: 0 1 130px;
  min-width: 0;
  padding-right: 28px;
  text-overflow: ellipsis;
  font-size: 14px;
}

/* Título de una sección que no va dentro de una tarjeta. Se usa cuando el enunciado tiene
   que llevar un dato variable —el año elegido, por ejemplo— que si no queda escondido en
   el menú de tres puntos y no se ve por ninguna parte. */
.titulo-seccion {
  font-size: 15px;
  font-weight: 800;
  margin-bottom: 10px;
}

/* Botón de lupa junto al título de una sección: despliega los filtros, que por defecto
   están guardados. Mismo tamaño y forma que el ⋮ de al lado para que se lean como un par
   de acciones, no como dos cosas distintas. */
.btn-lupa {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid var(--borde);
  border-radius: 10px;
  background: var(--blanco);
  color: var(--negro);
}

.btn-lupa svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.btn-lupa:active {
  background: var(--gris-suave);
}

/* Con los filtros abiertos, la lupa se queda marcada: si no, con los filtros desplegados
   no se sabe si se cierran tocando otra vez ahí. */
.btn-lupa.abierta {
  background: var(--amarillo);
  border-color: var(--amarillo);
}

/* Y cuando hay un filtro puesto pero guardado, un punto avisa de que lo que se está
   viendo no es todo. Sin él, un filtro escondido es una lista incompleta sin explicación. */
.btn-lupa.con-filtro::after {
  content: '';
  position: absolute;
  margin: -18px 0 0 18px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #c0392b;
  border: 2px solid var(--blanco);
}

/* Botón principal metido en una fila junto a un campo, en vez de ocupar una línea entera
   para él solo. Se encoge a su texto y no se estira. */
.buscador-fila > .btn-en-fila {
  flex: 0 0 auto;
  width: auto;
  margin: 0;
  padding: 12px 20px;
  white-space: nowrap;
}

/* COMPORTAMIENTOS COMUNES §4 — aviso de deshacer.
   Abajo, encima de la barra de navegación: es donde está la mano y donde no tapa la lista
   que uno acaba de tocar. */
.deshacer-banner {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: 78px;
  z-index: 60;
  display: none;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--negro, #1e1e1e);
  color: #fff;
  font-size: 14px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .25);
}

.deshacer-banner.visible { display: flex; }

.deshacer-texto {
  flex: 1;
  min-width: 0;
  line-height: 1.35;
}

.deshacer-btn {
  flex: 0 0 auto;
  padding: 7px 14px;
  border: none;
  border-radius: 6px;
  background: var(--amarillo, #f5c518);
  color: var(--negro, #1e1e1e);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}

/* La cuenta atrás dice cuánto queda para que deje de poder deshacerse. Sin ella, el aviso
   desaparece de golpe y uno no sabe si llegó a tiempo. */
.deshacer-cuenta {
  flex: 0 0 auto;
  font-size: 12px;
  opacity: .6;
  min-width: 22px;
  text-align: right;
}

/* FILA DE DATO: etiqueta a la izquierda, cifra a la derecha del todo.
   Es el ladrillo con el que están hechos los desgloses de toda la aplicación —el coste de un
   vehículo, el resumen de un pedido, las horas de una ficha—, y vive aquí porque lo usan doce
   pantallas.

   Estaba escrito solo en calidad.css, que carga UNA de esas doce. En las once restantes las
   filas salían como texto corrido: la etiqueta y el número pegados, sin separación ni
   alineación. Se veía sobre todo en el coste de Flota, que es una lista de siete cifras.

   `tabular-nums` hace que todos los dígitos ocupen lo mismo, así que las unidades de una
   columna de importes quedan una debajo de otra y se pueden comparar de un vistazo. */
.cal-linea {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--gris-suave, #eee);
  font-size: 14px;
}

.cal-linea:last-child {
  border-bottom: none;
}

/* La cifra: pegada a la derecha y sin partirse en dos líneas. */
.cal-linea > :last-child {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
}

/* Cuando la fila es solo texto (dos etiquetas), no tiene sentido forzar que no se parta. */
.cal-linea.cal-texto > :last-child {
  white-space: normal;
}

/* Un aviso corto pegado al campo que lo provoca: el carnet que pide el vehículo, y cosas así.
   No es una alerta de las de arriba —esas son para lo que acaba de pasar—, sino una nota que
   se queda ahí mientras el dato siga siendo el que es.

   Vive en base.css y no en la hoja de una pantalla porque la trampa ya nos ha costado un
   arreglo: `.cal-linea` estaba en calidad.css y once pantallas la usaban sin cargarla. */
.aviso-inline {
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.4;
  color: #7a5310;
  background: #fdf6e3;
  border-left: 3px solid #c9891a;
  border-radius: 5px;
  padding: 7px 9px;
}

.aviso-inline[hidden] { display: none; }

/* TRES O CUATRO TARJETAS EN UNA FILA.
   La rejilla de indicadores es de dos columnas, que está bien para dos tarjetas. Con tres, la
   tercera bajaba a una segunda línea y se quedaba a media anchura — y una tarjeta suelta a
   medio ancho se lee como si fuera otra cosa, no como la tercera de tres.

   Vive en base.css y no en la hoja de una pantalla: lo usa el indicador, que está en todas.
   (La misma trampa que ya costó un arreglo con `.cal-linea`.) */
.stat-grid.stat-grid-linea {
  grid-template-columns: repeat(3, 1fr);
  gap: 7px;
}

.stat-grid-linea .stat-card { padding: 12px 5px; }
.stat-grid-linea .stat-num { font-size: 21px; }
.stat-grid-linea .stat-label { font-size: 10.5px; line-height: 1.3; }

/* CON CUATRO, DOS Y DOS (05/09/2026).

   «Cuando son tres, en una línea; cuando son cuatro, que aparezcan en dos.» Antes se metían
   los cuatro en una sola fila y en el móvil cada tarjeta quedaba en una columna de setenta
   píxeles: el número cabía justo y la etiqueta se partía en tres renglones. Dos y dos se lee
   igual de rápido y cabe. */
.stat-grid.stat-grid-linea:has(> :nth-child(4)) {
  grid-template-columns: repeat(2, 1fr);
}

/* A partir de cinco, tres por fila: son pocos casos y con dos columnas se irían de alto. */
.stat-grid.stat-grid-linea:has(> :nth-child(5)) {
  grid-template-columns: repeat(3, 1fr);
}

/* GUARDAR Y CANCELAR EN LA MISMA LÍNEA.
   Dos botones idénticos uno debajo del otro obligan a leerlos para saber cuál es cuál. Guardar
   es lo que se viene a hacer; cancelar es una salida, y con aspecto de enlace se distingue sin
   leer.

   En base.css porque lo usan la ficha del trabajador y las facturas de proveedor. Estuvo en la
   hoja de la ficha y en facturas salía sin estilo — la misma trampa de `.cal-linea`. */
.acciones-guardar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 4px;
}

.acciones-guardar .btn-primary {
  flex: 1;
  margin-top: 0;
}

.btn-texto {
  background: none;
  border: none;
  color: #777;
  font-size: 15px;
  padding: 12px 4px;
  text-decoration: underline;
  flex-shrink: 0;
}

.btn-texto:active { color: var(--negro); }

/* LA CAMPANA DE AVISOS (§5 del módulo Oferta). Vive en la cabecera de todas las páginas:
   un aviso tiene que encontrarte estés donde estés. Nace escondida y solo aparece cuando
   hay algo — una campana siempre a cero deja de mirarse. */
.btn-campana {
  position: relative;
  background: none;
  border: none;
  padding: 6px;
  cursor: pointer;
  color: var(--amarillo);
  display: flex;
  align-items: center;
}

.btn-campana[hidden] {
  display: none;
}

.btn-campana svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* EL NÚMERO, AL LADO Y NO ENCIMA (16/09/2026). TERCERA VUELTA A LO MISMO.

   Empezó pegado a `top:0; right:0`, o sea DENTRO del botón, y con dos caracteres («9+»)
   tapaba la campana: se veía el número flotando y no se entendía qué era. Se reportó el
   05/09/2026 como «la forma de la campana desaparece y solo se ve el número» y se sacó unos
   píxeles hacia la esquina de fuera.

   NO BASTÓ, y se volvió a reportar el 16/09/2026 con las mismas palabras: «pinchas la campana
   y desaparece, se ve sólo el número». Un óvalo de 19 px sobre un icono de 20 px sigue
   pisándole la esquina, se mire desde donde se mire — está a la vista en
   `.verificacion/campana-vista.html`, que es una página hecha para mirarlo.

   Así que deja de flotar: va EN EL FLUJO del botón, a la derecha del icono. Entonces no puede
   taparlo pase lo que pase, ni con «9+» ni con lo que venga. El botón crece unos píxeles y en
   la cabecera sobra sitio. */
.campana-num {
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  border-radius: 8px;
  background: #c0392b;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}

/* El hueco entre la campana y su número. `margin-right` se queda: el botón de salir va justo
   detrás y sin él quedan pegados. */
.btn-campana { margin-right: 4px; gap: 4px; }

.campana-panel {
  position: absolute;
  top: 100%;
  right: 8px;
  width: min(320px, calc(100vw - 24px));
  max-height: 60vh;
  overflow-y: auto;
  background: var(--blanco);
  border-radius: 12px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
  z-index: 60;
}

.campana-panel[hidden] {
  display: none;
}

.campana-aviso {
  display: block;
  padding: 10px 12px;
  border-bottom: 1px solid var(--gris-suave);
  color: var(--negro);
  text-decoration: none;
}

.campana-aviso:last-child {
  border-bottom: none;
}

.campana-titulo {
  font-size: 13px;
  font-weight: 700;
}

.campana-texto {
  font-size: 11px;
  color: var(--gris-medio);
  margin-top: 2px;
}

/* La aceptación por actuación (§12) y los recursos de la mesa de valoración: una fila con
   su nombre a la izquierda, su importe a la derecha y sus botones debajo. */
.ace-fila {
  padding: 8px 0;
  border-bottom: 1px solid var(--gris-suave);
}

.ace-fila:last-child {
  border-bottom: none;
}

.ace-nombre {
  font-size: 13px;
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: baseline;
}

.ace-importe {
  font-weight: 700;
  white-space: nowrap;
}

.ace-botones {
  display: flex;
  gap: 6px;
  margin-top: 6px;
}

.ace-btn {
  flex: 1;
  padding: 6px;
  border: 1px solid var(--gris-suave);
  border-radius: 8px;
  background: var(--blanco);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.ace-btn.ace-si { background: #1e7e34; color: #fff; border-color: #1e7e34; }
.ace-btn.ace-no { background: #c0392b; color: #fff; border-color: #c0392b; }
.ace-btn.ace-pend { background: #c9891a; color: #fff; border-color: #c9891a; }

.ace-resumen {
  font-size: 12px;
  padding: 8px 0;
  border-bottom: 2px solid var(--negro);
  margin-bottom: 4px;
}

/* LA BANDEJA en la campana: «qué hay que mirar hoy».

   Lo urgente lleva una barra roja a la izquierda. No color de fondo: en una lista
   de diez avisos, tres fondos rojos no dejan leer ninguno. */
.campana-aviso.urgente { border-left: 3px solid #c0392b; }

.campana-importe {
  font-weight: 700;
  font-size: 14px;
  margin-top: 2px;
}

/* «Sigue pendiente» en vez de una fecha: en los avisos automáticos lo que importa
   no es cuándo se publicó, es que sigue pasando. Una fecha ahí haría creer que es
   una novedad de ese día. */
.campana-sigue { font-style: italic; opacity: .75; }

/* BOTONES EN UNA FILA, no apilados.
 *
 * `.btn-primary` ocupa el ancho entero, así que tres seguidos salen uno debajo de otro. Para
 * las acciones de un registro —activar, saltar, eliminar— eso ocupa media pantalla y hace
 * pensar que son tres pasos en orden, cuando son tres cosas sueltas. Pedido el 02/09/2026.
 *
 * En un móvil estrecho vuelven a apilarse solas (`flex-wrap`): tres botones de texto largo en
 * 320 px no caben sin cortar palabras. */
.botonera {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.botonera .btn-primary {
  width: auto;
  flex: 1 1 auto;
  min-width: 140px;
  margin: 0;
  padding: 13px 16px;
  font-size: 15px;
}

/* Un botón trabajando. Se ve apagado y no acepta el cursor: refuerza lo que ya dice el texto
   («Guardando…») y deja claro que no sirve de nada volver a pulsarlo. */
.boton-ocupado {
  opacity: .6;
  cursor: progress !important;
}

/* El mismo banner de avisos, en verde cuando es un acierto. Lo usa la campana al posponer:
   «vuelve el día 12» y «no vuelve» son cosas distintas y hay que decir cuál se ha elegido. */
#avisoErrorJs.aviso-ok {
  background: #1e6b3f;
}

/* La fila de un aviso de la campana: el aviso ocupa lo que puede y el reloj de posponer se
   queda a la derecha, sin empujarlo. */
.campana-fila {
  display: flex;
  align-items: stretch;
  gap: 0;
}
.campana-fila .campana-aviso { flex: 1; min-width: 0; }
.campana-posponer {
  flex: 0 0 auto;
  width: 42px;
  border: none;
  border-left: 1px solid var(--gris-suave, #eee);
  background: none;
  font-size: 16px;
  color: var(--gris, #888);
  cursor: pointer;
}
.campana-posponer:hover { background: var(--gris-suave, #f4f4f4); }

/* El modal de posponer lo crea la cabecera al vuelo, así que va por encima del panel de la
   campana, que ya está flotando. */
.modal-fondo.campana-modal { z-index: 9000; }

/* Un nombre que lleva a su ficha (02/09/2026, compartido/enlaceFicha.js). Se subraya con
   puntos en vez de a lo bruto: van dentro de tarjetas que ya tienen su propia acción, y un
   enlace azul de toda la vida ahí dentro compite con ella. */
.ficha-enlace {
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
.ficha-enlace:hover { color: #1a3a5c; text-decoration-style: solid; }

/* Una nota debajo de un campo: de dónde sale ese número, o qué va a pasar con lo que se
   escriba. Pegada al campo y en gris: es una aclaración, no un error. */
.campo-nota {
  display: block;
  margin-top: 4px;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--gris-medio);
}

/* UN AVISO PLEGABLE (04/09/2026).
 *
 * Hereda de `.ind-linea` —la línea de los indicadores— para que se comporte igual: mismo
 * gesto, misma flecha, misma memoria. Lo único propio es que va dentro de un `.alert`, que
 * ya trae su color de aviso, así que la línea no tiene que pintarse otra vez. */
.alert .aviso-plegable-linea {
  width: 100%;
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  text-align: left;
  padding: 0;
  cursor: pointer;
}

.alert .aviso-plegable-detalle {
  margin-top: 6px;
}

.alert .aviso-plegable-detalle .aviso-linea {
  line-height: 1.45;
  padding: 2px 0;
}
