/* ===========================================================================
   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);

  /* ===== Estados =====
     NO son marca y por eso no viven en tokens.css: la web pública no tiene
     solicitudes ni facturas que puedan estar pendientes. Pero hasta ahora
     tampoco eran tokens: estaban escritos a mano, en hex, repartidos por la
     hoja -#2c6446 aparecía cuatro veces y #fbecec otras cuatro-, que es
     exactamente la forma en que el gris de los textos se desincronizó entre
     el portal y la web, solo que dentro de un mismo fichero.

     Cada familia tiene tres tonos y cada tono un trabajo:
       -fondo   fondo claro de un bloque de mensaje;
       -suave   fondo de una píldora (algo más saturado que -fondo);
       (base)   el tono medio: borde de acento, círculo del icono y píldora
                sólida. Lleva SIEMPRE texto blanco encima, así que está
                elegido para pasar AA contra blanco;
       -texto   la tinta oscura sobre -fondo o -suave.

     Dos de los tonos medios hubo que oscurecerlos al nombrarlos: el glifo
     blanco del icono de .mensaje daba 4,20:1 sobre el verde de éxito y
     2,59:1 sobre el ámbar de aviso. Ninguno llegaba a AA y no lo veía
     ningún test, porque el que mira .mensaje compara su texto con su fondo,
     nunca el glifo con el acento. */
  --estado-error:       #b45454;
  --estado-error-fondo: #fdf4f4;
  --estado-error-suave: #fbecec;
  --estado-error-texto: #8a3b3b;
  /* El botón destructivo va más apagado que un mensaje de error: es una
     acción disponible, no algo que haya fallado ya. */
  --estado-error-borde: #e3cfcf;
  --estado-error-tinta: #8a5a5a;

  /* Antes eran dos verdes a 14 puntos de rgb uno del otro -#3d8a5f de acento
     y #2f7d5f de píldora sólida-: indistinguibles a ojo, pero solo el segundo
     admitía texto blanco. Se quedan en uno, y es el que cumple. */
  --estado-exito:       #2f7d5f;
  --estado-exito-fondo: #f1f7f2;
  --estado-exito-suave: #e8f2ea;
  --estado-exito-texto: #2c6446;

  /* El ámbar de acento era #c79a3c y no había blanco que se leyera encima.
     Este sigue siendo ámbar -no marrón- y da 4,75:1. */
  --estado-aviso:       #966b1d;
  --estado-aviso-fondo: #fdf8ee;
  --estado-aviso-suave: #fdf3e0;
  --estado-aviso-texto: #7a5a1f;

  /* Incidencia de la Seguridad Social: ni error nuestro ni aviso, un estado
     propio del trámite. Su tono claro sale del medio con color-mix, para no
     tener que mantener un cuarto hex a juego. */
  --estado-incidencia:       #9a5b2e;
  --estado-incidencia-texto: #7a4522;

  /* «Todavía no es nada»: borrador, cancelada, descartada. Gris verdoso, sin
     color, porque el color se reserva para lo que cambia una decisión. */
  --estado-neutro:        rgba(122, 138, 138, .15);
  --estado-neutro-fuerte: rgba(122, 138, 138, .20);

  /* ===== Escalas =====
     Tampoco son marca: la web pública tiene su propia escala, la de Tailwind.
     Están aquí porque sin ellas cada pantalla elegía su tamaño a ojo y la
     hoja había acumulado catorce tamaños de letra entre .6875rem y .95rem
     -.84, .85 y .86 conviviendo, que son ocho centésimas de píxel- y ocho
     radios en píxeles al lado de los tokens que ya existían.

     Al nombrarlos no se ha movido nada más de 0,5px: los tamaños que se
     juntan eran el mismo tamaño escrito tres veces, no tres decisiones. */
  --txt-2xs:  .72rem;   /* versalitas, contadores, la letra de una píldora */
  --txt-xs:   .8rem;    /* pies, notas al margen, chips */
  --txt-sm:   .85rem;   /* texto secundario denso */
  --txt-md:   .9rem;    /* etiquetas de campo y botones */
  --txt-base: .95rem;   /* el valor de un dato, lo que se escribe en un campo */
  --txt-lg:   1rem;
  --txt-xl:   1.1rem;

  /* Los titulares. Hasta ahora h1..h4 no tenían tamaño: seis componentes se
     lo ponían por su cuenta y las otras cuarenta y tantas pantallas
     heredaban el del navegador, así que el mismo nivel de título medía 2rem
     en una y 1,65rem en la de al lado. El 1,65 gana por ser el que ya habían
     elegido por su cuenta las dos pantallas de trámite. */
  --titulo-1: 1.65rem;
  --titulo-2: 1.3rem;
  --titulo-3: 1.1rem;
  --titulo-4: 1rem;

  /* Radios. --radius-card (20px), --radius-boton (14px) y --radius-pill
     vienen de la marca; estos tres son de uso interno. */
  --radius-xs:    8px;    /* icono en una fila, miniatura, celda editable */
  --radius-sm:    10px;   /* control pequeño dentro de otro componente */
  --radius-campo: 12px;   /* input, select, textarea y lo que los imite */

  /* Separaciones. Siete pasos: cada valor que había cae dentro de 0,05rem de
     uno de ellos. */
  --hueco-1: .25rem;
  --hueco-2: .35rem;
  --hueco-3: .5rem;
  --hueco-4: .6rem;
  --hueco-5: .7rem;
  --hueco-6: .9rem;
  --hueco-7: 1rem;
}

* { 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;
}
h1 { font-size: var(--titulo-1); }
h2 { font-size: var(--titulo-2); }
h3 { font-size: var(--titulo-3); }
h4 { font-size: var(--titulo-4); }

::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: var(--txt-2xs);
  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: var(--hueco-4); 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: var(--hueco-3);
  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: var(--txt-sm); color: var(--text); 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: var(--txt-base); }
.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: var(--txt-sm); 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, .cabecera .icono-boton.abierto { background: var(--teal-50); }
.cabecera .icono-boton:active { transform: scale(.93); }
/* El engranaje de Administración es un enlace sin texto: el
   .cabecera nav a[aria-current="page"] de arriba ya lo tiñe de --teal-700
   -el trazo hereda de currentColor-, pero un icono solo no tiene el peso de
   una palabra en negrita para notarse. El mismo fondo que ya usa el hover,
   pero fijo, es lo que hace que "estás aquí" se vea sin pasar el ratón. */
.cabecera .icono-boton[aria-current="page"] { background: var(--teal-50); }
/* «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: var(--estado-error-suave); color: var(--estado-error-tinta); }

.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;
}

/* Administración vive tras un botón con nombre. El trámite, en cambio, se
   abre con un documento y «+»: es una acción concreta, no un menú genérico,
   y conserva nombre accesible y tooltip para quien necesite confirmarlo. */
.grupo { position: relative; flex: 0 0 auto; }
.grupo-boton {
  display: inline-flex; align-items: center; gap: var(--hueco-2);
  border: none; background: none; cursor: pointer;
  font-family: inherit; font-size: var(--txt-base); 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; }
.cabecera .icono-tramite {
  width: 2.15rem; height: 2.15rem; padding: 0; justify-content: center;
  border-radius: var(--radius-pill); color: var(--text);
}
.cabecera .icono-tramite svg {
  width: 1.22rem; height: 1.22rem; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.cabecera .icono-tramite:hover, .cabecera .icono-tramite:focus-visible,
.cabecera .icono-tramite.actual { background: var(--teal-50); color: var(--teal-700); }
.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: var(--radius-boton); 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: var(--radius-xs); 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: var(--txt-2xs);
  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: var(--estado-neutro); color: var(--muted); }
