/*
  Layout compartido por toda página de listado con tabla (Clientes, Empresas,
  Centros, Trabajadores, ...). Ver Project-Hydra-Negocio/tecnico/CODING_STANDARDS.md: una vez un patrón se
  repite en un segundo módulo, se extrae en vez de duplicarse por página.
*/

.cabecera-pagina {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-6);
}

.cabecera-pagina .titulo-pagina {
    margin-bottom: 0;
}

.acciones-cabecera {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

.enlace-exportar {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font: var(--font-label-md);
    color: var(--color-text-muted);
    text-decoration: none;
}

.enlace-exportar:hover {
    color: var(--color-text);
    text-decoration: underline;
}

.barra-filtros {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    margin-bottom: var(--space-4);
    max-width: 480px;
}

.barra-filtros .campo {
    flex: 1;
}

/* Un botón de la barra (p. ej. «Guardar filtro» en Documentos) no se encoge por flex ni parte su
   rótulo: con max-width 480px y varios campos flex:1, el botón quedaba en «rdar f». */
.barra-filtros > button {
    flex-shrink: 0;
    white-space: nowrap;
}

/*
  Barra de filtros del patrón único de pantalla de lista (componente
  BarraFiltros; contrato Project-Hydra-Negocio/tecnico/CONTRATO-PATRON-PANTALLA-LISTA-2026-09-28.md
  § 3, pieza 2): tarjeta con buscador y selects (etiqueta visible encima) y,
  debajo, los chips de filtros activos. Global y no aislado a propósito: una
  regla aislada gana a la global y reabriría la copia por pantalla.
*/
.barra-filtros-lista {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--color-surface);
    border: var(--border-default);
    border-radius: var(--radius-lg);
}

.barra-filtros-lista-fila {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-3);
}

.barra-filtros-lista-fila > .campo {
    flex: 1 1 180px;
    min-width: 160px;
}

.barra-filtros-lista-fila > .barra-filtros-lista-buscador {
    flex: 2 1 260px;
    min-width: 200px;
}

.barra-filtros-lista-activos {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

/* Doble clase: .chips-filtros (más abajo, misma especificidad) fija margin-bottom y ganaría por orden. */
.chips-filtros.barra-filtros-lista-chips {
    align-items: center;
    margin-bottom: 0;
}

.limpiar-filtros-barra,
.guardar-filtro-barra,
.restablecer-vista-barra {
    border: 0;
    background: none;
    padding: 0;
    font: var(--font-caption);
    color: var(--color-primary-500);
    cursor: pointer;
    white-space: nowrap;
}

.limpiar-filtros-barra:hover,
.guardar-filtro-barra:hover,
.restablecer-vista-barra:hover {
    color: var(--color-primary-600);
    text-decoration: underline;
}

.limpiar-filtros-barra:focus-visible,
.guardar-filtro-barra:focus-visible,
.restablecer-vista-barra:focus-visible {
    outline: var(--border-focus);
}

/*
  Rediseño de listados, fase 1 (componentes CabeceraListado, BarraFiltros en modo
  pastillas y PastillaFiltro). Global por el mismo motivo que .barra-filtros-lista.
*/

/* Cabecera de una línea: el contador junto al título y los botones de icono. */
.cabecera-listado-contador {
    padding: 1px var(--space-2);
    border-radius: var(--radius-full);
    background-color: var(--color-surface-hover);
    color: var(--color-text-muted);
    font: var(--font-label-md);
}

.cabecera-listado-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: var(--border-default);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
    color: var(--color-text-muted);
    cursor: pointer;
}

.cabecera-listado-icono:hover {
    background-color: var(--color-surface-hover);
    color: var(--color-text);
}

.cabecera-listado-icono:focus-visible {
    outline: var(--border-focus);
    outline-offset: 2px;
}

.cabecera-listado-icono-activo {
    border-color: var(--color-primary-500);
    background-color: var(--color-primary-50);
    color: var(--color-text);
}

