/* Indicadores por responsable — identidad v0 completa: tipografía SF Pro /
   sistema Apple, radios y sombras de 3 niveles, escala de espaciado 4-40,
   y ahora la paleta de color real de v0 (superficie/texto/borde/primario/
   estado). Los roles semánticos abajo (--background, --card, --muted,
   --border, --pista-barra) son alias de conveniencia hacia los --color-*
   reales, mapeados 1:1 según lo pedido; todo lo demás (--muted-foreground,
   --ring, --color-verde/ambar/rojo del swap anterior) se retiró para usar
   los tokens reales directo en cada sitio, sin capas intermedias. */

:root {
  color-scheme: light;

  /* ============ Tokens reales de v0 ============ */
  --color-bg-base: #f1f4f8;
  --color-bg-gradient: #eef3ff;
  --color-surface: #ffffff;
  --color-surface-elevated: #ffffff;
  --color-surface-soft: #f7f8fa;
  --color-border-subtle: #f0f1f4;
  --color-border: #e1e5eb;
  --color-border-strong: #c7cdd6;
  --color-text-primary: #202b3f;
  --color-text-secondary: #687486;
  --color-text-muted: #9aa3af;
  --color-text-disabled: #c1c7d0;
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-primary-active: #1e40af;
  --color-primary-soft: #eef4ff;
  --color-success-text: #079669;
  --color-success-soft: #e8f8f1;
  --color-success-border: #a9e4cc;
  --color-warning-text: #d97706;
  --color-warning-soft: #fff5df;
  --color-warning-border: #f5d49a;
  --color-error-text: #ef4444;
  --color-error-soft: #fff0f0;
  --color-error-border: #f4b7b7;
  --color-info-text: #2563eb;
  --color-info-soft: #eef4ff;
  --color-info-border: #b7cbff;

  /* ============ Alias semánticos usados en el resto del CSS ============ */
  --background: var(--color-bg-base); /* fondo de página */
  --card: var(--color-surface); /* cards: barra de filtros, card de responsables */
  --muted: var(--color-surface-soft); /* campos de filtro, filas de tabla en hover */
  --border: var(--color-border); /* bordes de cards y controles */
  --pista-barra: var(--color-border-subtle); /* track de la barra de progreso */
  --foreground: var(--color-text-primary); /* títulos y valores */

  /* -- Tipografía -- */
  --fuente: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Segoe UI", sans-serif;

  /* -- Radios -- */
  --radio: 16px; /* card principal */
  --radio-kpi: 14px; /* card KPI / barra de filtros */
  --radio-boton: 10px;
  --radio-input: 9px;
  --radio-avatar: 8px;
  --radio-pill: 999px; /* pill/badge y barra de progreso */
  --radio-chico: var(--radio-input);

  /* -- Sombras (3 niveles) -- */
  --sombra-sutil: 0 1px 2px rgba(32, 43, 63, 0.04);
  --sombra-media: 0 8px 24px rgba(32, 43, 63, 0.07), 0 2px 6px rgba(32, 43, 63, 0.04);
  --sombra-elevada: 0 18px 45px rgba(32, 43, 63, 0.12), 0 4px 12px rgba(32, 43, 63, 0.06);
  --sombra: var(--sombra-sutil);
  --sombra-card: var(--sombra-media);

  /* -- Espaciado: escala 4/8/12/16/20/24/32/40 -- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;

  --ancho-contenido: 1920px;
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --color-bg-base: #101114;
    --color-bg-gradient: #171b27;
    --color-surface: #1c1d21;
    --color-surface-elevated: #25272d;
    --color-surface-soft: #202228;
    --color-border-subtle: #292c33;
    --color-border: #383c45;
    --color-border-strong: #565c68;
    --color-text-primary: #f5f7fa;
    --color-text-secondary: #b4bbc7;
    --color-text-muted: #7f8795;
    --color-text-disabled: #5e6470;
    --color-primary: #6c8cf4;
    --color-primary-hover: #86a0ff;
    --color-primary-active: #a8b9ff;
    --color-primary-soft: #202b4a;
    --color-success-text: #35bc87;
    --color-success-soft: #173b30;
    --color-success-border: #286c54;
    --color-warning-text: #f59e0b;
    --color-warning-soft: #493516;
    --color-warning-border: #8d641c;
    --color-error-text: #ff6b6b;
    --color-error-soft: #482124;
    --color-error-border: #8b3f43;
    --color-info-text: #6c8cf4;
    --color-info-soft: #202b4a;
    --color-info-border: #4562b7;

    /* Sombras: ~30% menos opacidad que en light (los bordes ya son más
       claros arriba, que es lo que las complementa en dark). */
    --sombra-sutil: 0 1px 2px rgba(0, 0, 0, 0.03);
    --sombra-media: 0 8px 24px rgba(0, 0, 0, 0.05), 0 2px 6px rgba(0, 0, 0, 0.03);
    --sombra-elevada: 0 18px 45px rgba(0, 0, 0, 0.08), 0 4px 12px rgba(0, 0, 0, 0.04);
  }
}