.pildora.pendiente { background: var(--estado-aviso-suave); color: var(--estado-aviso-texto); }
.pildora.aprobada  { background: var(--estado-exito-suave); color: var(--estado-exito-texto); }
.pildora.rechazada { background: var(--estado-error-suave); color: var(--estado-error-texto); }
/* Blanco sobre --teal daba 2,61:1. Sobre el 700, 5,39. */
.pildora.exportada { background: var(--teal-700); color: #fff; }
.pildora.pendiente_tgss  { background: var(--estado-neutro-fuerte); color: var(--teal-dark); }
.pildora.alta_confirmada { background: var(--estado-exito); color: #fff; }
.pildora.incidencia_ss   { background: var(--estado-incidencia); color: #fff; }
.pildora.revision        { background: color-mix(in srgb, var(--estado-incidencia) 16%, transparent); color: var(--estado-incidencia-texto); }
.pildora.asociada        { background: color-mix(in srgb, var(--estado-exito) 16%, transparent); color: var(--estado-exito-texto); }
.pildora.descartada      { background: var(--estado-neutro); color: var(--muted); }
.pildora.cancelada       { background: var(--estado-neutro); 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: var(--estado-exito-suave); color: var(--estado-exito-texto); }
.pildora.parcial     { background: var(--estado-aviso-suave); color: var(--estado-aviso-texto); }
.pildora.abono       { background: var(--estado-neutro-fuerte); color: var(--teal-dark); }
.pildora.sin_importe { background: var(--estado-neutro); color: var(--muted); }
.pildora.rectificada { background: var(--estado-neutro); 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: var(--radius-sm);
  border-left: 4px solid var(--muted);
  background: rgba(122,138,138,.08);
}
/* El titular llevaba el estado en un emoji de color -✅, ⚠️, ⏳-, que era el
   único sitio del portal donde se usaban. Tres problemas: los pinta la fuente
   del sistema, así que cada navegador enseña unos distintos y en Windows no
   se parecen a nada del producto; traen su propia paleta, que se salta la de
   marca; y un lector de pantalla los lee por su nombre Unicode. Ahora es un
   icono del sistema, en currentColor, que toma el tono del estado. */
.resultado-ss .resultado-titulo {
  display: flex; align-items: center; gap: var(--hueco-3);
  font-size: var(--txt-xl);
  font-weight: 500;
  margin: 0 0 .5rem;
}
.resultado-ss .resultado-titulo svg { flex: none; width: 20px; height: 20px; }
/* El icono hereda el color del titular y no el tono base del estado: el base
   está elegido para llevar texto blanco encima y sobre este fondo tan claro
   se queda en 4,4:1. El del texto da 6,2. */
.resultado-ss.correcto {
  border-left-color: var(--estado-exito);
  background: color-mix(in srgb, var(--estado-exito) 9%, transparent);
}
.resultado-ss.correcto .resultado-titulo { color: var(--estado-exito-texto); }
.resultado-ss.incidencia {
  border-left-color: var(--estado-incidencia);
  background: color-mix(in srgb, var(--estado-incidencia) 9%, transparent);
}
.resultado-ss.incidencia .resultado-titulo { color: var(--estado-incidencia-texto); }
.resultado-ss.esperando  { border-left-color: var(--teal); }
.resultado-ss.esperando .resultado-titulo { color: var(--teal-dark); }
.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: var(--txt-sm);
  background: rgba(122,138,138,.10);
  padding: .75rem .9rem;
  border-radius: var(--radius-xs);
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

.boton {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--hueco-3); white-space: nowrap;
  border: none; cursor: pointer;
  background-image: none;
  background-color: var(--marca-accion);
  color: #fff;
  padding: .62rem 1.4rem;
  border-radius: var(--radius-boton);
  font-family: inherit; font-size: var(--txt-md); 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 { background-color: var(--marca-accion-hover); }
.boton:active { transform: scale(.97); }
.boton:focus-visible { outline: 3px solid var(--teal-700); outline-offset: 3px; }
.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:hover { background-color: var(--bg); }
.boton.peligro {
  background-image: none; background-color: #fff;
  color: var(--estado-error-tinta); border: 1px solid var(--estado-error-borde); 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: var(--txt-md); color: var(--dark); }
/* El navegador le pinta a <fieldset> un marco gris en relieve y a <legend>
   un hueco recortado dentro de él: es el control que más «de otra web» se ve
   de todo el formulario. Se resetea aquí, una vez, en vez de en cada clase
   que envuelva un grupo de campos -.opciones-datos ya lo hacía por su cuenta-.
   min-width:0 es el arreglo del fieldset, que por defecto se niega a
   encogerse dentro de un flex o un grid y desborda en el móvil. */
fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
legend { padding: 0; font-size: var(--txt-lg); font-weight: 500; color: var(--dark); }
input, select, textarea {
  width: 100%;
  padding: .6rem .8rem;
  border: 1px solid var(--teal-200);
  border-radius: var(--radius-campo);
  font-family: inherit;
  font-weight: 300;
  font-size: var(--txt-base);
  background: #fff;
  color: var(--dark);
}
/* El borde de foco va en --teal-700: con --teal daba 2,6:1 sobre blanco, por
   debajo del 3:1 que WCAG pide a un indicador de foco, y el halo al 18% no
   llega a verse. Era lo único que marcaba en qué campo se está escribiendo. */
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--teal-700);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 18%, transparent);
}

/* El error de UN campo, que no es lo mismo que el aviso de la pantalla: va
   pegado al campo y en pequeño, no en una caja. Una .mensaje entera debajo de
   cada input daría más caja que formulario, y el error dejaría de leerse
   como parte del campo.
   El glifo no es adorno: ocupa exactamente el mismo sitio que .ayuda-campo
   -misma línea, mismo tamaño, bajo el mismo input-, así que sin él el color
   sería lo único que los distingue, que es justo lo que prohíbe WCAG 1.4.1.
   Peso 400 y no el 300 del cuerpo: a .82rem el 300 se deshilacha. */
.error-campo {
  display: flex; align-items: flex-start; gap: var(--hueco-2);
  margin: .3rem 0 0;
  color: var(--estado-error-texto);
  font-size: var(--txt-xs); font-weight: 400; line-height: 1.35;
}
/* El display de arriba le gana al [hidden] de la hoja del navegador -la
   trampa de .tarjeta-tiempo[hidden]-: el error vacío que campo_archivo()
   deja preparado para archivos.js enseñaba su aspa roja, sin texto, bajo
   cada selector de archivo del portal. */
.error-campo[hidden] { display: none; }
.error-campo::before {
  content: "\2715";
  flex: none; margin-top: .14rem;
  width: 1rem; height: 1rem; border-radius: 50%;
  background: var(--estado-error); color: #fff;
  display: grid; place-items: center;
  font-size: .58rem; font-weight: 700; line-height: 1;
}
/* El campo en rojo se engancha a aria-invalid, que las tres plantillas con
   errores ya emiten, y no a una clase nueva: así el estado visual y el que
   lee un lector de pantalla no se pueden separar: o están los dos o no está
   ninguno. */
input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--estado-error);
  background: var(--estado-error-fondo);
}
input[aria-invalid="true"]:focus,
select[aria-invalid="true"]:focus,
textarea[aria-invalid="true"]:focus {
  border-color: var(--estado-error);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--estado-error) 22%, transparent);
}

/* ===== Campo con sugerencias =====
   Un campo de texto que propone de una lista larga mientras se escribe
   (países, municipios de a3). Ver plantillas/_campo_lista.html. La lista
   flota bajo el campo y no empuja el formulario: si lo empujara, el botón de
   enviar bailaría con cada letra. */
.campo-lista { position: relative; }
.campo-lista-opciones {
  /* Al menos 22rem aunque la celda de la rejilla sea más estrecha: en una
     de 210px, «Sant Antoni de Portmany» se partía en dos líneas. */
  position: absolute; z-index: 30; left: 0;
  width: max(100%, min(22rem, calc(100vw - 2rem)));
  margin: var(--hueco-1) 0 0; padding: var(--hueco-1);
  list-style: none;
  background: #fff;
  border: 1px solid var(--teal-200); border-radius: var(--radius-campo);
  box-shadow: var(--shadow-card);
  /* Alto acotado también por la pantalla: en un móvil con el teclado fuera,
     18rem taparía el propio campo. */
  max-height: min(18rem, 45vh); overflow-y: auto; overscroll-behavior: contain;
}
/* 44px de alto: es una lista para el dedo antes que para el ratón. */
.campo-lista-opcion {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--hueco-5);
  min-height: 44px; padding: var(--hueco-3) var(--hueco-5);
  border-radius: var(--radius-sm);
  font-size: var(--txt-base); color: var(--dark);
  cursor: pointer;
}
.campo-lista-opcion:hover { background: var(--teal-50); }
/* La opción activa con el teclado no se distingue solo por el fondo: lleva
   además la barra a la izquierda, en --teal-700, que es la que pasa 3:1. */
