/*
 * Rúbrica — hoja de estilos propia, sin framework (ADR 0004: sin
 * compilación de frontend). Cubre el esqueleto compartido por todas las
 * pantallas (cabecera, layout general) y los componentes de la Zona 1 del
 * tablero de situación. Las pantallas B2+ y las Zonas 2/3 añaden reglas
 * propias sin rehacer estas.
 */

:root {
  --color-fondo: #f7f7f5;
  --color-superficie: #ffffff;
  --color-texto: #1f2328;
  --color-texto-tenue: #5b6470;
  --color-borde: #d9dce0;
  /* Gris de cabecera de tabla: `--color-fondo` (#f7f7f5) es el fondo de la
   * página y sobre el blanco de una tabla no se distingue — probado en el
   * navegador, la cabecera se veía blanca. Este sí separa cabecera de
   * cuerpo sin competir con el texto. */
  --color-superficie-tenue: #eceef1;

  /* Incidencia deja de reutilizar `--color-aviso` (#92660a, un dorado
   * apagado que no se leía como naranja) y pasa a tener color propio, como
   * el resto de fases: naranja llamativo, porque una incidencia abierta es
   * lo que más pide atención de la tabla. `--color-aviso` se queda para los
   * avisos genéricos de la app (ficha-ayuda), que no son una fase. Pareja
   * comprobada a contraste AA (4.56:1) para texto de 0.8rem en negrita. */
  --color-fase-incidencia: #c2410c;
  --color-fase-incidencia-tenue: #fdeee2;

  /* Fondos de fila: mucho más tenues que los fondos de etiqueta. Una
   * etiqueta ocupa 100px y puede permitirse saturación; una fila cruza toda
   * la pantalla y con el mismo tono grita. Anulado en rojo muy tenue e
   * incidencia en cálido — la señal fuerte la da la etiqueta, la fila solo
   * acompaña. */
  --color-fila-anulado: #fdf4f2;
  --color-fila-incidencia: #fef7f1;
  --color-acento: #2b4c7e;
  /* El acento un paso más oscuro, para el hover de los botones sólidos
     (R2b). Existe como token y no como color suelto en la regla: en
     cuanto el acento cambie, su hover tiene que cambiar con él. */
  --color-acento-fuerte: #1f3a63;
  --color-acento-tenue: #e8edf5;
  --color-alerta: #b3441e;
  --color-alerta-tenue: #f7e6df;
  --color-exito: #2f7d4f;
  --color-exito-tenue: #e6f3ea;
  --color-aviso: #92660a;
  --color-aviso-tenue: #f7ecd9;

  /* Colores de fase en prueba desde 2026-08-24 (a petición expresa, con
   * aviso de posible marcha atrás): una fase, un color — progresión
   * azul→teal a medida que el circuito avanza, terminando en el verde de
   * éxito que ya existía. `con_fecha_de_firma` reutiliza --color-acento,
   * `finalizada` --color-exito, `anulado` --color-alerta e `incidencia`
   * --color-aviso — ya existían, no se duplican. Hubo aquí un
   * `pendiente_envio` que reutilizaba el color de `pendiente_gestion`;
   * esa fase se retiró con el ADR 0011, así que la clase se va con ella.
   * Revertir a los cuatro grupos anteriores es cambiar solo
   * `Fase.grupo_color` (enums.py) — estos tokens pueden quedarse sin
   * usar si se revierte, no hace falta borrarlos con prisa. */
  --color-fase-pendiente-gestion: #64748b;
  --color-fase-pendiente-gestion-tenue: #eef1f4;
  --color-fase-pendiente-confirmacion: #6366f1;
  --color-fase-pendiente-confirmacion-tenue: #ecebfd;
  --color-fase-pendiente-inscripcion: #0e7490;
  --color-fase-pendiente-inscripcion-tenue: #e3eef1;
  --color-fase-pendiente-copia: #0d9488;
  --color-fase-pendiente-copia-tenue: #e1f2ef;
  --color-fase-pendiente-entrega-gestoria: #15803d;
  --color-fase-pendiente-entrega-gestoria-tenue: #e3f0e7;
  --fuente-base: system-ui, -apple-system, "Segoe UI", sans-serif;
  --fuente-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  --espacio-1: 0.25rem;
  --espacio-2: 0.5rem;
  --espacio-3: 1rem;
  --espacio-4: 1.5rem;
  --espacio-5: 2.5rem;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--fuente-base);
  color: var(--color-texto);
  background: var(--color-fondo);
  line-height: 1.4;
}

a {
  color: var(--color-acento);
}

/* LA CABECERA ANTERIOR SE RETIRA (zona 3 de la migración, issue #186).
 *
 * Veintiuna reglas y treinta y tres usos de token viejo que no pintaban
 * nada: la navegación se rehízo como `.ds-topbar` en la fase 2 del
 * rediseño, y ninguna plantilla usa ya `class="cabecera"`. Se comprobó
 * antes de borrar, no después.
 *
 * No es una migración, es una retirada: migrar CSS muerto a tokens nuevos
 * habría sido darle otra vida a algo que ya no se pinta, y habría dejado
 * treinta y tres usos «migrados» que nadie ve. Lo que no se usa se borra.
 */

/* --- Layout general --------------------------------------------------- */

.contenido {
  padding: var(--ds-e5);
  max-width: 1200px;
  margin: 0 auto;
}

/* Sin tope de ancho (diseño Stitch de referencia): el tope de 1200px es
 * correcto para texto largo — una línea de 200 caracteres no se lee — pero
 * en una tabla de datos desperdiciaba ~400px a cada lado en pantallas
 * grandes, que es justo el espacio que evita que las fincas múltiples se
 * corten con puntos suspensivos. Modificador, no cambio global: el resto
 * de pantallas conserva el tope (la ficha lo pidió también en la R1 de la
 * revisión visual: su barra de trece estados no cabe en el ancho de
 * lectura). `--espacio-5` deja un margen
 * respirable en vez de pegar la tabla al borde. */
.contenido--ancho {
  max-width: none;
  padding-inline: var(--ds-e6);
}

/* Rediseño 2026-09, fase 2/5: login y error a sangre completa —
 * `.ds-login`/`.ds-error-pagina` fijan su propio alto y color de
 * fondo, así que el relleno/tope de `.contenido` sobraría. */
.contenido--sin-relleno {
  max-width: none;
  padding: 0;
  margin: 0;
}

/* --- Utilidad: número de expediente monoespaciado (spec-04 R8) -------- */

.exp-gestoria {
  font-family: var(--fuente-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- Fase: único mapa de color, compartido entre tablero y ficha (issue
 * #72) --------------------------------------------------------------- */

/* Una fase, un color (`Fase.grupo_color`, enums.py — la única
 * clasificación, nunca reimplementada aquí), en prueba desde
 * 2026-08-24. Progresión azul→teal a medida que el circuito avanza,
 * terminando en verde; anulado e incidencia llevan cada uno el suyo,
 * distinto entre sí y del circuito, con borde discontinuo — ninguno de
 * los dos es una etapa más, la forma lo dice junto al color. */
/* La etapa, delante del estado: dice «qué se está haciendo» de un vistazo
   y el estado dice en qué punto. Discreta a propósito — es contexto del
   badge, no una segunda etiqueta que compita con él. */
.ficha-cabecera__etapa {
  color: var(--ds-texto-atenuado);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Qué documento falta, en la cabecera y no enterrado en la zona de
   documentos: es lo que dice qué hacer a continuación. En tono de aviso,
   no de error — no ha fallado nada, falta algo. */
.ficha-cabecera__faltan {
  margin: var(--ds-e1) 0 0;
  color: var(--ds-aviso);
  font-weight: 600;
}

/* La autorización es otra cosa: no bloquea (spec-07 D1), así que va más
   apagada que el aviso de arriba. Si las dos pesaran igual, la que no
   detiene nada acabaría tapando la que sí. */
.ficha-cabecera__falta-autorizacion {
  margin: var(--ds-e1) 0 0;
  color: var(--ds-texto-atenuado);
}

/* Dónde seguía el expediente cuando se interrumpió. Una salida no
   sustituye al estado: levantarla lo devuelve ahí. */
.ficha-cabecera__salida-desde {
  color: var(--ds-texto-atenuado);
  font-size: 0.85rem;
}

/* La retirada de la cohorte histórica, dicha en el tablero (spec-07 R12).
   En tono informativo y no de alerta: no ha fallado nada, se ha decidido
   qué se enseña. */
.tablero-circuito__historicos {
  margin: 0 0 var(--ds-e2);
  padding: var(--ds-e1) var(--ds-e2);
  color: var(--ds-texto-atenuado);
  background: var(--ds-fase-pendiente-gestion-tenue);
  border-radius: 4px;
}

/* Qué documentos faltan, en la fila del tablero: dice qué hacer a
   continuación sin abrir el expediente. */
.fase-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--ds-e1) var(--ds-e2);
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.fase-badge--pendiente_gestion {
  background: var(--ds-fase-pendiente-gestion-tenue);
  color: var(--ds-fase-pendiente-gestion);
}

/* Los siete estados nuevos de las etapas 1 a 3 (spec-07). Reutilizan los
   tokens que ya existen en vez de inventar siete colores: la progresión
   del circuito ya estaba pensada, y los estados nuevos ocupan el tramo
   ANTERIOR al que los tokens cubrían. Se agrupan por etapa —entrada en
   gris, preparación en índigo, envío en el acento— porque lo que importa
   de un vistazo es en qué etapa está, no cuál de los tres estados de esa
   etapa. Los de la etapa 4 comparten valor con sus fases homónimas
   (`estados.py`), así que sus clases ya existen más abajo. */
.fase-badge--sin_documentos,
.fase-badge--sin_clasificar {
  background: var(--ds-fase-pendiente-gestion-tenue);
  color: var(--ds-fase-pendiente-gestion);
}

.fase-badge--previo_pendiente,
.fase-badge--modelo_pendiente,
.fase-badge--paquete_pendiente {
  background: var(--ds-fase-pendiente-confirmacion-tenue);
  color: var(--ds-fase-pendiente-confirmacion);
}

.fase-badge--correo_pendiente,
.fase-badge--esperando_respuesta {
  background: var(--ds-seleccion-fondo);
  color: var(--ds-azul);
}

.fase-badge--conforme_recibido {
  background: var(--ds-fase-pendiente-inscripcion-tenue);
  color: var(--ds-fase-pendiente-inscripcion);
}

.fase-badge--pendiente_confirmacion {
  background: var(--ds-fase-pendiente-confirmacion-tenue);
  color: var(--ds-fase-pendiente-confirmacion);
}

.fase-badge--con_fecha_de_firma {
  background: var(--ds-seleccion-fondo);
  color: var(--ds-azul);
}

.fase-badge--pendiente_inscripcion {
  background: var(--ds-fase-pendiente-inscripcion-tenue);
  color: var(--ds-fase-pendiente-inscripcion);
}

.fase-badge--pendiente_copia {
  background: var(--ds-fase-pendiente-copia-tenue);
  color: var(--ds-fase-pendiente-copia);
}

.fase-badge--pendiente_entrega_gestoria {
  background: var(--ds-fase-pendiente-entrega-gestoria-tenue);
  color: var(--ds-fase-pendiente-entrega-gestoria);
}

.fase-badge--finalizada {
  background: var(--ds-correcto-fondo);
  color: var(--ds-correcto);
}

.fase-badge--anulado {
  background: var(--ds-error-fondo);
  color: var(--ds-error);
  border: 1px dashed var(--ds-error);
}

.fase-badge--incidencia {
  background: var(--ds-fase-incidencia-tenue);
  color: var(--ds-fase-incidencia);
  border: 1px dashed var(--ds-fase-incidencia);
}

/* --- Tablero de situación — Zona 1: fila del circuito ------------------ */

/* Compactado (diseño Stitch de referencia): el alto que gana el bloque
 * superior lo pierden las filas, y las filas son lo que se mira. El título
 * de la pantalla no necesita 1.5rem cuando la cabecera ya dice dónde
 * estás. */
.tablero__titulo {
  margin: 0 0 var(--ds-e2);
  font-size: 1.25rem;
}

.tablero-circuito {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e2);
}

/* Circuito y salidas en la misma fila (corrección de revisión, diseño
 * Stitch de referencia): "las siete del circuito, y aparte estas dos" —
 * la lista ocupa el espacio disponible, las salidas se quedan a su
 * ancho natural a la derecha, separadas por `.tablero-salidas`. */
.tablero-circuito__fila {
  display: flex;
  align-items: stretch;
  gap: var(--ds-e3);
}

.tablero-circuito__lista {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--ds-e1);
  margin: 0;
  padding: 0;
  list-style: none;
  flex: 1;
  min-width: 0;
}

/* Compactado (corrección de revisión, densidad de la Zona 1): padding y
 * tipografía reducidos sin perder legibilidad — el bloque superior no debe
 * ocupar media pantalla. */
/* La casilla es el hueco de la rejilla; la tarjeta es el enlace que lo
 * llena. Sin esto el enlace se quedaría a su alto natural y las tarjetas
 * de una fila dejarían de tener la misma altura. */
.tablero-circuito__casilla {
  display: flex;
}

.tablero-circuito__item {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  gap: var(--ds-e1);
  padding: var(--ds-e1) var(--ds-e2);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
  text-align: center;
}

/* Las tarjetas de recuento filtran la tabla por su fase. Heredan el color
 * del texto en vez del azul de enlace: son tarjetas que se pueden pulsar,
 * no un menú de enlaces, y siete títulos en azul competirían con el
 * número, que es lo protagonista.
 *
 * El hover NUNCA toca `border-color`: eso reescribiría los cuatro lados,
 * y el de arriba es la barra de 6px que identifica la fase. Fondo y
 * sombra dicen lo mismo sin pisar el color. */
.tablero-circuito__item,
.tablero-salidas__item {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.12s ease, box-shadow 0.12s ease;
}

.tablero-circuito__item:hover,
.tablero-salidas__item:hover {
  background: var(--ds-fondo-app);
  box-shadow: 0 2px 8px rgba(31, 35, 40, 0.1);
}

.tablero-circuito__item:focus-visible,
.tablero-salidas__item:focus-visible {
  outline: 2px solid var(--ds-azul);
  outline-offset: 2px;
}

/* Tarjeta activa: la fase por la que está filtrada la tabla. El anillo va
 * por fuera (`box-shadow`, no `outline` ni `border`) para no tapar la
 * barra de color ni descuadrar la rejilla. Pulsarla otra vez quita el
 * filtro, y el `title` de la plantilla lo dice. */
.tablero-circuito__item--activa,
.tablero-salidas__item--activa {
  background: var(--ds-seleccion-fondo);
  box-shadow: 0 0 0 1px var(--ds-azul);
}

.tablero-circuito__item--activa .tablero-circuito__etiqueta,
.tablero-salidas__item--activa .tablero-salidas__etiqueta {
  color: var(--ds-azul);
  font-weight: 600;
}

/* Color por fase en la barra superior, no en el fondo de la tarjeta
 * (corrección de revisión): siete fondos de color competirían con el
 * número, que es lo protagonista — la barra da la referencia cromática
 * sin ese ruido. Modificador `--{{ fase.grupo_color }}` (issue #72,
 * mismo mapa que `.fase-badge` y las cajas de salidas de abajo — nunca
 * una clasificación aparte). Grosor de 6px: a 3px la barra no se
 * reconocía sin fijarse. */
.tablero-circuito__item--pendiente_gestion {
  border-top: 6px solid var(--ds-fase-pendiente-gestion);
}

.tablero-circuito__item--pendiente_confirmacion {
  border-top: 6px solid var(--ds-fase-pendiente-confirmacion);
}

.tablero-circuito__item--con_fecha_de_firma {
  border-top: 6px solid var(--ds-azul);
}

.tablero-circuito__item--pendiente_inscripcion {
  border-top: 6px solid var(--ds-fase-pendiente-inscripcion);
}

.tablero-circuito__item--pendiente_copia {
  border-top: 6px solid var(--ds-fase-pendiente-copia);
}

.tablero-circuito__item--pendiente_entrega_gestoria {
  border-top: 6px solid var(--ds-fase-pendiente-entrega-gestoria);
}

.tablero-circuito__item--finalizada {
  border-top: 6px solid var(--ds-correcto);
}

.tablero-circuito__etiqueta {
  font-size: 0.8rem;
  color: var(--ds-texto-atenuado);
}

.tablero-circuito__conteo {
  font-size: 1.15rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* A la derecha de la fila, separadas por un borde vertical, no debajo
 * (corrección de revisión, diseño Stitch de referencia — spec-04 R1,
 * CA2 siguen pidiendo que se distingan del circuito, ahora con un
 * separador en vez de una fila aparte). Mismas proporciones que
 * `.tablero-circuito__item` para que se lean como parte de la misma
 * fila de tarjetas, solo que agrupadas aparte. */
.tablero-salidas {
  display: flex;
  /* La nota va debajo de las dos tarjetas, no en la misma línea: envuelve
   * y ocupa el ancho entero del grupo. */
  flex-wrap: wrap;
  gap: var(--ds-e1);
  flex-shrink: 0;
  padding-left: var(--ds-e3);
  border-left: 1px dashed var(--ds-borde);
}

/* Por qué estas dos no se suman a las casillas del circuito. Tenue y
 * pequeña, con el mismo tono informativo que la línea de históricos: tiene
 * que estar ahí cuando alguien haga la suma, sin competir con los números
 * que están justo encima. El tope de ancho evita que la nota estire el
 * grupo y le robe sitio a la fila de casillas. */
.tablero-salidas__nota {
  flex-basis: 100%;
  max-width: 16rem;
  margin: 0;
  color: var(--ds-texto-atenuado);
  font-size: 0.75rem;
  line-height: 1.35;
}

.tablero-salidas__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--ds-e1);
  padding: var(--ds-e1) var(--ds-e2);
  min-width: 5.5rem;
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
  text-align: center;
}