/* Semáforo: usa los tokens de ESTADO reales de v0 directo (sin alias
   intermedios) — así "verifica que use los tokens de estado de v0" es
   literal: éxito → verde, advertencia → ámbar, error → rojo. El dark mode
   sale solo, porque estos --color-*-text ya cambian con el tema arriba. */
.fila--verde {
  --color-fill: var(--color-success-text);
  --color-texto: var(--color-success-text);
}
.fila--ambar {
  --color-fill: var(--color-warning-text);
  --color-texto: var(--color-warning-text);
}
.fila--rojo {
  --color-fill: var(--color-error-text);
  --color-texto: var(--color-error-text);
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  padding: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Halo superior sutil (--color-bg-gradient -> --color-bg-base): decae a
     los 480px, así que el resto de la página siempre queda en el fondo
     base plano, no importa cuán larga sea. */
  background: linear-gradient(180deg, var(--color-bg-gradient) 0%, var(--color-bg-base) 480px);
  color: var(--foreground);
  font-family: var(--fuente);
  font-size: 13px; /* Cuerpo v0 = 0.8125rem con raíz de 16px */
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ---------- Header ---------- */
/* Comparte el mismo max-width + centrado que .contenido (mismo valor de
   --ancho-contenido, mismo padding lateral clamp): así el logo/título/logo
   de empresa quedan alineados en el mismo borde que las cards de abajo, en
   vez de flotar sueltos hacia el borde real del viewport. */

.header {
  flex: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-6) clamp(16px, 3vw, 32px) var(--space-2);
  max-width: var(--ancho-contenido);
  width: 100%;
  margin: 0 auto;
}

.header__marca {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-width: 0;
}

.header__logo-app {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: var(--radio-avatar);
  object-fit: contain;
  box-shadow: var(--sombra-sutil);
}

/* Microtexto: encabezados chicos / metadatos */
.header__app {
  margin: 0 0 2px;
  font-size: 9px;
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
}

/* Título: mismo escalón que el header de card (v0 no define un tier propio
   solo para el H1 de página; "Display" es para valores KPI, no texto). */
.header__titulos h1 {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.025em;
}

/* Cuerpo */
.header__fecha {
  margin: 6px 0 0;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
  /* Sentence-case: la mayúscula la pone format.js en el propio texto
     ("Martes, 15 de septiembre..."), no un text-transform (que forzaría
     Title Case en cada palabra: "De Septiembre De"). */
}

/* Badge blanco fijo (no sigue el tema): el logo de la empresa se veía muy
   solo flotando en el header, así que se envuelve en una pill blanca con
   el nombre al lado — un "sticker" de marca que se queda igual en light y
   dark, en vez de otro elemento que se funde con el fondo de la página. */
.header__badge-empresa {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px 6px 8px;
  background: #ffffff;
  border: 1px solid var(--color-border);
  border-radius: var(--radio-pill);
  box-shadow: var(--sombra-sutil);
}

.header__logo-empresa {
  flex: none;
  height: 26px;
  width: auto;
  object-fit: contain;
}

/* Color fijo (no var(--color-text-primary)): el badge es blanco siempre,
   en dark mode ese token se vuelve casi blanco y el texto desaparecería. */
.header__badge-empresa__texto {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #202b3f;
}

@media (max-width: 640px) {
  .header {
    flex-wrap: wrap;
  }
}

/* ---------- Layout general ---------- */
/* .contenido es el shell de "pantalla fija": ocupa el resto del viewport
   (flex:1 en un body que ya es 100vh) en columna, y solo la card de la
   tabla puede crecer/scrollear — el resto (filtros, estado) tiene alto
   natural. Así ~16 responsables entran sin que la PÁGINA scrollee. */