/* Barra de filtros en modo pastillas: una fila, sin tarjeta. */
.barra-filtros-pastillas {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

.barra-filtros-pastillas-fila {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.barra-filtros-buscador-pantalla {
    position: relative;
    flex: 1 1 260px;
    max-width: 360px;
    min-width: 200px;
}

/* CampoTexto aísla su .campo-input; tres clases para ganar a la regla aislada (0,2,0). */
.barra-filtros-buscador-pantalla .campo .campo-input {
    width: 100%;
    min-height: 36px;
    padding-left: calc(var(--space-3) + 20px);
    padding-right: calc(var(--space-3) + 24px);
}

.barra-filtros-buscador-icono,
.barra-filtros-tecla {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
}

.barra-filtros-buscador-icono {
    left: var(--space-3);
    display: inline-flex;
    color: var(--color-text-muted);
}

.barra-filtros-tecla {
    right: var(--space-3);
    padding: 0 var(--space-1);
    border: var(--border-default);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface-hover);
    color: var(--color-text-muted);
    font: var(--font-caption);
}

.barra-filtros-resumen {
    margin-left: auto;
    font: var(--font-caption);
    color: var(--color-text-muted);
}

/* «Más filtros»: rótulo de grupo y fila de un filtro guardado con su ✕. */
.menu-filtros-titulo {
    padding: var(--space-1) var(--space-3);
    font: var(--font-caption);
    color: var(--color-text-muted);
}

.menu-filtro-guardado {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
}

/*
  Fila con problema (vencido, bloqueo o crítico: peligro; urgente: aviso). ÚNICO sitio de la regla,
  para listados y fichas 360: el tono entra por la izquierda y se funde con la superficie al 75 %
  del ancho; al pasar el puntero la fila queda teñida entera. Sin franja lateral y sin borde.

  Cómo está hecho: el tono es el background-color (plano, que es lo que mide el trinquete de
  contraste por tema) y encima va una capa de degradado de transparente a --color-surface, el doble
  de ancha que la fila. En reposo se ve su mitad derecha (transparente hasta el 75 % de la fila,
  superficie después); con el puntero, la mitad izquierda, toda transparente. Se anima solo
  background-position. Las propiedades van sueltas (background-color, background-image...) y no
  en el atajo «background», para que el color siga siendo medible.

  Quién lo lleva: el <tr> de .tabla-datos, la cabecera de una fila de acordeón, la cabecera de un
  grupo y cualquier elemento con .fila-degradado-peligro / .fila-degradado-aviso (filas de las
  fichas 360, cuyo CSS es aislado y no puede colgarse de los selectores de listado).
*/
.tabla-datos tr.fila-tintada-peligro,
.tarjeta-fila-acordeon.fila-tintada-peligro > .tarjeta-fila-acordeon-cabecera,
.grupo-lista.fila-tintada-peligro > .grupo-lista-cabecera,
.fila-degradado-peligro {
    background-color: var(--color-danger-50);
    color: var(--color-text);
}

.tabla-datos tr.fila-tintada-aviso,
.tarjeta-fila-acordeon.fila-tintada-aviso > .tarjeta-fila-acordeon-cabecera,
.grupo-lista.fila-tintada-aviso > .grupo-lista-cabecera,
.fila-degradado-aviso {
    background-color: var(--color-warning-50);
    color: var(--color-text);
}

.tabla-datos tr.fila-tintada-peligro,
.tabla-datos tr.fila-tintada-aviso,
.tarjeta-fila-acordeon.fila-tintada-peligro > .tarjeta-fila-acordeon-cabecera,
.tarjeta-fila-acordeon.fila-tintada-aviso > .tarjeta-fila-acordeon-cabecera,
.grupo-lista.fila-tintada-peligro > .grupo-lista-cabecera,
.grupo-lista.fila-tintada-aviso > .grupo-lista-cabecera,
.fila-degradado-peligro,
.fila-degradado-aviso {
    background-image: linear-gradient(90deg, transparent 0, transparent 50%, var(--color-surface) 87.5%, var(--color-surface) 100%);
    background-size: 200% 100%;
    background-position: 100% 0;
    background-repeat: no-repeat;
    transition: background-position 360ms var(--ease-fluid);
}

.tabla-datos tr.fila-tintada-peligro:hover,
.tabla-datos tr.fila-tintada-aviso:hover,
.tarjeta-fila-acordeon.fila-tintada-peligro > .tarjeta-fila-acordeon-cabecera:hover,
.tarjeta-fila-acordeon.fila-tintada-aviso > .tarjeta-fila-acordeon-cabecera:hover,
.grupo-lista.fila-tintada-peligro > .grupo-lista-cabecera:hover,
.grupo-lista.fila-tintada-aviso > .grupo-lista-cabecera:hover,
.fila-degradado-peligro:hover,
.fila-degradado-aviso:hover {
    background-position: 0 0;
}

@media (prefers-reduced-motion: reduce) {
    .tabla-datos tr.fila-tintada-peligro,
    .tabla-datos tr.fila-tintada-aviso,
    .tarjeta-fila-acordeon.fila-tintada-peligro > .tarjeta-fila-acordeon-cabecera,
    .tarjeta-fila-acordeon.fila-tintada-aviso > .tarjeta-fila-acordeon-cabecera,
    .grupo-lista.fila-tintada-peligro > .grupo-lista-cabecera,
    .grupo-lista.fila-tintada-aviso > .grupo-lista-cabecera,
    .fila-degradado-peligro,
    .fila-degradado-aviso {
        transition: none;
    }
}

/* En la tabla el degradado es de la fila entera, así que sus celdas no pintan fondo: ni el gris
   del puntero (.tabla-datos tr:hover td) ni el azul del foco de j/k (.fila-enfocada td). */
.tabla-datos tr.fila-tintada-peligro td,
.tabla-datos tr.fila-tintada-aviso td,
.tabla-datos tr.fila-tintada-peligro:hover td,
.tabla-datos tr.fila-tintada-aviso:hover td {
    background-color: transparent;
}

/* Fila tintada que además tiene el foco de j/k: conserva el degradado de su estado y suma la
   señal de foco como líneas arriba y abajo, para que no se pierda ninguna de las dos. */
.tabla-datos tr.fila-enfocada.fila-tintada-peligro td,
.tabla-datos tr.fila-enfocada.fila-tintada-aviso td {
    box-shadow: inset 0 2px 0 var(--color-primary-400), inset 0 -2px 0 var(--color-primary-400);
}

/* En la fila del modo pastillas, «Expandir todo» y compañía van en línea con los filtros. */
.barra-filtros-pastillas-fila .barra-herramientas-lista {
    margin-bottom: 0;
}

/* Cabecera de grupo de un listado agrupado (CabeceraGrupoLista; hoy, Centros por Cliente
   empresarial): fila entera pulsable con chevron, nombre, contador y resumen por estado. Blanca,
   con el gris de fila al pasar el puntero; si el grupo contiene vencidos o urgentes lleva el mismo
   degradado que las filas (regla única de «Fila con problema», arriba). */
.grupo-lista {
    border-top: 1px solid var(--color-fila-divisor);
}

.grupo-lista-cabecera {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    min-height: 40px;
    padding: var(--space-2) var(--space-3);
    border: 0;
    background-color: var(--color-surface);
    color: var(--color-text);
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}

.grupo-lista-cabecera:hover {
    background-color: var(--color-fila-hover);
}

/* Grupos abiertos por algo ajeno a ellos (búsqueda, selección múltiple, Centro en la URL): la
   cabecera no contrae nada, así que no es un botón ni lo parece. */
.grupo-lista-cabecera-fija {
    cursor: default;
}

.grupo-lista-cabecera-fija .grupo-lista-chevron {
    visibility: hidden;
}

.grupo-lista-cabecera:focus-visible {
    outline: 2px solid var(--color-primary-400);
    outline-offset: -2px;
}

.grupo-lista-chevron {
    display: inline-flex;
    transform: rotate(-90deg);
    transition: transform 0.15s ease;
}

.grupo-lista-cabecera-abierta .grupo-lista-chevron {
    transform: none;
}

.grupo-lista-contador {
    font: var(--font-caption);
    color: var(--color-text-muted);
}

/* Resumen por estado del grupo entero: un punto del color del estado y «N estado» por cada uno
   con cifra. El punto usa los mismos tonos que el de la franja de estado y, como él, se pinta con
   currentColor: el token es de texto y sigue su variante por tema. */
.grupo-lista-resumen {
    display: inline-flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--space-1) var(--space-3);
    margin-left: auto;
    font: var(--font-caption);
    font-weight: 500;
    color: var(--color-text-muted);
}

.grupo-lista-resumen-estado {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    white-space: nowrap;
}

.grupo-lista-punto {
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    color: var(--color-text-muted);
    background-color: currentColor;
}

.grupo-lista-punto-peligro {
    color: var(--color-danger-700);
}

.grupo-lista-punto-advertencia {
    color: var(--color-warning-700);
}

.grupo-lista.fila-tintada-peligro .grupo-lista-contador,
.grupo-lista.fila-tintada-aviso .grupo-lista-contador,
.grupo-lista.fila-tintada-peligro .grupo-lista-resumen,
.grupo-lista.fila-tintada-aviso .grupo-lista-resumen {
    color: var(--color-text);
}

/* Persona con sus iniciales delante (Gestor CAE de la fila). */
.persona-identidad {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    vertical-align: middle;
}

/*
  Toolbar de Centros (lámina L3 ".toolbar", contrato de fidelidad
  2026-08-09 § 1.4): una sola fila con buscar/estado/orden/selección
  múltiple/expandir todos/exportar/nuevo centro, en vez de las 3 regiones
  fragmentadas (cabecera de página, barra de filtros, BarraHerramientasLista)
  que había antes. Es composición nueva y no una adaptación de
  BarraHerramientasLista (prohibida como región propia, § 1.2) ni de
  .barra-filtros — esta fila agrupa además la selección múltiple, expandir
  todos, exportar y el alta, que .barra-filtros no lleva en ninguna otra lista.
*/
.barra-trabajo-centros {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: var(--space-4);
}

/* CampoTexto renderiza su propio ".campo" como contenedor — se apunta por
   posición porque el "class" splatteado llega al <input> interno, no a este
   wrapper (mismo motivo que documenta CampoTexto.razor). */
.barra-trabajo-centros > .campo {
    flex: 1 1 220px;
    min-width: 160px;
}

.filtro-critico {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font: var(--font-body-md);
    white-space: nowrap;
}

/*
  Chips de filtros activos y de filtros guardados (H4, Project-Hydra-Negocio/tecnico/docs/ux-audit/02-clientes.md;
  Project-Hydra-Negocio/tecnico/docs/archive/design/UX_PATTERNS.md § Filtrar: "filtros activos se muestran como chips
  removibles"). Mismos tokens que .badge-neutro (Badge.razor.css), pero con
  su propio botón de quitar (icono "cerrar") — un Badge no lleva acción.
*/
.chips-filtros {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

/* Marca de "esto es un filtro" al frente de la fila de chips activos: sin
   ella la fila son etiquetas sueltas y no se lee como el estado del filtrado. */
.chips-filtros-indicador {
    display: inline-flex;
    align-items: center;
    color: var(--color-text-muted);
}

.chip-filtro {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px var(--space-2);
    border-radius: var(--radius-full);
    background-color: var(--color-surface-hover);
    color: var(--color-text);
    font: var(--font-label-md);
    font-size: 0.75rem;
}

.chip-filtro-quitar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--color-text-muted);
    cursor: pointer;
    padding: 0;
}