.tablero-salidas__item--anulado {
  border-top: 6px solid var(--ds-error);
}

/* Incidencia no es lo mismo que anulado — uno es terminal, el otro no
 * (issue #72, mismo mapa que `.fase-badge` y las tarjetas de arriba):
 * antes compartían el mismo color de aviso y solo la etiqueta los
 * distinguía. */
.tablero-salidas__item--incidencia {
  border-top: 6px solid var(--ds-fase-incidencia);
}

.tablero-salidas__etiqueta {
  font-size: 0.8rem;
  color: var(--ds-texto-atenuado);
}

.tablero-salidas__conteo {
  font-size: 1.15rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 900px) {
  .tablero-circuito__fila {
    flex-direction: column;
  }

  .tablero-salidas {
    padding-left: 0;
    padding-top: var(--ds-e1);
    border-left: none;
    border-top: 1px dashed var(--ds-borde);
  }
}

@media (max-width: 720px) {
  .tablero-circuito__lista {
    grid-template-columns: repeat(2, 1fr);
  }

  .tablero-salidas {
    flex-direction: column;
  }
}

/* Aviso "sin departamento" — distinto de una fila de fases en cero: un
 * departamento real sin expedientes no es lo mismo que no tener ninguno
 * asignado, y confundirlos deja al usuario sin saber a quién avisar. */
.tablero-aviso-sin-departamento {
  margin-bottom: var(--ds-e3);
  padding: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-error);
  border-left-width: 4px;
  border-radius: 6px;
  color: var(--ds-error);
}

/* --- Tablero de situación — Zona 2: panel de expedientes parados ------- */

/* Parados y filtros lado a lado, no apilados (corrección de revisión,
 * diseño Stitch de referencia): apilados ocupaban ~400px antes de la
 * tabla — en dos columnas se recupera esa altura para filas, que es lo
 * que más importa en esta pantalla. En pantallas estrechas vuelven a
 * apilarse: dos columnas finas serían ilegibles. */
.tablero-fila-superior {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  gap: var(--espacio-3);
  /* Separación entre zonas, no relleno dentro de ellas: las tres (tarjetas,
   * parados/filtros y tabla) se leían pegadas. El aire entre bloques ayuda
   * a recorrer la pantalla; el relleno dentro solo la alarga. */
  margin-top: var(--espacio-5);
}

@media (max-width: 900px) {
  .tablero-fila-superior {
    grid-template-columns: 1fr;
  }
}

/* Panel con el mismo lenguaje visual que las tarjetas de fase (borde,
 * radio, superficie) — antes flotaba sin caja propia; ahora se lee como
 * un bloque emparejado con el de filtros. */
.tablero-parados {
  padding: var(--ds-e2) var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.tablero-parados__titulo {
  font-size: 1rem;
  margin-bottom: var(--ds-e1);
}

.tablero-parados__lista {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  margin: 0 0 var(--ds-e1);
  padding: 0;
  list-style: none;
}

/* Compactado (corrección de revisión, densidad de la Zona 2): mismo piso
 * de 0.85rem que la tabla de la Zona 3 — el bloque superior no debe ocupar
 * media pantalla, pero el texto sigue siendo perfectamente legible. */
.tablero-parados__item {
  display: flex;
  align-items: center;
  gap: var(--ds-e3);
  padding: var(--ds-e1) var(--ds-e2);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
  font-size: 0.85rem;
}

.tablero-parados__dias {
  margin-left: auto;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.tablero-parados__vacio {
  color: var(--ds-texto-atenuado);
}

/* --- Login (issue #51) ------------------------------------------------- */

.login {
  max-width: 320px;
  margin-top: var(--ds-e5);
}

.login__error {
  padding: var(--ds-e2) var(--ds-e3);
  margin-bottom: var(--ds-e3);
  border: 1px solid var(--ds-error);
  border-radius: var(--ds-radio);
  color: var(--ds-error);
}

.login__formulario {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e3);
}

.login__campo {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  font-size: var(--ds-tamano-secundario);
  color: var(--ds-texto-atenuado);
}

/* El borde de control, no el de superficie: `--ds-borde` (#E5E7EB) separa
 * paneles, y sobre blanco un campo de texto con ese borde no se lee como
 * algo donde se escribe. `--ds-borde-control` existe para esto. */
.login__campo input {
  padding: var(--ds-e1) var(--ds-e2);
  border: 1px solid var(--ds-borde-control);
  border-radius: var(--ds-radio);
  font: inherit;
  color: var(--ds-texto);
}

/* Mismo botón sólido que el resto de acciones principales del proyecto
 * (`.ficha-preparacion__accion`), sin inventar uno nuevo. */
.login__boton {
  padding: var(--ds-e2) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: var(--ds-radio);
  background: var(--ds-azul);
  color: var(--ds-sobre-oscuro-texto);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--ds-transicion), border-color var(--ds-transicion);
}

.login__boton:hover {
  background: var(--ds-azul-oscuro);
  border-color: var(--ds-azul-oscuro);
}

/* --- Tablero de situación — Zona 3: tabla filtrable -------------------- */

/* Misma caja que `.tablero-parados` (corrección de revisión): las dos
 * viven ahora en `.tablero-fila-superior`, lado a lado, y deben leerse
 * como un par de paneles emparejados, no una tabla suelta y una lista. */
.tablero-tabla-filtros {
  padding: var(--ds-e2) var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.tablero-tabla-filtros__formulario {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--ds-e3);
}

.tablero-tabla-filtros__campo {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  font-size: 0.85rem;
  color: var(--ds-texto-atenuado);
}

.tablero-tabla-filtros__campo input,
.tablero-tabla-filtros__campo select {
  /* El `label` es el que crece dentro del formulario flex; sin esto el
   * control se quedaba en su ancho intrínseco y dejaba un hueco muerto a
   * su derecha, visible desde que el tablero usa todo el ancho. */
  width: 100%;
  padding: var(--ds-e1) var(--ds-e2);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
  font: inherit;
  color: var(--ds-texto);
}

/* Es el campo que más se usa (corrección de revisión): más ancho que los
 * desplegables y con su propio tamaño de letra, para que se note antes
 * de leer la etiqueta — sin cambiar el resto del formulario. */
.tablero-tabla-filtros__campo--buscar {
  flex: 2 1 320px;
}

.tablero-tabla-filtros__campo--buscar input {
  padding: var(--ds-e2) var(--ds-e3);
  font-size: 1rem;
}

/* Indicador discreto de búsqueda en vuelo (corrección de revisión): htmx
 * ya controla su visibilidad (`includeIndicatorStyles`, `hx-indicator`
 * en el formulario) — aquí solo el aspecto. */
.tablero-tabla-filtros__indicador {
  align-self: center;
  font-size: 0.8rem;
  color: var(--ds-texto-atenuado);
}

.tablero-tabla {
  margin-top: var(--ds-e6);
  overflow-x: auto;
}

.tablero-tabla__aviso-cerrados {
  margin: 0 0 var(--ds-e2);
  font-size: 0.8rem;
  color: var(--ds-error);
}

/* `table-layout: fixed` (diseño Stitch de referencia): las columnas se
 * reparten por porcentaje sobre el ancho disponible en vez de negociarlo
 * con el contenido. Es lo que hace que ensanchar la pantalla ensanche de
 * verdad la columna de fincas, y además fija el ancho en una sola pasada
 * — con 50 filas, el navegador ya no mide cada celda. `min-width` conserva
 * el desplazamiento horizontal de `.tablero-tabla` en pantallas estrechas:
 * seis columnas en 360px serían ilegibles a cualquier porcentaje. */
.tablero-tabla__tabla {
  width: 100%;
  min-width: 62rem;
  table-layout: fixed;
  border-collapse: collapse;
  background: var(--ds-superficie);
}

/* Fincas y titular se llevan la mayor parte del ancho entre las dos: son
 * los dos únicos campos de largo imprevisible. El resto tiene largo
 * acotado (número de expediente, nombre de entidad, etiqueta de fase o
 * de previo, un entero). Suman 100 exactos — en `table-layout: fixed` lo
 * que falte o sobre lo reparte el navegador por su cuenta, y entonces
 * esto deja de ser un reparto decidido.
 *
 * Columna «Previo» añadida (issue #104): 10% salidos de titular, fincas
 * y fase (24→20, 24→20, 16→14) — el número de expediente y entidad no
 * se tocan, ya estaban en su mínimo probado. */
/* El número de expediente nunca debe recortarse con elipsis: es el
 * identificador, y medio número no identifica nada. Con 10% se cortaba en
 * el ancho mínimo de la tabla (probado en el navegador a 820px). */
.tablero-tabla__th--expediente { width: 12%; }
.tablero-tabla__th--titular { width: 20%; }
.tablero-tabla__th--entidad { width: 14%; }
.tablero-tabla__th--fincas { width: 20%; }
.tablero-tabla__th--fase { width: 14%; }
.tablero-tabla__th--previo { width: 10%; }
.tablero-tabla__th--dias { width: 10%; }

/* Cabecera con fondo gris tenue (diseño Stitch de referencia): separa la
 * cabecera del cuerpo y le da un ancla visual al recorrer 50 filas, en vez
 * de ser una fila más en blanco con la letra algo más pequeña. El borde
 * inferior sube a 2px por el mismo motivo. */
.tablero-tabla__tabla th {
  padding: var(--ds-e2) var(--ds-e3);
  text-align: left;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ds-texto-atenuado);
  background: var(--ds-fondo-cabecera-tabla);
  border-bottom: 2px solid var(--ds-borde);
}

/* Altura de fila fija y uniforme, a propósito (CA8): la densidad de la
 * tabla se mide contando filas visibles sin desplazamiento, y esa medida
 * solo es honesta si ninguna fila crece por contenido largo sin control —
 * el texto que no cabe se recorta con elipsis en vez de estirar la fila.
 * Subida de 1.75rem a 2rem (corrección de revisión, probado con datos
 * reales): con 50 filas seguidas quedaba demasiado apretada para seguir
 * la línea — este es el nuevo piso, sin bajar la densidad ganada en la
 * compactación anterior ni tocar el tamaño de letra (0.85rem). */
.tablero-tabla__fila {
  height: 2.5rem;
}

.tablero-tabla__fila td {
  padding: 0 var(--ds-e3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px solid var(--ds-borde);
  font-size: 0.85rem;
}

/* Lectura por bloques: cada fila que pide atención lleva el tono de su
 * propia fase, no un genérico compartido — incidencia en cálido, anulado
 * en rojo muy tenue. Antes anulado e incidencia iban al revés de lo que
 * dice la etiqueta: anulado (rojo en el badge) salía gris, e incidencia
 * (naranja) salía en un ocre tan cargado que la fila entera se leía
 * naranja. */
.tablero-tabla__fila--incidencia {
  background: var(--ds-fila-incidencia);
}

.tablero-tabla__fila--anulado {
  background: var(--ds-fila-anulado);
}

/* Finalizada no lleva fondo, solo texto apagado. El gris de fondo anterior
 * funcionaba en una lista mezclada, pero al filtrar por "Finalizada" la
 * tabla ENTERA salía gris y parecía desactivada, no cerrada — una señal
 * que se aplica a todas las filas ha dejado de señalar nada. El texto
 * apagado dice lo mismo sin teñir la pantalla. El enlace hay que apagarlo
 * aparte: `a` fija su color por su cuenta y no lo hereda. */
.tablero-tabla__fila--finalizada {
  color: var(--ds-texto-atenuado);
}

.tablero-tabla__fila--finalizada a {
  color: var(--ds-texto-atenuado);
}

/* Hover: sombra semitransparente sobre la celda, no un color de fondo
 * propio. Un fondo opaco borraría el tono de incidencia o de anulado justo
 * en la fila que se está mirando; esto oscurece lo que ya hubiera y
 * funciona igual sobre blanco, sobre cálido y sobre rojo tenue, con una
 * regla en vez de una por variante. */
.tablero-tabla__fila:hover td {
  background-color: rgba(31, 35, 40, 0.05);
}

/* El cursor solo cambia donde de verdad se puede pulsar: la fila de "no
 * hay resultados" no lleva `data-href` y no debe parecer clicable. */
.tablero-tabla__fila[data-href] {
  cursor: pointer;
}

.tablero-tabla__fila--vacia td {
  color: var(--ds-texto-atenuado);
  white-space: normal;
  text-align: center;
}

/* Días a la derecha (diseño Stitch de referencia): son cantidades, y
 * alineadas a la derecha se comparan de un vistazo columna abajo — con
 * `tabular-nums` las cifras caen unas sobre otras. En rojo cuando superan
 * el umbral de su fase (`fila.parado`, decidido en `tablero.py`): así los
 * parados saltan a la vista sin buscarlos. El rojo se impone también en
 * las filas atenuadas, que si no lo apagarían. */
.tablero-tabla__dias {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.tablero-tabla__th--dias {
  text-align: right;
}

.tablero-tabla__fila td.tablero-tabla__dias--parado {
  color: var(--ds-error);
  font-weight: 700;
}

.tablero-tabla__dias-vacio {
  display: inline-block;
  width: 100%;
  height: 100%;
}

/* Recuento y paginación juntos al pie de la tabla (corrección de
 * revisión, diseño Stitch de referencia) — antes el recuento vivía
 * suelto encima de la tabla. */
.tablero-tabla__pie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-e3);
  margin-top: var(--ds-e2);
}

.tablero-tabla__recuento {
  margin: 0;
  font-size: 0.8rem;
  color: var(--ds-texto-atenuado);
}

/* Lo que la tabla NO enseña, al lado de lo que sí. Hereda el tamaño y el
 * tono del recuento: es la misma frase, no un aviso aparte. */
.tablero-tabla__ocultas {
  color: var(--ds-texto-atenuado);
}

.tablero-tabla__paginacion {
  display: flex;
  align-items: center;
  gap: var(--ds-e2);
  font-size: 0.85rem;
}

.tablero-tabla__paginacion-estado {
  color: var(--ds-texto-atenuado);
}

/* --- Pantalla de importación (issue #55) ------------------------------- */

.importacion {
  max-width: 720px;
  margin-top: var(--ds-e5);
}

.importacion__formulario {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e3);
  padding: var(--ds-e3);
  border: 1px solid var(--ds-borde);
  border-radius: var(--ds-radio);
  background: var(--ds-superficie);
}

.importacion__campo {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  font-size: var(--ds-tamano-secundario);
  color: var(--ds-texto-atenuado);
}