.contenido {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: var(--space-4) clamp(16px, 3vw, 32px) var(--space-6);
  max-width: var(--ancho-contenido);
  width: 100%;
  margin: 0 auto;
}

/* ---------- Barra de filtros ---------- */
/* Una sola fila horizontal compacta: rótulo, dos pills condensados (Periodo,
   Cliente), el rango manual (oculto salvo "Rango personalizado"), y a la
   derecha el rango ya resuelto en texto + Limpiar. Debajo, la línea de
   contexto en lenguaje natural.
   Radio "card KPI" (14px) porque es una card secundaria, no la principal
   (esa es la de la tabla, 16px). 24px de separación con la card principal
   de abajo = "entre secciones principales" de la escala de espaciado. */

.filtros-bar {
  flex: none;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radio-kpi);
  box-shadow: var(--sombra-sutil);
  padding: var(--space-2) var(--space-4);
  margin-bottom: var(--space-6);
}

.filtros-bar__fila {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  min-height: 36px;
}

/* Subtítulo: título de grupo (el rótulo abre la barra) */
.filtros-bar__rotulo {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--color-text-secondary);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  padding-right: var(--space-2);
  border-right: 1px solid var(--color-border-subtle);
}

/* ---------- Pill: label chico arriba, valor abajo, un solo borde ---------- */

.pill {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  padding: 4px var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radio-input);
  background: var(--muted);
}

/* Label: labels de filtros */
.pill__label {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
  line-height: 1.3;
}

.pill__select,
.pill__input {
  appearance: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--foreground);
  background: transparent;
  border: none;
  padding: 0;
  line-height: 1.3;
  min-width: 0;
}

.pill__select {
  cursor: pointer;
}

/* "Inputs en foco" (--color-border-strong) para el borde + el halo con el
   azul primario (--color-primary) alrededor — dos roles v0 distintos. */
.pill:has(.pill__select:focus-visible),
.pill:has(.pill__input:focus-visible) {
  border-color: var(--color-border-strong);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 25%, transparent);
}

.pill:hover {
  border-color: var(--color-border-strong);
}

.pill__select:focus-visible,
.pill__input:focus-visible {
  outline: none;
}

/* Siempre visible (no vive dentro de .rango-manual, que se oculta/muestra
   según el Periodo) — marca la zona de fecha del filtro de punta a punta. */
.filtros-bar__icono-fecha {
  flex: none;
  color: var(--color-text-secondary);
}

.rango-manual {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.rango-manual[hidden] {
  display: none;
}

/* ---------- Derecha: rango resuelto + Limpiar ---------- */

.filtros-bar__derecha {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-left: auto;
  padding-left: var(--space-3);
}

/* Cuerpo, con tabular-nums porque es una fecha */
.filtros-bar__rango {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
  white-space: nowrap;
}

/* Acento/enlace: primario + sus variantes hover/active de v0 */
.filtros-bar__limpiar {
  appearance: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--color-primary);
  background: none;
  border: none;
  padding: 4px 2px;
  cursor: pointer;
  white-space: nowrap;
}

.filtros-bar__limpiar:hover {
  color: var(--color-primary-hover);
  text-decoration: underline;
}

.filtros-bar__limpiar:active {
  color: var(--color-primary-active);
}

.filtros-bar__limpiar:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radio-boton);
}

/* ---------- Línea de contexto (Cuerpo) ---------- */

.filtros-bar__resumen {
  margin: 6px 2px 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--color-text-secondary);
}

.filtros-bar__resumen strong {
  color: var(--foreground);
  font-weight: 600;
}

@media (max-width: 760px) {
  .filtros-bar__derecha {
    margin-left: 0;
    padding-left: 0;
    width: 100%;
    justify-content: space-between;
  }
}

/* ---------- Estado (loading / error) ---------- */

.estado {
  flex: none;
  color: var(--color-text-secondary);
  font-size: 13px;
  padding: 4px 4px 16px;
}

.estado[data-tipo="error"] {
  color: var(--color-error-text);
}