.campo-lista-opcion[aria-selected="true"] {
  background: var(--teal-50);
  box-shadow: inset 3px 0 0 var(--teal-700);
}
.campo-lista-opcion mark { background: none; color: var(--teal-700); font-weight: 500; }
.campo-lista-detalle { flex: none; color: var(--muted); font-size: var(--txt-xs); }
.campo-lista-vacio { padding: var(--hueco-5); color: var(--muted); font-size: var(--txt-sm); }
/* Elegido de la lista: el borde se queda en teal, sin halo. Es la única pista
   de que lo escrito ya está casado con un código de a3. */
.campo-lista.elegido input:not([aria-invalid="true"]) { border-color: var(--teal-400); }

/* ===== Selector de archivo =====
   Lo que había aquí era el ::file-selector-button repintado en teal. Arregla
   el botón y deja lo de al lado: el «Sin archivos seleccionados» que escribe
   el navegador, en su tipografía y en el idioma del sistema. Ahora el input
   va oculto a la vista (.visualmente-oculto, que no es display:none: eso lo
   sacaría del orden de tabulación y de la validación del formulario) y esta
   caja es su <label>, así que pulsarla abre el diálogo sin una línea de JS y
   el área táctil es la caja entera, no un botón de 2 cm.
   Ver plantillas/_campo_archivo.html. */
.campo-archivo { margin-bottom: var(--hueco-5); }
.campo-archivo-zona {
  display: flex; align-items: center; gap: var(--hueco-5);
  margin: 0; padding: var(--hueco-5) var(--hueco-6);
  border: 1px dashed var(--teal-200); border-radius: var(--radius-campo);
  background: #fff; cursor: pointer;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}
/* El borde discontinuo dice «aquí se suelta algo» sin escribirlo. Al posar el
   ratón o arrastrar encima se vuelve continuo: la caja pasa de sugerencia a
   destino. */
.campo-archivo-zona:hover { background: var(--teal-50); border-color: var(--teal-400); }
.campo-archivo-zona:focus-within {
  border-style: solid; border-color: var(--teal);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 18%, transparent);
}
.campo-archivo.arrastrando .campo-archivo-zona {
  border-style: solid; border-color: var(--teal); background: var(--teal-50);
}
.campo-archivo-icono { flex: none; color: var(--teal-700); display: grid; place-items: center; }
.campo-archivo-icono svg { width: 20px; height: 20px; }
.campo-archivo-texto { flex: 1 1 auto; min-width: 0; display: grid; gap: .1rem; }
/* El nombre de un fichero no se parte por la mitad ni estira la caja: si no
   cabe, se corta con puntos suspensivos y el title lo dice entero. */
.campo-archivo-texto strong {
  font-weight: 500; font-size: var(--txt-md); color: var(--dark);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.campo-archivo-pista { color: var(--muted); font-size: var(--txt-xs); }
.campo-archivo-accion { flex: none; padding: .45rem 1rem; font-size: var(--txt-sm); }
/* Con fichero elegido la caja deja de ofrecerse -borde continuo, marca en
   teal- y aparece el «Quitar». */
.campo-archivo.elegido .campo-archivo-zona { border-style: solid; border-color: var(--teal-300); }
.campo-archivo.elegido .campo-archivo-icono { color: var(--estado-exito); }
.campo-archivo-quitar {
  margin-top: var(--hueco-1); padding: 0;
  border: none; background: none; cursor: pointer;
  font-family: inherit; font-size: var(--txt-xs);
  color: var(--teal-dark); text-decoration: underline;
}
.campo-archivo-quitar:hover { color: var(--estado-error-texto); }
.campo-archivo.con-error .campo-archivo-zona {
  border-style: solid; border-color: var(--estado-error); background: var(--estado-error-fondo);
}
.campo-archivo .error-campo { margin-top: var(--hueco-1); }
/* En el móvil la caja se apila: el nombre de un fichero y un botón al lado no
   caben en 360px sin que uno de los dos se quede en dos letras. */
@media (max-width: 640px) {
  .campo-archivo-zona { flex-wrap: wrap; gap: var(--hueco-3); }
  .campo-archivo-texto { flex-basis: calc(100% - 2.6rem); }
  .campo-archivo-accion { width: 100%; }
}

.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: var(--txt-md);
  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: var(--hueco-5);
  padding: .85rem 1.2rem; border-radius: var(--radius-boton); 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: var(--txt-2xs); font-weight: 700; line-height: 1;
  margin-top: .05rem;
}
.mensaje-cuerpo { flex: 1 1 auto; }
.mensaje.error {
  --acento: var(--estado-error); background: var(--estado-error-fondo); color: var(--estado-error-texto);
}
.mensaje.exito {
  --acento: var(--estado-exito); background: var(--estado-exito-fondo); color: var(--estado-exito-texto);
}
.mensaje.aviso {
  --acento: var(--estado-aviso); background: var(--estado-aviso-fondo); color: var(--estado-aviso-texto);
}
/* 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: var(--radius-xs);
  background: none; color: inherit; opacity: .55;
  font-size: var(--txt-xl); 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: var(--hueco-5); flex-wrap: wrap; margin-top: 1rem; }
/* Una nota (texto de estado, error...) con su acción a la derecha, cuando no
   encaja en una lista con fila propia (esa es .aviso) ni es la barra de
   acciones principal de la tarjeta (esa es .acciones). Ej.: el estado de la
   carpeta de Drive de una empresa, en su ficha. */
.linea-con-accion {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--hueco-5); flex-wrap: wrap; margin-top: .4rem;
}
.linea-con-accion .nota { margin: 0; }
.centrado { max-width: 420px; margin: 3rem auto; }
.pie { text-align: center; color: var(--muted); font-size: var(--txt-xs); padding: 2rem 0; }
.fecha-volcado { color: var(--muted); font-size: var(--txt-sm); }
.nota { color: var(--muted); font-size: var(--txt-md); }
/* La ayuda bajo un campo, fuera de un trámite (dentro, .flujo-tramite la
   aprieta más). Sin esta regla se pintaba como texto normal, más grande que
   la etiqueta del campo al que ayuda. */
.ayuda-campo { margin: .25rem 0 0; color: var(--muted); font-size: var(--txt-xs); line-height: 1.35; }
.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; }
/* Un precio pactado (catálogo de conceptos, tramos de cuota) o el nombre de
   un concepto manual se editan con doble clic -ver edicion_en_linea.js-, el
   precio sin tocarlo a mano ni borrarlo. El punteado avisa de que hay algo
   que hacer ahí sin otro botón junto al dato, que ya iba apretado en una
   tabla de por sí densa. */
td.editable-en-linea { vertical-align: top; }
.editar-celda { margin-left: .5rem; padding: .3rem .6rem; }
.edicion-celda { min-width: 15rem; text-align: left; }
.edicion-celda .acciones { flex-wrap: wrap; }
td.editable-en-linea:hover, td.editable-en-linea:focus-visible {
  color: var(--teal-700);
  background: color-mix(in srgb, var(--teal) 7%, transparent);
}
/* El input hereda el ancho completo por defecto (como en cualquier
   formulario del portal) y desborda la celda; aquí vive en una tabla, no en
   un formulario. Un precio se encoge a lo que ocupa una cifra; un nombre
   -no ``.numerico``- se queda con el ancho de la celda, que ya es el de su
   columna de texto. */