.importacion__acciones {
  display: flex;
  gap: var(--ds-e2);
}

/* El botón de contorno del proyecto: fondo de superficie y el acento en el
 * borde y el texto. El sólido es el modificador `--principal`, que es el
 * mismo botón de `.login__boton`. */
.importacion__boton {
  padding: var(--ds-e2) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: var(--ds-radio);
  background: var(--ds-superficie);
  color: var(--ds-azul);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--ds-transicion), color var(--ds-transicion);
}

.importacion__boton--principal {
  background: var(--ds-azul);
  color: var(--ds-sobre-oscuro-texto);
}

.importacion__boton--principal:hover {
  background: var(--ds-azul-oscuro);
  border-color: var(--ds-azul-oscuro);
}

/* El hover del de contorno NO invierte a sólido: al lado del principal,
 * dos botones sólidos dejan de decir cuál es la acción de la pantalla. */
.importacion__boton:hover {
  background: var(--ds-seleccion-fondo);
}

/* Deshabilitado gana al hover — si no, un botón en espera se ilumina al
 * pasar por encima y parece que sigue pulsable. */
.importacion__boton:disabled,
.importacion__boton:disabled:hover {
  opacity: 0.6;
  cursor: wait;
  background: var(--ds-superficie);
}

.importacion__boton--principal:disabled,
.importacion__boton--principal:disabled:hover {
  background: var(--ds-azul);
}

.importacion__progreso {
  margin-top: var(--ds-e2);
  color: var(--ds-texto-atenuado);
  font-style: italic;
}

.importacion__error {
  padding: var(--ds-e2) var(--ds-e3);
  margin-top: var(--ds-e3);
  border: 1px solid var(--ds-error);
  border-radius: var(--ds-radio);
  color: var(--ds-error);
  white-space: pre-wrap;
}

.importacion__resultado {
  margin-top: var(--ds-e5);
}

/* La píldora se queda en 999px: es una forma, no un radio de caja — el
 * mismo criterio que la etiqueta de fase del tablero. */
.importacion__estado {
  display: inline-block;
  padding: var(--ds-e1) var(--ds-e2);
  border-radius: 999px;
  background: var(--ds-fondo-app);
  border: 1px solid var(--ds-borde);
  font-size: var(--ds-tamano-secundario);
  margin-bottom: var(--ds-e3);
}

.importacion__contadores {
  display: flex;
  gap: var(--ds-e5);
  margin-bottom: var(--ds-e3);
  font-size: var(--ds-tamano-secundario);
}

.importacion__grupo {
  margin-bottom: var(--ds-e2);
}

.importacion__grupo-detalle {
  margin-left: var(--ds-e3);
  font-size: var(--ds-tamano-secundario);
  color: var(--ds-texto-atenuado);
}

/* --- Ficha de expediente (spec-05, issue #66) -------------------------- */

.ficha__barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-e3);
  margin-bottom: var(--ds-e3);
}

.ficha__volver {
  font-size: 0.85rem;
  text-decoration: none;
  color: var(--ds-texto-atenuado);
}

.ficha__volver:hover {
  color: var(--ds-azul);
}

/* "Ver hoja de trabajo" pedía más presencia (issue #79) — botón con
 * icono y borde marcado, no un enlace de texto que se confunde con
 * "← Volver al tablero". */
.ficha__hoja-trabajo {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-e1);
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: 4px;
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--ds-azul);
  background: var(--ds-superficie);
}

.ficha__hoja-trabajo:hover {
  color: var(--ds-superficie);
  background: var(--ds-azul);
}

/* Las puertas a documentos del expediente, agrupadas a la derecha de la
 * barra: `.ficha__barra` reparte con `space-between`, así que sin este
 * envoltorio un elemento suelto rompería el reparto.
 *
 * Ya no son «los imprimibles»: desde la R2b abre el grupo «Ver previo»,
 * que es una pantalla de trabajo y no un documento para imprimir. Lo que
 * comparten los tres es ser accesos a información del expediente, que es
 * justo lo que los separa del bloque de acción. Todos usan
 * `.ficha__hoja-trabajo` —el mismo botón perfilado— porque tienen el
 * mismo peso entre sí: ninguno es «el que toca». */
.ficha__documentos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ds-e2);
}

/* Deshabilitado y con el motivo al lado, no oculto: que no se pueda pedir
 * la carátula es información, y esconder el botón deja a quien la busca
 * pensando que la aplicación no la tiene. */
.ficha__hoja-trabajo--deshabilitada {
  border-color: var(--ds-borde);
  color: var(--ds-texto-atenuado);
  cursor: not-allowed;
}

.ficha__hoja-trabajo--deshabilitada:hover {
  color: var(--ds-texto-atenuado);
  background: var(--ds-superficie);
}

.ficha-estado__error {
  padding: var(--ds-e2) var(--ds-e3);
  margin-bottom: var(--ds-e3);
  border: 1px solid var(--ds-error);
  border-radius: var(--ds-radio);
  color: var(--ds-error);
}

/* Rediseño issue #79: hechos+documentos a la izquierda, anotaciones en
 * columna lateral a la derecha — antes todo apilado en una sola columna. */
/* EL LAYOUT DE DOS COLUMNAS SE RETIRÓ EN LA R5. Existía para dar sitio a
 * las anotaciones al lado de los hechos; ahora son una pestaña, y una
 * columna lateral vacía no es un layout, es un hueco. Con él se van
 * `.ficha-anotaciones-seccion` y su título: la lengüeta ya dice
 * «Anotaciones», y repetirlo dentro del panel sería el mismo rótulo dos
 * veces seguidas. */

/* --- Identidad y barra del circuito (revisión visual, R1) ------------- */

/* Dos líneas y se acabó: número y titular arriba, el resto abajo en tono
   tenue. Antes esto eran cinco datos en una fila y tres más en otra, y
   competían con lo único que hay que leer primero — dónde está el
   expediente y qué toca hacer. */
.ficha-identidad {
  margin-bottom: var(--ds-e3);
}

.ficha-identidad__principal {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--ds-e3);
}

.ficha-identidad__expediente {
  font-size: 1.35rem;
  font-weight: 700;
}

.ficha-identidad__titular {
  font-weight: 600;
}

.ficha-identidad__secundaria {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-e3);
  margin-top: var(--ds-e1);
  font-size: 0.85rem;
  color: var(--ds-texto-atenuado);
}

/* La fecha de firma se lee, no se busca. Comparte línea con la entidad,
   la finca y la gestoría —es un dato de identificación como ellos— pero
   en el color del texto y en negrita: es el único de esa línea que
   organiza el trabajo del día, y quien abre la ficha suele venir a por
   él. El resto de la línea sigue en tono tenue. */
.ficha-identidad__firma {
  color: var(--ds-texto);
  font-weight: 600;
}

.ficha-circuito {
  padding: var(--ds-e3) var(--ds-e5);
  margin-bottom: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
  /* Trece círculos no caben en pantallas estrechas, y partirlos en dos
     líneas rompe la lectura de izquierda a derecha que es el punto
     entero de la barra. Se desplaza en su propio contenedor: la página
     nunca se desplaza en horizontal. */
  overflow-x: auto;
}

.ficha-circuito__etapas {
  display: flex;
  align-items: flex-start;
  gap: var(--ds-e5);
  /* Trece círculos con su rótulo necesitan este ancho para que ninguno
     parta una palabra. Por debajo, la barra se desplaza dentro de su
     contenedor — ver `.ficha-circuito`. Partir «Esperando respuesta» en
     cuatro trozos es peor que obligar a desplazar: un rótulo cortado no
     se lee, solo se adivina. */
  min-width: 60rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* El ancho de cada etapa es proporcional a CUÁNTOS estados tiene, no
   igual para todas: con las cuatro etapas del dominio los grupos salen
   muy desiguales —dos círculos en Entrada, seis en Firma y cierre— y
   repartir a partes iguales apretaría seis en el mismo hueco que dos. */
.ficha-circuito__etapa {
  flex: var(--circulos, 1) 1 0;
  min-width: 0;
}

.ficha-circuito__etapa-titulo {
  display: block;
  margin-bottom: var(--ds-e2);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ds-texto-atenuado);
}

/* La etapa que contiene el estado actual, resaltada: es lo que sitúa de
   un vistazo en qué parte del proceso está el expediente antes de
   buscar el círculo concreto. */
.ficha-circuito__etapa--activa .ficha-circuito__etapa-titulo {
  color: var(--ds-azul);
}

.ficha-circuito__estados {
  display: flex;
  align-items: flex-start;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ficha-circuito__estado {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-items: center;
  gap: var(--ds-e1);
  min-width: 0;
  position: relative;
}

/* La línea que une un círculo con el siguiente. Va como pseudo-elemento
   y no como elemento propio para que la plantilla no tenga que saber
   cuál es el último de cada grupo. */
.ficha-circuito__estado:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 0.6rem;
  left: 50%;
  width: 100%;
  height: 1px;
  background: var(--ds-borde);
}

.ficha-circuito__marca {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.2rem;
  height: 1.2rem;
  border: 2px solid var(--ds-borde);
  border-radius: 50%;
  background: var(--ds-superficie);
  position: relative;
  z-index: 1;
}

/* La marca, más pequeña que el círculo que la contiene. Ya solo para
 * `.ds-lucide`: los SVG a mano cayeron con la zona 7 y `.icono` se retiró
 * con ellos. */
.ficha-circuito__marca .ds-lucide {
  width: 0.85rem;
  height: 0.85rem;
}

.ficha-circuito__nombre {
  font-size: 0.68rem;
  line-height: 1.25;
  text-align: center;
  color: var(--ds-texto-atenuado);
  /* NUNCA `overflow-wrap: anywhere`: partía «Esperando respuesta» en
     «Esperan / do / respuest / a». Las palabras se parten enteras o no se
     parten — un rótulo cortado a la mitad no se lee, se adivina, y
     entonces la abreviatura no habría servido de nada. */
  hyphens: none;
  overflow-wrap: normal;
}

/* El actual lleva el nombre ENTERO, así que necesita más sitio que los
   abreviados. Se le da con `flex`, no con un ancho fijo: el rótulo más
   largo cambia según dónde esté el expediente. */
.ficha-circuito__estado--actual {
  flex: 1.6 1 0;
}

.ficha-circuito__estado--cumplido .ficha-circuito__marca {
  border-color: var(--ds-texto-atenuado);
  color: var(--ds-texto-atenuado);
}

/* El actual: relleno y con el nombre entero, en negrita. Es el único
   círculo que hay que poder leer sin acercarse. */
.ficha-circuito__estado--actual .ficha-circuito__marca {
  border-color: var(--ds-azul);
  background: var(--ds-azul);
  box-shadow: 0 0 0 3px var(--ds-seleccion-fondo);
}

.ficha-circuito__estado--actual .ficha-circuito__nombre {
  font-weight: 700;
  color: var(--ds-azul);
}

.ficha-circuito__estado--pendiente .ficha-circuito__marca {
  border-color: var(--ds-borde);
}

.ficha-circuito__estado--pendiente .ficha-circuito__nombre {
  opacity: 0.6;
}

/* El anulado cae en la posición donde se anuló, no al principio ni al
   final: dice hasta dónde llegó el expediente antes de pararse, que es
   lo que ninguna lista de estados diría. */
.ficha-circuito__estado--anulado .ficha-circuito__marca {
  border-color: var(--ds-error);
  background: var(--ds-error-fondo);
  color: var(--ds-error);
}

.ficha-circuito__estado--anulado .ficha-circuito__nombre {
  font-weight: 700;
  color: var(--ds-error);
}

/* --- Aviso de salida y bloque de acción (revisión visual, R2a) -------- */

/* El aviso va ENCIMA del bloque, no en su lugar: una incidencia
   interrumpe sin bloquear, y debajo el bloque sigue ofreciendo lo que
   toque. Tono de aviso, no de bloqueo — el color lo pone el modificador. */
.ficha-aviso {
  display: flex;
  gap: var(--ds-e3);
  padding: var(--ds-e3);
  margin-bottom: var(--ds-e3);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.ficha-aviso--incidencia {
  border-color: var(--ds-aviso);
  background: var(--ds-aviso-fondo);
}

.ficha-aviso--anulado {
  border-color: var(--ds-error);
  background: var(--ds-error-fondo);
}

.ficha-aviso__icono {
  flex: 0 0 auto;
  line-height: 1;
}

.ficha-aviso--incidencia .ficha-aviso__icono {
  color: var(--ds-aviso);
}

.ficha-aviso--anulado .ficha-aviso__icono {
  color: var(--ds-error);
}

.ficha-aviso__cuerpo {
  min-width: 0;
}

.ficha-aviso__titulo {
  margin: 0;
  font-weight: 700;
}

.ficha-aviso--incidencia .ficha-aviso__titulo {
  color: var(--ds-aviso);
}

.ficha-aviso--anulado .ficha-aviso__titulo {
  color: var(--ds-error);
}

/* Las observaciones enteras y sin recortar: son obligatorias justo
   porque el motivo puede quedarse corto, así que truncarlas dejaría a la
   vista solo la parte que ya se sabía. */
.ficha-aviso__texto {
  margin: var(--ds-e1) 0 0;
}

.ficha-aviso__firma {
  margin: var(--ds-e2) 0 0;
  font-size: 0.8rem;
  color: var(--ds-texto-atenuado);
}

/* EL BLOQUE ES LO ÚNICO QUE DEBE DESTACAR. De ahí el borde izquierdo
   grueso y el fondo propio: en una pantalla donde todo lo demás son
   cajas blancas, esto tiene que ganar sin gritar. */
.ficha-accion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-e5);
  padding: var(--ds-e5);
  margin-bottom: var(--ds-e3);
  border: 1px solid var(--ds-borde);
  border-left: 4px solid var(--ds-azul);
  border-radius: 6px;
  background: var(--ds-seleccion-fondo);
}

.ficha-accion__titulo {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--ds-azul);
}

.ficha-accion__explicacion {
  margin: var(--ds-e1) 0 0;
  color: var(--ds-texto);
}

/* Terminado: en verde, y sin botón. El expediente está cerrado y la
   pantalla lo dice en el mismo sitio donde diría qué falta. */
.ficha-accion--cerrado {
  border-left-color: var(--ds-correcto);
  background: var(--ds-correcto-fondo);
}

.ficha-accion--cerrado .ficha-accion__titulo {
  color: var(--ds-correcto);
}

/* Esperando: sin acción NUESTRA. Tono neutro y no de alerta — la espera
   es parte del proceso, no un problema; el aviso de que se ha pasado del
   umbral lo da el tablero, que es donde se mira el conjunto. */
.ficha-accion--esperando {
  border-left-color: var(--ds-texto-atenuado);
  background: var(--ds-fondo-cabecera-tabla);
}

.ficha-accion--esperando .ficha-accion__titulo {
  color: var(--ds-texto);
}

/* Anulado: apagado del todo. No hay nada que hacer y la pantalla no debe
   invitar a buscarlo — el porqué está en el aviso de encima. */
.ficha-accion--sin_accion {
  border-left-color: var(--ds-borde);
  background: var(--ds-superficie);
  opacity: 0.7;
}

.ficha-accion--sin_accion .ficha-accion__titulo {
  color: var(--ds-texto-atenuado);
}

/* El botón (R2b). Sólido y en el acento: es LA acción de la pantalla, y
   compite con una lista de hechos llena de controles pequeños. Si se
   pareciera a ellos, no serviría de nada haberla separado.

   `white-space: nowrap` porque el bloque es flex y el texto de la
   explicación es largo: sin él, «Clasificar documentos» se parte en dos
   líneas y el botón queda más alto que ancho. */
.ficha-accion__boton {
  flex-shrink: 0;
  padding: var(--ds-e2) var(--ds-e5);
  border-radius: 6px;
  background: var(--ds-azul);
  color: var(--ds-superficie);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.ficha-accion__boton:hover,
.ficha-accion__boton:focus-visible {
  background: var(--ds-azul-oscuro);
  text-decoration: none;
}

/* El gesto (R2c): el formulario que registra desde el propio bloque.
   En columna y alineado al final para que el botón quede donde estaba el
   enlace — el bloque reparte con `space-between` y el gesto ocupa su
   mismo hueco, tenga campo o no. */
.ficha-accion__gesto {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--ds-e1);
  flex-shrink: 0;
}