/* ---------- Fila de 3 KPIs (entregas) ---------- */
/* flex:none y compacta a propósito: va ARRIBA de la card de responsables
   (que es flex:1) dentro del mismo shell de pantalla fija — cada px que se
   ahorra acá es presupuesto vertical para que quepan los 16 responsables.
   La altura de la fila la sigue marcando la card de OTIF (la más alta de
   las 3, con la dona) — agregar las otras 2 al lado NO le sumó alto a la
   fila, solo la repartió en 3 columnas iguales. */

.kpis-fila {
  flex: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

/* Card base compartida por las 3 (header + body). display:flex en columna +
   el body con flex:1 centrado es lo que hace que, si el grid las estira
   parejo (la fila la marca la más alta, con la dona), las cards con menos
   contenido (Completadas, En proceso) no queden con el texto pegado arriba
   — se centran solas en el alto disponible. */
.kpi-card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radio);
  box-shadow: var(--sombra-card);
  overflow: hidden;
  transition: opacity 0.15s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.kpi-card.cargando {
  opacity: 0.5;
  pointer-events: none;
}

.kpi-card:hover {
  box-shadow: var(--sombra-elevada);
}

.kpi-card__header {
  flex: none;
  padding: var(--space-2) var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
}

/* Subtítulo: un escalón por debajo del Título de "Responsables de proyecto"
   — esa sigue siendo la sección principal, esta fila es un resumen arriba. */