.chip-filtro-quitar:hover {
    color: var(--color-text);
}

.campo-checkbox {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font: var(--font-body-md);
}

.campo-con-boton {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
}

.campo-con-boton > .campo {
    flex: 1;
}

.lista-seleccion-multiple {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    max-height: 200px;
    overflow-y: auto;
    border: var(--border-default);
    border-radius: var(--radius-md);
    padding: var(--space-3);
}

.lista-seleccion-multiple.lista-seleccion-multiple-natural {
    max-height: none;
    overflow-y: visible;
}

.glosario-tipo-documento {
    background-color: var(--color-surface-hover);
    border: var(--border-default);
    border-radius: var(--radius-sm);
    padding: var(--space-3);
    font: var(--font-body-sm);
    color: var(--color-text-muted);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.glosario-tipo-documento p {
    margin: 0;
}

.glosario-tipo-documento strong {
    color: var(--color-text);
}

.alerta-formulario {
    background-color: var(--color-danger-50);
    color: var(--color-danger-700);
    border-radius: var(--radius-sm);
    padding: var(--space-3);
    font: var(--font-body-sm);
}

/* Bloque "Se solicita a" de la reclamación documental: los contactos de la
   agenda que van a recibir el correo, con el motivo por el que entra cada uno.
   Global y no aislado porque tiene dos superficies —la pestaña Reclamaciones
   de /documentos y el drawer de Centro 360— y debe leerse igual en las dos. */
.reclamacion-destinatarios {
    border: var(--border-default);
    border-radius: var(--radius-md);
    padding: var(--space-3);
    margin: var(--space-3) 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.reclamacion-destinatarios legend {
    font: var(--font-label);
    padding: 0 var(--space-1);
}

.reclamacion-motivo {
    color: var(--color-text-muted);
    font: var(--font-caption);
}

.alerta-info {
    background-color: var(--color-primary-50);
    color: var(--color-primary-500);
    border-radius: var(--radius-sm);
    padding: var(--space-3);
    font: var(--font-body-sm);
    margin-bottom: var(--space-3);
}

/* Fase B: preflight no bloqueante al asignar en lote — ver Asignaciones.razor. */
.alerta-preflight-asignacion {
    background-color: var(--color-warning-50);
    color: var(--color-warning-700);
    border-radius: var(--radius-sm);
    padding: var(--space-3);
    font: var(--font-body-sm);
    margin-top: var(--space-3);
}

.alerta-preflight-asignacion ul {
    margin: var(--space-2) 0 0;
    padding-left: var(--space-5);
}

.texto-ayuda-matriz {
    color: var(--color-text-muted);
    font: var(--font-body-sm);
    margin: var(--space-2) 0;
}

/* Ayuda bajo un campo de formulario: explica qué escribir, no un error. */
.texto-ayuda-campo {
    color: var(--color-text-muted);
    font: var(--font-body-sm);
    margin: calc(var(--space-2) * -1) 0 var(--space-4);
}

.matriz-asignaciones-contenedor {
    overflow-x: auto;
}

.matriz-asignaciones {
    border-collapse: collapse;
    width: 100%;
}

.matriz-asignaciones th,
.matriz-asignaciones td {
    padding: var(--space-2) var(--space-3);
    border: var(--border-default);
    text-align: center;
    white-space: nowrap;
}

.matriz-asignaciones th[scope="row"] {
    text-align: left;
}

/* Fase C: Bandeja del gestor — ver PanelResolverItem.razor. */
.panel-resolver-item {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background-color: var(--color-surface);
    border: var(--border-default);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-2);
}

.panel-resolver-item-enfocado {
    border-color: var(--color-primary-500);
    box-shadow: 0 0 0 1px var(--color-primary-500);
}

.panel-resolver-item-info {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex: 1;
    min-width: 0;
}

.panel-resolver-item-titulo {
    margin: 0;
    font: var(--font-body-md);
    font-weight: 600;
}

.panel-resolver-item-subtitulo {
    margin: 0;
    color: var(--color-text-muted);
    font: var(--font-body-sm);
}

.panel-resolver-item-fecha {
    color: var(--color-text-muted);
    font: var(--font-body-sm);
    white-space: nowrap;
}

.lista-bandeja {
    display: flex;
    flex-direction: column;
}

.paginador {
    margin-top: var(--space-4);
}

.paginador-simple {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.paginador-texto {
    color: var(--color-text-muted);
    font: var(--font-body-sm);
}

/* H5 (Project-Hydra-Negocio/tecnico/docs/ux-audit/05-trabajadores-vehiculos.md): selector de tamaño de página, compartido por PaginadorSimple.razor. */
.paginador-tamano {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text-muted);
    font: var(--font-body-sm);
    margin-left: auto;
}

.paginador-tamano-select {
    padding: var(--space-1) var(--space-2);
    /* Borde que identifica un control: sujeto al 3:1 de 02 § 8
       (DDL-062/063). --color-border no lo alcanza (1,44:1). */
    border: var(--border-control);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: var(--font-body-sm);
}

/*
  Centro 360 (Project-Hydra-Negocio/tecnico/docs/ux-audit/PLAN-EJECUCION-UX.md § 0.1): fila de /centros como tarjeta con
  SeccionColapsable anidada, en vez de <tr> de QuickGrid — QuickGrid no
  soporta filas expandibles. La cabecera con checkbox/nombre/acciones queda
  FUERA del <button> de SeccionColapsable (que solo envuelve el chevron y el
  título "Asignaciones") porque anidar botones/checkboxes dentro de un
  <button> es HTML inválido y rompería el toggle del acordeón.
*/
.lista-filas-acordeon {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/*
  overflow:hidden RETIRADO (era lo que recortaba VentanaContexto — nivel
  Overlay, tiene que flotar sobre el contenido — cuando su panel necesitaba
  salir de los límites de la tarjeta: bug real reportado, "el cuadro de
  contexto aparece detrás del fondo"). El redondeo de esquinas lo llevan
  ahora los hijos que sí necesitan recortarse (cabecera/contenido), no toda
  la tarjeta.
*/
.tarjeta-fila-acordeon {
    background-color: var(--color-surface);
    border: var(--border-default);
    border-radius: var(--radius-lg);
}

/*
  Densidad de fila (Centro 360 § 0.9): padding vertical y gap reducidos
  respecto a space-4/space-3 para que quepan más centros por pantalla. El
  padding horizontal se mantiene — apretar los lados no gana filas, solo
  aprieta. Los Badge y el badge-visita de la fila también bajan de tamaño
  más abajo, por el mismo motivo.
*/
.tarjeta-fila-acordeon-cabecera {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    border-bottom: var(--border-default);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    transition: background-color var(--motion-fast) var(--ease-standard);
}

/*
  Identidad del centro en dos líneas (lámina L3). Ocupa el espacio sobrante y
  recorta con elipsis: es la única zona elástica de la fila, para que todo lo
  demás pueda tener posición fija.
*/
.tarjeta-fila-acordeon-identidad {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.tarjeta-fila-acordeon-identidad > * {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
}

/*
  Nombre del centro en negrita (lámina L3 ".rname", font-weight 600) — no se
  toca `.enlace-nombre-fila` en general (patrón compartido por 9+ pantallas,
  contrato § 1.3): solo se refuerza aquí, donde es la primera línea de la
  identidad de la fila.
*/
.tarjeta-fila-acordeon-identidad > .enlace-nombre-fila {
    font-weight: 600;
    font-size: 0.8125rem; /* 13px, ESPECIFICACION-VISUAL-HYDRA (documento que ya no existe) § 3.7 ".rnombre" */
    line-height: 1.3;
}

.tarjeta-fila-acordeon-meta {
    color: var(--color-text-muted);
    font: var(--font-body-sm);
}

/*
  Zona de indicadores de ANCHO FIJO (lámina L3, blueprint § 3.2, contrato de
  fidelidad 2026-08-09 § 1.6, bug C-2).

  Grid de 3 ranuras fijas — vencidos · próximos · estado-o-visita — igual que
  ".rbadges"/".wbadges" de la lámina: 200px de ancho total, 26px + 26px +
  el resto para la 3ª ranura. Antes eran solo 2 columnas (recuento + un "resto"
  que cargaba a la vez el Badge de Estado y la visita), y ese resto no
  alcanzaba para los dos — el badge de visita caía a una segunda línea. Con 3
  ranuras fijas y la 3ª mutuamente excluyente (ver Centros.razor), cada
  indicador tiene su propio hueco reservado.
*/
.tarjeta-fila-acordeon-indicadores {
    display: grid;
    grid-template-columns: 26px 26px minmax(0, 1fr);
    gap: var(--space-1);
    align-items: center;
    width: 200px;
    flex-shrink: 0;
}

/*
  3ª ranura (estado o visita, mutuamente excluyentes): overflow visible para
  que el panel de VentanaContexto de la visita no quede recortado por el
  ancho fijo de la ranura, igual que ".bs3" en la lámina.
*/
.ranura-recuento-final {
    overflow: visible;
}

/*
  Las VentanaContexto de la fila de Centro se abren hacia ABAJO, no hacia
  arriba (por defecto en VentanaContexto.razor.css): es la fila más alta de
  cada tarjeta, y hacia arriba puede quedar recortada por el borde superior
  del viewport o de un contenedor con scroll — mismo motivo que
  ".c360 .rowhead .tip" en el lámina.
*/
/*
  !important en "bottom" necesario: VentanaContexto.razor.css es CSS con
  ámbito de Blazor, que añade un selector de atributo
  (".ventana-contexto-panel[b-xxxxxxxx]") con la MISMA especificidad que
  este selector de dos clases — sin !important, "bottom" se quedaba en el
  valor del componente base y "top" en el de aquí, los dos a la vez
  (ninguno "auto"). Con ambos bordes fijados, el navegador calcula la altura
  como la distancia entre ellos en vez de ajustarla al contenido — así se
  producía el panel de 18px de alto que recortaba el desglose entero
  (bug real reportado, "mini lista que no se ve").
*/
.tarjeta-fila-acordeon-indicadores .ventana-contexto-panel {
    bottom: auto !important;
    top: calc(100% + var(--space-1));
}

.tarjeta-fila-acordeon-acciones {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
}

/*
  Patrón de listados sin menú «⋯»: un clic en cualquier punto de la fila abre su vista
  rápida. La fila lo anuncia con el cursor; los controles de dentro (casilla, desplegable,
  identificador copiable, icono 360) conservan el suyo y no dejan subir el clic.
*/
.fila-pulsable {
    cursor: pointer;
}

/*
  Fondo distinto del contenido expandido (lámina L3 ".expand", --c-subtle):
  el segundo/tercer nivel se lee como una superficie "hundida" respecto a la
  cabecera del centro, no como una continuación del mismo plano — es lo que
  distingue visualmente "estás dentro del desplegable" sin depender del
  borde superior.
*/
.tarjeta-fila-acordeon-contenido {
    padding: var(--space-3) var(--space-4) var(--space-4);
    background-color: var(--color-surface-subtle);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/*
  Fila continua para las listas de acordeón (propuesta de listados, 2026-10-09): la lista es UNA
  tarjeta, con la cabecera de columnas arriba y las filas pegadas, separadas por una línea, en vez de
  una tarjeta suelta por fila. Se usa envolviendo la cabecera de columnas de la pantalla y
  .lista-filas-acordeon en un <div class="marco-lista-acordeon">. La cabecera de columnas sigue en el
  CSS de cada pantalla (su rejilla es propia). Sin overflow: recortaría las ventanas de contexto.
*/
.marco-lista-acordeon {
    background-color: var(--color-surface);
    border: var(--border-default);
    border-radius: var(--radius-lg);
}

.marco-lista-acordeon .lista-filas-acordeon {
    gap: 0;
}

.marco-lista-acordeon .tarjeta-fila-acordeon {
    border: 0;
    border-bottom: 1px solid var(--color-fila-divisor);
    border-radius: 0;
}

.marco-lista-acordeon .tarjeta-fila-acordeon:last-child {
    border-bottom: 0;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.marco-lista-acordeon .tarjeta-fila-acordeon-cabecera {
    min-height: 48px;
    border-bottom: 0;
    border-radius: 0;
}

.marco-lista-acordeon .tarjeta-fila-acordeon:last-child > .tarjeta-fila-acordeon-cabecera:last-child {
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.marco-lista-acordeon .tarjeta-fila-acordeon-contenido {
    border-top: var(--border-default);
    border-radius: 0;
}

.marco-lista-acordeon .tarjeta-fila-acordeon:last-child > .tarjeta-fila-acordeon-contenido {
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/*
  Guía de lectura (Tier A, 07 § 3 / ESPECIFICACION-VISUAL-HYDRA (documento que ya no existe) § 3.7):
  la fila entera se resalta al apuntarla o enfocarla — sin ella, en una fila
  ancha hay que recorrer el renglón dos veces para confirmar que se está en
  la fila correcta.
*/
.tarjeta-fila-acordeon-cabecera:hover {
    background-color: var(--color-fila-hover);
}

@media (prefers-reduced-motion: reduce) {
    .tarjeta-fila-acordeon-cabecera {
        transition: none;
    }
}

/*
  Chevron de expandir/colapsar de la fila (§ 0.9). Vive donde antes vivía
  siempre el checkbox; con "Selección múltiple" activo el checkbox vuelve a
  su sitio, a la izquierda de este botón, y ambos conviven. No reutiliza
  SeccionColapsable: su CSS está scoped al componente y su estado es
  interno, y aquí la expansión la decide la página para poder hacer
  "Expandir/Colapsar todos".
*/
.boton-expandir-fila {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: var(--space-1);
    border: none;
    background: none;
    color: var(--color-text-muted);
    cursor: pointer;
    border-radius: var(--radius-sm);
    /* Tier B (ESPECIFICACION-VISUAL-HYDRA (documento que ya no existe) § 3.8): el chevron controla un
       bloque que se expande/revela, no un simple color/estado de control —
       eso es lo que separa Tier A de Tier B (07 § 8), y antes usaba el
       primero. */
    transition: transform var(--motion-transition) var(--ease-fluid);
    transform: rotate(-90deg);
}

.boton-expandir-fila-abierta {
    transform: rotate(0deg);
}

.boton-expandir-fila:hover {
    color: var(--color-text);
}

.boton-expandir-fila:focus-visible {
    outline: var(--border-focus);
    outline-offset: 1px;
}

/*
  Barra de herramientas de lista (§ 0.9) — controles que actúan sobre la
  lista entera, bajo la barra de filtros.
*/
.barra-herramientas-lista {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

/*
  Badge "Visita dd/mm–dd/mm" (Centro 360 § 0.3) — no es <Badge> porque ese
  componente renderiza un <span> (Badge.razor); aquí hace falta un <button>
  real (clicable, foco de teclado) con el mismo aspecto visual. Mismos
  tokens que .badge-info de Badge.razor.css — ese CSS está scoped al
  componente y no llega hasta aquí.
*/
.badge-visita {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    /* Métrica de .badge-pequeno (Badge.razor.css) — densidad de fila, § 0.9. */
    padding: 0 var(--space-2);
    border-radius: var(--radius-full);
    font: var(--font-label-md);
    font-size: 0.6875rem;
    line-height: 1.125rem;
    background-color: var(--color-info-50);
    color: var(--color-info-500);
    border: none;
    cursor: pointer;
}

.badge-visita:hover {
    text-decoration: underline;
}

/*
  Badge "N detección(es)" en Empresas (Project-Hydra-Negocio/tecnico/docs/ux-audit/03-empresas-subcontratas.md
  H2) — mismo motivo que .badge-visita (botón clicable, no <Badge>), mismos
  tokens que .badge-advertencia de Badge.razor.css.
*/
.badge-deteccion {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0 var(--space-2);
    border-radius: var(--radius-full);
    font: var(--font-label-md);
    font-size: 0.6875rem;
    line-height: 1.125rem;
    background-color: var(--color-warning-50);
    color: var(--color-warning-700);
    border: none;
    cursor: pointer;
}

.badge-deteccion:hover {
    text-decoration: underline;
}

/*
  Modificador "vigente con riesgo en ventana de visita" (Centro 360 § 0.3,
  dado de alta también en Project-Hydra-Negocio/tecnico/docs/archive/design/DESIGN_SYSTEM.md y
  Project-Hydra-Negocio/tecnico/docs/archive/design/UX_PATTERNS.md): sigue siendo un
  badge Exito (el documento SÍ está vigente hoy) — el borde ámbar es la
  única señal de que caduca antes de que termine la próxima visita del
  centro. No es un cuarto color del semáforo, es un modificador encima de
  uno de los tres ya existentes.
*/
.badge-riesgo-ventana-visita {
    box-shadow: inset 0 0 0 1.5px var(--color-warning-500);
}

.acordeon-asignaciones-cabecera {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

/* Búsqueda de trabajadores del cuerpo de Centro 360 (AcordeonAsignacionesCentro) — solo aparece con más de un trabajador en la lista ya filtrada. */
.acordeon-asignaciones-busqueda {
    max-width: 320px;
    margin-bottom: var(--space-3);
}

.lista-trabajadores-acordeon {
    display: flex;
    flex-direction: column;
}

/*
  Vista previa de /centros (hallazgo en vivo 2026-08-16, SoloIncidencias):
  cierra la lista recortada indicando cuántos trabajadores al día se
  ocultaron y ofrece el enlace a la página propia Centro 360, que es la
  única vista que conserva la lista completa sin recortar.
*/
.nota-trabajadores-ocultos {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding-top: var(--space-2);
    margin-top: var(--space-2);
    border-top: var(--border-default);
    color: var(--color-text-muted);
    font: var(--font-caption);
}

/*
  El checkbox de selección va como hermano de ancho fijo a la izquierda del
  cuerpo de la fila (mismo motivo que .tarjeta-fila-acordeon-cabecera con su
  propio checkbox): anidarlo dentro del <button> del chevron sería HTML
  inválido.
*/
.fila-trabajador-acordeon {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding-top: var(--space-2);
    border-top: var(--border-default);
}

.fila-trabajador-acordeon:first-child {
    border-top: none;
}

.fila-trabajador-acordeon > .fila-trabajador-acordeon-cuerpo {
    flex: 1;
    min-width: 0;
}

/* Motivo del bloqueo de un Trabajador en el Centro (ficha 12): bajo la fila, una línea por documento con su «Pedir». */
.motivo-bloqueo {
    margin: 0.25rem 0 0.5rem 2.25rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--color-danger-700);
}

.motivo-bloqueo-lista {
    list-style: none;
    margin: 0;
    padding: 0;
}

.motivo-bloqueo-linea {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.125rem 0;
}

.motivo-bloqueo-texto {
    min-width: 0;
    overflow-wrap: anywhere;
}

.motivo-bloqueo-sin-pedir,
.motivo-bloqueo-subtitulo {
    color: var(--color-text-muted);
}

.motivo-bloqueo-subtitulo {
    margin: 0.5rem 0 0.125rem;
}

/*
  Fila de Trabajador (contrato de fidelidad 2026-08-09 § 1.4, lámina L3
  ".wrow"): mismo grid de 5 columnas fijas que la fila de Centro, sin anillo
  de cumplimiento — el lámina solo lo pone a nivel de Centro, aquí va la
  fracción "7/9" en su lugar.
*/
.fila-trabajador-rejilla {
    display: grid;
    grid-template-columns: 14px minmax(0, 1fr) 46px 200px 76px;
    gap: var(--space-2);
    align-items: center;
    padding: var(--space-1) 0;
    border-radius: var(--radius-sm);
    transition: background-color var(--motion-fast) var(--ease-standard);
}

/* Guía de lectura (Tier A) — mismo motivo que la fila de Centro. */
.fila-trabajador-rejilla:hover,
.fila-trabajador-rejilla:focus-within {
    background-color: var(--color-surface);
}

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

/*
  Selector compuesto (no ".fila-trabajador-nombre" sola): ".enlace-nombre-fila"
  define "font: inherit" más abajo en esta misma hoja, y con la misma
  especificidad (una sola clase) gana por orden de cascada — el peso 600 se
  perdía en runtime aunque estuviera declarado aquí. Mismo motivo por el que
  el nombre del Centro usa ".tarjeta-fila-acordeon-identidad > .enlace-nombre-fila".
*/
.enlace-nombre-fila.fila-trabajador-nombre {
    font: var(--font-body-md);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fila-trabajador-fraccion {
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
    font: var(--font-body-sm);
    text-align: right;
}

.fila-trabajador-accion {
    display: flex;
    justify-content: flex-end;
}

/*
  Enlace de acción de fila ("Detalles", "Eliminar", "Gestionar" en Centro
  360) — ESPECIFICACION-VISUAL-HYDRA (documento que ya no existe) § 3.1/§ 3.7: en el lámina estas
  acciones son un <a> plano (color enlace, sin relleno ni borde), no un
  botón Fantasma con borde (ese es el estilo de la barra de herramientas).
  Se aplica como clase adicional sobre <Boton Variante="Fantasma"> —
  conserva el padding/min-height del botón base (objetivo táctil WCAG
  2.5.5 ya documentado en Boton.razor.css) y solo cambia el aspecto.
  !important necesario: Boton.razor.css es CSS con ámbito de Blazor, que
  añade un selector de atributo (".boton-fantasma[b-xxxxxxxx]") con más
  especificidad que una clase sola en esta hoja global.
*/
.accion-fila-enlace {
    background-color: transparent !important;
    border-color: transparent !important;
    color: var(--color-primary-500) !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
}

.accion-fila-enlace:not(:disabled):hover {
    background-color: transparent !important;
    transform: none !important;
    text-decoration: underline;
}

/* Acción disponible pero sin nada que gestionar — atenuada, nunca disabled real (04 § 2.5). */
.accion-fila-enlace.accion-atenuada {
    color: var(--color-text-muted) !important;
}

.accion-fila-enlace.accion-atenuada:hover,
.accion-fila-enlace.accion-atenuada:focus-visible {
    color: var(--color-primary-500) !important;
}

/*
  Tercer nivel del Centro 360 — variante A (OD-12, blueprint § 3.4, DDL-034).

  La rejilla se declara UNA vez, en el contenedor, y la heredan cabecera y
  filas: es lo unico que garantiza que las cuatro columnas caigan en la misma
  vertical cuando una fila no tiene fecha de vigencia. Con flex libre cada fila
  reparte el espacio segun su propio contenido y la lectura por columna, que es
  el motivo de existir de esta variante, se pierde.

  Los anchos vienen del banco visual: 168px basta para el badge de estado mas
  largo del lexico cerrado, y 76px para "Gestionar".
*/
.tabla-documentos-requeridos {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 168px minmax(0, 150px) 76px;
    /*
      stretch, no center: con "center" cada celda se recorta a la altura de
      su propio contenido y se centra dentro de la fila — la celda de
      "Gestionar" (con el padding vertical del botón) queda más alta que las
      demás, y el resaltado de fila al pasar el ratón (abajo) pintaba
      rectángulos de altura distinta por celda en vez de una fila continua.
      Con "stretch" las 4 celdas ocupan la altura completa de la fila y cada
      una centra su propio contenido por dentro (ver ".fila-documento-requerido > *").
    */
    align-items: stretch;
    column-gap: var(--space-3);
    border-left: 2px solid var(--color-border);
    padding-left: var(--space-3);
    margin-left: var(--space-6);
}

/* La cabecera y cada fila son `display: contents`: sus celdas participan en la
   rejilla del padre en vez de crear una anidada. */
.documentos-requeridos-cabecera,
.fila-documento-requerido {
    display: contents;
}

.documentos-requeridos-cabecera > * {
    font: var(--font-body-sm);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
    padding-bottom: var(--space-1);
    border-bottom: var(--border-default);
    margin-bottom: var(--space-1);
}

.fila-documento-requerido > * {
    display: flex;
    align-items: center;
    padding: var(--space-1) var(--space-2);
    margin: 0 calc(var(--space-2) * -1);
    min-width: 0;
    border-radius: var(--radius-sm);
    transition: background-color var(--motion-fast) var(--ease-standard);
}

.fila-documento-requerido > .columna-accion {
    justify-content: flex-end;
}

/*
  Guía de lectura (Tier A) — "display: contents" en la fila (arriba) no
  genera caja propia, así que no hay un único elemento al que ponerle fondo:
  se resalta cada celda por separado con el mismo color, y el margen
  negativo compensa el padding para que seguan alineadas con la cabecera.
*/
.fila-documento-requerido:hover > *,
.fila-documento-requerido:focus-within > * {
    background-color: var(--color-surface);
}

/* Tercer nivel de Centro 360: solo existe mientras la fila de Trabajador está expandida; entra con la misma cascada del sistema. */
.tabla-documentos-requeridos > * {
    animation: tabla-documentos-entra var(--motion-transition) var(--ease-fluid) backwards;
}

.tabla-documentos-requeridos > :nth-child(1) { animation-delay: 70ms; }
.tabla-documentos-requeridos > :nth-child(2) { animation-delay: 120ms; }
.tabla-documentos-requeridos > :nth-child(n + 3) { animation-delay: 170ms; }

@keyframes tabla-documentos-entra {
    from {
        opacity: 0;
        transform: translateY(-4px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .fila-documento-requerido > * {
        transition: none;
    }

    .tabla-documentos-requeridos > * {
        animation: none;
    }
}

.celda-documento-nombre {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}

/* Con segunda línea (LineaPlataformaYReclamacion: estado en la plataforma del Centro y última reclamación), el
   nombre y la línea se apilan; sin ella la celda no cambia. */
.celda-documento-nombre:has(> .linea-plataforma-reclamacion) {
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
}

.celda-documento-vigencia {
    font: var(--font-body-sm);
    color: var(--color-text-muted);
    /* Fechas en columna: sin numeracion tabular los digitos no alinean y la
       comparacion vertical, que es para lo que existe la columna, cuesta. */
    font-variant-numeric: tabular-nums;
}

/* «Sin confirmar»: cuenta como al día, con aviso. Mismo ámbar que el aviso del panel Documentación base. */
.celda-documento-vigencia-sin-confirmar {
    color: var(--color-warning-700);
}

/*
  Sin `justify-self: end`: eso encoge la celda al ancho de su contenido y su
  borde izquierdo deja de coincidir con el de la cabecera — la columna se ve
  desalineada aunque la rejilla sea correcta. La celda ocupa su columna entera
  y es el CONTENIDO el que se alinea a la derecha.
*/
.columna-accion {
    text-align: right;
}

/*
  Accion presente pero atenuada cuando el documento no la necesita
  (04 § 2.5). No se oculta: sigue siendo alcanzable con teclado y recupera
  contraste completo al enfocarla o apuntarla.
*/
.accion-atenuada {
    opacity: 0.55;
}

.accion-atenuada:hover,
.accion-atenuada:focus-visible {
    opacity: 1;
}

/* Cada linea del detalle de una ventana de contexto, como bloque propio. */
.ventana-linea {
    display: block;
    padding: 1px 0;
}

.texto-vacio-seccion {
    color: var(--color-text-muted);
    font: var(--font-body-md);
}

/*
  Click en el nombre/identificador de una fila = misma acción que el botón
  "Ver" de esa fila — evita tener que mover el ratón hasta la columna de
  Acciones para abrir el detalle. Se ve como el texto normal de la celda
  (no como un enlace azul de manual): el cursor y el subrayado al pasar por
  encima son la única pista de que es interactivo.
*/
.enlace-nombre-fila {
    display: inline;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.enlace-nombre-fila:hover {
    text-decoration: underline;
}

/* Pieza 5 del patrón de lista: el nombre de la entidad va en negrita, sin
   subrayado en reposo, y abre la vista previa lateral. */
.enlace-nombre-fila.nombre-fila-entidad {
    font-weight: 600;
    color: var(--color-text);
    text-decoration: none;
}

.enlace-nombre-fila.nombre-fila-entidad:hover {
    text-decoration: underline;
}

.tabla-datos {
    width: 100%;
    border-collapse: collapse;
    background-color: var(--color-surface);
    border: var(--border-default);
    border-radius: var(--radius-lg);
    /* Sin overflow: hidden: el panel de MenuAcciones (position: absolute) sale de
       la fila y, en una lista de pocas filas, sobresale de la tabla; con el
       recorte quedaba cortado. Las esquinas redondeadas las llevan las celdas
       de las cuatro esquinas (reglas de abajo). */
}

.tabla-datos th:first-child { border-top-left-radius: calc(var(--radius-lg) - 1px); }
.tabla-datos th:last-child { border-top-right-radius: calc(var(--radius-lg) - 1px); }
.tabla-datos tr:last-child td:first-child { border-bottom-left-radius: calc(var(--radius-lg) - 1px); }
.tabla-datos tr:last-child td:last-child { border-bottom-right-radius: calc(var(--radius-lg) - 1px); }

.tabla-datos th {
    text-align: left;
    padding: var(--space-4);
    font: var(--font-label-md);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.6875rem;
    color: var(--color-text-muted);
    background-color: var(--color-surface);
    border-bottom: 1px solid var(--color-fila-divisor);
}

/*
  Columna ordenable de QuickGrid: pinta la cabecera como <button class="col-title"> y un botón
  no hereda font, color ni text-transform del <th> (el agente de usuario los fija). Sin esto, en
  la misma tabla las columnas Sortable salían en minúsculas y con otro tamaño, y las demás en
  versalitas. El nombre accesible no cambia: es el texto del botón.
*/
.tabla-datos th button {
    font: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    color: inherit;
}

/* Divisor entre filas: va en la celda, por encima del fondo de la fila, así que se ve igual
   sobre el rojo y el ámbar de una fila con problema. */
.tabla-datos td {
    padding: var(--space-4);
    border-bottom: 1px solid var(--color-fila-divisor);
    font: var(--font-body-md);
}

/*
  Relleno de las tablas que pinta QuickGrid. El tema por defecto del paquete trae sus propias reglas, sin
  capa y con más especificidad que las de arriba, así que ganaban ellas:

      .quickgrid[theme=default] > tbody > tr > td   { padding: 0.1rem calc(0.4rem + var(--col-gap)) 0.1rem 0.4rem }   (0,2,3)
      .quickgrid[theme=default] .col-title          { padding: 0.1rem 0.4rem }                                        (0,3,0)
      .quickgrid[theme=default] .col-header-content { padding-right: var(--col-gap) }                                 (0,3,0)

  El resultado eran filas de 44 px con el contenido pegado al borde, y el rótulo de cada cabecera desplazado
  respecto al contenido de su columna (la celda sangraba 0.4rem; la cabecera, los 16 px del <th> más los
  0.4rem del título). Estas tres reglas añaden «.tabla-datos» al mismo selector para superarlas (0,3,3 y
  0,4,0) sin !important, y dejan UNA sola sangría horizontal, la del <th> (--space-4), para celda y cabecera:
  el rótulo cae sobre el contenido. Arriba y abajo, 7 px y un alto mínimo de 54 px: la fila de dos líneas
  de la maqueta de listados (identidad y dato de apoyo). En una celda de tabla, «height» es un mínimo.
*/
.quickgrid[theme=default].tabla-datos > tbody > tr > td {
    height: 54px;
    padding: 7px var(--space-4);
}

.quickgrid[theme=default].tabla-datos .col-title {
    padding: 0;
}

.quickgrid[theme=default].tabla-datos .col-header-content {
    padding-right: 0;
}

.tabla-datos tr:last-child td {
    border-bottom: none;
}

/* Resalte de fila: es la funcion que --motion-base declara (07 § 8). */
.tabla-datos tr:hover td {
    background-color: var(--color-fila-hover);
    transition: background-color var(--motion-base) var(--ease-standard);
}

/* Fila con foco de teclado (atajos j/k, P3-31) */
.fila-enfocada td {
    background-color: var(--color-primary-50);
    box-shadow: inset 2px 0 0 var(--color-primary-400);
}

/* Misma señal de foco que .fila-enfocada, para una tarjeta en vez de un <tr> (Centro 360). */
.tarjeta-fila-acordeon.fila-enfocada {
    box-shadow: 0 0 0 1px var(--color-primary-400);
}

/* Fila enfocada con j/k en una ficha 360 (atajos-ficha.js pone el atributo; Blazor no lo
   pinta). La barra interior es la señal: el tinte de una fila con problema no la tapa. La fila
   tiene además el foco real, así que el anillo por defecto se deja transparente para no doblar
   la señal: en contraste forzado (forced-colors) el navegador sí lo pinta, y ahí la barra no. */
[data-fila-enfocada] {
    background-color: var(--color-surface-hover);
    box-shadow: inset 3px 0 0 var(--color-primary-500);
}

[data-fila-enfocada]:focus,
[data-fila-enfocada]:focus-visible {
    outline: 2px solid transparent;
    outline-offset: -2px;
}

/* La fila de documento es «display: contents»: no tiene caja, la señal va en sus celdas. */
.fila-documento-requerido[data-fila-enfocada] > * {
    background-color: var(--color-surface-hover);
}

.fila-documento-requerido[data-fila-enfocada] > :first-child {
    box-shadow: inset 3px 0 0 var(--color-primary-500);
}

.celda-acciones-revision {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-2);
    white-space: nowrap;
}

.fila-previsualizacion td {
    padding: var(--space-4);
    background-color: var(--color-surface-hover);
}

.previsualizacion-documento {
    display: block;
    width: 100%;
    height: 600px;
    border: var(--border-default);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
}

/*
  QuickGrid rellena el cuerpo de la tabla con filas <tr><td></td></tr>
  vacías hasta completar ItemsPerPage cuando hay menos resultados que el
  tamaño de página, incluso sin Virtualize — es un comportamiento del
  componente, no del ItemsProvider (que ya devuelve solo los elementos
  reales). Se ocultan por CSS las filas donde ninguna celda tiene contenido.
*/
.tabla-datos tbody tr:not(:has(td:not(:empty))) {
    display: none;
}

/*
  Revelado escalonado: cada fila/tarjeta entra un poco después que la
  anterior en vez de aparecer todas a la vez. Solo se dispara cuando el
  navegador inserta el elemento en el DOM — Blazor reutiliza las filas
  existentes al paginar/filtrar (mismo índice, solo cambia el contenido),
  así que esto se ve en la carga inicial de una pantalla, no se repite en
  cada tecla de un buscador en vivo (sería ruido, no pulido).
  .stagger-item es la clase genérica para reutilizar el mismo patrón fuera
  de tablas (p. ej. tarjetas de KPI en Dashboard).
*/
@keyframes revelar-escalonado {
    from {
        opacity: 0;
        transform: translateY(6px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.tabla-datos tbody tr,
.stagger-item {
    animation: revelar-escalonado var(--motion-transition) var(--ease-fluid) backwards;
}

.tabla-datos tbody tr:nth-child(1), .stagger-item:nth-child(1)   { animation-delay: 0ms; }
.tabla-datos tbody tr:nth-child(2), .stagger-item:nth-child(2)   { animation-delay: 25ms; }
.tabla-datos tbody tr:nth-child(3), .stagger-item:nth-child(3)   { animation-delay: 50ms; }
.tabla-datos tbody tr:nth-child(4), .stagger-item:nth-child(4)   { animation-delay: 75ms; }
.tabla-datos tbody tr:nth-child(5), .stagger-item:nth-child(5)   { animation-delay: 100ms; }
.tabla-datos tbody tr:nth-child(6), .stagger-item:nth-child(6)   { animation-delay: 125ms; }
.tabla-datos tbody tr:nth-child(7), .stagger-item:nth-child(7)   { animation-delay: 150ms; }
.tabla-datos tbody tr:nth-child(8), .stagger-item:nth-child(8)   { animation-delay: 175ms; }
.tabla-datos tbody tr:nth-child(9), .stagger-item:nth-child(9)   { animation-delay: 200ms; }
.tabla-datos tbody tr:nth-child(10), .stagger-item:nth-child(10) { animation-delay: 225ms; }
.tabla-datos tbody tr:nth-child(11), .stagger-item:nth-child(11) { animation-delay: 250ms; }
.tabla-datos tbody tr:nth-child(n+12), .stagger-item:nth-child(n+12) { animation-delay: 275ms; }

@media (prefers-reduced-motion: reduce) {
    .tabla-datos tbody tr,
    .stagger-item {
        animation: none;
    }
}

/*
  Acabado de tablas (ficha 14). Cabecera fija: la tabla desplaza dentro de
  .contenido (o del cuerpo de un Drawer/Modal), así que top:0 la pega al borde
  del contenedor que desplaza. Sin overflow en .tabla-datos (ver arriba), el
  sticky llega al contenedor real. En móvil .tabla-datos pasa a ser su propio
  contenedor (overflow-x) y la cabecera deja de pegarse: no es un fallo.
  Lo mismo pasa, a cualquier ancho, en una tabla envuelta en un contenedor con
  overflow-x propio (listado de Documentos, .documentos-tabla-desplazable): ni
  la cabecera ni la sombra de abajo se pegan.
*/
.tabla-datos thead th {
    position: sticky;
    top: 0;
    z-index: 1;
}

/*
  Sombra bajo la cabecera mientras se desplaza, con la línea de tiempo de
  scroll del navegador (sin JS). Sin soporte, la cabecera simplemente no lleva
  sombra. El rango 0–40px la hace crecer a medida que el contenido se va.
*/
@supports (animation-timeline: scroll()) {
    @media (prefers-reduced-motion: no-preference) {
        .tabla-datos thead th {
            animation: sombra-cabecera-tabla linear both;
            animation-timeline: scroll(nearest block);
            animation-range: 0 40px;
        }
    }
}

@keyframes sombra-cabecera-tabla {
    from {
        box-shadow: 0 0 0 0 transparent;
    }
    to {
        box-shadow: var(--shadow-cabecera-tabla);
    }
}

/*
  Destello de la fila nueva o modificada por una acción del usuario: lo pone
  js/destello-fila.js (o la propia pantalla, añadiendo la clase), nunca en la
  carga inicial. Anima solo el fondo de las celdas hacia el que ya tengan, así
  que no hay que repetir el color final.
*/
.tabla-datos tr.fila-destello td {
    animation: destello-fila 1.5s var(--ease-standard);
}

@keyframes destello-fila {
    from {
        background-color: color-mix(in srgb, var(--color-primary-500) 24%, transparent);
    }
}

@media (prefers-reduced-motion: reduce) {
    .tabla-datos tr.fila-destello td {
        animation: none;
    }
}

/*
  Móvil: la tabla ya no cabe con todas sus columnas en ~375-767px, y
  table-layout:auto la aplastaría hasta ser ilegible en vez de desbordar.
  display:block convierte el <table> en la caja que scrollea; thead/tbody
  siguen generando su caja de tabla anónima interna con su ancho natural
  (sin comprimirse), así que el contenido real desborda ese bloque y aquí
  es donde aparece el scroll horizontal — sin envolver cada tabla en un div
  nuevo por página (esta clase la comparten ~15 pantallas de listado, ver
  cabecera del archivo).
*/
@media (max-width: 767px) {
    .tabla-datos {
        display: block;
        overflow-x: auto;
    }

    .tabla-datos th,
    .tabla-datos td {
        white-space: nowrap;
    }
}


/*
  Ranura individual del grid de indicadores (Centro y Trabajador — ver
  ".tarjeta-fila-acordeon-indicadores" / ".wbadges-fila-trabajador"). Existe
  aunque la fila no tenga ese recuento: es lo que permite leer la columna en
  vertical y lo que impide que el contenido de una ranura se corra hacia la
  ranura vecina cuando falta un número.
*/
.ranura-recuento {
    display: flex;
    justify-content: flex-start;
    min-width: 0;
}

/*
  Badge de solo recuento (DDL-036): sin etiqueta de texto. Solo es admisible
  porque va dentro de una VentanaContexto, que aporta el nombre accesible y el
  desglose literal — el número por sí solo dejaría el color como único
  portador de significado.
*/
.badge-solo-recuento {
    min-width: 26px;
    justify-content: center;
    font-variant-numeric: tabular-nums;
}

/* Cabecera de ámbito dentro del desglose de una ventana de contexto. */
.ventana-grupo {
    font: var(--font-caption);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
    margin-top: var(--space-1);
}

.ventana-grupo:first-child {
    margin-top: 0;
}

/*
  Cabecera de cada ventana de vencimiento de Preventivo (D-24): a ancho
  completo, con el rótulo en una línea y el recuento en línea al final. Antes
  reutilizaba la rejilla de 5 columnas fijas de la fila de Trabajador con solo
  3 hijos, y el rótulo caía en la columna de 14 px y se partía en cinco líneas.
*/
.cabecera-ventana-preventivo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) 0;
}

.cabecera-ventana-preventivo > .fila-trabajador-nombre {
    font: var(--font-body-md);
    font-weight: 600;
    white-space: nowrap;
}

.cabecera-ventana-preventivo > .fila-trabajador-fraccion {
    margin-left: auto;
    white-space: nowrap;
}


/*
  Ámbito Empresa dentro del acordeón de un Centro (OD-13, blueprint § 3.3).

  Los dos ámbitos van declarados y separados: sin el rótulo, el bloque de la
  empresa se leería como "un trabajador más" y el recuento del Centro —que
  agrega los dos— dejaría de poder explicarse.
*/
.separador-ambito {
    font: var(--font-caption);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--color-text-muted);
    padding: var(--space-3) 0 var(--space-1);
}

.fila-sujeto-ambito {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) 0;
    border-bottom: var(--border-default);
}

.sujeto-ambito-identidad {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.sujeto-ambito-nombre {
    font: var(--font-body-md);
    font-weight: 600;
}

/*
  Distintivo junto al nombre de la fila Empresa (ESPECIFICACION-VISUAL-HYDRA (documento que ya no existe)
  § 3.7, ".etiqueta-ambito") — el separador "Empresa" de arriba da contexto a
  todo el bloque, pero al leer solo esta fila (fuera de contexto, p. ej. al
  volver de un scroll) el nombre por sí solo no dice si es una empresa o un
  trabajador más.
*/
.etiqueta-ambito {
    font: var(--font-caption);
    font-size: 0.5625rem; /* 9px */
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
    border: var(--border-default);
    border-radius: var(--radius-sm);
    padding: 1px 5px;
}

/*
  La nota que exige el blueprint: sin ella, una lista corta se leería como
  "la empresa casi no tiene documentación" en vez de "esto es lo que falla".
*/
.sujeto-ambito-nota {
    font: var(--font-body-sm);
    color: var(--color-text-muted);
}

/*
  Misma anchura que la zona de indicadores de la fila de Centro (200px,
  contrato de fidelidad 2026-08-09 § 1.6), para que el recuento de la empresa
  caiga en la vertical de los recuentos de arriba.
*/
.sujeto-ambito-indicadores {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 200px;
    flex-shrink: 0;
}

.sujeto-ambito-accion {
    flex-shrink: 0;
}

/*
  Columna de estado de un listado (EstadoFila): ancho fijo y contenido alineado a la izquierda, para que las
  pastillas formen una columna recta de fila en fila y de un listado a otro, lleven o no motivo debajo.
  QuickGrid pone la clase de la columna tanto en el <th> como en el <td>.
*/
.tabla-datos th.col-estado,
.tabla-datos td.col-estado {
    width: 200px;
    min-width: 200px;
    max-width: 200px;
    text-align: left;
}

/*
  Columna «Registrados vigentes» de un listado de propietarios: ancho fijo, justo antes de la de estado, para
  que caiga en el mismo sitio de fila en fila. La regla es compartida (vive aquí, no en el CSS de una
  pantalla); hoy solo la usa el listado de Trabajadores. La celda aloja la barra de cumplimiento compartida, con la
  fracción («8/10») como cifra.
*/
.tabla-datos th.col-registrados-vigentes,
.tabla-datos td.col-registrados-vigentes {
    width: 176px;
    min-width: 176px;
    max-width: 176px;
    text-align: left;
}

.celda-registrados-vigentes {
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