.ficha-accion__hilo-etiqueta {
  font-size: 0.75rem;
  color: var(--ds-texto-atenuado);
}

/* «(opcional)» se dice y no se calla: el campo va dentro del gesto que
   registra el envío, y sin esta marca parecería un requisito para poder
   pulsarlo. Un peaje que obliga a inventarse un dato es una fábrica de
   datos falsos. */
.ficha-accion__opcional {
  font-style: italic;
}

.ficha-accion__hilo {
  min-width: 15rem;
  padding: var(--ds-e1) var(--ds-e2);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
  font-size: 0.85rem;
}

.ficha-accion__gesto .ficha-accion__boton {
  border: 0;
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
}

.ficha-cabecera {
  padding: var(--ds-e3);
  margin-bottom: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.ficha-cabecera__principal {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--ds-e3);
}

.ficha-cabecera__expediente {
  font-size: 1.1rem;
  font-weight: 700;
}

.ficha-cabecera__titular {
  font-weight: 600;
}

.ficha-cabecera__entidad,
.ficha-cabecera__fincas {
  color: var(--ds-texto-atenuado);
}

/* Color y borde vienen de `.fase-badge` (issue #72) — aquí solo el
 * tamaño de letra propio de la cabecera. */
.ficha-cabecera__fase {
  font-size: 0.85rem;
}

.ficha-cabecera__dias {
  margin-left: auto;
  font-size: 0.85rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ds-texto-atenuado);
}

/* Antes había además un párrafo de alerta repitiendo estos mismos días y
 * la misma fase (issue #79 corrección) — ahora el aviso vive aquí, como
 * color, no como texto duplicado. */
.ficha-cabecera__dias--parado {
  color: var(--ds-error);
}

/* Anulación e incidencia informadas se muestran junto a la fase, no como
 * fila de la lista de hechos (issue #79) — el registro de #80 (motivo
 * tipificado) extenderá este mismo bloque, sin cambiar dónde vive. */
.ficha-cabecera__salida {
  margin-top: var(--ds-e2);
  padding-top: var(--ds-e2);
  border-top: 1px dashed var(--ds-borde);
}

.ficha-cabecera__salida-texto {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ds-error);
}

/* Las observaciones de la anulación (spec-07 R11, rebanada 7). En su
   propia línea y en el tono tenue del resto de detalles: son obligatorias
   y pueden ser largas, así que compartir renglón con el motivo dejaría una
   línea que se lee mal. No se recortan — son lo que explica la anulación
   cuando el motivo no la cubre entera (D9: catálogo abierto), y truncarlas
   dejaría a la vista solo la parte que ya se sabía. */
/* La marca de la fila de un hecho heredado del circuito anterior
   (revisión de 2026-09-08). En tono tenue y pequeño, nunca de alerta: no
   ha fallado nada, es un dato que el expediente arrastra. Que se lea como
   aviso haría pensar que hay algo que corregir, y no lo hay. */
.ficha-hecho__heredado {
  margin-left: var(--ds-e1);
  padding: 0 0.35rem;
  border: 1px solid var(--ds-borde);
  border-radius: 3px;
  font-size: 0.7rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ds-texto-atenuado);
  white-space: nowrap;
}

.ficha-cabecera__salida-observaciones {
  display: block;
  margin-top: var(--ds-e1);
  font-size: 0.85rem;
  color: var(--ds-texto-atenuado);
}

/* Letra pequeña, a propósito (issue #66): previo de IN, gestoría y fecha
 * de entrada son identificadores de referencia, no lo primero que hay que
 * leer — la fase y los días en fase ya están arriba, en la fila principal. */
.ficha-cabecera__secundaria {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-e3);
  margin-top: var(--ds-e2);
  padding-top: var(--ds-e2);
  border-top: 1px solid var(--ds-borde);
  font-size: 0.75rem;
  color: var(--ds-texto-atenuado);
}

/* Lo primero que hay que ver (issue #66): antes que la cabecera visual,
 * arriba del todo del contenedor dinámico. */
.ficha-alertas {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  margin-bottom: var(--ds-e3);
}

.ficha-alertas__item {
  padding: var(--ds-e2) var(--ds-e3);
  border: 1px solid var(--ds-error);
  border-left-width: 4px;
  border-radius: 6px;
  background: var(--ds-superficie);
  color: var(--ds-error);
  font-size: 0.9rem;
}

/* Las observaciones son texto importado, no un aviso propio del sistema —
 * mismo lugar que la alerta de "parado" (es lo primero que hay que ver),
 * pero un tono neutro, no de alarma. */
.ficha-alertas__item--observaciones {
  border-color: var(--ds-borde);
  color: var(--ds-texto);
}

/* Preparación — los dos pasos de la etapa 2 (spec-07, rebanada 3).
 * Reutiliza el contenedor de `.ficha-hechos` (mismo panel, mismo título):
 * es la misma clase de bloque, y darle un aspecto propio haría parecer
 * que es otra cosa. Lo que cambia es la fila, que aquí tiene tres celdas
 * y no cuatro — estos pasos no tienen valor que corregir ni historial que
 * desplegar en línea. */
.ficha-preparacion {
  margin-bottom: var(--ds-e3);
  padding: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.ficha-preparacion__titulo {
  margin: 0 0 var(--ds-e2);
  font-size: 1rem;
}

.ficha-preparacion__lista {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ficha-preparacion__paso {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-e2);
  align-items: center;
}

.ficha-preparacion__etiqueta {
  flex: 1 1 12rem;
}

/* Cuándo y quién, en el tono secundario de los datos de cabecera: es
 * constancia, no la acción. */
.ficha-preparacion__constancia,
.ficha-preparacion__motivo {
  color: var(--ds-texto-atenuado);
  font-size: 0.875rem;
}

/* Mismo botón que el resto de acciones de formulario del proyecto
 * (`.previos-gestionar__boton`), sin inventar uno nuevo. */
.ficha-preparacion__accion {
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: 4px;
  background: var(--ds-azul);
  color: var(--ds-superficie);
  font-weight: 600;
  cursor: pointer;
}

/* Deshacer no es la acción principal: retira algo, no lo hace avanzar. */
.ficha-preparacion__accion--deshacer {
  border-color: var(--ds-borde);
  background: none;
  color: var(--ds-texto);
  font-weight: 400;
}

/* Apagado, y con el motivo en el `title` — nunca un botón gris a secas. */
.ficha-preparacion__accion--deshabilitada {
  display: inline-block;
  opacity: 0.5;
  cursor: not-allowed;
}

/* Envío — la etapa 3 (spec-07, rebanada 4). Mismo panel que preparación y
 * hechos: es la misma clase de bloque. */
.ficha-envio {
  margin-bottom: var(--ds-e3);
  padding: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.ficha-envio__titulo {
  margin: 0 0 var(--ds-e2);
  font-size: 1rem;
}

.ficha-envio__fechas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-e2);
  margin: 0 0 var(--ds-e1);
}

/* La del primer envío es la que mide la espera: se lee primero y con más
 * peso que la del último, que es contexto. */
.ficha-envio__fecha--primera {
  font-weight: 600;
}

.ficha-envio__fecha--ultima,
.ficha-envio__umbral,
.ficha-envio__fechas--sin-enviar,
.ficha-envio__hilo-solo-lectura {
  color: var(--ds-texto-atenuado);
  font-size: 0.875rem;
}

.ficha-envio__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-e2);
  margin-bottom: var(--ds-e2);
}

.ficha-envio__hilo {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-e1);
  align-items: center;
}

.ficha-envio__hilo input {
  flex: 1 1 18rem;
  padding: var(--ds-e1);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
}

.ficha-envio__accion {
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: 4px;
  background: var(--ds-azul);
  color: var(--ds-superficie);
  font-weight: 600;
  cursor: pointer;
}

/* Retirar y guardar el hilo no son la acción principal. */
.ficha-envio__accion--deshacer,
.ficha-envio__accion--hilo {
  border-color: var(--ds-borde);
  background: none;
  color: var(--ds-texto);
  font-weight: 400;
}

/* Retroceso — spec-07 R7, rebanada 5. Mismo panel que los demás bloques
 * de la ficha. */
.ficha-retroceso {
  margin-bottom: var(--ds-e3);
  padding: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.ficha-retroceso__titulo {
  margin: 0 0 var(--ds-e2);
  font-size: 1rem;
}

.ficha-retroceso__opciones {
  margin: 0 0 var(--ds-e2);
  padding: 0;
  border: none;
}

.ficha-retroceso__leyenda {
  padding: 0 0 var(--ds-e1);
  font-weight: 600;
}

/* Cada opción en bloque, con su detalle debajo: elegir mal la profundidad
 * es el fallo caro (R7), así que a dónde devuelve cada una se lee al
 * elegir, no de memoria. */
.ficha-retroceso__opcion {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 var(--ds-e1);
  margin-bottom: var(--ds-e2);
  cursor: pointer;
}

.ficha-retroceso__opcion-titulo {
  font-weight: 600;
}

.ficha-retroceso__opcion-detalle {
  grid-column: 2;
  color: var(--ds-texto-atenuado);
  font-size: 0.875rem;
}

.ficha-retroceso__accion {
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: 4px;
  background: var(--ds-azul);
  color: var(--ds-superficie);
  font-weight: 600;
  cursor: pointer;
}

/* Los dos botones del retroceso, juntos y con pesos distintos: el que
   registra manda, el que desmarca acompaña. */
.ficha-retroceso__botones {
  display: flex;
  align-items: center;
  gap: var(--ds-e2);
}

/* «Desmarcar» es una salida, no una acción: perfilado y en tono tenue
   para que no compita con el que registra — que es destructivo, y no debe
   tener un vecino del mismo peso al lado. */
.ficha-retroceso__limpiar {
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
  background: var(--ds-superficie);
  color: var(--ds-texto-atenuado);
  font-family: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.ficha-retroceso__limpiar:hover,
.ficha-retroceso__limpiar:focus-visible {
  color: var(--ds-texto);
  border-color: var(--ds-texto-atenuado);
}

.ficha-retroceso__historial {
  margin: var(--ds-e2) 0 0;
  padding: var(--ds-e2) 0 0;
  border-top: 1px dashed var(--ds-borde);
  list-style: none;
}

.ficha-retroceso__apunte {
  color: var(--ds-texto-atenuado);
  font-size: 0.875rem;
}

/* Obsoleto (spec-07 R8/D8): se distingue, no se esconde. Atenuado y con
 * una etiqueta, porque sigue siendo un documento válido para consultar —
 * lo que ya no es, es el vigente. */
.ficha-documentos__item--obsoleto .ficha-documentos__nombre {
  text-decoration: line-through;
  color: var(--ds-texto-atenuado);
}

.ficha-documentos__obsoleto {
  padding: 0 var(--ds-e1);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
  color: var(--ds-texto-atenuado);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ficha-hechos {
  padding: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.ficha-hechos__titulo {
  margin: 0 0 var(--ds-e2);
  font-size: 1rem;
}

.ficha-hechos__lista {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Anulación e incidencia son dos hechos más de la lista (issue #68/#79
 * corrección), separados del circuito principal por una línea, no sacados
 * de la lista al informarlas. */
.ficha-salidas:has(li) {
  margin-top: var(--ds-e3);
  padding-top: var(--ds-e2);
  border-top: 1px dashed var(--ds-borde);
}

/* Rejilla de cuatro columnas fijas (issue #79 corrección de alineación):
 * icono/etiqueta/valor/acciones, la misma anchura en toda la lista sea
 * cual sea el largo del contenido de cada fila. Los paneles de
 * historial/borrado (`.ficha-hecho__panel`, más abajo) son hijos DIRECTOS
 * de esta rejilla — `grid-column: 1 / -1` solo funciona en hijos
 * directos, nunca en algo anidado dentro de `.ficha-hecho__acciones` —
 * así se abren a ancho completo empujando lo que sigue hacia abajo, en
 * vez de quedar encajonados en la celda estrecha de acciones. */
.ficha-hecho {
  display: grid;
  grid-template-columns: 1.75rem minmax(9ch, 16ch) 1fr auto;
  align-items: center;
  gap: var(--ds-e2);
  padding: var(--ds-e2);
  border-radius: 4px;
  font-size: 0.9rem;
}

/* La fila "disponible ahora" — la única acción que toca dar ahora mismo —
 * lleva el borde de activa, como en la referencia de diseño (issue #79). */
.ficha-hecho--activa {
  border-left: 3px solid var(--ds-azul);
  background: var(--ds-fondo-app);
}

/* LOS SVG DIBUJADOS A MANO SE RETIRARON (zona 7 de la migración, issue
 * #186). `.icono` y sus cuatro variantes estilaban las nueve formas de
 * `_icono.html`, que se borró al pasar la ficha a Lucide — quedaban aquí
 * sin nadie a quien estilar.
 *
 * Se descubrieron al desglosar lo que faltaba por migrar y ver tres usos
 * de token viejo bajo una clase que ya no existía en ninguna plantilla.
 * Ver `.ds-lucide` en `sistema-visual.css`. */

/* Hechos que todavía no corresponden (ni informados ni el siguiente):
 * apagados, sin ningún control — ver la columna entera sin que compita
 * por atención con el que sí toca ahora mismo. */
.ficha-hecho--apagado {
  color: var(--ds-texto-atenuado);
  opacity: 0.6;
}

.ficha-hecho__icono-estado {
  display: flex;
  justify-content: center;
}

.ficha-hecho__etiqueta {
  font-weight: 600;
}

.ficha-hecho__valor-columna {
  display: flex;
  align-items: center;
  gap: var(--ds-e2);
  min-width: 0;
}

.ficha-hecho__valor {
  font-variant-numeric: tabular-nums;
}

.ficha-hecho__badge-disponible {
  padding: 0.15rem var(--ds-e2);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ds-azul) 12%, transparent);
  color: var(--ds-azul);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ficha-hecho__pendiente {
  color: var(--ds-texto-atenuado);
}

/* Issue #87: la formalizadora respondió algo distinto de "conforme" —
 * mismo tratamiento que `.ficha-hecho__badge-disponible`, con el color
 * de aviso en vez del de acento. */
.ficha-hecho__aviso {
  padding: 0.15rem var(--ds-e2);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ds-aviso) 12%, transparent);
  color: var(--ds-aviso);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ficha-hecho__boton-registrar {
  padding: var(--ds-e1) var(--ds-e2);
  border: 1px solid var(--ds-azul);
  border-radius: 4px;
  background: var(--ds-azul);
  color: var(--ds-superficie);
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
}

.ficha-hecho__input,
.ficha-hecho__select {
  padding: var(--ds-e1);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
  font: inherit;
  font-size: 0.85rem;
}

.ficha-hecho__form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-e1);
}

/* Corregir es tan frecuente como registrar (issue #66 review: corrección
 * de jerarquía) — mismo nivel de esfuerzo, un gesto en línea sin clic de
 * más. El formulario permanece oculto (issue #73) hasta que se pulsa el
 * icono de editar (issue #79: ya no el propio valor, un icono dedicado a
 * la derecha como el resto de acciones): `ficha-edicion.js` alterna
 * `--editando` en `.ficha-hecho__edicion`, nunca los dos a la vez. */
.ficha-hecho__edicion {
  display: flex;
  align-items: center;
  gap: var(--ds-e1);
  min-width: 0;
}

.ficha-hecho__form--corregir {
  display: none;
}

.ficha-hecho__edicion--editando .ficha-hecho__valor {
  display: none;
}

.ficha-hecho__edicion--editando .ficha-hecho__form--corregir {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-e1);
}

.ficha-hecho__boton-corregir {
  padding: var(--ds-e1) var(--ds-e2);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
  background: var(--ds-superficie);
  color: var(--ds-texto-atenuado);
  font-size: 0.8rem;
  cursor: pointer;
}

.ficha-hecho__boton-corregir:hover {
  color: var(--ds-azul);
  border-color: var(--ds-azul);
}