.kpi-card__titulo {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kpi-card__body {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  padding: var(--space-4) var(--space-5);
}

/* -- OTIF: dona + métricas lado a lado -- */

.kpi-card__body--dona {
  gap: var(--space-4);
}

/* -- Dona: SVG puro, sin librerías -- */

.dona {
  position: relative;
  flex: none;
  width: 84px;
  height: 84px;
}

.dona__svg {
  width: 100%;
  height: 100%;
}

.dona__track {
  fill: none;
  stroke: var(--color-border-subtle);
  stroke-width: 10;
}

/* Circunferencia de r=40 (2πr ≈ 251.33): dasharray fijo, dashoffset animado
   por JS (mismo mecanismo que .barra__fill, pero con stroke-dashoffset en
   vez de width). rotate(-90deg) para que arranque arriba (12 en punto) en
   vez del 0° por defecto de SVG (3 en punto). */
.dona__arco {
  fill: none;
  stroke: var(--color-primary);
  stroke-width: 10;
  stroke-linecap: round;
  stroke-dasharray: 251.33px;
  stroke-dashoffset: 251.33px;
  transform: rotate(-90deg);
  transform-origin: 50px 50px;
  transition: stroke-dashoffset 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

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

.dona__centro {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Hero figure: proporcional (no tabular-nums), peso/tracking de "Display" */
.dona__pct {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-text-primary);
}

/* -- Los 3 números, apilados verticalmente -- */

.otif-metricas {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.otif-metrica {
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.otif-metrica__valor {
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-primary);
}

/* El valor lleva el color de estado; el label se queda neutro (el color no
   debe repetirse en el texto descriptivo, solo en el dato). */
.otif-metrica--exito .otif-metrica__valor {
  color: var(--color-success-text);
}

.otif-metrica--error .otif-metrica__valor {
  color: var(--color-error-text);
}

.otif-metrica__label {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
}

/* -- "Órdenes completadas": barra doble (track + fill encima) + resumen -- */

.kpi-card__body--completadas {
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: var(--space-3);
}

.progreso-doble {
  height: 10px;
  border-radius: var(--radio-pill);
  background: var(--color-border-subtle); /* la barra "base" (total) */
  overflow: hidden;
}

.progreso-doble__fill {
  height: 100%;
  border-radius: var(--radio-pill);
  background: var(--color-success-text); /* la barra "encima" (completadas) */
  transition: width 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: reduce) {
  .progreso-doble__fill {
    transition: none;
  }
}

.completadas-resumen {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

/* Neutro a propósito (no verde): a diferencia de "A tiempo"/"Atrasadas" del
   OTIF, acá no hay dos categorías compitiendo por color — el verde ya lo
   lleva la barra de arriba, el número es simplemente el valor KPI. */
.completadas-pct {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-text-primary);
}

.completadas-detalle {
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
}

/* -- "En proceso": número héroe + desglose -- */

.kpi-card__body--proceso {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-1);
}

.proceso-hero {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

/* Display literal (2rem/700/-0.04em): a diferencia de la celda % de la
   tabla de responsables, acá sí hay espacio de sobra para el tamaño real
   que pide el sistema v0 para "el valor KPI principal". */
.proceso-valor {
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  color: var(--color-text-primary);
}

.proceso-label {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
}

.proceso-detalle {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
}

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

@media (max-width: 480px) {
  .kpi-card__body--dona {
    flex-wrap: wrap;
    gap: var(--space-4);
  }
}

/* ---------- Card contenedora de la tabla ---------- */
/* flex:1 la hace ocupar todo el resto del viewport disponible; min-height:0
   es lo que permite que su contenido (.tabla-scroll) pueda scrollear en vez
   de forzar a la card (y a la página) a crecer más allá del viewport. */

.tabla-card {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radio);
  box-shadow: var(--sombra-card);
  overflow: hidden;
  transition: opacity 0.15s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.tabla-card:hover {
  box-shadow: var(--sombra-elevada);
}

.tabla-card.cargando {
  opacity: 0.5;
  pointer-events: none;
}

.tabla-card__header {
  flex: none;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
}

/* Título: encabezado de card */
.tabla-card__titulo {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.025em;
}

/* Resumen de faltantes: compacto a propósito (padding chico) — vive dentro
   de la card de responsables, entre el título y la tabla, y le resta alto a
   .tabla-scroll (que es flex:1). El scroll interno absorbe la diferencia si
   hace falta, tal como ya pasa con el resto del contenido de esta card. */
.tabla-card__resumen {
  flex: none;
  padding: var(--space-2) var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
}

.faltantes-principal {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

/* Display literal (2rem/700/-0.04em) — mismo tratamiento que "En proceso". */
.faltantes-valor {
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  color: var(--color-text-primary);
}

/* Atención sutil: solo cuando hay algo pendiente (>0). Un único tono, sin
   escalar a rojo por volumen — "sin exagerar" pedía el brief. */
.faltantes-valor--atencion {
  color: var(--color-warning-text);
}

.faltantes-label {
  font-size: 0.8125rem;
  color: var(--color-text-secondary);
}

.faltantes-detalle {
  margin: 2px 0 0;
  font-size: 0.75rem;
  color: var(--color-text-secondary);
}

.faltantes-detalle span {
  font-variant-numeric: tabular-nums;
}

/* Única región que scrollea cuando los responsables no caben verticalmente;
   la página en sí nunca lo hace. */
.tabla-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: auto;
  position: relative;
}

.tabla-vacio {
  text-align: center;
  color: var(--color-text-secondary);
  padding: var(--space-8) var(--space-4);
}

/* ---------- Dos columnas ---------- */

.tabla-columnas {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
}

/* [hidden] de por sí ya oculta, pero como .tabla-columnas define su propio
   `display: grid` (misma especificidad, origen "autor"), necesita este
   override explícito o ganaría por sobre la regla del navegador. */
.tabla-columnas[hidden] {
  display: none;
}

.tabla-columnas > .tabla:first-child {
  border-right: 1px solid var(--color-border-subtle);
}

@media (max-width: 900px) {
  .tabla-columnas {
    grid-template-columns: 1fr;
  }

  .tabla-columnas > .tabla:first-child {
    border-right: none;
    border-bottom: 1px solid var(--color-border-subtle);
  }

  /* En pantallas chicas no vale la pena forzar "una sola pantalla": se deja
     crecer la card y scrollea la página entera, como cualquier sitio normal. */
  .tabla-card {
    flex: none;
  }

  .tabla-scroll {
    overflow-y: visible;
  }

  .contenido {
    padding-bottom: 48px;
  }
}

/* ---------- Tabla ---------- */

.tabla {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}

/* Microtexto: encabezados de tabla */
.tabla__th {
  text-align: left;
  font-size: 0.5625rem;
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border-subtle);
  white-space: nowrap;
}

.tabla__th--num {
  text-align: right;
}

.tabla__th--grafica {
  text-align: left;
  min-width: 110px;
}

.tabla__fila {
  border-bottom: 1px solid var(--color-border-subtle);
  transition: background-color 0.15s ease;
}

.tabla__fila:last-child {
  border-bottom: none;
}

.tabla__fila:hover {
  background: var(--muted);
}

.tabla__td {
  padding: 8px 12px;
  vertical-align: middle;
}

.tabla__td--num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--foreground);
}