td.editable-en-linea.numerico input {
  width: 100%;
  padding: .2rem .4rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
td.editable-en-linea:not(.numerico) input { padding: .2rem .4rem; }
/* 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: var(--estado-error); background: var(--estado-error-suave); }
/* 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 var(--estado-incidencia); }

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

.resumen { display: flex; gap: var(--hueco-7); flex-wrap: wrap; margin-bottom: 1.4rem; }
.tarjeta-stat {
  display: flex; align-items: center; gap: var(--hueco-6);
  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); }
/* Una métrica que no lleva a ninguna parte (un <div>, no un <a>) no puede
   parecer un botón: con el cursor de mano y el levantarse al pasar por
   encima, se pulsa y no pasa nada, que es peor que no invitar a pulsar. */
div.tarjeta-stat { cursor: default; }
div.tarjeta-stat:hover { transform: none; border-color: transparent; box-shadow: var(--shadow-soft); }
div.tarjeta-stat:active { transform: none; }
.stat-ico {
  width: 38px; height: 38px; display: grid; place-items: center;
  border-radius: var(--radius-sm); background: color-mix(in srgb, var(--teal) 16%, transparent);
  color: var(--teal-dark); font-size: var(--txt-xl);
}
.stat-txt { display: flex; flex-direction: column; }
.stat-label { font-size: var(--txt-2xs); 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: var(--hueco-5); 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: var(--hueco-4); 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: var(--txt-xl); line-height: 1;
}

.pastillas { display: flex; gap: var(--hueco-2); flex-wrap: wrap; }
.plantilla-filtros { margin: 1rem 0 .65rem; align-items: end; }
.filtros-plantilla-secundarios { display: flex; gap: 1rem 1.5rem; flex-wrap: wrap; margin-bottom: .35rem; }
.etiqueta-filtro { display: block; font-size: var(--txt-xs); color: var(--muted); margin-bottom: .3rem; }
.pastilla {
  display: inline-flex; align-items: center; gap: var(--hueco-2);
  padding: .3rem .85rem; border-radius: var(--radius-pill);
  border: 1px solid var(--teal-light); background: #fff;
  color: var(--teal-dark); font-size: var(--txt-sm); 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: var(--txt-2xs); opacity: .75; }
/* Sigue siendo un filtro utilizable, pero un contador a cero no compite
   visualmente con una opción que sí tiene resultados. */
.pastilla.sin-resultados,
.pastilla.sin-resultados:hover {
  color: var(--muted);
  border-color: color-mix(in srgb, var(--muted) 24%, transparent);
  background: color-mix(in srgb, var(--muted) 7%, transparent);
}
.pastilla.sin-resultados.activa {
  color: var(--muted);
  border-color: color-mix(in srgb, var(--teal) 22%, transparent);
  background: var(--teal-50);
}
/* 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: var(--txt-2xs); letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted); font-family: inherit; font-weight: 600;
}
.panel label { display: flex; align-items: center; gap: var(--hueco-3); margin: .35rem 0; font-size: var(--txt-md); }
.panel label input { width: auto; }

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

/* <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: var(--txt-2xs); }
.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: var(--radius-sm); color: var(--dark);
  text-decoration: none; font-size: var(--txt-md);
}
.menu-alta-panel a:hover { background: var(--teal-50); }

.chips { display: flex; gap: var(--hueco-3); flex-wrap: wrap; align-items: center; margin-bottom: .8rem; }
.chip {
  display: inline-flex; align-items: center; gap: var(--hueco-2);
  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: var(--txt-xs);
}
.chip button { border: none; background: none; color: inherit; cursor: pointer; font-size: var(--txt-lg); line-height: 1; padding: 0 .1rem; }
.chip-limpiar { border: none; background: none; color: var(--teal-dark); cursor: pointer; font-size: var(--txt-xs); 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: var(--hueco-2); 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-700); outline-offset: -2px; }
.orden { opacity: .45; font-size: var(--txt-2xs); }
#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-700); outline-offset: -2px; }
/* El filtrado oculta filas y, con el algoritmo automático de las tablas, el
   navegador volvería a repartir el ancho usando solo las visibles. Fijamos
   la rejilla y sus proporciones: buscar no mueve ninguna columna. */
#plTabla { table-layout: fixed; min-width: 760px; }
#plTabla .pl-col-trabajador { width: 46%; }
#plTabla .pl-col-puesto { width: 21%; }
#plTabla .pl-col-dni { width: 11%; }
#plTabla .pl-col-antiguedad { width: 13%; }
#plTabla .pl-col-estado { width: 9%; }
#plTabla td:nth-child(2) { overflow-wrap: anywhere; }
#plTabla td:nth-child(3),
#plTabla td:nth-child(4),
#plTabla td:nth-child(5) { white-space: nowrap; }

/* 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-700); outline-offset: -2px; }

.persona { display: flex; align-items: center; gap: var(--hueco-4); }
.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: var(--txt-xs); font-weight: 600;
}
.persona .nombre { font-weight: 500; }

/* Ficha en modal */
.modal {
  display: none; position: fixed; inset: 0; z-index: 100;
  /* El velo iba en gris neutro y la caja proyectaba en negro puro, que es
     justo lo que la marca no hace: sus sombras van teñidas de teal porque en
     negro se ven baratas. Se derivan de la tinta, que ya es verdosa. */
  background: color-mix(in srgb, var(--dark) 55%, transparent);
  padding: 2rem 1rem; overflow-y: auto;
}
.modal.visible { display: block; }
.modal-caja {
  position: relative; background: #fff; border-radius: var(--radius-card);
  box-shadow: var(--shadow-lift); padding: 1.8rem;
  max-width: 640px; margin: 2rem auto;
}
/* El aspa era un glifo suelto: sin caja, su área pulsable eran los ~18px que
   ocupa el propio carácter, menos de la mitad de los 44 que pide un objetivo
   táctil. Ahora es un cuadrado del tamaño de .boton-icono -el resto de
   botones de solo icono del portal- y sigue viéndose igual de discreto:
   redondo y sin fondo hasta que se pasa por encima. */
.modal-cerrar {
  position: absolute; top: .55rem; right: .7rem;
  width: 2.35rem; height: 2.35rem; padding: 0;
  display: grid; place-items: center;
  border: none; border-radius: var(--radius-pill); background: none;
  font-size: 1.4rem; line-height: 1; color: var(--muted); cursor: pointer;
  transition: background-color .15s var(--ease), color .15s var(--ease),
              transform .12s var(--ease);
}
.modal-cerrar:hover { background: var(--teal-50); color: var(--teal-dark); }
.modal-cerrar:active { transform: scale(.94); }
.modal h3 { font-size: var(--txt-lg); 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: var(--txt-xl); 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: var(--txt-2xs); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.dato .v { font-size: var(--txt-base); }

/* ===== 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: var(--hueco-7); 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; }
/* Un campo al final de la fila (el correo de cada uno en «Acceso de la
   plantilla»): ancho fijo para que los campos queden en columna, y en el
   móvil, debajo del nombre a todo el ancho. */
.aviso-campo { flex: 0 1 20rem; min-width: 0; }
@media (max-width: 640px) {
  .aviso:has(> .aviso-campo) { flex-wrap: wrap; }
  .aviso-campo { flex-basis: 100%; }
}
.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: var(--txt-2xs); }
.aviso-cuerpo, .aviso-fecha { font-size: var(--txt-sm); color: var(--muted); }
.aviso-fecha { font-size: var(--txt-2xs); }

/* ===== Paginador ===== */
.paginador {
  display: flex; align-items: center; gap: var(--hueco-7); 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: var(--txt-md); }
.paginador-pos .nota { font-size: var(--txt-xs); }
.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: var(--radius-sm); padding: .7rem 1rem; margin: .8rem 0; font-size: var(--txt-md);
}

/* ===== 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: var(--hueco-4); }

/* 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: var(--radius-xs);
}
.titulo-con-logo { display: flex; align-items: center; gap: var(--hueco-6); flex-wrap: wrap; }
label.linea { display: inline-flex; align-items: center; gap: var(--hueco-2); font-size: var(--txt-md); }
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: var(--hueco-2); align-items: center; }
.pie-marca {
  font-family: var(--sans); font-weight: 700;
  letter-spacing: .19em; font-size: var(--txt-2xs); 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: var(--hueco-3); 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: var(--txt-2xs);
}
.ficha-sub { margin: 0 0 .5rem; font-size: var(--txt-base); }
.ficha-movimientos td { padding: .5rem .4rem; font-size: var(--txt-md); }

/* 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: var(--txt-xs); 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) {
  /* Sin esto, .cabecera-interior seguía en una sola fila: el logo se
     quedaba con casi todo el ancho y nav -que sigue con margin-left:auto,
     pensado para "empújate a la derecha en una fila ancha"- se comía el
     hueco que sobraba y envolvía SUS PROPIOS enlaces dentro de esa columna
     estrecha, uno debajo de otro pegados al borde derecho. El logo y nav
     pasan a ser dos filas -el logo arriba, nav a lo ancho debajo- y ahí
     dentro nav ya envuelve sus enlaces de izquierda a derecha con
     normalidad, como en escritorio. */
  .cabecera-interior { padding: .8rem 1rem; gap: var(--hueco-4); flex-wrap: wrap; }
  .cabecera nav { margin-left: 0; width: 100%; 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: var(--txt-sm); 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: var(--txt-sm);
  border-radius: var(--radius-xs);
  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: var(--txt-xs);
  /* 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); }

/* Una píldora que lleva a donde se arregla su estado: sin el subrayado de
   un enlace, que la partía en dos; el hover dice que se puede pulsar. */
a.pildora { text-decoration: none; }
a.pildora:hover { filter: brightness(.95); }
.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: var(--txt-md);
  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: var(--hueco-4);
  background: var(--teal-50);
  border: 1px solid var(--teal-200);
  border-radius: var(--radius-card);
  padding: .7rem 1rem;
  font-size: var(--txt-sm);
  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: var(--hueco-7);
  color: var(--muted); font-size: var(--txt-sm);
  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: var(--radius-xs);
  color: var(--muted); text-decoration: none;
}
.icono-fila svg { width: 16px; height: 16px; }
.icono-fila:hover { color: var(--teal-dark); background: var(--teal-50); }