/* Iconos de acción (issue #79): sobrios hasta que se interactúa con
 * ellos (DESIGN.md: "solo mostrar color al interactuar") — la papelera es
 * la única excepción a propósito, siempre en rojo, para que se note antes
 * de pulsarla, no solo después. */
.ficha-hecho__acciones {
  display: flex;
  align-items: center;
  gap: var(--ds-e1);
  justify-self: end;
}

.ficha-hecho__boton-icono {
  display: inline-flex;
  padding: var(--ds-e1);
  border: none;
  border-radius: 4px;
  background: none;
  color: var(--ds-texto-atenuado);
  cursor: pointer;
  list-style: none;
}

.ficha-hecho__boton-icono::-webkit-details-marker {
  display: none;
}

.ficha-hecho__boton-icono:hover,
.ficha-hecho__boton-icono:focus-visible {
  color: var(--ds-azul);
  background: var(--ds-fondo-app);
}

.ficha-hecho__boton-icono--borrar,
.ficha-hecho__boton-icono--borrar:hover,
.ficha-hecho__boton-icono--borrar:focus-visible {
  color: var(--ds-error);
}

.ficha-hecho__boton-icono--borrar:hover,
.ficha-hecho__boton-icono--borrar:focus-visible {
  background: var(--ds-fondo-app);
}

/* El disparador (`<summary>`, dentro de `.ficha-hecho__acciones`) y el
 * panel visible son elementos distintos (issue #79): un `<details>`
 * anidado no puede ocupar su propia columna en la rejilla del `<li>`, así
 * que el panel vive aparte, como hijo directo de `.ficha-hecho`, y
 * `:has()` lo muestra según si su `<details>` — en otro lugar del árbol —
 * está abierto. Oculto por defecto: sin fila vacía cuando está cerrado. */
.ficha-hecho__panel {
  display: none;
  grid-column: 1 / -1;
  margin-top: var(--ds-e1);
  padding: var(--ds-e2) var(--ds-e3);
  background: var(--ds-fondo-app);
  border-top: 1px dashed var(--ds-borde);
  font-size: 0.85rem;
}

.ficha-hecho:has(.ficha-hecho__accion--historial[open]) .ficha-hecho__panel--historial {
  display: block;
}

.ficha-hecho:has(.ficha-hecho__accion--borrar[open]) .ficha-hecho__panel--borrar {
  display: block;
}

.ficha-hecho__borrar-aviso {
  margin: 0 0 var(--ds-e1);
  font-size: 0.8rem;
  color: var(--ds-error);
}

.ficha-hecho__borrar-boton {
  padding: var(--ds-e1) var(--ds-e2);
  border: 1px solid var(--ds-error);
  border-radius: 4px;
  background: var(--ds-superficie);
  color: var(--ds-error);
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
}

/* Historial en frase (issue #79): "Modificado por X el fecha · Valor
 * anterior: Y", una línea por cambio, más reciente primero — antes era
 * una lista de campos sueltos (autor, acción, fecha) sin leerse como
 * texto corrido. */
.ficha-historial__lista {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8rem;
  color: var(--ds-texto-atenuado);
  text-align: left;
  white-space: normal;
}

.ficha-historial__item {
  line-height: 1.5;
}

.ficha-historial__autor {
  font-weight: 600;
  color: var(--ds-texto);
}

.ficha-historial__dato {
  font-style: italic;
  color: var(--ds-texto);
}

.ficha-historial__vacio {
  font-size: 0.8rem;
  color: var(--ds-texto-atenuado);
}

/* Documentos como lista compacta con contador (issue #79) — antes un
 * párrafo de aviso. Desde B3 (ADR 0009) pinta documentos reales: la
 * lista pasa a ser vertical, una fila por documento con su nombre
 * enlazado a la descarga, porque ya no son cuatro etiquetas de tipo
 * sino ficheros con nombre largo. */
/* Sin caja propia desde la R5, igual que las anotaciones: la caja es el
 * panel de la pestaña. */
.ficha-documentos {
  padding: 0;
}

.ficha-documentos__titulo {
  margin: 0 0 var(--ds-e2);
  font-size: 1rem;
}

.ficha-documentos__lista {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ficha-documentos__item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--ds-e1) var(--ds-e2);
  padding: var(--ds-e1) 0;
  border-bottom: 1px solid var(--ds-borde);
  font-size: 0.85rem;
}

.ficha-documentos__item:last-child {
  border-bottom: none;
}

.ficha-documentos__nombre {
  font-weight: 600;
  color: var(--ds-azul);
}

.ficha-documentos__meta {
  color: var(--ds-texto-atenuado);
  font-size: 0.78rem;
}

/* «Sin clasificar» no es un error: es el estado normal de un documento
 * recién subido en esta rebanada, y no bloquea nada (issue #137). Por eso
 * va en el gris de lo secundario, no en el color de alerta. */
.ficha-documentos__sin-tipo {
  font-style: italic;
}

.ficha-documentos__vacio {
  padding: var(--ds-e1) 0;
  color: var(--ds-texto-atenuado);
  font-size: 0.85rem;
}

.ficha-documentos__form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-e2);
  margin-bottom: var(--ds-e3);
}

.ficha-documentos__fichero {
  flex: 1 1 16rem;
  min-width: 0;
  font-size: 0.85rem;
}

.ficha-documentos__boton {
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: 4px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ds-superficie);
  background: var(--ds-azul);
  cursor: pointer;
}

/* Ocupa la fila entera bajo el campo y el botón: es una aclaración, no
 * un tercer control que compita con ellos. */
.ficha-documentos__limites {
  flex-basis: 100%;
  margin: 0;
  color: var(--ds-texto-atenuado);
  font-size: 0.78rem;
}

/* El acuse de una tanda: un bloque, no dos avisos sueltos. El borde
 * común es lo que lo hace leer como un balance — dentro va el recuento,
 * luego lo que entró y al final lo que no. */
.ficha-documentos__acuse {
  margin: 0 0 var(--ds-e3);
  padding: var(--ds-e2);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
}

.ficha-documentos__balance {
  margin: 0 0 var(--ds-e2);
  font-size: 0.85rem;
  font-weight: 600;
}

.ficha-documentos__subidos {
  margin: 0 0 var(--ds-e2);
  padding-left: var(--ds-e5);
  color: var(--ds-correcto);
  font-size: 0.85rem;
}

.ficha-documentos__subidos li + li {
  margin-top: var(--ds-e1);
}

/* Dentro del acuse el error no lleva caja propia: la del acuse ya
 * agrupa, y una caja dentro de otra rompe el balance en dos avisos. */
.ficha-documentos__acuse .ficha-documentos__error {
  margin: 0;
  padding: 0 0 0 var(--ds-e5);
  border: none;
}

.ficha-documentos__error {
  margin: 0 0 var(--ds-e2);
  padding: var(--ds-e2) var(--ds-e2) var(--ds-e2) var(--ds-e5);
  border: 1px solid var(--ds-error);
  border-radius: 4px;
  color: var(--ds-error);
  font-size: 0.85rem;
}

.ficha-documentos__error li + li {
  margin-top: var(--ds-e1);
}

/* `.ficha-documentos__aviso` y `.ficha-documentos__contador` se retiraron
 * en la R5: el aviso de «quedan N sin clasificar» y el total del título se
 * fueron los dos a la lengüeta de la pestaña, donde se leen sin abrirla.
 * Ver `.ficha-pestanas__contador`. */

@media (max-width: 720px) {
  .ficha-hecho {
    grid-template-columns: 1.5rem minmax(8ch, 12ch) 1fr auto;
  }
}

/* --- Ficha de expediente — anotaciones (spec-05, issue #67) ------------ */

/* Sin caja propia desde la R5: la caja es el panel de la pestaña, y una
 * dentro de otra deja dos bordes a dos milímetros. */
.ficha-anotaciones {
  padding: 0;
}

.ficha-anotaciones__error {
  padding: var(--ds-e2) var(--ds-e3);
  margin-bottom: var(--ds-e2);
  border: 1px solid var(--ds-error);
  border-radius: 4px;
  color: var(--ds-error);
  font-size: 0.85rem;
}

.ficha-anotaciones__form {
  display: flex;
  gap: var(--ds-e2);
  margin-bottom: var(--ds-e3);
}

.ficha-anotaciones__textarea {
  flex: 1;
  padding: var(--ds-e2);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
  font: inherit;
  font-size: 0.85rem;
  resize: vertical;
}

.ficha-anotaciones__boton {
  align-self: flex-start;
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-azul);
  border-radius: 4px;
  background: var(--ds-azul);
  color: var(--ds-superficie);
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
}

.ficha-anotaciones__lista {
  display: flex;
  flex-direction: column;
  gap: var(--ds-e2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ficha-anotaciones__item {
  padding: var(--ds-e2);
  border-left: 3px solid var(--ds-borde);
  background: var(--ds-fondo-app);
}

.ficha-anotaciones__texto {
  margin: 0 0 var(--ds-e1);
  font-size: 0.9rem;
  white-space: pre-wrap;
}

.ficha-anotaciones__meta {
  margin: 0;
  font-size: 0.75rem;
  color: var(--ds-texto-atenuado);
}

.ficha-anotaciones__vacio {
  color: var(--ds-texto-atenuado);
  font-size: 0.85rem;
}

/* --- Ficha — Zona 5: ayuda de campos (issue #74) ----------------------- */

/* SOLO LA DEL PREVIO DESDE 2026-09-09. La ayuda de campos de la FICHA se
 * retiró —sus campos habían cambiado y vuelve rediseñada—, pero
 * `_previo_ayuda_campos.html` sigue en pie y usa estas mismas clases.
 * Borrarlas al retirar la otra la habría dejado sin estilo. */
.ficha-ayuda {
  margin-top: var(--espacio-4);
  padding: var(--espacio-3);
  background: var(--color-superficie);
  border: 1px solid var(--color-borde);
  border-radius: 6px;
  font-size: 0.85rem;
  color: var(--color-texto-tenue);
}

.ficha-ayuda__titulo {
  margin: 0 0 var(--espacio-3);
  font-size: 0.95rem;
  color: var(--color-texto);
}

.ficha-ayuda__lista {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--espacio-1) var(--espacio-3);
  margin: 0;
}

.ficha-ayuda__lista dt {
  font-weight: 600;
  color: var(--color-texto);
  white-space: nowrap;
}

.ficha-ayuda__lista dd {
  margin: 0 0 var(--espacio-2);
}

.ficha-ayuda__marcas {
  margin-top: var(--espacio-3);
  padding-top: var(--espacio-2);
  border-top: 1px dashed var(--color-borde);
}

.ficha-ayuda__marcas-titulo {
  margin: 0 0 var(--espacio-1);
  font-size: 0.85rem;
  color: var(--color-texto);
}

.ficha-ayuda__marcas p {
  margin: 0 0 var(--espacio-1);
}

/* El aviso de hipótesis no confirmada lleva el mismo tono que el resto de
 * avisos de la app (issue #74) — no es un error, pero tampoco un dato
 * cerrado, y debe notarse igual que "parado" o una incidencia abierta. */
.ficha-ayuda__marcas-aviso {
  color: var(--color-aviso);
}

@media (max-width: 640px) {
  .ficha-ayuda__lista {
    grid-template-columns: 1fr;
  }
}

/* --- Mensajes flash (issue #97) ----------------------------------------
 * `django.contrib.messages` estaba configurado pero sin usar en todo el
 * proyecto hasta la pantalla del previo: sin confirmación visible al
 * volver a la cola, alguien reabre el expediente para comprobar que se
 * guardó, y se pierde el ahorro de no escribir el correo. Vive en
 * `base.html`, así que cualquier pantalla futura la hereda gratis. */
/* Vacío no ocupa. El contenedor existe siempre —hace falta un `id` fijo
   al que apuntar el intercambio fuera de banda que lo limpia—, así que
   sin esto dejaría su `padding` en blanco en todas las páginas. */
.mensajes:empty {
  display: none;
}

.mensajes {
  list-style: none;
  margin: 0;
  padding: var(--ds-e3) var(--ds-e5) 0;
  display: flex;
  flex-direction: column;
  gap: var(--ds-e2);
}

.mensajes__item {
  padding: var(--ds-e2) var(--ds-e3);
  border-radius: var(--ds-radio);
  font-size: var(--ds-tamano-secundario);
}

/* Los tres estados llevan borde además del fondo. Los fondos del contrato
 * son mucho más lavados que los `--color-*-tenue` de los que vienen
 * (#F1F7F3 frente a #e6f3ea), y sin borde una confirmación sobre el fondo
 * de la aplicación se lee como un hueco en blanco y no como un aviso. El
 * correcto no tiene borde propio en el contrato: usa su color de texto,
 * que es lo mismo que hace el bloque de error de la ficha. */
.mensajes__item--success {
  background: var(--ds-correcto-fondo);
  border: 1px solid var(--ds-correcto);
  color: var(--ds-correcto);
}

.mensajes__item--error {
  background: var(--ds-error-fondo);
  border: 1px solid var(--ds-error-borde);
  color: var(--ds-error);
}

.mensajes__item--warning {
  background: var(--ds-aviso-fondo);
  border: 1px solid var(--ds-aviso-borde);
  color: var(--ds-aviso);
}

/* --- Previos: cola del previo (issue #97, rebanada 2/3) ----------------
 * Misma antigüedad-primero que el criterio de "quien más espera" del
 * tablero, pero aquí es literal por `fecha_entrada`, no por días en fase:
 * es la cola personal de un previo, no el circuito completo. */
.previos-lista__titulo {
  margin-bottom: var(--espacio-3);
}

.previos-lista__vacio {
  color: var(--color-texto-tenue);
}

/* Contención en tarjeta, homogénea con la ficha (issue #109): cada bloque
 * de contenido de la ficha es una caja con borde sobre el fondo de la
 * página (`.ficha-hechos`, `.ficha-documentos`) — las pantallas de
 * previos no lo tenían, y era la razón real de que se sintieran toscas,
 * más que cualquier diferencia de tipografía. */
.previos-lista__tarjeta {
  padding: var(--ds-e3);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 6px;
}

.previos-lista__tabla {
  width: 100%;
  border-collapse: collapse;
  background: var(--color-superficie);
}

.previos-lista__tabla th {
  padding: var(--espacio-2) var(--espacio-3);
  text-align: left;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-texto-tenue);
  background: var(--color-superficie-tenue);
  border-bottom: 2px solid var(--color-borde);
}

.previos-lista__tabla td {
  padding: var(--espacio-2) var(--espacio-3);
  border-bottom: 1px solid var(--color-borde);
  font-size: 0.85rem;
}

.previos-lista__estado {
  display: inline-flex;
  align-items: center;
  padding: var(--espacio-1) var(--espacio-2);
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  /* También se usa como enlace (ficha → previo, issue #104): sin
   * subrayado, el color de estado ya distingue que es interactivo. */
  text-decoration: none;
}

/* En el tablero la columna «Previo» es estrecha y el detalle es largo —el
 * motivo del bloqueo, o desde cuándo está reabierto—, así que metido
 * DENTRO de la píldora la sacaba de su celda y la montaba encima de «Días
 * en el estado actual»: medido en pantalla, 293 px de píldora en una celda
 * de 145. No lo trajo el estado reabierto, ya pasaba con «Bloqueado —
 * Falta la nota simple»; el texto nuevo solo lo hizo imposible de ignorar.
 *
 * Envolver el texto dentro de la píldora lo arreglaba y se veía peor: un
 * `border-radius` de 999px sobre cuatro líneas deja un globo. Así que aquí
 * la píldora lleva SOLO la etiqueta —que cabe— y el detalle va debajo, en
 * texto tenue. En «Mis previos» la columna es ancha y los dos caben en una
 * línea, que se lee mejor: por eso la excepción vive aquí y no en el
 * componente compartido. */
.tablero-previo {
  display: flex;
  flex-direction: column;
  gap: var(--espacio-1);
  align-items: start;
}

.tablero-previo__detalle {
  font-size: 0.75rem;
  line-height: 1.3;
  color: var(--color-texto-tenue);
  /* La celda de esta tabla es `nowrap` —lo hereda todo lo de dentro— y con
   * `table-layout: fixed` la columna no se ensancha para acomodarlo: el
   * detalle se salía y quedaba cortado a media fecha. Envolver es la única
   * salida que no le roba ancho a las demás columnas. */
  white-space: normal;
}