.tabla__td--muted {
  color: var(--color-text-muted);
}

/* El % de cada fila toma el peso/tracking de "Display" (los valores KPI
   principales) pero NO su tamaño literal (2rem): en una tabla de 6 columnas
   x 2 filas por fila eso rompería la pantalla fija de ~16 responsables sin
   scroll, que el pedido pidió explícitamente no tocar. Se conserva el
   tamaño de columna y se adopta el peso 700 + tracking negativo.
   display:flex con el badge ANTES del texto en el DOM (ver render.js) deja
   el % siempre pegado al borde derecho, con o sin badge — si el badge fuera
   el último elemento, sería él el que quedaría flush-right y el número se
   correría hacia el centro, desalineando la columna entre filas. */
.tabla__td--pct {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 5px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-texto);
}

/* Badge "casi completo": punto discreto, mismo tono en light/dark porque
   --color-warning-text ya cambia solo por tema. Estático a propósito (sin
   pulso) — es una señal, no una alarma, y así no hay nada que apagar bajo
   prefers-reduced-motion. */
.badge-casi-completo {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-warning-text);
  cursor: default;
}

/* Nombre: rank + avatar + texto */

.fila-nombre {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* Microtexto */
.fila-nombre__rank {
  flex: none;
  width: 16px;
  font-size: 0.5625rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}

/* Avatar/icono: cuadrado redondeado (8px), no círculo — token de v0 */
.avatar {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: var(--radio-avatar);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
}

.fila-nombre__texto {
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Gráfica: barra de progreso, color de estatus */

.barra {
  height: 6px;
  border-radius: var(--radio-pill);
  background: var(--pista-barra);
  overflow: hidden;
  min-width: 70px;
}

.barra__fill {
  height: 100%;
  border-radius: var(--radio-pill);
  background: var(--color-fill);
  width: 0%;
  transition: width 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}

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

/* ---------- Responsive ---------- */

@media (max-width: 640px) {
  .filtros-bar__rotulo {
    border-right: none;
    padding-right: 0;
  }
}

/* ---------- Vida sensorial: entrada escalonada + hover con gracia ---------- */
/* Todo esto es decorativo puro (opacity/transform/box-shadow) — nunca cambia
   tamaños ni posiciones finales, así que no puede romper la pantalla fija.
   Va TODO adentro de `no-preference`: si el usuario pide reducir movimiento,
   ninguna de estas reglas existe para el navegador y los elementos aparecen
   de una, en su estado final — no hay nada que "cancelar" en la rama reduce,
   que es la forma más robusta de respetar la preferencia (el default es
   "sin animación"; la animación es la que se gana el permiso, no al revés). */
@media (prefers-reduced-motion: no-preference) {
  @keyframes entrada {
    from {
      opacity: 0;
      transform: translateY(14px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  .header,
  .filtros-bar,
  .kpi-card,
  .tabla-card {
    animation: entrada 420ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  .header {
    animation-delay: 0ms;
  }

  .filtros-bar {
    animation-delay: 70ms;
  }

  /* Las 3 cards de KPI, una tras otra (~70ms entre ellas). */
  .kpis-fila .kpi-card:nth-child(1) {
    animation-delay: 140ms;
  }
  .kpis-fila .kpi-card:nth-child(2) {
    animation-delay: 210ms;
  }
  .kpis-fila .kpi-card:nth-child(3) {
    animation-delay: 280ms;
  }

  .tabla-card {
    animation-delay: 350ms;
  }

  /* Filas: JS agrega esta clase + --delay (índice local a su columna) SOLO
     en el primer pintado de la página — ver renderTabla() en render.js. Con
     ~8 filas por columna y 32ms entre cada una, la cascada de filas termina
     bien adentro del ~1s de presupuesto total pedido. */
  .tabla__fila--entrada {
    animation: entrada 360ms cubic-bezier(0.16, 1, 0.3, 1) both;
    animation-delay: calc(380ms + var(--delay, 0ms));
  }

  /* Elevación al hover: cards de KPI + card de responsables. El box-shadow
     (arriba, siempre activo) ya da la sensación de "se levanta"; acá solo
     se suma el desplazamiento — la parte que sí cuenta como "movimiento". */
  .kpi-card:hover,
  .tabla-card:hover {
    transform: translateY(-2px);
  }
}