/* El CCC es un dato, no un formulario persistente. Solo el lápiz abre la
   edición; si falta, «Añadir CCC» deja claro qué acción falta completar. */
.ccc-edicion { display: inline-flex; align-items: center; gap: var(--hueco-1); }
.ccc-edicion summary { list-style: none; cursor: pointer; }
.ccc-edicion summary::-webkit-details-marker { display: none; }
.ccc-edicion summary.icono-fila { width: auto; min-width: 2rem; gap: var(--hueco-1); }
.ccc-valor { font-variant-numeric: tabular-nums; color: var(--text); }
.ccc-edicion .icono-fila svg, .ccc-edicion .enlace-ccc svg { width: 15px; height: 15px; }
.enlace-ccc { display: inline-flex; align-items: center; gap: var(--hueco-1); color: var(--teal-dark); font-size: var(--txt-sm); text-decoration: underline; text-underline-offset: .15em; }
.ccc-edicion[open] { display: inline-flex; }
.ccc-edicion[open] > summary { display: none; }
.ccc-edicion form { display: inline-flex; align-items: center; gap: var(--hueco-2); }
.ccc-edicion input { width: 9.5rem; min-width: 0; }

/* Icono de tipo de archivo del explorador de documentos: a diferencia de
   .icono-fila, que es una acción y se apaga hasta el hover, este es el dato
   -qué tipo de archivo es-, así que va siempre visible. */
.icono-tipo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.7rem; height: 1.7rem; flex: none; color: var(--muted);
}
.icono-tipo svg { width: 19px; height: 19px; }
.icono-tipo.es-carpeta { color: var(--teal); }

/* Migas de pan del explorador: la carpeta actual no es un enlace -ya se está
   en ella-, el resto sí. */
/* Ruta del explorador de documentos: una sola fila -flecha «subir» + migas-,
   nunca en columna. Las migas NO envuelven (`nowrap`) y hacen scroll
   horizontal dentro de su propia barra si la ruta fuera muy honda, en vez de
   apilarse hacia abajo y empujar la tabla fuera de la pantalla. El «/» es un
   ::before y no un elemento con clase, para no volver a chocar con la
   `.separador` global (la línea degradada a todo lo ancho de la marca). */
/* Cabecera del explorador: ruta a la izquierda (ocupa el hueco sobrante) y
   buscador a la derecha. En pantalla estrecha el buscador se cae debajo
   (flex-wrap) y se estira a todo el ancho. */
.docs-cabecera {
  display: flex; align-items: center; gap: var(--hueco-7); flex-wrap: wrap;
  margin-bottom: 1rem;
}
.docs-cabecera .ruta-docs { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }
.docs-buscador { flex: 0 1 300px; }
.ruta-docs { display: flex; align-items: center; gap: var(--hueco-3); margin-bottom: 1rem; }
.ruta-atras {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 1.9rem; height: 1.9rem; border-radius: var(--radius-pill);
  color: var(--teal-dark);
}
.ruta-atras svg { width: 1.2rem; height: 1.2rem; }
.ruta-atras:hover { background: var(--teal-50); }
.ruta-migas {
  display: flex; align-items: center; gap: var(--hueco-2); flex-wrap: nowrap;
  overflow-x: auto; min-width: 0; margin: 0; padding: 0;
  list-style: none; font-size: var(--txt-md);
}
.ruta-migas li { display: flex; align-items: center; gap: var(--hueco-2); white-space: nowrap; }
.ruta-migas li:not(:first-child)::before { content: "/"; color: var(--muted); }
.ruta-migas a { color: var(--teal-dark); text-decoration: none; }
.ruta-migas a:hover { text-decoration: underline; }
.ruta-migas [aria-current="page"] { color: var(--text); font-weight: 500; }

/* ===== 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. Y van en el teal de la marca: sin accent-color el
   navegador las pinta marcadas en su azul, el único azul del portal. */
input[type="checkbox"], input[type="radio"] { width: auto; accent-color: var(--teal-700); }
.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: var(--txt-2xs); letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.rejilla-datos .dato p { margin: .15rem 0 0; font-size: var(--txt-base); }

/* 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: var(--estado-error-tinta); 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: var(--hueco-4);
  background: var(--teal-50); border: 1px solid var(--teal-200);
  border-radius: var(--radius-card); padding: .8rem 1rem;
  margin-bottom: 1rem; font-size: var(--txt-md);
}
.confirmar-revision input { margin-top: .2rem; }

/* ===== Inicio (dashboard del gestor/admin) =================================
   La fila de KPI reutiliza .tarjeta-stat/.stat-ico/.stat-txt tal cual; aquí
   solo se añade lo que le falta para esta pantalla: la píldora de variación
   (flecha + %) y el panel de dos columnas donde vive lo que antes era toda
   la pantalla de Bandeja (pendientes/aprobadas), para no perder ni una fila
   ni obligar a un clic de más para verlas. */

.fila-superior {
  display: grid; grid-template-columns: 1.7fr 1fr; gap: var(--hueco-7); margin-bottom: 1.4rem;
  align-items: stretch;
}
@media (max-width: 900px) {
  .fila-superior { grid-template-columns: 1fr; }
}

/* flex-wrap, no grid con auto-fit: con 4 tarjetas y auto-fit, en cuanto el
   ancho daba para 3 columnas la 4ª ("Incidencias") caía sola a una fila
   nueva con dos huecos en blanco a su lado -la columna se reserva aunque no
   haya tarjeta que la ocupe-. Flexbox no reserva columna: la última
   tarjeta, si va sola en su fila, crece y ocupa el ancho entero. Mismo
   patrón que ya usa .resumen (ajustes/admin) para esto mismo. */
.kpis {
  display: flex; flex-wrap: wrap; gap: var(--hueco-7);
}
.kpis .tarjeta-stat {
  flex: 1 1 190px; min-width: 0; align-items: stretch; flex-direction: column; gap: var(--hueco-4);
}
.stat-top { display: flex; align-items: center; justify-content: space-between; gap: var(--hueco-4); }
.stat-ico svg { width: 1.15rem; height: 1.15rem; }

/* Mismos tres tonos que .pildora.aprobada/.rechazada/.pendiente_tgss: la
   variación de un KPI es otra forma de estado, no un color nuevo. */
.stat-var {
  display: inline-flex; align-items: center; gap: var(--hueco-1);
  font-size: var(--txt-2xs); font-weight: 600; line-height: 1;
  padding: .2rem .5rem; border-radius: var(--radius-pill);
  white-space: nowrap;
}
.stat-var.buena  { background: var(--estado-exito-suave); color: var(--estado-exito-texto); }
.stat-var.mala   { background: var(--estado-error-suave); color: var(--estado-error-texto); }
.stat-var.neutra { background: var(--teal-50); color: var(--teal-dark); }

/* --- Card del tiempo -------------------------------------------------------
   Portada de NewFox: mismo METAR, mismo endpoint propio, mismo comportamiento
   (oculta hasta que llega el dato, sin ruido si no llega). El diseño ya no
   copia la tarjeta clara y plana de NewFox: un degradado teal muy suave
   -mismo `--marca-degradado` que ya usan los botones, aquí aclarado casi al
   blanco- y el icono en una chapa circular la distinguen de un vistazo de
   las tarjetas de KPI que tiene al lado, sin salirse de la paleta de marca. */