.previos-lista__estado--sin_empezar {
  background: var(--color-superficie-tenue);
  color: var(--color-texto-tenue);
}

.previos-lista__estado--completado {
  background: var(--color-exito-tenue);
  color: var(--color-exito);
}

.previos-lista__estado--bloqueado {
  background: var(--color-alerta-tenue);
  color: var(--color-alerta);
}

/* Reabierto: atención, pero no alarma. Usa el token de aviso —el mismo
 * ámbar que ya señala "mira esto" en el resto de la interfaz— y no el
 * rojo de bloqueado ni el verde de completado: un reabierto tiene una
 * corrección concreta esperando, pero nadie de fuera lo tiene atascado.
 * Con el rojo competiría con los bloqueados, que son lo urgente de
 * verdad, y una pantalla donde todo grita no señala nada. */
.previos-lista__estado--reabierto {
  background: var(--color-aviso-tenue);
  color: var(--color-aviso);
}

/* --- Previos: formulario de completar/bloquear/desbloquear ------------- */
.previos-formulario__volver {
  display: inline-block;
  margin-bottom: var(--espacio-3);
  font-size: 0.85rem;
  color: var(--color-texto-tenue);
}

.previos-formulario__titulo {
  margin-bottom: var(--espacio-1);
}

.previos-formulario__meta {
  margin: 0 0 var(--espacio-3);
  color: var(--color-texto-tenue);
  font-size: 0.9rem;
}

.previos-formulario__aviso-bloqueado {
  padding: var(--espacio-2) var(--espacio-3);
  margin-bottom: var(--espacio-3);
  border-radius: 4px;
  background: var(--color-alerta-tenue);
  color: var(--color-alerta);
  font-weight: 600;
}

/* Estado siempre visible arriba del formulario (revisión ciega del
 * manual, 2026-08-30) — mismo patrón que el aviso de bloqueado, con tono
 * propio para no competir visualmente con él. */
.previos-formulario__aviso-completado {
  padding: var(--espacio-2) var(--espacio-3);
  margin-bottom: var(--espacio-3);
  border-radius: 4px;
  background: var(--color-exito-tenue);
  color: var(--color-exito);
  font-weight: 600;
}

/* Por qué el previo está cerrado y cómo se reabre (spec-07 R17). Va
 * DENTRO del aviso de completado y no en un bloque aparte: es la misma
 * noticia —esto terminó— contada con una frase más, y separarla en dos
 * cajas haría que la explicación pareciera un aviso distinto.
 *
 * Pierde la negrita que hereda del contenedor y baja de tamaño: el
 * titular es «Completado», esto es la letra pequeña que lo explica. En
 * negrita competiría con él y se leerían los dos como alarma. */
.previos-formulario__motivo-cierre {
  margin: var(--espacio-1) 0 0;
  font-weight: 400;
  font-size: 0.85rem;
  line-height: 1.45;
}

/* Guion, no guion bajo: estos avisos siguen la convención de
 * `previos-formulario__*`, no la de las píldoras de estado. */
.previos-formulario__aviso-reabierto {
  padding: var(--espacio-2) var(--espacio-3);
  margin-bottom: var(--espacio-3);
  border-radius: 4px;
  background: var(--color-aviso-tenue);
  color: var(--color-aviso);
  font-weight: 600;
}

.previos-formulario__aviso-sin-empezar {
  padding: var(--espacio-2) var(--espacio-3);
  margin-bottom: var(--espacio-3);
  border-radius: 4px;
  background: var(--color-superficie-tenue);
  color: var(--color-texto-tenue);
  font-weight: 600;
}

.previos-formulario__error {
  padding: var(--espacio-2) var(--espacio-3);
  margin-bottom: var(--espacio-3);
  border: 1px solid var(--color-alerta);
  border-radius: 4px;
  color: var(--color-alerta);
}

.previos-formulario__form {
  display: flex;
  flex-direction: column;
  gap: var(--espacio-3);
  max-width: 40rem;
  padding: var(--espacio-3);
  background: var(--color-superficie);
  border: 1px solid var(--color-borde);
  border-radius: 6px;
}

.previos-formulario__campo {
  display: flex;
  flex-direction: column;
  gap: var(--espacio-1);
  font-size: 0.85rem;
  color: var(--color-texto-tenue);
}

.previos-formulario__campo input[type='text'],
.previos-formulario__campo input[type='number'],
.previos-formulario__campo textarea,
.previos-formulario__campo select {
  padding: var(--espacio-1) var(--espacio-2);
  border: 1px solid var(--color-borde);
  border-radius: 4px;
  font: inherit;
  color: var(--color-texto);
}

/* --- El previo cerrado se lee como DATO, no como formulario roto -------
 * (issue #206, defecto que introdujo la PR #202.)
 *
 * EL PROBLEMA NO ERA QUE NO SE VIERA, ERA QUE SE VEÍA MAL. Los campos
 * iban solo con `disabled`, y el gris que pone el navegador por su cuenta
 * —`rgba(239,239,239,.3)`, un 30 % de opacidad sobre blanco— deja una caja
 * con su borde, su fondo y su texto en negro que se lee como «este
 * formulario ha fallado», no como «esto está cerrado». Medido: fondo casi
 * imperceptible, texto `rgb(31,35,40)` y borde idéntico al de un campo
 * editable.
 *
 * LA SALIDA ES QUITAR EL FORMULARIO, NO APAGARLO. Un previo completado se
 * consulta —ese es su caso normal—, así que lo que hay que enseñar es el
 * DATO: sin caja, sin relleno lateral, alineado con su etiqueta. Lo que
 * queda es una ficha de lectura, que es lo que de verdad es.
 *
 * EL TEXTO NO SE ATENÚA. La tentación es bajarle el contraste para que
 * «parezca inactivo», y sería exactamente al revés de lo que hace falta:
 * el dato es lo único que se viene a leer aquí. Lo que se apaga es el
 * envoltorio.
 *
 * QUEDA UN BORDE INFERIOR, Y HACE FALTA. Sin ninguna marca, un campo
 * VACÍO desaparece del todo y no hay forma de distinguir «no se rellenó»
 * de «aquí no había campo». La línea dice dónde está el hueco sin
 * prometer que se pueda escribir en él.
 *
 * Zona `previos-*`, que NO está migrada al contrato: se usan sus tokens
 * (`--color-*`, `--espacio-*`) y no `--ds-*`, para no dejar una isla
 * incoherente que el guardián de zonas no vigila. */
.previos-formulario__campo input:disabled,
.previos-formulario__campo textarea:disabled,
.previos-formulario__campo select:disabled {
  padding-left: 0;
  padding-right: 0;
  border: none;
  border-bottom: 1px solid var(--color-borde);
  border-radius: 0;
  background: none;
  color: var(--color-texto);
  opacity: 1;
  cursor: default;
  /* Safari y iOS aclaran el texto de los controles inhabilitados por su
   * cuenta, y aquí el texto es justo lo que hay que poder leer. */
  -webkit-text-fill-color: var(--color-texto);
}

/* El textarea cerrado deja de ser una caja redimensionable: nadie va a
 * redimensionar algo que no se puede escribir, y el tirador de la esquina
 * es una invitación que no lleva a ninguna parte.
 *
 * Y SOBRE TODO DEJA DE OCUPAR LO QUE NO TIENE. Medido: `rows=10` son
 * 199px por campo, y los tres del previo —tracto, detalle de discrepancia
 * y observaciones— los ocupaban enteros aunque el texto fuese de una
 * línea, o aunque estuvieran VACÍOS. Casi seiscientos píxeles de hueco en
 * una pantalla que se abre para leer cuatro datos: el primer intento de
 * este arreglo quitó la caja y dejó el agujero donde estaba.
 *
 * `field-sizing: content` es lo que ajusta el alto a lo que hay. Donde
 * todavía no está (Firefox y Safari, a fecha de hoy) el campo se queda
 * como antes: sigue leyéndose como dato, solo que con el hueco. Es una
 * mejora que se degrada sin romper nada, no una que haga falta esperar.
 *
 * El `max-height` es para el caso contrario —un tracto largo de verdad—:
 * sin él, un campo podría empujar la columna hasta descuadrar las dos.
 * Con `auto` en el desbordamiento, la barra solo aparece si hace falta. */
.previos-formulario__campo textarea:disabled {
  resize: none;
  field-sizing: content;
  min-height: 1.5em;
  max-height: 14em;
  overflow-y: auto;
}

/* EL PLACEHOLDER SE CALLA EN CONSULTA, Y ESTO ES LO MÁS IMPORTANTE DE
 * TODO EL BLOQUE. Quitarle la caja al campo dejó los ejemplos leyéndose
 * como valores: «Discrepancia valor a: Ej: 105.177,00 € (certificado)»
 * sobre un campo VACÍO. Dentro de un recuadro, un texto gris se entiende
 * como sugerencia; sin recuadro, en una ficha que se abre justamente
 * para ver qué se anotó, se lee como el importe.
 *
 * El contraste no basta como defensa: gris sobre blanco sigue siendo un
 * texto en el sitio donde va el dato. Y el precio de equivocarse aquí no
 * es estético — es alguien leyendo una cifra que nadie escribió.
 *
 * Un campo vacío tiene que verse vacío. Su línea inferior ya dice que
 * ahí había un hueco, que es toda la información que hace falta. */
.previos-formulario__campo input:disabled::placeholder,
.previos-formulario__campo textarea:disabled::placeholder {
  color: transparent;
  /* **Y ESTA LÍNEA ES LA QUE DE VERDAD LO APAGA EN CHROME**, aunque
   * parezca redundante. Cuatro reglas más arriba, el campo cerrado lleva
   * `-webkit-text-fill-color` para que Safari no atenúe el dato; en los
   * navegadores de Blink esa propiedad GANA a `color` también dentro del
   * placeholder, así que el ejemplo se seguía pintando con el color del
   * texto mientras `getComputedStyle(::placeholder).color` respondía
   * `rgba(0,0,0,0)`.
   *
   * Se descubrió porque la CAPTURA y el DOM decían cosas distintas, y
   * mandó la captura: es lo que ve quien usa la pantalla. Medir el estilo
   * calculado habría dado por bueno un arreglo que no arreglaba nada. */
  -webkit-text-fill-color: transparent;
}

/* Las casillas SÍ se atenúan, y es la excepción que confirma la regla: su
 * dato es la marca, no un texto, y una casilla con el aspecto de siempre
 * pide que la pulses. Atenuarla dice «esto ya está decidido» sin esconder
 * si estaba marcada. */
.previos-formulario__campo--casillas input:disabled,
.previos-formulario__campo--casillas input:disabled + span,
.previos-formulario__campo--casillas label:has(input:disabled) {
  color: var(--color-texto-tenue);
  cursor: default;
}

.previos-formulario__campo--casillas {
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--espacio-3);
}

.previos-formulario__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--espacio-2);
}

.previos-formulario__boton-completar,
.previos-formulario__boton-bloquear,
.previos-formulario__boton-desbloquear,
.previos-formulario__completar-boton {
  padding: var(--espacio-2) var(--espacio-3);
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
}

/* El disparador es un `<summary>`, no un `<button>`: el gesto de dar el
 * previo por bueno se pide en dos pasos (issue #159), igual que el borrado
 * de un documento. `list-style: none` + `::-webkit-details-marker` porque
 * un `<summary>` trae su triángulo por defecto y aquí tiene que leerse
 * como el botón que era. `display: inline-block` para que el relleno de
 * arriba valga: un `summary` es `list-item` de serie. */
.previos-formulario__boton-completar {
  display: inline-block;
  border: 1px solid var(--color-acento);
  background: var(--color-acento);
  color: var(--color-superficie);
  list-style: none;
}

.previos-formulario__boton-completar::-webkit-details-marker {
  display: none;
}

/* ABIERTO, EL RENGLÓN ENTERO. El panel explica qué pasa al confirmar y no
 * cabe junto a «Bloquear»; dejándolo estrecho, el aviso quedaría en una
 * columna de tres palabras justo donde más falta hace leerlo. Mismo
 * criterio que `.ficha-pie:has(details[open])`. */
.previos-formulario__dar-por-bueno[open] {
  flex-basis: 100%;
}

.previos-formulario__panel-completar {
  margin-top: var(--espacio-2);
  padding: var(--espacio-3);
  border-radius: 4px;
  background: var(--color-alerta-tenue);
}

.previos-formulario__completar-aviso {
  margin: 0 0 var(--espacio-1);
  font-weight: 600;
}

/* La salida para quien solo quería guardar. En tono secundario a
 * propósito: lo primero que hay que leer es qué se está declarando, no la
 * alternativa. */
.previos-formulario__completar-detalle {
  margin: 0 0 var(--espacio-2);
  font-size: 0.8rem;
  color: var(--color-texto-tenue);
}

.previos-formulario__completar-boton {
  border: 1px solid var(--color-acento);
  background: var(--color-acento);
  color: var(--color-superficie);
}

/* La nota del número de previo: dice que ya no es obligatorio, justo
 * debajo de la casilla. Misma escala que el aviso de «bloquear no borra lo
 * escrito», que es el otro texto de esta pantalla que acompaña a un
 * control. */
.previos-formulario__nota-campo {
  margin: 0;
  font-size: 0.8rem;
  color: var(--color-texto-tenue);
}

.previos-formulario__boton-bloquear,
.previos-formulario__boton-desbloquear {
  border: 1px solid var(--color-alerta);
  background: var(--color-superficie);
  color: var(--color-alerta);
}

/* Requisito explícito del usuario: el mensaje de que bloquear no borra lo
 * escrito tiene que ser evidente junto al botón, no un tooltip escondido
 * — si alguien cree que va a perder el trabajo, no bloqueará y volverá a
 * avisar por correo. */
.previos-formulario__aviso-no-se-pierde {
  font-size: 0.8rem;
  color: var(--color-texto-tenue);
}

/* Django renderiza los errores de campo como `<ul class="errorlist">` sin
 * ningún estilo propio del navegador (revisión ciega del manual,
 * 2026-08-30) — "El motivo es obligatorio para bloquear" pasaba
 * inadvertido. Scoped a esta pantalla porque es la única que hoy renderiza
 * `{{ field.errors }}` de Django (verificado: `rg -rn '\.errors' templates/`). */
.previos-formulario__campo .errorlist {
  padding: var(--espacio-1) var(--espacio-2);
  margin: 0;
  list-style: none;
  border-radius: 4px;
  background: var(--color-alerta-tenue);
  color: var(--color-alerta);
  font-weight: 600;
}

/* --- Previos: pantalla del jefe de departamento (issue #97, rebanada
 * 3/3) — asignación en lote y estado del área, sustituto del Excel a
 * mano y el correo de aviso. Reutiliza `.previos-lista__tabla` para las
 * dos tablas (carga por previo, expedientes por asignar) en vez de
 * duplicar sus reglas. */
.previos-gestionar__titulo {
  margin-bottom: var(--espacio-3);
}

.previos-gestionar__error {
  padding: var(--espacio-2) var(--espacio-3);
  margin-bottom: var(--espacio-3);
  border-radius: 4px;
  background: var(--color-alerta-tenue);
  color: var(--color-alerta);
}

.previos-gestionar__seccion {
  margin-bottom: var(--espacio-5);
  padding: var(--espacio-3);
  background: var(--color-superficie);
  border: 1px solid var(--color-borde);
  border-radius: 6px;
}

.previos-gestionar__subtitulo {
  margin-bottom: var(--espacio-2);
  font-size: 1rem;
}

.previos-gestionar__resumen {
  margin: 0 0 var(--espacio-2);
}

.previos-gestionar__bloqueados {
  display: flex;
  flex-direction: column;
  gap: var(--espacio-1);
  padding-left: var(--espacio-3);
  color: var(--color-alerta);
}

.previos-gestionar__form {
  display: flex;
  flex-direction: column;
  gap: var(--espacio-3);
}

