/* ===========================================================================
   ACUBERO — portal de tramitación
   Los tokens de marca están en tokens.css, compartido con la web pública para
   que las dos piezas se vean como una sola: misma paleta teal + crema, mismos
   radios, sombras siempre teñidas de teal y nunca de negro puro, y el peso
   ligero (300) que le da el aire de consultoría boutique.
   =========================================================================== */

:root {
  /* Los valores viven en tokens.css, que cargamos antes que esta hoja (ver
     plantillas/base.html) y que comparte la web pública. Aquí solo se les
     ponen los nombres cortos que usa el portal: así un cambio de marca se
     hace en un sitio y llega a las dos piezas. */

  /* Marca */
  --teal-50:  var(--marca-teal-50);
  --teal-100: var(--marca-teal-100);
  --teal-200: var(--marca-teal-200);
  --teal-300: var(--marca-teal-300);
  --teal-400: var(--marca-teal-400);
  --teal:     var(--marca-teal-500);
  --teal-600: var(--marca-teal-600);
  --teal-700: var(--marca-teal-700);
  --teal-800: var(--marca-teal-800);
  --teal-900: var(--marca-teal-900);
  /* alias heredados */
  /* Texto, no marca. El 600 sobre blanco da 3,73:1 y no llega al 4,5 que pide
     WCAG AA; el 700 da 5,39 y a ojo no se distingue en un enlace. La paleta de
     marca no se toca: lo que cambia es qué token se usa para escribir. Todos
     los enlaces del portal van de este color, así que esta línea sola arregla
     quince sitios. */
  --teal-dark: var(--teal-700);
  --teal-light: var(--teal-300);

  /* Superficies cálidas */
  --cream: var(--marca-cream);
  --bg: var(--marca-sand);

  /* Tinta: verdosa, no gris neutro */
  --dark: var(--marca-ink);
  --text: var(--marca-ink-soft);
  --muted: var(--marca-muted);
  --hairline: var(--marca-hairline);

  /* Tipografía */
  --serif: var(--marca-serif);
  --sans: var(--marca-sans);

  /* Radios */
  --radius-card: var(--marca-radius-card);
  --radius-xl2: var(--marca-radius-xl2);
  --radius-pill: var(--marca-radius-pill);
  --radius-boton: var(--marca-radius-boton);

  /* Sombras, siempre en teal */
  --shadow-soft: var(--marca-shadow-soft);
  --shadow-card: var(--marca-shadow-card);
  --shadow-lift: var(--marca-shadow-lift);
  --shadow-brand: var(--marca-shadow-brand);

  /* Degradado de marca */
  --degradado: var(--marca-degradado);

  --ease: var(--marca-ease);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--dark);
  font-family: var(--sans);
  font-weight: 300;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Los titulares van en serif y en peso normal, no en negrita: la jerarquía
   la marca el tamaño, no el grosor. */
h1, h2, h3, h4 {
  font-family: var(--serif);
  color: var(--dark);
  font-weight: 400;
  letter-spacing: -.015em;
  line-height: 1.25;
  text-wrap: balance;
}

::selection { background: var(--teal-200); color: var(--teal-900); }

:focus-visible {
  outline: 2px solid var(--teal-600);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Separador que se desvanece en los extremos, nunca una línea sólida dura. */
.separador {
  height: 1px; width: 100%; border: 0; margin: 1.4rem 0;
  background: linear-gradient(to right, transparent,
              color-mix(in srgb, var(--teal) 35%, transparent) 30%, color-mix(in srgb, var(--teal) 35%, transparent) 70%, transparent);
}

a { color: var(--teal-dark); }

/* Textos pequeños en mayúsculas con tracking amplio: el patrón de la marca. */
small, .etiqueta, thead th, .stat-label, .dato .k {
  letter-spacing: .14em;
  text-transform: uppercase;
  font-size: .6875rem;
  font-weight: 500;
}

/* Cabecera propia del portal, con enlace de vuelta a la web pública */
.cabecera {
  background: rgba(255,255,255,.86);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--hairline);
  position: sticky; top: 0; z-index: 50;
}
.cabecera-interior {
  max-width: 78rem; margin: 0 auto; padding: .9rem 1.5rem;
  display: flex; align-items: center; gap: 1.5rem;
}

/* Logotipo: marca + wordmark. La jerarquía es la inversa de la habitual —
   «ACUBERO» en sans pesada y muy espaciada, descriptor en serif. */
.logotipo { display: inline-flex; align-items: center; gap: .6rem; text-decoration: none; }
.logo-marca { width: 2.75rem; height: 2.75rem; flex: 0 0 auto; }
.logotipo-texto { display: flex; flex-direction: column; line-height: 1; }
.logotipo-nombre {
  font-family: var(--sans); font-size: 1.15rem; font-weight: 700;
  letter-spacing: .19em; color: var(--dark);
}
.logotipo-descriptor {
  margin-top: .38rem; font-family: var(--serif); font-size: .5rem;
  text-transform: uppercase; letter-spacing: .16em; color: var(--teal-700);
}

/* Logo de la empresa cliente, junto al de la asesoría en la cabecera.
   Esta regla estaba duplicada más abajo (junto a «Logos: asesoría en la
   cabecera») con valores distintos y contradictorios -gap y padding
   distintos, el borde de otro color-: la que ganaba era la última del
   fichero, así que la mitad de esta declaración no llegaba a aplicarse
   nunca. Queda una sola, aquí. */
.marca-empresa {
  display: inline-flex; align-items: center; gap: .55rem;
  padding-left: 1.1rem; margin-left: .2rem;
  border-left: 1px solid var(--hairline);
  min-width: 0;
}
.marca-empresa img { max-height: 2rem; max-width: 8rem; display: block; }
/* El nombre iba solo en el title (tooltip): quien abre el enlace de alta no
   ha oído hablar de ACUBERO en su vida y necesita ver, sin pasar el ratón,
   qué empresa se lo ha mandado. 11rem cortaba nombres de sobra cortos
   -"ASSOCIACIO ESPORTIVA STA GERTRUDIS" ya no cabía- con hueco vacío al
   lado en la propia cabecera: el tope solo hace falta para no pelearse con
   la navegación del cliente logueado, así que sube a algo que deje pasar
   una razón social normal y solo recorte las de verdad largas. */