.tarjeta-tiempo {
  display: flex; flex-direction: column; justify-content: center; gap: var(--hueco-5);
  min-width: 0; padding: 1.1rem 1.3rem 1rem;
  background:
    linear-gradient(155deg, var(--teal-50) 0%, #fff 62%);
  border: 1px solid var(--teal-100);
  border-radius: var(--radius-card); box-shadow: var(--shadow-soft);
}
/* El atributo hidden lo pone display:none la hoja del navegador, y un
   selector de clase con display:flex le gana: sin esto la tarjeta saldría
   vacía hasta que llegara el METAR, y para siempre si el servicio está caído. */
.tarjeta-tiempo[hidden] { display: none; }

/* Eyebrow con el nombre del pueblo de la estación (LEIB, Sant Jordi de ses
   Salines): antes decía «Ahora» al pie, un dato redundante con que la
   tarjeta es en tiempo real. De dónde sale el parte es lo que de verdad
   faltaba por decir. */
.tiempo-lugar {
  display: flex; align-items: center; gap: var(--hueco-2);
  font-size: var(--txt-2xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--teal-dark);
}
.tiempo-lugar svg { width: .85rem; height: .85rem; flex: 0 0 auto; }

.tiempo-cabecera { display: flex; align-items: center; gap: var(--hueco-7); }
.tiempo-icono {
  display: flex; align-items: center; justify-content: center;
  width: 3rem; height: 3rem; flex: 0 0 auto; padding: .6rem;
  color: var(--teal-dark); background: var(--teal-100); border-radius: 50%;
}
.tiempo-icono span[data-icono] { display: block; width: 100%; height: 100%; }
/* Los ocho iconos viven todos en el DOM, uno por condición posible
   (tiempo.js solo decide cuál dejar de ocultar): sin este `display: none`
   -misma trampa que en .tarjeta-tiempo[hidden], mismo motivo- los siete que
   deberían estar ocultos se pintarían igual encima del que toca. */
.tiempo-icono span[hidden] { display: none; }
.tiempo-icono svg { width: 100%; height: 100%; }
.tiempo-temp-linea { display: block; }
.tiempo-temp {
  font-family: ui-monospace, "Courier New", monospace; font-variant-numeric: tabular-nums;
  font-size: 1.9rem; font-weight: 600; line-height: 1.05; color: var(--text);
}
.tiempo-unidad { font-size: var(--txt-md); font-weight: 500; color: var(--muted); margin-left: .15rem; }
.tiempo-cond { display: block; font-size: var(--txt-xs); color: var(--muted); margin-top: .15rem; }

.tiempo-detalle {
  display: flex; align-items: center; gap: var(--hueco-3); padding-top: .6rem;
  border-top: 1px solid var(--teal-100); font-size: var(--txt-2xs); color: var(--teal-dark);
}
.tiempo-dato {
  display: inline-flex; align-items: center; gap: var(--hueco-2);
  background: #fff; border-radius: var(--radius-pill); padding: .28rem .6rem;
  box-shadow: var(--shadow-soft);
}
.tiempo-dato svg { width: .78rem; height: .78rem; color: var(--teal-dark); opacity: .85; }
/* La flecha se gira por JS con los grados del parte. */
.tiempo-flecha { display: inline-flex; transition: transform .15s var(--ease); }

/* --- Gráficos ---------------------------------------------------------
   Configuración de ApexCharts adaptada de la portada de NewFox: alto fijo
   de 152px, sin toolbar/datalabels/leyenda propia -la leyenda va en HTML,
   aquí abajo-, rejilla discontinua y tenue, animación de 350ms que respeta
   prefers-reduced-motion. La paleta es la teal de la casa (portal/servicios/
   panel.py), no la de NewFox. */
.graficos {
  display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: var(--hueco-7); margin-bottom: 1.4rem;
}
/* La barra de actividad -la más ancha- pasa a ocupar las dos columnas en
   cuanto las tres empiezan a apretar; las dos ruedas, que son más pequeñas
   y cuadradas, siguen cabiendo una junto a otra debajo. */
@media (max-width: 1100px) {
  .graficos { grid-template-columns: 1fr 1fr; }
  .graficos .tarjeta-grafico:first-child { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .graficos { grid-template-columns: 1fr; }
  .graficos .tarjeta-grafico:first-child { grid-column: auto; }
}
/* Columna flex, no bloque: cuando la rejilla estira una tarjeta para
   igualar la altura de sus vecinas -por ejemplo "Bajas del mes" cuando
   "Altas del mes" trae más filas de leyenda-, un bloque no reparte ese
   espacio de más entre sus hijos y se queda como un hueco en blanco debajo
   del contenido. Con flex, .grafico-vacio (flex:1 más abajo) lo absorbe y
   centra su aviso en vez de dejarlo pegado arriba. */
.tarjeta-grafico {
  display: flex; flex-direction: column;
  background: #fff; border-radius: var(--radius-card); box-shadow: var(--shadow-soft);
  padding: 1.1rem 1.2rem;
}
.tarjeta-grafico h2 { font-size: var(--txt-lg); font-family: var(--sans); font-weight: 600; margin: 0; }
.tarjeta-grafico .nota { margin: .2rem 0 0; }

.grafico-leyenda {
  display: flex; gap: var(--hueco-6); flex-wrap: wrap; margin-top: .7rem;
  font-size: var(--txt-xs); color: var(--muted);
}
.grafico-leyenda span { display: inline-flex; align-items: center; gap: var(--hueco-2); }
.grafico-leyenda i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

.grafico-vacio {
  flex: 1; display: flex; align-items: center; justify-content: center;
  min-height: 152px; text-align: center; color: var(--muted); font-size: var(--txt-md);
}
/* .grafico-vacio{display:flex} es un selector de autor y le gana en cascada
   al [hidden]{display:none} de la hoja del navegador -misma trampa que ya
   documenta .tarjeta-tiempo[hidden] más arriba-: sin esto, la tarjeta
   asomaría el aviso de vacío incluso con datos. */
.grafico-vacio[hidden] { display: none; }

/* Tooltip propio, anclado arriba a la izquierda del gráfico en vez de seguir
   al cursor: el que sigue al cursor se salía por debajo de la tarjeta y
   dejaba el dato fuera de la vista. */
.grafico-tt {
  background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card); padding: .5rem .65rem; font-size: var(--txt-xs);
  font-family: var(--sans); min-width: 130px;
}
.grafico-tt-cabecera { font-weight: 600; margin-bottom: .3rem; color: var(--text); }
.grafico-tt-fila { display: flex; align-items: center; gap: var(--hueco-3); justify-content: space-between; }
.grafico-tt-fila + .grafico-tt-fila { margin-top: .2rem; }
.grafico-tt-punto { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.grafico-tt-total {
  margin-top: .35rem; padding-top: .35rem; border-top: 1px solid var(--hairline);
  font-weight: 600; display: flex; justify-content: space-between;
}

.panel-inicio {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.2rem; align-items: start;
}
@media (max-width: 900px) {
  .panel-inicio { grid-template-columns: 1fr; }
}

/* --- Interruptor (Sí/No, Activar/Desactivar) ------------------------------
   No existía un control on/off en el sistema -las «pastillas» son chips de
   filtro, no esto- y las capturas de referencia de los trámites lo usan una
   docena de veces. Es una casilla real por debajo (foco, teclado y lector de
   pantalla gratis) vestida de interruptor; el texto de su estado ("No"/"Sí",
   "Desactivado"/"Activado"...) lo escribe la plantilla al lado, nunca el CSS,
   porque el color solo no le dice nada a quien no lo distingue. */
.interruptor {
  display: inline-flex; align-items: center; gap: var(--hueco-4);
  cursor: pointer; user-select: none;
}
.interruptor input {
  position: absolute; opacity: 0; width: 1px; height: 1px;
}
.interruptor-pista {
  position: relative; flex: none; width: 2.6rem; height: 1.5rem;
  border-radius: var(--radius-pill); background: color-mix(in srgb, var(--teal) 22%, transparent);
  transition: background-color .15s var(--ease);
}
.interruptor-pista::before {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 1.2rem; height: 1.2rem; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,.25);
  transition: transform .15s var(--ease);
}
.interruptor input:checked + .interruptor-pista { background: var(--teal-700); }
.interruptor input:checked + .interruptor-pista::before { transform: translateX(1.1rem); }
.interruptor input:focus-visible + .interruptor-pista {
  outline: 2px solid var(--teal-dark); outline-offset: 2px;
}
.interruptor-texto { font-size: var(--txt-md); }

/* --- Selector de tipo de petición (modal) --------------------------------
   Sustituye al desplegable "Trámites" de la cabecera: un solo punto de
   entrada, tres filas igual de visibles -ni Alta destaca sobre Baja ni al
   revés-, con la letra como referencia rápida (mismo criterio que un avatar
   de iniciales en la tabla de plantilla). */
.tramite-lista { display: flex; flex-direction: column; }
.tramite-fila {
  display: flex; align-items: center; gap: var(--hueco-6);
  padding: .9rem 0; border-bottom: 1px solid color-mix(in srgb, var(--teal) 14%, transparent);
  text-decoration: none; color: inherit;
}
.tramite-fila:last-child { border-bottom: none; }
.tramite-letra {
  flex: none; width: 2.3rem; height: 2.3rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-weight: 600; color: var(--teal-800);
  background: var(--teal-50);
}
.tramite-texto { flex: 1 1 auto; }
.tramite-texto strong { display: block; font-size: var(--txt-lg); }
.tramite-texto span { display: block; color: var(--muted); font-size: var(--txt-sm); }
.tramite-fila:hover .tramite-letra { background: var(--teal-100); }
.tramite-flecha { flex: none; display: inline-grid; place-items: center; width: 1.8rem; height: 1.8rem; color: var(--teal-700); font-size: var(--txt-xl); line-height: 1; }
.tramite-fila:hover .tramite-flecha { transform: translateX(2px); }
.tramite-fila.cargando { pointer-events: none; }
.tramite-fila.cargando .tramite-flecha { transform: none; font-size: 0; }
.tramite-fila.cargando .tramite-flecha::before {
  content: '↻'; font-size: 1.25rem;
  animation: girar-flecha-tramite .7s linear infinite;
}

/* --- Modal grande de un trámite (iframe) ----------------------------------
   La página real del trámite (Alta, Baja, o la Modificación/Llamamiento de
   la ficha de "Mi plantilla"), enmarcada. `max-height`, no `height`: una
   ficha de alta ya completada es una tarjeta pequeña, y un alta rellenada a
   mano es un formulario largo -el mismo hueco fijo de 92vh para las dos
   dejaba media pantalla en blanco en la primera. tramite.js mide el
   contenido real del iframe y le pone esa altura; el tope de aquí es solo
   la red para lo que no quepa en la pantalla, que entonces hace scroll en
   `.modal-tramite-cuerpo`, no en el iframe -así no hay una barra de scroll
   dentro de otra-. La barra de cierre queda fuera de ese scroll, fija
   arriba: el `.modal-cerrar` de base no puede ir flotando en una esquina
   como en el resto de modales porque el iframe ocuparía ese mismo sitio. */
.modal-tramite .modal-caja {
  /* Se centra respecto al área útil. El máximo deja el mismo respiro arriba
     y abajo; los formularios largos desplazan el scroll al cuerpo interno. */
  max-width: 1100px; width: min(96vw, 1100px);
  max-height: calc(100dvh - 4rem); margin: 0 auto;
  border-radius: 18px;
  padding: 0; display: flex; flex-direction: column; overflow: hidden;
}
.modal-tramite { padding: 2rem 1rem; overflow: hidden; }
.modal-tramite.visible { display: flex; align-items: center; }
/* Al filtrar se reduce el contenido, pero el selector conserva su tamaño.
   Solo desaparece el desplazamiento que ya no es necesario. */
.modal-tramite-selector .modal-caja { height: calc(100dvh - 4rem); }
.modal-tramite-barra {
  /* El cierre pertenece a la superficie del modal, no a una franja propia.
     Se superpone en su esquina y queda fijo aunque el cuerpo haga scroll. */
  position: absolute; top: .55rem; right: .7rem; z-index: 2;
  padding: 0; border: 0;
}
.modal-tramite-barra .modal-cerrar {
  position: static; display: grid; place-items: center; width: 2rem; height: 2rem;
  padding: 0; border-radius: 50%; background: color-mix(in srgb, #fff 86%, var(--teal-50));
}
.modal-tramite-barra .modal-cerrar:hover { background: var(--teal-50); }
.modal-tramite-cuerpo { position: relative; flex: 1 1 auto; min-height: 0; overflow-y: auto; background: #fff; }
.modal-tramite-carga { display: none; min-height: 9rem; padding: 2rem; place-content: center; justify-items: center; }
.modal-tramite.cargando .modal-tramite-carga { display: grid; }
.modal-tramite.cargando .modal-caja { min-height: 9rem; }
.modal-tramite.cargando iframe { display: none; }
.carga-tramite-indicador {
  font-size: 1.35rem; animation: girar-flecha-tramite .7s linear infinite;
}
@keyframes girar-flecha-tramite { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .tramite-fila.cargando .tramite-flecha::before,
  .carga-tramite-indicador { animation-duration: 1.8s; }
}
.modal-tramite iframe {
  display: block; width: 100%; border: none; background: #fff;
  /* Arranque antes de que tramite.js mida nada -y red por si el contenido
     mide 0 (about:blank, o una página que no llega a cargar)-, no el valor
     final: que un aviso corto se quede a esta altura no es lo normal, pero
     tampoco un modal en blanco. */
  height: 220px; min-height: 0;
}
@media (max-width: 640px) {
  .modal-tramite { padding: .8rem 0; }
  .modal-tramite .modal-caja { width: 100vw; max-height: calc(100vh - 1.6rem); margin: 0; border-radius: var(--radius-boton); }
  .modal-tramite-selector .modal-caja { height: calc(100vh - 1.6rem); }
}

/* El visor de documentos reutiliza el marco grande del modal de trámite, pero
   su iframe no es una página del portal que se pueda medir: es un PDF o una
   imagen servidos por /ver. Se le da una altura fija generosa -no la mide
   nadie, no hay documentos.js midiendo como en el trámite- y el
   `.modal-tramite-cuerpo` hace scroll si el visor del navegador no cabe. */
.modal-visor iframe { height: 82vh; min-height: 320px; }
.visor-titulo {
  flex: 1 1 auto; min-width: 0; align-self: center; margin-right: .5rem;
  font-weight: 500; font-size: var(--txt-md); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis;
}

/* Cuando una pantalla de trámite se carga dentro de ese iframe
   (base_modal.html), no lleva cabecera ni pie: el `main` que en la página
   completa centra el contenido bajo la cabecera aquí ocupa toda la altura
   sin ese margen superior, que dentro de un iframe se leería como un hueco
   vacío sin motivo. */
body.cuerpo-modal { background: #fff; }
body.cuerpo-modal main { max-width: none; margin: 0; padding: 0; }
body.cuerpo-modal .tarjeta {
  border: 0; border-radius: 0; box-shadow: none; margin: 0;
  padding: 1rem 1.35rem 1.4rem;
}

/* --- Tabla de selección de trabajador (baja, modificación) ---------------
   Fila completa clicable -no un enlace suelto dentro de la celda-, mismo
   patrón de foco y teclado que la ficha de "Mi plantilla". */
.tabla-seleccion tbody tr { cursor: pointer; }
.tabla-seleccion tbody tr:hover, .tabla-seleccion tbody tr:focus-visible {
  background: var(--teal-50);
}
/* Solo el fondo teal-50 no se distingue del blanco (1,05:1): con teclado no se
   sabía en qué fila estaba el foco. Mismo contorno que la ficha de plantilla. */
.tabla-seleccion tbody tr:focus-visible { outline: 2px solid var(--teal-700); outline-offset: -2px; }
.tabla-seleccion .persona-sub { display: block; color: var(--muted); font-size: var(--txt-xs); }

/* Selector de modificación: la decisión es elegir una persona, no consultar
   toda la pantalla de plantilla. Por eso las filas son enlaces amplios y los
   filtros viven arriba, como un selector y no como un panel de analítica. */
.selector-tramite { max-width: 1040px; margin: 0 auto; padding: 1rem 1.35rem; }
.selector-tramite h1 { margin: 0 0 .18rem; line-height: 1.15; }
.selector-tramite > .nota { margin: 0; font-size: var(--txt-sm); }
/* Flex y no una rejilla de columnas fijas: los filtros no son siempre los
   mismos -la baja no pinta el de estado, porque solo carga a los activos- y
   una cuarta columna declarada a mano dejaba un hueco vacío donde faltara
   un control. Las proporciones son las de antes: la búsqueda el doble que
   cada desplegable, y todos con el mismo mínimo. */
.selector-tramite-filtros { display: flex; flex-wrap: wrap; gap: var(--hueco-3); margin: .75rem 0 .35rem; }
.selector-tramite-filtros > label { flex: 1 1 9rem; min-width: 0; }
.selector-tramite-filtros > .selector-busqueda { flex: 2 1 15rem; }
.selector-tramite-filtros input, .selector-tramite-filtros select { width: 100%; height: 2.35rem; padding: .45rem .65rem; font-size: var(--txt-md); }
.selector-contador { color: var(--muted); font-size: var(--txt-xs); margin: .4rem 0; }
.selector-lista { border-top: 1px solid color-mix(in srgb, var(--teal) 18%, transparent); background: #fff; }
.selector-trabajador { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: var(--hueco-4); padding: .52rem .45rem; color: inherit; text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--teal) 14%, transparent); }
.selector-trabajador.cebra { background: color-mix(in srgb, var(--teal) 3.5%, #fff); }
.selector-trabajador[hidden] { display: none; }
.selector-trabajador:hover, .selector-trabajador:focus-visible { background: var(--teal-50); outline: 2px solid var(--teal-700); outline-offset: -2px; }
.selector-trabajador-datos { min-width: 0; display: grid; gap: .05rem; }
.selector-trabajador-datos strong { font-size: var(--txt-md); }
.selector-trabajador-datos span { color: var(--muted); font-size: var(--txt-2xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.selector-dni { font-size: var(--txt-xs); }
/* 720 y no los 640 del resto del portal, que es el corte habitual: los
   filtros de arriba miden 15rem + 3 de 9rem, o sea 42rem = 672px de mínimo.
   Entre 641 y 720 caben en dos líneas descompensadas, así que este corte lo
   fija el ancho de los filtros, no el gusto. */
@media (max-width: 720px) {
  .selector-tramite { padding: 1rem; }
  .selector-tramite-filtros > .selector-busqueda { flex-basis: 100%; }
  .selector-trabajador { grid-template-columns: auto minmax(0, 1fr) auto; }
  .selector-dni { display: none; }
}

/* Formularios operativos dentro del marco: jerarquía suficiente para
   escanear, sin títulos y tarjetas que conviertan cada decisión en una
   pantalla. Las etiquetas y los controles mantienen su tamaño táctil. */
/* El marco ya controla el ancho según el trámite. El contenido debe ocupar
   todo su espacio útil para conservar el mismo margen a izquierda y derecha. */
.flujo-tramite { max-width: none; }
.flujo-cabecera { margin: 0 0 .8rem; }
.flujo-etiqueta { margin: 0 0 .15rem; color: var(--teal-700); font-size: var(--txt-2xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.flujo-cabecera h1 { margin: 0; line-height: 1.15; }
.flujo-cabecera .nota { margin: .28rem 0 0; font-size: var(--txt-sm); }
.flujo-bloque { border-top: 1px solid color-mix(in srgb, var(--teal) 18%, transparent); margin-top: .75rem; padding-top: .7rem; }
.flujo-bloque h2 { font-family: var(--sans); font-weight: 600; font-size: var(--txt-lg); margin: 0 0 .35rem; }
.flujo-bloque h3 { font-family: var(--sans); font-weight: 600; font-size: var(--txt-md); margin: 0; }
.flujo-bloque .rejilla { gap: .25rem .8rem; }
.flujo-tramite label { margin: .45rem 0 .15rem; font-size: var(--txt-xs); }
.flujo-tramite input, .flujo-tramite select, .flujo-tramite textarea { padding: .48rem .65rem; font-size: var(--txt-md); }
.flujo-tramite .ayuda-campo, .flujo-tramite .nota { margin: .18rem 0; font-size: var(--txt-2xs); line-height: 1.32; }
.flujo-tramite .seccion-cambio { margin-top: .75rem; padding-top: .7rem; }
#formAlta .opciones-datos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--hueco-3); }
#formAlta .opciones-datos legend { grid-column: 1 / -1; }
#formAlta .opciones-datos label { padding: .45rem .55rem; margin: 0; font-size: var(--txt-xs); }
.flujo-opcional { margin-top: .75rem; padding-top: 0; border-top: 0; }
.flujo-opcional summary { display: flex; align-items: center; justify-content: space-between; padding: .48rem .65rem; border: 1px solid var(--teal-200); border-radius: var(--radius-xs); font-size: var(--txt-xs); }
.flujo-opcional summary::before { display: none; }
.flujo-opcional summary span { color: var(--muted); font-size: var(--txt-2xs); font-weight: 400; }
.flujo-acciones { margin-top: .8rem; }

/* Cuatro decisiones se leen de una vez. Al activar una, crece solo en alto
   dentro de su columna: el resto de decisiones no salta de sitio. */
.cambios-compactos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem .8rem; }
.cambio-compacto { margin: 0; padding: .5rem .6rem; border: 1px solid var(--teal-200); border-radius: var(--radius-sm); }
.cambio-compacto:has(input:checked) { background: var(--teal-50); border-color: var(--teal); }
.cambio-compacto-cabecera { display: flex; align-items: center; justify-content: space-between; gap: var(--hueco-5); }
.cambio-compacto p { margin: .08rem 0 0; color: var(--muted); font-size: var(--txt-2xs); line-height: 1.25; }
.cambio-compacto .interruptor { margin: 0; flex: none; }
.cambio-compacto .seccion-cambio-campos { margin-top: .45rem; }
.cambio-compacto .valor-actual { color: var(--muted); }
/* Contrato y jornada es el único cambio con seis campos dependientes. Al
   activarlo usa todo el ancho y los reparte en filas cortas, en vez de crear
   una torre en media columna. */
.cambio-contrato:has(input:checked) { grid-column: 1 / -1; }
.cambio-contrato .rejilla { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 640px) {
  .cambios-compactos { grid-template-columns: 1fr; }
  .cambio-contrato:has(input:checked) { grid-column: auto; }
  .cambio-contrato .rejilla { grid-template-columns: 1fr; }
  #formAlta .opciones-datos { grid-template-columns: 1fr; }
}

/* --- Secciones activables de la modificación ------------------------------
   Cada bloque (categoría, salario, centro, otros) se abre solo si su
   interruptor está encendido: mismo criterio que .mas-datos, pero disparado
   por una casilla en vez de un <details>, porque aquí el estado SÍ hace
   falta enviarlo al servidor. */
.seccion-cambio { border-top: 1px solid color-mix(in srgb, var(--teal) 20%, transparent); padding-top: 1rem; margin-top: 1rem; }
.seccion-cambio-campos { margin-top: .9rem; }
.seccion-cambio-campos[hidden] { display: none; }
.opciones-datos { border: 0; padding: 0; margin: 0; }
.opciones-datos legend { font-size: var(--txt-xl); font-weight: 500; margin-bottom: .5rem; }
.opciones-datos label { display: flex; align-items: center; gap: var(--hueco-4); padding: .75rem; border: 1px solid var(--teal-200); border-radius: var(--radius-campo); }
.opciones-datos label:has(input:checked) { background: var(--teal-50); border-color: var(--teal-700); }
.opciones-datos input { width: auto; margin: 0; accent-color: var(--teal-700); }
.valor-actual {
  display: inline-flex; align-items: center; gap: var(--hueco-2);
  color: var(--muted); font-size: var(--txt-sm); margin: .2rem 0 .8rem;
}
.valor-actual strong { color: var(--text); font-weight: 500; }

/* Las reglas genéricas de secciones activables están inmediatamente arriba;
   estas prevalecen en la matriz compacta de modificación. */
.cambios-compactos .cambio-compacto {
  margin: 0; padding: .5rem .6rem; border: 1px solid var(--teal-200);
}
.cambios-compactos .cambio-compacto .seccion-cambio-campos { margin-top: .45rem; }
.flujo-tramite .seccion-cambio { margin-top: .75rem; padding-top: .7rem; }

/* --- 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;
}

/* --- Área táctil de los iconos sueltos ------------------------------------
   La campana, «Salir», el lápiz de una fila y el aspa de los modales miden
   32-37 px: bien con ratón, cortos para un dedo (WCAG 2.5.8 y la guía de
   Apple piden ~44). Agrandarlos de verdad descuadraría la cabecera y las
   filas de la tabla, así que en pantallas táctiles se amplía solo la zona
   que recibe el toque, con un pseudo-elemento invisible. */
@media (pointer: coarse) {
  .icono-fila,
  .modal-tramite-barra .modal-cerrar { position: relative; }
  .cabecera .icono-boton::after,
  .icono-fila::after,
  .modal-cerrar::after { content: ""; position: absolute; inset: -6px; }
}