/* Separa la tabla + acciones de "Asignar a" (o el aviso de "sin
 * resultados") del bloque de filtros que la precede en
 * `previos_gestionar.html` (issue #97, corrección del 2026-08-27, punto
 * 4): filtrar qué se ve y actuar sobre lo seleccionado son dos cosas
 * conceptualmente distintas y deben leerse como tal, no pegadas una a la
 * otra. En el propio contenedor, no en `.previos-gestionar__form`, para
 * que la separación se mantenga también cuando no hay filas que mostrar.
 * Mismo criterio que `.tablero-tabla` con la Zona 3 del tablero. */
#tabla-previos-gestion {
  margin-top: var(--ds-e6);
}

.previos-gestionar__acciones {
  display: flex;
  align-items: center;
  gap: var(--espacio-2);
}

.previos-gestionar__select {
  padding: var(--espacio-1) var(--espacio-2);
  border: 1px solid var(--color-borde);
  border-radius: 4px;
}

.previos-gestionar__boton {
  padding: var(--espacio-1) var(--espacio-3);
  border: 1px solid var(--color-acento);
  border-radius: 4px;
  background: var(--color-acento);
  color: var(--color-superficie);
  font-weight: 600;
  cursor: pointer;
}

/* Selector duplicado arriba de la tabla (issue #97, punto 2b): separado
 * del borde superior de la tabla para que no se lea pegado a la cabecera
 * — el de abajo ya tiene ese margen porque sigue al `</table>`. */
.previos-gestionar__acciones--arriba {
  margin-bottom: var(--espacio-3);
}

/* Nombre del previo en la columna "Asignado" (issue #97, mejora d): texto
 * plano y tenue detrás de la etiqueta de estado — el usuario pidió que el
 * estado (bloqueado/completado/sin empezar) se note primero, el nombre
 * es la información secundaria. */
.previos-gestionar__asignado-a {
  display: block;
  margin-top: var(--espacio-2);
  font-size: 0.8rem;
  color: var(--color-texto-tenue);
}

/* ---------------------------------------------------------------------
   Pantalla del previo a dos columnas (#137a)

   Formulario a la izquierda, documento a la derecha. El reparto es
   proporcional (`fr`) y no en píxeles: en un monitor grande el visor se
   lleva el espacio de sobra, y en un portátil de 1366 sigue siendo
   legible sin que el formulario se estreche hasta romperse. El
   `minmax(0, ...)` es lo que impide que el `iframe` empuje la columna
   más allá de su parte — sin él, un PDF ancho desborda la rejilla.

   El visor se queda pegado arriba al desplazar el formulario: son once
   campos, y leer el certificado a la vez que se rellenan los últimos es
   justo el caso que motiva la pantalla.
   --------------------------------------------------------------------- */
.previo-layout {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: var(--espacio-4);
  align-items: start;
}

.previo-layout__documentos {
  position: sticky;
  top: var(--espacio-3);
}

@media (max-width: 1100px) {
  /* Una sola columna. No hace falta reordenar nada: el formulario ya va
     primero en el HTML, y en pantalla estrecha es lo que se viene a
     hacer — el visor no cunde ahí. Solo se suelta el pegado, que sin dos
     columnas no tiene sentido. */
  .previo-layout {
    grid-template-columns: 1fr;
  }

  .previo-layout__documentos {
    position: static;
  }
}

.previo-docs {
  background: var(--color-superficie);
  border: 1px solid var(--color-borde);
  border-radius: 6px;
  padding: var(--espacio-3);
}

.previo-docs__cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--espacio-2);
}

.previo-docs__titulo {
  margin: 0;
  font-size: 1rem;
}

.previo-docs__contador {
  font-weight: normal;
  color: var(--color-texto-tenue);
}

/* Una sola fila que se desplaza, no una rejilla que crece hacia abajo.
   Los nombres que manda SDOC son del tipo
   `Cancelaciones_c3b77a80_7631_4828_b3df_a18443afda1c.pdf`: con seis
   documentos y ajuste de línea, la tira ocupaba cuatro filas y echaba el
   visor fuera de la pantalla — justo lo que se viene a mirar. */
.previo-docs__lista {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--espacio-1);
  margin: 0 0 var(--espacio-2);
  padding: 0 0 var(--espacio-1);
  overflow-x: auto;
  list-style: none;
}

.previo-docs__pestana {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  gap: 2px;
  max-width: 14rem;
  padding: var(--espacio-1) var(--espacio-2);
  font: inherit;
  text-align: left;
  color: var(--color-texto);
  background: var(--color-superficie-tenue);
  border: 1px solid var(--color-borde);
  border-radius: 4px;
  cursor: pointer;
}

.previo-docs__pestana:hover {
  border-color: var(--color-acento);
}

.previo-docs__pestana[aria-current='true'] {
  background: var(--color-acento-tenue);
  border-color: var(--color-acento);
}

/* El nombre se recorta aquí y sale entero en la barra del visor: en la
   pestaña lo que hace falta es distinguir uno de otro, no leerlo. */
.previo-docs__pestana-nombre {
  overflow: hidden;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.previo-docs__pestana-tipo {
  font-size: 0.8rem;
  color: var(--color-texto-tenue);
}

.previo-docs__pestana-tipo--sin {
  color: var(--color-aviso);
}

.previo-docs__visor {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-borde);
  border-radius: 4px;
  overflow: hidden;
}

.previo-docs__barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espacio-2);
  padding: var(--espacio-1) var(--espacio-2);
  background: var(--color-superficie-tenue);
  border-bottom: 1px solid var(--color-borde);
}

.previo-docs__abierto {
  margin: 0;
  overflow: hidden;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.previo-docs__acciones {
  display: flex;
  flex-shrink: 0;
  gap: var(--espacio-2);
  align-items: center;
}

.previo-docs__ampliar {
  padding: var(--espacio-1) var(--espacio-2);
  font: inherit;
  color: var(--color-acento);
  background: var(--color-superficie);
  border: 1px solid var(--color-borde);
  border-radius: 4px;
  cursor: pointer;
}

.previo-docs__descargar {
  color: var(--color-acento);
}

/* Alto en `vh` y no en píxeles: el visor tiene que ocupar lo que dé la
   pantalla de cada uno. En un portátil de 1366x768 son unos 480px de
   documento, que es una página de A4 legible; en un monitor grande, más. */
.previo-docs__marco {
  width: 100%;
  height: 70vh;
  min-height: 380px;
  border: 0;
}

/* Ampliado: la ventana entera, para cuando el ancho de la columna se
   queda corto. No usa la API de pantalla completa del navegador a
   propósito — esa esconde la barra de direcciones y las pestañas, y se
   sale de ella con un gesto distinto en cada navegador. Esto es la misma
   página, se cierra con Escape o con el botón, y no sorprende. */
.previo-docs__visor--ampliado {
  position: fixed;
  inset: 0;
  z-index: 50;
  border-radius: 0;
  background: var(--color-superficie);
}

.previo-docs__visor--ampliado .previo-docs__marco {
  height: calc(100vh - 3rem);
}

.sin-desplazamiento {
  overflow: hidden;
}

/* El aviso de pendientes: visible, pero no una alarma. No bloquea nada
   —dejar documentos sin clasificar es un estado válido— así que va en el
   tono de aviso, no en el de error. */
.previo-docs__pendientes {
  margin: 0 0 var(--espacio-2);
  padding: var(--espacio-1) var(--espacio-2);
  color: var(--color-aviso);
  background: var(--color-aviso-tenue);
  border-radius: 4px;
}

/* Clasificar, entre la barra del visor y el documento: se decide el tipo
   leyendo, y el control tiene que estar donde está la mirada. */
.previo-docs__clasificar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espacio-2);
  align-items: center;
  padding: var(--espacio-2);
  background: var(--color-superficie);
  border-bottom: 1px solid var(--color-borde);
}

.previo-docs__clasificar-etiqueta {
  font-weight: 600;
}

.previo-docs__clasificar-selector {
  flex: 1 1 12rem;
  min-width: 0;
  padding: var(--espacio-1);
  font: inherit;
  border: 1px solid var(--color-borde);
  border-radius: 4px;
}

.previo-docs__clasificar-boton {
  padding: var(--espacio-1) var(--espacio-3);
  font: inherit;
  color: #fff;
  cursor: pointer;
  background: var(--color-acento);
  border: 1px solid var(--color-acento);
  border-radius: 4px;
}

.previo-docs__clasificar-noscript {
  flex-basis: 100%;
  color: var(--color-texto-tenue);
}

/* La subida, arriba y siempre visible: también con el expediente vacío,
   que hoy es el caso normal al abrir un previo. */
.previo-docs__subida {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espacio-2);
  align-items: center;
  margin-bottom: var(--espacio-3);
}

.previo-docs__limites {
  flex-basis: 100%;
  margin: 0;
  color: var(--color-texto-tenue);
}

/* El aviso de que está trabajando. `htmx-indicator` lo enseña HTMX
   mientras dura la petición: un zip con cinco escaneos tarda, y sin señal
   alguien pulsa otra vez y sube todo dos veces. */
.previo-docs__trabajando {
  color: var(--color-acento);
}

.previo-docs__trabajando.htmx-indicator {
  display: none;
}

.previo-docs__trabajando.htmx-request,
.htmx-request .previo-docs__trabajando {
  display: inline;
}

.previo-docs__subir:disabled {
  cursor: progress;
  opacity: 0.6;
}

.previo-docs__acuse-tanda {
  margin-bottom: var(--espacio-3);
  padding: var(--espacio-2);
  background: var(--color-superficie-tenue);
  border-radius: 4px;
}

.previo-docs__balance {
  margin: 0 0 var(--espacio-1);
  font-weight: 600;
}

.previo-docs__subidos,
.previo-docs__error {
  margin: 0;
  padding-left: var(--espacio-4);
}

.previo-docs__error {
  color: var(--color-alerta);
}

.previo-docs__vacio {
  padding: var(--espacio-4) var(--espacio-3);
  text-align: center;
  border: 1px dashed var(--color-borde);
  border-radius: 4px;
}

.previo-docs__vacio-titulo {
  margin: 0 0 var(--espacio-1);
  font-weight: 600;
}

.previo-docs__vacio-detalle {
  margin: 0 0 var(--espacio-3);
  color: var(--color-texto-tenue);
}

.previo-docs__vacio-enlace {
  color: var(--color-acento);
}

/* Una fila de documento con la misma forma que una de hechos (#79):
   estado, contenido, acciones. Así las dos listas de la ficha se leen
   igual y el mismo icono significa lo mismo en las dos. */
.ficha-documentos__item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--ds-e2);
  align-items: start;
  padding: var(--ds-e2) 0;
  border-bottom: 1px solid var(--ds-borde);
}

.ficha-documentos__principal {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.ficha-documentos__tipo {
  font-weight: 600;
}

.ficha-documentos__acciones {
  display: flex;
  gap: var(--ds-e1);
  align-items: center;
}

.ficha-documentos__boton-icono {
  display: inline-flex;
  padding: var(--ds-e1);
  color: var(--ds-texto-atenuado);
  cursor: pointer;
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
}

.ficha-documentos__boton-icono:hover {
  color: var(--ds-azul);
  border-color: var(--ds-borde);
}

/* Lo que todavía no existe (#142): se ve, dice por qué en el `title` y no
   responde. Un icono que reacciona al clic sin efecto se prueba dos veces
   y se da por roto. */
.ficha-documentos__boton-icono--futuro {
  color: var(--ds-borde);
  cursor: not-allowed;
}

.ficha-documentos__boton-icono--futuro:hover {
  color: var(--ds-borde);
  border-color: transparent;
}

/* El formulario de clasificar, oculto hasta pulsar el lápiz — mismo gesto
   y mismo script que corregir un hecho. */
.ficha-documentos__edicion {
  display: none;
  grid-column: 1 / -1;
}

.ficha-documentos__edicion--editando {
  display: block;
}

.ficha-documentos__acuse-clasificacion,
.previo-docs__acuse {
  margin: 0 0 var(--ds-e2);
  padding: var(--ds-e1) var(--ds-e2);
  color: var(--ds-correcto);
  background: var(--ds-correcto-fondo);
  border-radius: 4px;
}

.ficha-documentos__clasificar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-e2);
  align-items: center;
  margin-top: var(--ds-e1);
}

.ficha-documentos__clasificar-etiqueta {
  color: var(--ds-texto-atenuado);
}

.ficha-documentos__clasificar-selector {
  padding: var(--ds-e1);
  font: inherit;
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
}

.ficha-documentos__clasificar-boton {
  padding: var(--ds-e1) var(--ds-e2);
  font: inherit;
  color: var(--ds-azul);
  cursor: pointer;
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-radius: 4px;
}

.ficha-documentos__clasificar-noscript {
  color: var(--ds-texto-atenuado);
}

/* El acuse del borrado, en tono de aviso y no de error: no ha fallado
   nada, pero tampoco es una confirmación cualquiera. */
.ficha-documentos__acuse-borrado {
  margin: 0 0 var(--ds-e2);
  color: var(--ds-aviso);
}

/* Borrar un documento (#142b), con la misma jerarquía que borrar un hecho:
   el disparador es un `<summary>` dentro de la columna de acciones y el
   panel es hijo DIRECTO de la rejilla — `grid-column` solo afecta a hijos
   directos, no a nietos, así que el panel no puede vivir dentro de
   `__acciones`. Se despliega a ancho completo bajo la fila, empujando lo
   que sigue hacia abajo en vez de taparlo. */
.ficha-documentos__boton-icono--borrar:hover {
  color: var(--ds-error);
}

.ficha-documentos__panel-borrar {
  display: none;
  grid-column: 1 / -1;
  padding: var(--ds-e2);
  background: var(--ds-error-fondo);
  border-radius: 4px;
}

.ficha-documentos__item:has(.ficha-documentos__accion--borrar[open]) .ficha-documentos__panel-borrar {
  display: block;
}

.ficha-documentos__borrar-aviso {
  margin: 0 0 var(--ds-e1);
  font-weight: 600;
  color: var(--ds-error);
}

.ficha-documentos__borrar-detalle {
  margin: 0 0 var(--ds-e2);
  color: var(--ds-texto-atenuado);
}

.ficha-documentos__borrar-homonimo {
  margin: 0 0 var(--ds-e2);
  font-weight: 600;
  color: var(--ds-error);
}

.ficha-documentos__borrar-boton {
  padding: var(--ds-e1) var(--ds-e3);
  color: var(--ds-fondo-app);
  cursor: pointer;
  background: var(--ds-error);
  border: none;
  border-radius: 4px;
}

/* =====================================================================
 * EL PIE DE LA FICHA — ZONA 1 DE LA MIGRACIÓN AL CONTRATO (issue #186)
 *
 * Primera zona migrada, y por eso lleva escrito el patrón que siguen las
 * demás. Se eligió la más pequeña que existe —diez usos, nueve reglas, con
 * tests de navegador ya escritos— porque en la primera de una serie es
 * donde se descubre lo que no se había previsto, y es mejor descubrirlo
 * aquí que en la barra que sale en todas las pantallas.
 *
 * LA REGLA DE LA MIGRACIÓN: al terminar una zona no puede quedar dentro
 * ni un `--color-*` ni un `--espacio-*`. Si queda, no se ha migrado: se ha
 * añadido una capa encima. Lo comprueba `test_migracion_por_zonas.py`, que
 * lee este fichero y falla solo — no depende de que nadie se acuerde.
 *
 * QUÉ CAMBIA ADEMÁS DE LOS TOKENS. La migración no es un cambia-nombres:
 * el contrato trae reglas que esta zona no cumplía.
 *   - CADA CONTROL AL COLOR DE SU CONSECUENCIA. Antes los dos enlaces se
 *     oscurecían y se subrayaban igual: el mismo gesto para marcar una
 *     incidencia que para anular el expediente. Ahora incidencia se tiñe
 *     de ámbar y anular de rojo, y el color avisa ANTES de pulsar.
 *   - ICONO CON SIGNIFICADO. Los dos llevan icono de tamaño «aviso»
 *     (16px), que es lo que son: no decoran, dicen de qué familia es cada
 *     control antes de leerlo.
 *   - EL SUBRAYADO SE RETIRA. Con el color haciendo el trabajo, subrayar
 *     además es decir lo mismo dos veces — y el subrayado no distinguía
 *     las dos consecuencias, que es justo lo que había que distinguir.
 * ===================================================================== */