.marca-empresa-nombre {
  font-size: .85rem; color: var(--ink-soft); min-width: 0;
  max-width: 22rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Sin logo propio, las iniciales de la empresa en un círculo de marca. El
   selector era «.marca-empresa .iniciales», un descendiente que no
   coincidía con nada: base.html pinta la clase suelta «marca-iniciales», así
   que el círculo no se veía y las iniciales salían como texto corrido. */
.marca-iniciales {
  width: 2rem; height: 2rem; border-radius: var(--radius-pill);
  background: var(--teal-100); color: var(--teal-700);
  display: grid; place-items: center; font-size: .72rem;
  font-weight: 600; letter-spacing: .04em;
}
.cabecera nav { margin-left: auto; display: flex; gap: 1.1rem; align-items: center; flex-wrap: wrap; }
.cabecera nav a { color: var(--text); text-decoration: none; font-size: .95rem; }
.cabecera nav a:hover { color: var(--teal-dark); }
/* Único indicio de en qué sección estás: sin esto, con 8 enlaces al mismo
   peso visual, la única pista era el <h1> de la página. Color, no negrita:
   el resto de la marca reserva el peso para tamaños, no para estado. */
.cabecera nav a[aria-current="page"] { color: var(--teal-700); font-weight: 500; }
.volver-web { font-size: .85rem; color: var(--muted); }

/* Icono discreto de la cabecera: campana y «Salir». Circular y transparente
   hasta que se usa, para que no compitan por atención con lo que se mira a
   diario. */
.cabecera .icono-boton {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.15rem; height: 2.15rem; flex: 0 0 auto;
  border: none; border-radius: var(--radius-pill);
  background: transparent; cursor: pointer;
  transition: background-color .16s var(--ease), color .16s var(--ease);
}
.cabecera .icono-boton svg { width: 1.2rem; height: 1.2rem; }
.cabecera .icono-boton:hover { background: var(--teal-50); }
.cabecera .icono-boton:active { transform: scale(.93); }
/* «Salir» es la única acción destructiva de la cabecera: el mismo rojo
   apagado que ya usan .boton.peligro y .pildora.rechazada, y solo al posar
   el ratón — en reposo es un icono más, no hace falta que grite. */
.cabecera .icono-peligro:hover { background: #fbeceC; color: #8a5a5a; }

.divisor-nav { width: 1px; height: 1.4rem; background: var(--hairline); flex: 0 0 auto; }

.cabecera nav .nota {
  max-width: 10rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Lo que se toca de vez en cuando —Trámites en el cliente, Más en quien
   administra— vive tras un botón con nombre, nunca tras un icono a secas:
   un «···» sin texto es lo menos autoexplicativo de la cabecera. */
.grupo { position: relative; flex: 0 0 auto; }
.grupo-boton {
  display: inline-flex; align-items: center; gap: .3rem;
  border: none; background: none; cursor: pointer;
  font-family: inherit; font-size: .95rem; color: var(--text);
  padding: .3rem .1rem;
}
.grupo-boton:hover, .grupo-boton.abierto { color: var(--teal-dark); }
.grupo-boton.actual { color: var(--teal-700); font-weight: 500; }
.grupo-flecha { width: .8rem; height: .8rem; transition: transform .18s var(--ease); }
.grupo-boton.abierto .grupo-flecha { transform: rotate(180deg); }

/* Menú flotante genérico, anclado a la derecha del botón que lo abre. Lo usa
   el grupo de arriba, pero no es exclusivo de la cabecera: cualquier botón
   con data-menu (ver cabecera.js) puede abrir uno igual.
   No se llama «.desplegable»: ese nombre ya lo usa el envoltorio de los
   paneles de filtro (más abajo, junto a .pastilla), con otra forma y otro
   anclaje —izquierda, no derecha—; reutilizarlo aquí pisaba esa regla y el
   menú se quedaba en flujo normal en vez de flotar, estirando la cabecera
   entera al alto del menú abierto. */
.menu-flotante {
  position: absolute; top: calc(100% + .6rem); right: 0; z-index: 60;
  background: #fff; border: 1px solid var(--hairline);
  border-radius: 14px; box-shadow: var(--shadow-card);
  min-width: 12rem; padding: .4rem;
  opacity: 0; visibility: hidden; transform: translateY(-6px) scale(.98);
  transition: opacity .16s var(--ease), transform .16s var(--ease), visibility .16s;
  transform-origin: top right;
}
.menu-flotante.abierto { opacity: 1; visibility: visible; transform: translateY(0) scale(1); }
/* Puente sobre el hueco de .6rem que el panel deja bajo el botón: sin él, ir
   del botón al menú cruza una franja que no es de nadie, el ratón sale del
   grupo y el menú se cierra en la cara de quien iba a pulsarlo (cabecera.js
   abre al posar el ratón). Cuelga del panel, así que solo existe con el menú
   abierto —visibility lo apaga con él— y no se estira más a la derecha que el
   botón; por debajo solo le queda franja vacía, porque los enlaces de al lado
   son más bajos y no llegan a ella. */
.menu-flotante::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: .6rem;
}
.menu-flotante a { display: block; padding: .55rem .7rem; border-radius: 9px; text-decoration: none; }
.menu-flotante a:hover { background: var(--teal-50); }

main { max-width: 78rem; margin: 2.2rem auto; padding: 0 1.5rem; }

.tarjeta {
  background: #fff;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  /* Antes este borde escribía el color de --hairline a mano, en decimal, al
     60% de opacidad: el mismo tipo de duplicado que ya rompió el gris de la
     web, solo que en otra notación. La web ya usaba el token en sus tarjetas
     (border-hairline); el portal era la pieza que se había quedado atrás. */
  border: 1px solid color-mix(in srgb, var(--hairline) 60%, transparent);
  padding: 1.7rem;
  margin-bottom: 1.4rem;
}

.pildora {
  display: inline-block;
  padding: .2rem .85rem;
  border-radius: var(--radius-pill);
  font-size: .74rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  background: color-mix(in srgb, var(--teal) 16%, transparent);
  color: var(--teal-dark);
}
/* Pendiente, aprobada y exportada eran tres opacidades del mismo teal: para
   distinguirlas había que leerlas. El color se reserva para el estado, que es
   lo que cambia una decisión; el borrador se queda en gris porque todavía no
   es nada. */
.pildora.borrador  { background: rgba(122,138,138,.15); color: var(--muted); }
.pildora.pendiente { background: #fdf3e0; color: #7a5a1f; }
.pildora.aprobada  { background: #e8f2ea; color: #2c6446; }
.pildora.rechazada { background: #fbeceC; color: #8a3b3b; }
/* Blanco sobre --teal daba 2,61:1. Sobre el 700, 5,39. */
.pildora.exportada { background: var(--teal-700); color: #fff; }
.pildora.pendiente_tgss  { background: rgba(122,138,138,.20); color: var(--teal-dark); }
.pildora.alta_confirmada { background: #2f7d5f; color: #fff; }
.pildora.incidencia_ss   { background: #9a5b2e; color: #fff; }
.pildora.revision        { background: rgba(154,91,46,.16); color: #7a4522; }
.pildora.asociada        { background: rgba(47,125,95,.16); color: #2f7d5f; }
.pildora.descartada      { background: rgba(122,138,138,.15); color: var(--muted); }
.pildora.cancelada       { background: rgba(122,138,138,.15); color: var(--muted); }

/* Estados de cobro de una factura. No son colores de marca -por eso viven
   aquí y no en tokens.css-: son semántica de estado, como los de arriba.
   `pendiente` ya está definido más arriba y se reutiliza tal cual: una
   solicitud pendiente de revisar y una factura pendiente de cobro son la
   misma idea y merecen el mismo color. */
.pildora.pagada      { background: #e8f2ea; color: #2c6446; }
.pildora.parcial     { background: #fdf3e0; color: #7a5a1f; }
.pildora.abono       { background: rgba(122,138,138,.20); color: var(--teal-dark); }
.pildora.sin_importe { background: rgba(122,138,138,.15); color: var(--muted); }

/* El resultado del trámite en Seguridad Social, tal como lo ve la empresa.
   El color hace la mitad del trabajo: verde es «ya está», ámbar es «alguien
   lo está mirando», gris es «esperando». */
.resultado-ss {
  margin: 1.25rem 0;
  padding: 1rem 1.15rem;
  border-radius: 10px;
  border-left: 4px solid var(--muted);
  background: rgba(122,138,138,.08);
}
.resultado-ss .resultado-titulo {
  font-size: 1.15rem;
  font-weight: 500;
  margin: 0 0 .5rem;
}
.resultado-ss.correcto   { border-left-color: #2f7d5f; background: rgba(47,125,95,.09); }
.resultado-ss.incidencia { border-left-color: #9a5b2e; background: rgba(154,91,46,.09); }
.resultado-ss.esperando  { border-left-color: var(--teal); }
.resultado-ss small { color: var(--muted); }

/* Los datos técnicos de una comunicación: literal de la TGSS, huellas,
   nombres de fichero. Monoespaciada y que no desborde en móvil. */
.tecnico {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .85rem;
  background: rgba(122,138,138,.10);
  padding: .75rem .9rem;
  border-radius: 8px;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

.boton {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .45rem; white-space: nowrap;
  border: none; cursor: pointer;
  background-image: var(--degradado);
  color: #fff;
  padding: .62rem 1.4rem;
  border-radius: var(--radius-boton);
  font-family: inherit; font-size: .9rem; font-weight: 500;
  letter-spacing: .02em;
  text-decoration: none;
  transition: transform .12s var(--ease), box-shadow .2s var(--ease), opacity .2s;
  box-shadow: var(--shadow-brand);
}
.boton:hover { opacity: .93; }
.boton:active { transform: scale(.97); opacity: .9; }
.boton.secundario {
  background-image: none; background-color: #fff; color: var(--teal-700);
  box-shadow: none; border: 1px solid var(--teal-200);
}
.boton.secundario:hover { background-color: var(--teal-50); }
.boton.peligro {
  background-image: none; background-color: #fff;
  color: #8a5a5a; border: 1px solid #e3cfcf; box-shadow: none;
}

/* Botón de solo icono: la misma acción de siempre (mismo color según
   .secundario/.peligro), pero cuadrado y sin texto -aria-label lleva el
   nombre accesible, title el tooltip nativo del navegador-. */
.boton-icono { width: 2.35rem; height: 2.35rem; padding: 0; flex: none; }
.boton-icono svg { width: 17px; height: 17px; }
/* El desplegable de Nueva alta reutiliza el mismo <summary class="boton">
   de siempre: aquí solo se le quita el hueco que dejaba el texto. */
.menu-alta.icono > summary { width: 2.35rem; height: 2.35rem; padding: 0; }
.menu-alta.icono > summary svg { width: 17px; height: 17px; }
.menu-alta.icono > summary::after { margin-left: .15rem; }

table { width: 100%; border-collapse: collapse; }
thead th { text-align: left; color: var(--muted); padding: .5rem .6rem; border-bottom: 2px solid color-mix(in srgb, var(--teal) 20%, transparent); }
tbody td { padding: .7rem .6rem; border-bottom: 1px solid color-mix(in srgb, var(--teal) 12%, transparent); }
tbody tr:hover { background: color-mix(in srgb, var(--teal) 5%, transparent); }

label { display: block; margin: .9rem 0 .25rem; font-size: .9rem; color: var(--dark); }
input, select, textarea {
  width: 100%;
  padding: .6rem .8rem;
  border: 1px solid var(--teal-200);
  border-radius: 12px;
  font-family: inherit;
  font-weight: 300;
  font-size: .95rem;
  background: #fff;
  color: var(--dark);
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--teal);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 18%, transparent);
}

/* El campo hereda el borde y el radio de arriba, pero el botón nativo de
   «Seleccionar archivo» no hereda nada del sistema de diseño: sale gris y en
   relieve, como un control de otra web. Se rehace en teal para que combine
   con el resto de botones secundarios. */
input[type="file"] {
  padding: .45rem .8rem .45rem .5rem;
  color: var(--muted);
  font-size: .88rem;
  cursor: pointer;
}
input[type="file"]::file-selector-button {
  font-family: inherit;
  font-size: .85rem;
  font-weight: 500;
  color: var(--teal-700);
  background: var(--teal-50);
  border: 1px solid var(--teal-200);
  border-radius: 10px;
  padding: .5rem 1rem;
  margin-right: .9rem;
  cursor: pointer;
  transition: background-color .15s var(--ease), transform .12s var(--ease);
}
input[type="file"]::file-selector-button:hover { background-color: var(--teal-100); }
input[type="file"]::file-selector-button:active { transform: scale(.96); }
/* Mismo pseudo-elemento, prefijo antiguo: Safari no reconoció el estándar
   hasta la versión 17 y esto es lo que usa el resto del sitio en el móvil. */
input[type="file"]::-webkit-file-upload-button {
  font-family: inherit;
  font-size: .85rem;
  font-weight: 500;
  color: var(--teal-700);
  background: var(--teal-50);
  border: 1px solid var(--teal-200);
  border-radius: 10px;
  padding: .5rem 1rem;
  margin-right: .9rem;
  cursor: pointer;
}
.rejilla { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 0 1.2rem; }

/* Campos que no hacen falta siempre en pantalla (ver comentario en la
   plantilla que los usa): un <summary> con el mismo tacto que un botón
   secundario, para que no parezca un desplegable nativo del navegador. */
.mas-datos { margin-top: 1.3rem; border-top: 1px solid color-mix(in srgb, var(--teal) 20%, transparent); padding-top: .2rem; }
.mas-datos summary {
  cursor: pointer;
  list-style: none;
  padding: .7rem 0;
  font-size: .9rem;
  font-weight: 500;
  color: var(--teal-700);
}
.mas-datos summary::-webkit-details-marker { display: none; }
.mas-datos summary::before {
  content: "▸";
  display: inline-block;
  margin-right: .5rem;
  transition: transform .15s var(--ease);
}
.mas-datos[open] summary::before { transform: rotate(90deg); }
.mas-datos .rejilla { margin-top: .3rem; }

.avisos { margin-bottom: 1.2rem; }
/* Un error y un éxito eran dos opacidades del mismo teal y un texto de color
   ligeramente distinto: había que leerlos para saber cuál era cuál. Después de
   comunicar una baja, la diferencia entre «acuse registrado» y «no se ha podido
   registrar» tiene que verse desde el otro lado de la mesa.

   La base sigue siendo monocroma; el color se reserva para lo que cambia una
   decisión. Y cada tipo lleva su icono, porque el color no puede ser lo único
   que porte el significado (WCAG 1.4.1) y aquí lo era.

   --acento guarda el color fuerte de cada tipo -antes solo vivía repartido
   entre `color` y `border-left-color`-, para que el icono relleno y su halo
   puedan leerlo sin depender de qué texto tenga encima. */
.mensaje {
  --acento: var(--teal-dark);
  position: relative;
  display: flex; align-items: flex-start; gap: .7rem;
  padding: .85rem 1.2rem; border-radius: 14px; margin-bottom: .6rem;
  background: color-mix(in srgb, var(--teal) 12%, transparent); color: var(--teal-dark);
  border-left: 3px solid var(--acento);
  box-shadow: var(--shadow-soft);
  animation: aviso-entrada .35s var(--ease);
}
/* Círculo relleno del color de acento, glifo en blanco: se ve desde más
   lejos que el círculo perfilado de antes, y de paso sube el contraste del
   propio glifo (blanco sobre color fuerte, en vez de color fuerte sobre un
   fondo ya teñido de ese mismo color). */
.mensaje-icono {
  flex: none; width: 1.4rem; height: 1.4rem; border-radius: 50%;
  background: var(--acento); color: #fff;
  box-shadow: 0 2px 6px color-mix(in srgb, var(--acento) 45%, transparent);
  display: grid; place-items: center;
  font-size: .74rem; font-weight: 700; line-height: 1;
  margin-top: .05rem;
}
.mensaje-cuerpo { flex: 1 1 auto; }
.mensaje.error {
  --acento: #b45454; background: #fdf4f4; color: #8a3b3b;
}
.mensaje.exito {
  --acento: #3d8a5f; background: #f1f7f2; color: #2c6446;
}
.mensaje.aviso {
  --acento: #c79a3c; background: #fdf8ee; color: #7a5a1f;
}
/* Cerrar un aviso a mano: mismo criterio que .modal-cerrar (color heredado,
   se resalta al pasar por encima), pero con feedback físico al pulsar -la
   misma regla que ya siguen los .boton- en vez de quedarse quieto. */
.mensaje-cerrar {
  flex: none; margin: -.15rem -.4rem -.15rem .2rem;
  padding: .15rem .35rem; border: none; border-radius: 6px;
  background: none; color: inherit; opacity: .55;
  font-size: 1.05rem; line-height: 1; cursor: pointer;
  transition: opacity .15s var(--ease), background-color .15s var(--ease),
    transform .1s var(--ease);
}
.mensaje-cerrar:hover { opacity: 1; background: color-mix(in srgb, currentColor 14%, transparent); }
.mensaje-cerrar:active { transform: scale(.88); }
.mensaje.saliendo { animation: aviso-salida .18s var(--ease) forwards; }

@keyframes aviso-entrada {
  from { opacity: 0; transform: translateY(-6px); }
}
@keyframes aviso-salida {
  to { opacity: 0; transform: scale(.97) translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  .mensaje { animation: none; }
  .mensaje.saliendo { animation: none; opacity: 0; }
}

/* align-items: center, no el stretch por defecto: una fila normal de
   botones no se nota la diferencia -miden lo mismo-, pero en cuanto se
   mezcla un botón de icono de alto fijo con uno de texto normal (o el
   divisor-nav de empresa_detalle.html), stretch los desalineaba en vez de
   centrarlos en la fila. */
.acciones { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; margin-top: 1rem; }
.centrado { max-width: 420px; margin: 3rem auto; }
.pie { text-align: center; color: var(--muted); font-size: .82rem; padding: 2rem 0; }
.fecha-volcado { color: var(--muted); font-size: .85rem; }
.nota { color: var(--muted); font-size: .88rem; }
.campo-monospace { font-family: ui-monospace, "Courier New", monospace; }

/* Facturación. Los importes se alinean a la derecha y con cifras de la misma
   anchura: una columna de dinero solo se compara de un vistazo si las
   unidades caen unas debajo de otras. `tabular-nums` lo consigue sin cambiar
   de tipografía. */
.numerico { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
th.numerico, td.numerico { text-align: right; }
/* Celdas editables de la revisión: estrechas, para que la tabla quepa. */
.celda-numero { width: 5.5rem; text-align: right; font-variant-numeric: tabular-nums; }
/* Un precio sin tarifa pactada se ve. No se esconde el problema detrás de un
   0 discreto: si nadie lo mira, se factura a cero. El borde y el color hacen
   de aviso, y el texto de debajo dice «sin tarifa pactada» -el color no es lo
   único que lo distingue (WCAG 1.4.1). */
.celda-numero.sin-tarifa { border-color: #a35a5a; background: #fbeceC; }
/* La fila de la nota interna cuelga de la de arriba: sin borde superior para
   que las dos se lean como una sola fila. */
.fila-nota td { border-top: none; padding-top: 0; }
.fila-nota input { width: 100%; }
/* Un cobro anulado se sigue viendo, tachado: borrarlo de la pantalla es
   perder la explicación de por qué el saldo cambió. */
tr.anulado td { opacity: .55; text-decoration: line-through; }
tr.anulado td:last-child { text-decoration: none; }
.aviso-configuracion { border-left: 4px solid #9a5b2e; }

/* ===== Listado de plantilla del cliente ===== */

.resumen { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.4rem; }
.tarjeta-stat {
  display: flex; align-items: center; gap: .9rem;
  background: #fff; border: 1px solid transparent;
  border-radius: var(--radius-card); box-shadow: var(--shadow-soft);
  padding: 1rem 1.3rem; min-width: 210px;
  font-family: inherit; text-decoration: none; color: var(--text);
  cursor: pointer;
  transition: transform .12s ease, box-shadow .2s ease, border-color .2s ease;
}
.tarjeta-stat:hover { transform: translateY(-1px); border-color: var(--teal-light); box-shadow: var(--shadow-brand); }
.tarjeta-stat:active { transform: scale(.98); }
.stat-ico {
  width: 38px; height: 38px; display: grid; place-items: center;
  border-radius: 11px; background: color-mix(in srgb, var(--teal) 16%, transparent);
  color: var(--teal-dark); font-size: 1.1rem;
}
.stat-txt { display: flex; flex-direction: column; }
.stat-label { font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.stat-valor { font-size: 1.5rem; font-weight: 600; line-height: 1.1; }

.barra { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; margin: 1.2rem 0 .6rem; }
/* En una .barra, align-items: center mide la altura de cada hijo completo:
   un botón suelto queda centrado con el bloque label+campo de al lado, no
   con el campo, y sale más arriba de la cuenta. Este botón se alinea a su
   pie en vez de al centro del grupo. */
.alinea-al-campo { align-self: flex-end; }
/* Un campo de solo lectura con su botón de "copiar" al lado, sin que el
   input pierda el ancho flexible ni el botón se comprima. */
.campo-con-boton { display: flex; gap: .6rem; align-items: stretch; }
.campo-con-boton input { flex: 1 1 auto; min-width: 0; }
.campo-con-boton .boton { flex: 0 0 auto; }
.buscador { position: relative; flex: 1 1 260px; }
.buscador input { padding-right: 2rem; }
/* input[type=search] trae su propia «x» nativa en Chrome/Safari: con el
   botón de limpiar propio (más grande, con área de toque, mismo estilo que
   el resto del sitio) al lado, salían las dos a la vez. */
.buscador input[type="search"]::-webkit-search-cancel-button { display: none; }
/* El estado inicial (oculto) lo pone la clase «oculto» en el HTML, no esta
   regla: con «display: none» aquí, quitar la clase por JS no lo enseñaba
   nunca —la base seguía ganando— y el botón de limpiar no se veía jamás,
   ni con texto en el buscador. */
.buscador .limpiar {
  position: absolute; right: .5rem; top: 50%; transform: translateY(-50%);
  border: none; background: none; color: var(--muted); cursor: pointer;
  font-size: 1.1rem; line-height: 1;
}

.pastillas { display: flex; gap: .4rem; flex-wrap: wrap; }
.pastilla {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .3rem .85rem; border-radius: var(--radius-pill);
  border: 1px solid var(--teal-light); background: #fff;
  color: var(--teal-dark); font-size: .84rem; cursor: pointer;
  font-family: inherit; transition: background .15s ease, transform .08s ease;
}
.pastilla:hover { background: color-mix(in srgb, var(--teal) 10%, transparent); }
.pastilla:active { transform: scale(.96); }
.pastilla.activa { background: var(--teal); border-color: var(--teal); color: #fff; }
.pastilla .n { font-size: .74rem; opacity: .75; }
/* Además de <button> (paneles con JS), una pastilla puede ser un <a> que
   navega con el filtro en la URL, para un listado paginado en servidor. */
a.pastilla { text-decoration: none; }

.desplegable { position: relative; }
.panel {
  display: none; position: absolute; top: calc(100% + .4rem); left: 0; z-index: 40;
  background: #fff; border-radius: var(--radius-card); box-shadow: 0 8px 28px color-mix(in srgb, var(--teal) 28%, transparent);
  padding: 1rem; min-width: 250px; border: 1px solid color-mix(in srgb, var(--teal) 20%, transparent);
}
.panel .grupo + .grupo { margin-top: .9rem; }
.panel h6 {
  margin: 0 0 .45rem; font-size: .72rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted); font-family: inherit; font-weight: 600;
}
.panel label { display: flex; align-items: center; gap: .5rem; margin: .35rem 0; font-size: .9rem; }
.panel label input { width: auto; }

.contador { margin-left: auto; color: var(--muted); font-size: .82rem; }

/* <details> como desplegable de acciones: el estado abierto/cerrado y el
   Enter/Espacio en el <summary> los da el navegador solo. */
.menu-alta { position: relative; display: inline-flex; }
.menu-alta > summary { list-style: none; cursor: pointer; }
/* Un icono opcional delante del texto (empresa_detalle.html); el gap del
   .boton ya separa uno de otro, esto solo evita que el SVG, sin width ni
   height propios, ocupe su tamaño intrínseco por defecto. */
.menu-alta > summary svg { width: 15px; height: 15px; flex: none; }
.menu-alta > summary::-webkit-details-marker { display: none; }
.menu-alta > summary::after { content: '▾'; margin-left: .5rem; font-size: .7rem; }
.menu-alta-panel {
  position: absolute; top: calc(100% + .4rem); left: 0; z-index: 40;
  background: #fff; border-radius: var(--radius-card); box-shadow: 0 8px 28px color-mix(in srgb, var(--teal) 28%, transparent);
  border: 1px solid color-mix(in srgb, var(--teal) 20%, transparent); min-width: 220px; padding: .4rem;
  display: flex; flex-direction: column;
}
.menu-alta-panel a {
  padding: .55rem .7rem; border-radius: 10px; color: var(--dark);
  text-decoration: none; font-size: .9rem;
}
.menu-alta-panel a:hover { background: var(--teal-50); }

.chips { display: flex; gap: .45rem; flex-wrap: wrap; align-items: center; margin-bottom: .8rem; }
.chip {
  display: inline-flex; align-items: center; gap: .3rem;
  background: color-mix(in srgb, var(--teal) 14%, transparent); color: var(--teal-dark);
  border-radius: var(--radius-pill); padding: .22rem .6rem .22rem .75rem; font-size: .8rem;
}
.chip button { border: none; background: none; color: inherit; cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 .1rem; }
.chip-limpiar { border: none; background: none; color: var(--teal-dark); cursor: pointer; font-size: .8rem; text-decoration: underline; font-family: inherit; }

.tabla-scroll { overflow-x: auto; }
/* La celda ya no es clicable: lo es el control de dentro (th.ordenable >
   .th-orden, un <button> con JS en el listado de plantilla o un <a> que
   pide la página ordenada en un listado paginado en servidor), para que
   aria-sort viva en la celda y el Enter/Espacio salga gratis del navegador.
   No va con #plTabla delante: lo usan ambos listados. */
th.ordenable { padding: 0; user-select: none; white-space: nowrap; }
.th-orden {
  display: flex; align-items: center; gap: .3rem; width: 100%;
  padding: .5rem .6rem; border: none; background: none;
  color: inherit; font: inherit; text-align: left; cursor: pointer;
  text-decoration: none;
}
.th-orden:hover { color: var(--teal-dark); }
.th-orden:focus-visible { outline: 2px solid var(--teal); outline-offset: -2px; }
.orden { opacity: .45; font-size: .7rem; }
#plTabla tbody tr { cursor: pointer; }
#plTabla tbody tr.cebra { background: color-mix(in srgb, var(--teal) 3.5%, transparent); }
#plTabla tbody tr:focus-visible { outline: 2px solid var(--teal); outline-offset: -2px; }

/* Filas del listado de empresas: la fila entera navega (empresas.js), el
   hover heredado de «tbody tr» ya lo insinuaba y antes era falso —solo
   navegaba el enlace «Ver», al otro extremo de la fila del nombre que se
   acaba de leer. */
#empTabla tbody tr { cursor: pointer; }
#empTabla tbody tr:focus-visible { outline: 2px solid var(--teal); outline-offset: -2px; }

.persona { display: flex; align-items: center; gap: .65rem; }
.avatar {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: 50%;
  background: color-mix(in srgb, var(--teal) 20%, transparent); color: var(--teal-dark);
  display: grid; place-items: center; font-size: .78rem; font-weight: 600;
}
.persona .nombre { font-weight: 500; }

/* Ficha en modal */
.modal {
  display: none; position: fixed; inset: 0; z-index: 100;
  background: rgba(26,26,26,.45); padding: 2rem 1rem; overflow-y: auto;
}
.modal.visible { display: block; }
.modal-caja {
  position: relative; background: #fff; border-radius: var(--radius-card);
  box-shadow: 0 18px 50px rgba(0,0,0,.2); padding: 1.8rem;
  max-width: 640px; margin: 2rem auto;
}
.modal-cerrar {
  position: absolute; top: .8rem; right: 1rem; border: none; background: none;
  font-size: 1.6rem; line-height: 1; color: var(--muted); cursor: pointer;
}
.modal-cerrar:hover { color: var(--teal-dark); }
.modal h3 { font-size: 1rem; margin: 1.4rem 0 .5rem; }

/* Confirmación de un envío destructivo: mucho más estrecha que la ficha en
   modal -es una pregunta de una línea, no una tabla de datos-, y sus
   acciones van a la derecha porque es la lectura habitual de un diálogo de
   confirmación (cancelar cerca del borde, aceptar al final del recorrido). */
.modal-confirmar { max-width: 420px; }
.modal-confirmar h2 { font-size: 1.15rem; margin: 0 1.6rem .6rem 0; }
.modal-confirmar p { margin: 0 0 1.3rem; color: var(--text); }
.modal-confirmar .acciones { justify-content: flex-end; margin-top: 0; }
.dato { padding: .45rem 0; border-bottom: 1px solid color-mix(in srgb, var(--teal) 12%, transparent); }
.dato .k { display: block; font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.dato .v { font-size: .95rem; }

/* ===== Campana de avisos =====
   La insignia va superpuesta a la esquina del icono, no en línea con él —el
   icono ya no lleva texto al lado que le dé referencia de tamaño. El fondo
   pasa de --teal a --teal-700 por lo mismo que .pildora.exportada: blanco
   sobre --teal da 2,61:1, sobre el 700 da 5,39. */
.campana-n {
  position: absolute; top: .1rem; right: .1rem;
  background: var(--teal-700); color: #fff; border-radius: var(--radius-pill);
  font-size: .58rem; min-width: .95rem; height: .95rem; padding: 0 .22rem;
  font-weight: 600; line-height: 1; display: grid; place-items: center;
  border: 1.5px solid #fff;
}

/* Aviso de llegada: un anillo que se expande y se apaga, dos veces, cuando
   el número de avisos sin leer ha subido desde la última vez que este
   navegador vio la cabecera (la comparación vive en cabecera.js, con
   localStorage — no hace falta guardar nada en el servidor para esto).
   Dos veces y para: un parpadeo continuo es justo el ruido que la cabecera
   lleva evitando desde que se rehizo entera. */
@keyframes campana-pulso {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--teal-700) 55%, transparent); }
  70%  { box-shadow: 0 0 0 .5rem color-mix(in srgb, var(--teal-700) 0%, transparent); }
  100% { box-shadow: 0 0 0 .5rem color-mix(in srgb, var(--teal-700) 0%, transparent); }
}
.cabecera .icono-boton.recien-llegado .campana-n {
  animation: campana-pulso 1s var(--ease) 2;
}
.visualmente-oculto {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
.avisos-lista { list-style: none; margin: 0; padding: 0; }
.aviso {
  display: flex; align-items: center; gap: 1rem; justify-content: space-between;
  padding: .9rem .2rem; border-bottom: 1px solid color-mix(in srgb, var(--teal) 14%, transparent);
}
.aviso:last-child { border-bottom: none; }
.aviso.leido { opacity: .62; }
.aviso-texto { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.aviso-titulo { font-weight: 500; }
.aviso-titulo .punto { color: var(--teal); font-size: .7rem; }
.aviso-cuerpo, .aviso-fecha { font-size: .85rem; color: var(--muted); }
.aviso-fecha { font-size: .76rem; }

/* ===== Paginador ===== */
.paginador {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  margin-top: 1.2rem; padding-top: 1rem;
  border-top: 1px solid color-mix(in srgb, var(--teal) 14%, transparent);
}
.paginador-pos { color: var(--text); font-size: .9rem; }
.paginador-pos .nota { font-size: .8rem; }
.paginador .inerte { opacity: .4; cursor: default; box-shadow: none; }
.paginador-total { margin-top: 1rem; }
.aviso-tope {
  background: color-mix(in srgb, var(--teal) 12%, transparent); border-left: 3px solid var(--teal);
  border-radius: 10px; padding: .7rem 1rem; margin: .8rem 0; font-size: .88rem;
}

/* ===== Logos: asesoría en la cabecera, empresa cliente al lado =====
   .marca-empresa está más arriba, junto a la cabecera: es donde vive de
   verdad, y aquí solo estaba duplicada. */
.marca { display: inline-flex; align-items: center; gap: .6rem; }

/* Mismo tamaño y forma que .avatar (círculo de 34px): así una fila con logo
   propio y otra con iniciales guardan el mismo ritmo vertical en la columna.
   object-fit: cover porque el logo que sube una empresa rara vez es
   cuadrado. */
.logo-mini {
  width: 34px; height: 34px; flex: 0 0 34px;
  border-radius: 50%; object-fit: cover;
}
.logo-previo {
  max-height: 60px; max-width: 200px; display: block;
  margin: .3rem 0 .5rem; border-radius: 8px;
}
.titulo-con-logo { display: flex; align-items: center; gap: .9rem; flex-wrap: wrap; }
label.linea { display: inline-flex; align-items: center; gap: .4rem; font-size: .88rem; }
label.linea input { width: auto; }

/* ===== Identidad ACUBERO ===== */

/* Elipse degradada del hero, el gesto de marca de la web pública. */
.velo-hero {
  position: absolute; inset: 0 0 auto; height: 340px; z-index: -1;
  background: linear-gradient(160deg, var(--teal) 0%, var(--teal-300) 50%, var(--bg) 100%);
  clip-path: ellipse(120% 100% at 50% 0%);
  opacity: .5;
}
body { position: relative; }

.acceso { margin-top: 3.5rem; }
.acceso h1 { font-size: 1.7rem; margin: 0 0 .3rem; }
.acceso-intro { margin-top: 0; margin-bottom: 1.4rem; }

.pie { display: flex; flex-direction: column; gap: .3rem; align-items: center; }
.pie-marca {
  font-family: var(--sans); font-weight: 700;
  letter-spacing: .19em; font-size: .7rem; color: var(--teal-700);
}

/* Logo de la asesoría cuando se configura un fichero en vez del vectorial */
.marca-logo { max-height: 2.6rem; max-width: 12rem; display: block; }

/* ===== Ficha giratoria (patrón de la tarjeta NFC) =====
   Delante quién es, detrás sus datos. Las dos caras viven siempre en el DOM
   y se apilan en la misma celda de grid, así la altura la marca la cara más
   alta y no hay saltos al girar. */

.flip { perspective: 900px; }
.flip-interior {
  display: grid;
  transform-style: preserve-3d;
  transition: transform .65s var(--ease);
}
.flip.girada .flip-interior { transform: rotateY(180deg); }
.flip-cara {
  grid-area: 1 / 1;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.flip-dorso { transform: rotateY(180deg); }

/* Cara de identidad */
.flip-frente {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: .55rem; text-align: center;
  padding: 1.6rem 1rem;
}
.ficha-avatar {
  width: 140px; height: 140px; border-radius: 50%;
  background-image: var(--degradado); color: #fff;
  display: grid; place-items: center;
  font-family: var(--serif); font-size: 2.6rem; letter-spacing: .04em;
  box-shadow: 0 8px 32px color-mix(in srgb, var(--teal) 35%, transparent);
}
.ficha-nombre { margin: .5rem 0 0; font-size: 1.35rem; }
.ficha-puesto {
  margin: 0; color: var(--muted);
  text-transform: uppercase; letter-spacing: .14em; font-size: .6875rem;
}
.ficha-sub { margin: 0 0 .5rem; font-size: .95rem; }
.ficha-movimientos td { padding: .5rem .4rem; font-size: .88rem; }

/* Micro-hint bilingüe, como en la tarjeta */
.flip-hint {
  display: block; margin: 1rem auto 0; border: 0; background: none;
  cursor: pointer; font-family: inherit; color: var(--muted);
  line-height: 1.35; padding: .4rem .8rem; border-radius: var(--radius-pill);
  transition: color .2s, background .2s, transform .12s var(--ease);
}
.flip-hint:hover { color: var(--teal-700); background: var(--teal-50); }
.flip-hint:active { transform: scale(.97); }
.flip-hint .es { display: block; font-size: .78rem; letter-spacing: .1em;
                 text-transform: uppercase; }
.flip-hint .en { display: block; font-size: .66rem; opacity: .6; }

/* Quien pide menos movimiento no recibe el giro: se cambia de cara y ya. */
@media (prefers-reduced-motion: reduce) {
  .flip-interior { transition-duration: .001ms; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ===== Móvil =====
   Todo el fichero se apoyaba en flex-wrap y en grid auto-fit para reflotar
   solo, y funciona para el contenido -las tarjetas, los formularios-, pero
   no para el marco: la cabecera, las tarjetas y el modal llevaban el mismo
   padding fijo en un móvil de 360px que en un escritorio de 1200, y ahí sí
   se nota: menos sitio para el contenido justo donde menos sobra. */
@media (max-width: 640px) {
  .cabecera-interior { padding: .8rem 1rem; gap: 1rem; }
  .cabecera nav { gap: .8rem; }
  main { padding: 0 1rem; margin: 1.4rem auto; }
  .tarjeta { padding: 1.1rem; }
  .modal { padding: 1rem .5rem; }
  .modal-caja { padding: 1.2rem; }
  /* Un botón a lo ancho es más fácil de acertar con el pulgar que una fila
     de botones estrechos, y en un formulario largo ya vienen uno debajo de
     otro de todas formas. */
  .acciones { flex-direction: column; align-items: stretch; }
  .acciones .boton { text-align: center; }
  .marca-empresa-nombre { max-width: 6rem; }
}

/* --- Revisión de una importación desde a3 --------------------------------
   La tabla es un formulario disfrazado: cada fila lleva tres campos de texto
   editables. Se aprieta la tipografía y el relleno porque una plantilla de
   cincuenta personas tiene que caber en una pantalla sin parecer un muro. */
.tabla-importacion { font-size: .86rem; width: 100%; table-layout: fixed; }
/* Repartir el ancho a mano: sin esto el navegador se lo come la columna del
   original de a3 y los campos editables cortan el nombre a media palabra,
   que es justo lo que hay que poder leer para corregirlo. */
.tabla-importacion col.col-marca   { width: 2.2rem; }
.tabla-importacion col.col-codigo  { width: 4.5rem; }
.tabla-importacion col.col-nombre  { width: 15%; }
.tabla-importacion col.col-original{ width: 12%; }
.tabla-importacion col.col-dni     { width: 7rem; }
.tabla-importacion col.col-alta    { width: 6rem; }
.tabla-importacion col.col-estado  { width: 11rem; }
.tabla-importacion td { padding: .35rem .5rem; vertical-align: middle; }
.tabla-importacion input[type="text"],
.tabla-importacion input:not([type]) {
  padding: .3rem .5rem;
  font-size: .86rem;
  border-radius: 8px;
  width: 100%;
}
/* El original de a3 se enseña al lado del reparto propuesto para poder
   compararlos de un vistazo; va apagado para que no compita con los campos. */
.tabla-importacion .original {
  color: var(--muted);
  font-size: .8rem;
  /* Se deja partir en varias líneas: con table-layout fijo, un nombre largo
     sin partir se sale de su celda y se monta encima del DNI. */
  overflow-wrap: anywhere;
}
.tabla-importacion .fila-revisar { background: color-mix(in srgb, var(--teal) 7%, transparent); }

.pildora.pildora-aviso { background: color-mix(in srgb, var(--teal) 30%, transparent); color: var(--teal-800); }

.nota-aviso {
  background: var(--teal-50);
  border: 1px solid var(--teal-200);
  border-radius: var(--radius-card);
  padding: .9rem 1.1rem;
  font-size: .88rem;
  color: var(--teal-800);
  margin-bottom: 1.2rem;
}

/* Aviso de qué empresa pidió esto, dentro de la propia tarjeta: en un
   formulario que se abre casi siempre desde el móvil, la cabecera se pierde
   de vista en cuanto se hace scroll. Mismo tono que .nota-aviso, con la
   marca de la empresa al lado para que se lea de un vistazo. */
.aviso-empresa {
  display: flex; align-items: center; gap: .65rem;
  background: var(--teal-50);
  border: 1px solid var(--teal-200);
  border-radius: var(--radius-card);
  padding: .7rem 1rem;
  font-size: .85rem;
  color: var(--teal-800);
  margin-bottom: 1.3rem;
}
.aviso-empresa .marca-iniciales { width: 1.6rem; height: 1.6rem; font-size: .62rem; flex: none; }
.aviso-empresa img { width: 1.6rem; height: 1.6rem; border-radius: 50%; object-fit: cover; flex: none; }
.aviso-empresa b { color: var(--teal-900); font-weight: 500; }

/* Separador entre dos formas de hacer lo mismo (subir el ZIP de a3 o teclear
   la empresa a mano). La raya a los lados evita que parezca un título. */
.separador-o {
  display: flex; align-items: center; gap: 1rem;
  color: var(--muted); font-size: .85rem;
  margin: -.4rem 0 1.4rem;
}
.separador-o::before, .separador-o::after {
  content: ""; flex: 1; height: 1px; background: var(--hairline);
}

/* Icono suelto en una fila de tabla (p.ej. «Editar» en un listado): apagado
   hasta que se pasa el ratón, para no competir con el dato de la fila. */
.icono-fila {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: 8px;
  color: var(--muted); text-decoration: none;
}
.icono-fila svg { width: 16px; height: 16px; }
.icono-fila:hover { color: var(--teal-dark); background: var(--teal-50); }

/* ===== Utilidades ===== */

/* Ocultar por clase y no con style="display:none" en línea: la CSP del portal
   no admite atributos de estilo en línea, y así el JS toca una clase en vez de
   escribir estilos. */
.oculto { display: none !important; }
.en-linea { display: inline; }
/* Varias acciones sueltas (cada una su <form>) en la misma celda de tabla. */
.acciones-en-linea .en-linea + .en-linea { margin-left: .4rem; }

/* Los paneles desplegables se abren con una clase, por lo mismo. */
.panel.abierto { display: block; }

/* Casillas y radios no ocupan el ancho completo, a diferencia del resto de
   campos del formulario. */
input[type="checkbox"], input[type="radio"] { width: auto; }
.bloque-separado { margin-top: 1rem; }

/* --- Datos del trabajador en el detalle del gestor -----------------------
   La pantalla donde se aprueba una exportación. Se agrupa como el registro 01
   (identificación · domicilio · banco e IRPF · contrato) para que el gestor
   lea en el mismo orden en que se va a escribir el fichero. */
.rejilla-datos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0 1.4rem;
  margin-bottom: 1.4rem;
}
.rejilla-datos .ancho-2 { grid-column: span 2; }
.rejilla-datos .dato small {
  display: block; font-size: .72rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.rejilla-datos .dato p { margin: .15rem 0 0; font-size: .95rem; }

/* Un hueco es justo lo que hay que ver antes de exportar, así que se marca en
   vez de esconderse; y se marca con texto además de con color, porque el color
   solo no lo ve todo el mundo. */
.dato-falta { color: #8a5a5a; font-style: italic; }

/* La casilla de «he revisado»: obliga a mirar y deja constancia. Deshabilitar
   el botón sin decir por qué sería una trampa, así que el aviso va al lado. */
.confirmar-revision {
  display: flex; align-items: flex-start; gap: .6rem;
  background: var(--teal-50); border: 1px solid var(--teal-200);
  border-radius: var(--radius-card); padding: .8rem 1rem;
  margin-bottom: 1rem; font-size: .9rem;
}
.confirmar-revision input { margin-top: .2rem; }

/* --- Legibilidad del texto pequeño ---------------------------------------
   El cuerpo va a peso 300, que es lo que da su aire a la marca en los tamaños
   grandes. Por debajo de 0,8rem ese peso deja de ser estilo y empieza a costar
   legibilidad: son las etiquetas en mayúsculas, las píldoras de estado y los
   contadores, o sea donde vive la mitad de la información. Se sube a 400 solo
   ahí. Es lo que hacen las tipografías bien ajustadas —ligero en titulares,
   normal en texto pequeño—; aquí estaba al revés.

   Va al final del fichero a propósito: así gana a las reglas de arriba sin
   tener que tocarlas una a una ni repetir sus selectores. */
small,
.nota,
.pildora,
.stat-label,
.contador,
.chip,
.dato .k,
.rejilla-datos .dato small,
.aviso-fecha,
.pie,
thead th {
  font-weight: 400;
}