/* `:has(details)` para desaparecer entera cuando ninguna de las dos se
 * pinta — el `<footer>` sigue en el HTML aunque esté vacío (es el ancla
 * del intercambio fuera de banda), y sin esto quedaría una franja con su
 * línea de separación y nada dentro. Mismo criterio que
 * `.ficha-salidas:has(li)`.
 *
 * Al pie y a la derecha, fuera del recorrido de lectura: la columna de
 * hechos se lee de arriba abajo por la izquierda, y estas dos no son un
 * paso de ese recorrido. Se encuentran cuando se buscan, que es la única
 * vez que hacen falta. */
.ficha-pie:has(details) {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: var(--ds-e3);
  margin-top: var(--ds-e5);
  padding-top: var(--ds-e2);
  border-top: 1px solid var(--ds-borde);
}

/* El separador entre las dos, puesto por CSS y no escrito en la
 * plantilla: con un «·» literal entre ellas, ocultar una por permisos
 * dejaría el punto colgando al principio de la que quede. Aquí solo
 * existe cuando de verdad hay dos. */
.ficha-pie__salida + .ficha-pie__salida::before {
  content: '·';
  margin-right: var(--ds-e3);
  color: var(--ds-texto-inactivo);
}

/* Aspecto de enlace, nunca de botón (R4): un botón propone, y nadie abre
 * una ficha con intención de anular el expediente.
 *
 * `list-style: none` + `::-webkit-details-marker` porque un `<summary>`
 * trae su triángulo por defecto, y aquí tiene que leerse como un enlace.
 *
 * El color y el hover los pone `.ds-consecuencia--*` desde el contrato,
 * no esta clase: son los mismos tres tonos que usan las demás zonas, y
 * repetirlos aquí sería tener dos sitios donde cambiarlos. */
.ficha-pie__enlace {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-e1);
  font-size: var(--ds-tamano-secundario);
  cursor: pointer;
  list-style: none;
}

.ficha-pie__enlace::-webkit-details-marker {
  display: none;
}

/* ABIERTO, CADA UNO A SU RENGLÓN. La anulación pide tres campos (fecha,
 * motivo y observaciones) y no caben junto al otro enlace en la misma
 * línea. Se le da el renglón entero al que está abierto — y también al
 * otro, porque si solo uno rompe la línea el que queda arriba se separa
 * del suyo y los dos parecen de sitios distintos. */
.ficha-pie:has(details[open]) .ficha-pie__salida {
  flex-basis: 100%;
  text-align: right;
}

/* Y EL SEPARADOR SE VA CON ELLOS. El «·» lo pone el hermano siguiente en
 * el DOM, que en cuanto hay dos renglones ya no está al lado de nada: se
 * quedaba colgando al principio de la segunda línea, como si faltara algo
 * delante. */
.ficha-pie:has(details[open]) .ficha-pie__salida + .ficha-pie__salida::before {
  content: none;
}

/* Las observaciones de la anulación, con sitio para leerse. Heredaban el
 * ancho estrecho de `.ficha-hecho__input`, pensado para una fecha, y el
 * propio rótulo «Observaciones (obligatorias)» se cortaba a media
 * palabra: un campo obligatorio que no puede decir que lo es. Aquí hay
 * renglón entero, así que se le da. */
.ficha-pie__form input[name='observaciones'] {
  flex: 1 1 22ch;
  min-width: 22ch;
}

.ficha-pie__form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ds-e2);
  margin-top: var(--ds-e2);
}

/* El botón de confirmar SÍ es un botón, y en tono de alerta: para entonces
 * ya no se está ofreciendo nada — quien ha abierto el formulario y ha
 * rellenado los tres campos ha decidido. Mismo criterio que el de
 * confirmar borrado. */
.ficha-pie__boton {
  padding: var(--ds-e1) var(--ds-e3);
  border: 1px solid var(--ds-error);
  border-radius: var(--ds-radio);
  background: transparent;
  font-size: var(--ds-tamano-secundario);
  color: var(--ds-error);
  cursor: pointer;
}

.ficha-pie__boton:hover,
.ficha-pie__boton:focus-visible {
  background: var(--ds-error);
  color: var(--ds-superficie);
}

/* =====================================================================
 * LAS DOS PESTAÑAS — ZONA 2 DE LA MIGRACIÓN AL CONTRATO (issue #186)
 *
 * Documentos y anotaciones dejan de competir por la pantalla (R5). Antes
 * vivían en dos columnas a la vez —los documentos abajo a la izquierda,
 * las anotaciones en una barra lateral—, y las dos pedían sitio siempre
 * aunque casi nunca se necesiten las dos a la vez.
 *
 * QUÉ TRAE EL CONTRATO ADEMÁS DE LOS TOKENS:
 *   - EL CONTADOR PASA A SER UNA PÍLDORA. Era un número suelto en gris al
 *     lado del rótulo, y se leía como parte del nombre de la pestaña
 *     —«Documentos 5» parecía un título—. Con fondo propio se lee como lo
 *     que es: un recuento que acompaña, no una palabra más.
 *   - Y LA PÍLDORA CAMBIA CON LA PESTAÑA. En la abierta va en azul sobre
 *     azul al 10 %; en las cerradas, gris sobre gris. Así el contador de
 *     la pestaña que no estás mirando no compite con el de la que sí.
 *   - El foco de la lengüeta usa `--ds-foco`, el mismo anillo que el
 *     resto de la aplicación, en vez de un `outline` propio.
 * ===================================================================== */
.ficha-pestanas {
  margin-top: var(--ds-e5);
}

/* EL RADIO SE ESCONDE, PERO NO SE QUITA. `display: none` lo sacaría del
 * orden de tabulación y las pestañas dejarían de poder cambiarse con el
 * teclado — que es como se mueve quien no usa el ratón, y como las
 * cambian las flechas dentro de un grupo de radios. Se aparta de la vista
 * sin salir del documento. */
.ficha-pestanas__radio {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.ficha-pestanas__lenguetas {
  display: flex;
  gap: var(--ds-e1);
  border-bottom: 1px solid var(--ds-borde);
}

/* La lengüeta apagada: es una puerta que no está abierta, no un botón que
 * pida que lo pulsen. El borde inferior transparente —y no ausente— para
 * que al activarse no se mueva un píxel: un cambio de grosor aquí empuja
 * el panel entero hacia abajo cada vez que se cambia de pestaña. */
.ficha-pestanas__lengueta {
  display: flex;
  align-items: baseline;
  gap: var(--ds-e2);
  padding: var(--ds-e3) var(--ds-e4);
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font-size: var(--ds-tamano-secundario);
  font-weight: 500;
  color: var(--ds-texto-atenuado);
  cursor: pointer;
}

.ficha-pestanas__lengueta:hover {
  color: var(--ds-texto);
}

/* El foco se pinta SOBRE LA LENGÜETA aunque lo reciba el radio, que está
 * escondido: sin esto, quien navega con el teclado cambia de pestaña sin
 * ver dónde está. `~` porque los dos radios son hermanos anteriores de la
 * barra de lengüetas.
 *
 * `--ds-foco` y no un `outline` propio: es el mismo anillo que el resto
 * de la aplicación, y tenerlo escrito en dos sitios es tener dos sitios
 * donde cambiarlo. */
#pestana-documentos:focus-visible ~ .ficha-pestanas__lenguetas [for='pestana-documentos'],
#pestana-anotaciones:focus-visible ~ .ficha-pestanas__lenguetas [for='pestana-anotaciones'] {
  outline: none;
  box-shadow: var(--ds-foco);
  border-radius: var(--ds-radio);
}

#pestana-documentos:checked ~ .ficha-pestanas__lenguetas [for='pestana-documentos'],
#pestana-anotaciones:checked ~ .ficha-pestanas__lenguetas [for='pestana-anotaciones'] {
  border-bottom-color: var(--ds-azul);
  color: var(--ds-azul-oscuro);
}

/* EL CONTADOR ES UNA PÍLDORA, no un número suelto. Con el número a secas
 * al lado del rótulo, «Documentos 5» se leía como un título; con fondo
 * propio se lee como lo que es, un recuento que acompaña.
 *
 * Redondo del todo (`999px`) y no `--ds-radio`: es la única excepción al
 * radio único de la aplicación, y es la misma que ya tenía el avatar —
 * una píldora con esquinas de 2px se lee como un botón diminuto. */
.ficha-pestanas__contador {
  padding: 1px var(--ds-e2);
  border-radius: 999px;
  background: var(--ds-fondo-app);
  font-size: var(--ds-texto-rotulo);
  font-weight: 500;
  color: var(--ds-texto-atenuado);
  /* Cifras de ancho fijo: sin esto, pasar de 9 a 10 documentos mueve la
     lengüeta de al lado. */
  font-variant-numeric: tabular-nums;
}

/* La de la pestaña ABIERTA se tiñe de azul. El contador de la pestaña que
 * no estás mirando no debe competir con el de la que sí.
 *
 * `:not(--urgente)` Y NO UNA REGLA MÁS ESPECÍFICA DESPUÉS. Sin esto, este
 * selector —un id y tres clases— le gana al `--urgente` de abajo, y
 * «2 sin clasificar» salía en azul en vez de en ámbar: se veía en la
 * captura, y perseguirlo subiendo la especificidad del otro habría dejado
 * dos reglas peleándose por el mismo elemento. Dicho así, la excepción se
 * lee donde está la regla. */
#pestana-documentos:checked ~ .ficha-pestanas__lenguetas [for='pestana-documentos'] .ficha-pestanas__contador:not(.ficha-pestanas__contador--urgente),
#pestana-anotaciones:checked ~ .ficha-pestanas__lenguetas [for='pestana-anotaciones'] .ficha-pestanas__contador:not(.ficha-pestanas__contador--urgente) {
  background: var(--ds-seleccion-fondo);
  color: var(--ds-azul);
}

/* SALVO CUANDO DICE QUE QUEDA TRABAJO. «2 sin clasificar» es lo único de
 * esta barra que pide que alguien haga algo, y en el mismo gris que el
 * total no se distinguiría de él — que es justo la diferencia que el
 * contador existe para marcar. Manda sobre el azul de la pestaña abierta:
 * lo pendiente se dice esté la pestaña donde esté.
 *
 * `--ds-aviso` Y NO `--ds-error`: sin clasificar es un estado válido y no
 * bloquea nada. En rojo diría que algo ha fallado, y no ha fallado nada:
 * hay trabajo pendiente, que es otra cosa. */
.ficha-pestanas__contador--urgente {
  background: var(--ds-aviso-fondo);
  color: var(--ds-aviso);
}

/* Vacío no ocupa: sin nada que contar, la lengüeta va sola y el `gap` de
 * la lengüeta no debe dejar un hueco detrás del nombre. */
.ficha-pestanas__contador:empty {
  display: none;
}

/* El panel: una caja sola, la de la pestaña. Los dos paneles de dentro
 * (`.ficha-documentos`, `.ficha-anotaciones`) perdieron la suya en la R5
 * para no dejar dos bordes a dos milímetros. */
.ficha-pestanas__panel {
  display: none;
  padding: var(--ds-e4);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borde);
  border-top: none;
  border-radius: 0 0 var(--ds-radio) var(--ds-radio);
}

#pestana-documentos:checked ~ .ficha-pestanas__panel--documentos,
#pestana-anotaciones:checked ~ .ficha-pestanas__panel--anotaciones {
  display: block;
}

/* --- Carátula no disponible (issue #204) -------------------------------
 * La respuesta cuando se fuerza la URL de una carátula que no procede.
 * Antes era un 404; ahora es una página que dice por qué.
 *
 * ZONA NUEVA, ASÍ QUE NACE EN EL CONTRATO (`--ds-*`) y no en los tokens
 * viejos: lo que se migra por zonas es lo que ya existía. Empezar algo
 * nuevo en el sistema antiguo sería crear deuda a propósito. Va en
 * `ZONAS_MIGRADAS` desde el primer día. */
.caratula-no-disponible {
  max-width: 640px;
  margin-top: var(--ds-e5);
}

.caratula-no-disponible__titulo {
  margin: var(--ds-e4) 0 var(--ds-e3);
  font-size: var(--ds-texto-titulo);
  color: var(--ds-texto);
}

/* El motivo es lo que se viene a leer aquí, así que es lo que más pesa
 * de la página — por eso va a tamaño de texto destacado y no de cuerpo. */
.caratula-no-disponible__motivo {
  margin: 0 0 var(--ds-e4);
  font-size: var(--ds-texto-destacado);
  line-height: 1.5;
  color: var(--ds-texto);
}

.caratula-no-disponible__expediente {
  margin: 0;
  font-size: var(--ds-tamano-secundario);
  color: var(--ds-texto-atenuado);
}

/* ---------------------------------------------------------------------------
 * Las fincas del expediente, editables desde el previo (spec-08 §4.3).
 *
 * Va debajo del formulario del previo y comparte su columna, así que hereda
 * su ancho. No se pega arriba como la de documentos: no se consulta mientras
 * se rellenan los campos de al lado, se toca cuando la importación troceó mal.
 * ------------------------------------------------------------------------ */
.previo-fincas {
  margin-top: var(--espacio-4);
  padding: var(--espacio-3);
  border: 1px solid var(--color-borde);
  border-radius: 4px;
}

.previo-fincas__cabecera {
  margin-bottom: var(--espacio-2);
}

.previo-fincas__titulo {
  margin: 0;
  font-size: 1rem;
}

.previo-fincas__contador {
  color: var(--color-texto-tenue);
  font-weight: 400;
}

/* EL AVISO NO ES DECORACIÓN. Es la única parte de esta pantalla que se
 * comporta distinta al resto del previo —se guarda al pulsar, no al
 * completar—, así que se lee antes de actuar, no después. */
.previo-fincas__al-momento {
  margin: 0 0 var(--espacio-3);
  color: var(--color-texto-tenue);
  font-size: 0.9rem;
}

.previo-fincas__acuse {
  margin: 0 0 var(--espacio-2);
  color: var(--color-exito);
}

.previo-fincas__error {
  margin: 0 0 var(--espacio-2);
  color: var(--color-alerta);
}

.previo-fincas__lista {
  margin: 0 0 var(--espacio-3);
  padding: 0;
  list-style: none;
}

.previo-fincas__fila + .previo-fincas__fila {
  margin-top: var(--espacio-2);
}

/* CADA FINCA ES UNA FICHA, no una línea: desde la rebanada 3 lleva cinco
 * campos —identificador, domicilio, población, código postal y registro— y
 * en una fila sola quedarían ilegibles en la columna estrecha del previo.
 * Rejilla que se reacomoda: los campos declaran cuánto quieren y el
 * navegador decide cuántos caben. */
.previo-fincas__editar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--espacio-2);
  align-items: end;
  padding: var(--espacio-2);
  border: 1px solid var(--color-borde);
  border-radius: 4px;
}

.previo-fincas__orden {
  grid-column: 1 / -1;
  margin: 0;
  font-weight: 600;
}

.previo-fincas__alta {
  display: flex;
  gap: var(--espacio-2);
  align-items: end;
  flex-wrap: wrap;
}

.previo-fincas__campo {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.previo-fincas__campo--ancho {
  grid-column: span 2;
}

.previo-fincas__campo--corto {
  max-width: 8rem;
}

.previo-fincas__campo label {
  color: var(--color-texto-tenue);
  font-size: 0.85rem;
}

.previo-fincas__campo input {
  min-width: 0;
}

/* Los dos botones, juntos y en su propia línea de la rejilla: pegados al
 * último campo se leerían como parte de él. */
.previo-fincas__botones {
  grid-column: 1 / -1;
  display: flex;
  gap: var(--espacio-2);
}

.previo-fincas__nota-alta {
  margin: var(--espacio-1) 0 0;
  color: var(--color-texto-tenue);
  font-size: 0.85rem;
}

.previo-fincas__vacio {
  margin: 0 0 var(--espacio-3);
  padding: var(--espacio-3);
  color: var(--color-texto-tenue);
  text-align: center;
  border: 1px dashed var(--color-borde);
  border-radius: 4px;
}

.previo-fincas__cerrado {
  margin: 0;
  color: var(--color-texto-tenue);
  font-size: 0.9rem;
}
