/* ==========================================================================
   AVANCE DE OBRA — carta Gantt, bitácora, Telegram e informe público.

   ESTE ARCHIVO SIRVE A TRES VISTAS Y SOLO DOS SON DE ESTE MÓDULO:
     views/panel/avance.php      (panel)   → vocabulario `av-*`
     views/panel/telegram.php    (panel)   → vocabulario `av-*` y `tg-*`
     views/showroom/avance.php   (público) → vocabulario `avance-*` y `gantt-*`

   La vista pública NO se puede tocar en esta entrega, así que su vocabulario
   entero se conserva intacto en la PARTE B. El rediseño del panel vive en la
   PARTE A con prefijo propio: así una regla del panel no puede cambiarle la
   cara al informe que el comprador abre desde un WhatsApp.

   No declara ni un token: todo sale de base.css, y por eso el módulo tiene
   modo claro y oscuro sin escribir una línea de color de más.

   LA DECISIÓN QUE MANDA EN LAS DOS PARTES
   ---------------------------------------
   En celular la carta Gantt arranca en "Línea de tiempo", NO en la tabla. Una
   tabla de siete columnas metida en 326 px es ilegible, y ese diagnóstico ya
   está hecho: no se vuelve a discutir. Se resuelve con `[data-vista="auto"]`,
   que es el estado inicial y depende solo de una @media — así funciona sin
   JavaScript. El botón de cambiar vista escribe `data-vista="linea"` o
   `"tabla"` y a partir de ahí manda la persona, no el ancho de pantalla.

   Reglas de auditoría que este archivo respeta (DISENO §7):
   - Cero colores en duro salvo los que vienen de la base de datos (el color de
     cada etapa, que llega por una custom property en línea).
   - Ningún texto por debajo de 13 px (--t-xs). El diseño original pedía 10,5 y
     11 px en las metas: no se copian, se suben al piso del sistema.
   - 44×44 de área táctil en todo control.
   - El body no hace scroll horizontal: lo hacen los contenedores internos.
   ========================================================================== */


/* ##########################################################################
   PARTE A — PANEL
   ########################################################################## */

/* --------------------------------------------------------------------------
   A1. Cascarón

   El panel es NUESTRA marca (DISENO §1): --p ya lo declara panel.css en el
   <html>, así que aquí solo se compone. Las superficies salen de los neutrales
   del sistema y no de los colores del cliente.
   -------------------------------------------------------------------------- */

.av {
  /* Ancho de la columna de nombres del Gantt. Vive acá y no repartido por las
     reglas porque la línea de HOY se posiciona a partir de él: si se
     desincronizan, el marcador cae en el día equivocado. */
  --av-col: clamp(96px, 26%, 168px);

  display: flex;
  flex-direction: column;
  gap: var(--e-5);
  min-width: 0;
}

.av-encabezado {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--e-3) var(--e-4);
}

.av-intro {
  flex: 1 1 22rem;
  min-width: 0;
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
  color: var(--txt-2);
  max-width: 62ch;
  text-wrap: pretty;
}

.av-encabezado__acc {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
}

/* Nota al pie de cualquier bloque. 13 px es el piso del sistema y acá se toca:
   por debajo no existe texto en este módulo. */
.av-pie {
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  color: var(--txt-3);
  max-width: 68ch;
  text-wrap: pretty;
}

.av-enlace {
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  font-weight: var(--peso-enfasis);
  color: var(--p);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.av-enlace:hover { color: var(--p-hover); }

/* --------------------------------------------------------------------------
   A2. Bandas de aviso
   -------------------------------------------------------------------------- */

.av-banda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-3) var(--e-4);
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
}

.av-banda__txt {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 20rem;
  min-width: 0;
  text-wrap: pretty;
}

.av-banda__txt strong { font-weight: var(--peso-titulo); }
.av-banda__txt span { color: var(--txt-2); }

.av-banda--aviso {
  background: var(--aviso-suave);
  border-color: color-mix(in oklab, var(--aviso) 40%, transparent);
}

/* El plan es una oferta, no un error: azul de marca, nunca rojo. */
.av-banda--plan {
  background: var(--p-suave);
  border-color: var(--p-borde);
}

/* --------------------------------------------------------------------------
   A3. Tarjeta
   -------------------------------------------------------------------------- */

.av-tarjeta {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  padding: var(--e-4);
  border-radius: var(--r-lg);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-0);
  box-shadow: var(--sombra-1);
  min-width: 0;
}

/* Tarjeta de apoyo: sin sombra y con el fondo hundido. Se usa en la columna
   lateral, donde tres sombras seguidas ensucian en vez de elevar. */
.av-tarjeta--suave {
  background: var(--sup-1);
  box-shadow: none;
}

/* Estado vacío que ADEMÁS es la tarjeta. Manda el borde punteado del sistema:
   es la señal de "acá va a haber algo", y una tarjeta sólida vacía parece un
   error de carga. base.css lo declara antes, así que hay que repetirlo. */
.av-tarjeta.estado-vacio {
  border-style: dashed;
  border-color: var(--borde-fuerte);
  box-shadow: none;
  padding: var(--e-7) var(--e-4);
}

.av-tarjeta__cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--e-2) var(--e-3);
}

.av-tarjeta__titulo {
  font-size: var(--t-base);
  line-height: var(--lh-h3);
  font-weight: var(--peso-titulo);
  letter-spacing: -.01em;
}

.av-tarjeta__nota {
  margin-top: 2px;
  font-size: var(--t-xs);
  line-height: var(--lh-sm);
  color: var(--txt-2);
  max-width: 62ch;
  text-wrap: pretty;
}

/* Sección sin tarjeta: título + tarjetas hijas (Etapas y tareas). */
.av-seccion {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  min-width: 0;
}

.av-seccion__cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2) var(--e-3);
}

.av-seccion__titulo {
  font-size: var(--t-h3);
  line-height: var(--lh-h3);
  font-weight: var(--peso-titulo);
  letter-spacing: -.01em;
}

.av-seccion__acc { margin-left: auto; }

/* --------------------------------------------------------------------------
   A4. Rejilla de dos columnas

   El corte NO va en 1024 px: la barra lateral del panel se come 248 px, así
   que a 1024 px de ventana el contenido mide ~730 px y partirlo en dos deja la
   carta Gantt en 370. Se parte cuando de verdad sobra ancho.
   -------------------------------------------------------------------------- */

.av-rejilla {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--e-4);
  align-items: start;
  min-width: 0;
}

.av-columna,
.av-lateral {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
  min-width: 0;
}

@media (min-width: 1280px) {
  .av-rejilla { grid-template-columns: minmax(0, 1fr) 320px; }
}

@media (min-width: 1560px) {
  .av-rejilla { grid-template-columns: minmax(0, 1fr) 360px; }
}

/* --------------------------------------------------------------------------
   A5. Avance general
   -------------------------------------------------------------------------- */

.av-general {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--e-4);
  padding: var(--e-5);
}

@media (min-width: 720px) {
  .av-general { grid-template-columns: minmax(0, 1fr) minmax(260px, 300px); }
}

.av-general__izq {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  min-width: 0;
}

.av-general__cifra {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--e-2);
  font-weight: var(--peso-cifra);
  font-size: clamp(2.25rem, 1.6rem + 2.6vw, 3.25rem);
  line-height: 1;
  letter-spacing: -.04em;
}

.av-general__caja {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  padding: var(--e-3);
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
}

.av-general__valor {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
}

.av-general__valor .btn { margin-left: auto; }

/* Barra de progreso. El valor entra por --pct desde el HTML, ya recortado
   entre 0 y 100 en PHP. */
.av-barra {
  position: relative;
  height: 10px;
  border-radius: var(--r-full);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-2);
  overflow: hidden;
}

.av-barra--fina { height: 7px; }

.av-barra__relleno {
  display: block;
  height: 100%;
  width: calc(var(--pct, 0) * 1%);
  border-radius: inherit;
  background: var(--etapa, var(--p));
  transition: width var(--ms-normal) var(--ease-ambos);
}

/* --------------------------------------------------------------------------
   A6. Insignias

   El estado nunca se comunica solo con color (DISENO §2.4): además del tono
   cada estado lleva su propio punto, con forma distinta, y su texto.
   -------------------------------------------------------------------------- */

.av-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--e-1);
  /* Font de interfaz aunque el padre sea .num: una insignia dentro de la cifra
     grande heredaría la monoespaciada y se leería como un dato más. */
  font-family: var(--fuente);
  padding: 3px var(--e-2);
  border-radius: var(--r-sm);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-2);
  color: var(--txt-2);
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  font-weight: var(--peso-enfasis);
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.av-chip--ac      { color: var(--p);     background: var(--p-suave);     border-color: var(--p-borde); }
.av-chip--ok      { color: var(--ok);    background: var(--ok-suave);    border-color: color-mix(in oklab, var(--ok) 45%, transparent); }
.av-chip--info    { color: var(--info);  background: var(--info-suave);  border-color: color-mix(in oklab, var(--info) 45%, transparent); }
.av-chip--aviso   { color: var(--aviso); background: var(--aviso-suave); border-color: color-mix(in oklab, var(--aviso) 45%, transparent); }
.av-chip--error   { color: var(--error); background: var(--error-suave); border-color: color-mix(in oklab, var(--error) 45%, transparent); }
.av-chip--neutro  { color: var(--txt-2); background: var(--sup-2); }

/* Estados de etapa. Color MÁS forma MÁS texto. */
.av-chip--pendiente,
.av-chip--en_curso,
.av-chip--completada,
.av-chip--atrasada { padding-left: var(--e-2); }

.av-chip--pendiente  { color: var(--txt-2); background: var(--sup-2); }
.av-chip--en_curso   { color: var(--info);  background: var(--info-suave);  border-color: color-mix(in oklab, var(--info) 45%, transparent); }
.av-chip--completada { color: var(--ok);    background: var(--ok-suave);    border-color: color-mix(in oklab, var(--ok) 45%, transparent); }
.av-chip--atrasada   { color: var(--error); background: var(--error-suave); border-color: color-mix(in oklab, var(--error) 45%, transparent); }

.av-chip--pendiente::before,
.av-chip--en_curso::before,
.av-chip--completada::before,
.av-chip--atrasada::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: var(--r-full);
  border: 2px solid currentColor;
}

.av-chip--completada::before { background: currentColor; }
.av-chip--en_curso::before   { border-style: dashed; }
.av-chip--atrasada::before   { border-radius: 2px; }

/* Punto de color de una etapa. El color llega de la base por --etapa. */
.av-punto {
  flex: none;
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 3px;
  background: var(--etapa, var(--info));
}

/* --------------------------------------------------------------------------
   A7. Selector de vista (segmentado)
   -------------------------------------------------------------------------- */

.av-segmentado {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-2);
}

.av-segmentado__btn {
  position: relative;
  min-height: 34px;
  padding: 0 var(--e-3);
  border-radius: var(--r-sm);
  font-size: var(--t-xs);
  font-weight: var(--peso-enfasis);
  color: var(--txt-2);
  display: inline-flex;
  align-items: center;
  transition: background var(--ms-instantaneo) var(--ease-ambos),
              color var(--ms-instantaneo) var(--ease-ambos);
}

/* Área táctil real de 44 px sin agrandar el dibujo (DISENO §4.2). */
.av-segmentado__btn::after {
  content: "";
  position: absolute;
  inset: 50%;
  width: var(--tactil);
  height: var(--tactil);
  transform: translate(-50%, -50%);
}

.av-segmentado__btn:hover { color: var(--txt); }
.av-segmentado__btn:active { transform: scale(.97); }

.av-segmentado__btn[aria-pressed="true"] {
  background: var(--sup-0);
  color: var(--txt);
  box-shadow: var(--sombra-1);
}

/* --------------------------------------------------------------------------
   A8. Carta Gantt — conmutación de vista
   -------------------------------------------------------------------------- */

.av-gantt { min-width: 0; }

/* Estado inicial: manda el ancho de pantalla, sin JavaScript.

   Las reglas que ENCIENDEN la línea de tiempo dicen `flex` y no `block`: este
   selector pesa más que el `.av-gantt__linea { display:flex }` de A9 (atributo
   + clase contra una clase suelta), así que un `block` aquí ganaba siempre y
   la caja no era flex nunca — el gap entre la carta y su nota al pie no se
   aplicaba jamás. */
[data-vista="auto"] > .av-gantt__tabla { display: none; }
[data-vista="auto"] > .av-gantt__linea { display: flex; }

@media (min-width: 1024px) {
  [data-vista="auto"] > .av-gantt__tabla { display: block; }
  [data-vista="auto"] > .av-gantt__linea { display: none; }
}

/* Estado elegido a mano: manda la persona, en cualquier ancho. */
[data-vista="linea"] > .av-gantt__linea { display: flex; }
[data-vista="linea"] > .av-gantt__tabla { display: none; }
[data-vista="tabla"] > .av-gantt__tabla { display: block; }
[data-vista="tabla"] > .av-gantt__linea { display: none; }

/* --------------------------------------------------------------------------
   A9. Vista línea de tiempo
   -------------------------------------------------------------------------- */

.av-gantt__linea {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

/* El scroll horizontal vive DENTRO de esta caja. El body no hace scroll
   horizontal nunca. Con la columna de nombres en clamp() la carta cabe hasta en
   326 px, así que esto casi nunca llega a desplazarse: está por seguridad y
   porque avance.js centra el marcador de HOY en este contenedor. */
.av-gantt__scroll {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.av-gantt__lienzo {
  min-width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

.av-gantt__escala,
.av-fila {
  display: grid;
  grid-template-columns: var(--av-col) minmax(0, 1fr);
  gap: var(--e-3);
  align-items: center;
}

.av-gantt__escala {
  padding-bottom: var(--e-1);
  border-bottom: var(--b-fino) solid var(--borde);
}

/* Celda vacía que reserva la columna de nombres: sin ella la escala de meses
   arrancaría pegada al borde y no cuadraría con las barras de abajo. */
.av-gantt__hueco { display: block; }

.av-gantt__meses { display: flex; min-width: 0; }

.av-gantt__mes {
  flex: 0 0 auto;
  min-width: 0;
  width: calc(var(--ancho, 0) * 100%);
  padding-left: var(--e-1);
  border-left: var(--b-fino) solid var(--borde);
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  color: var(--txt-3);
  text-transform: capitalize;
  white-space: nowrap;
  overflow: hidden;
}

.av-gantt__mes:first-child { border-left: 0; padding-left: 0; }

.av-gantt__filas {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
  /* Sitio para la etiqueta de HOY, que se dibuja por encima de la primera
     fila. Sin esto la corta el recorte del contenedor de scroll. */
  padding-top: var(--e-5);
}

.av-fila {
  padding: var(--e-2);
  border-radius: var(--r-md);
  border: var(--b-fino) solid transparent;
  text-decoration: none;
  color: inherit;
  transition: background var(--ms-instantaneo) var(--ease-ambos);
}

.av-fila:hover { background: var(--sup-1); }
.av-fila--activa {
  background: var(--p-suave);
  border-color: var(--p-borde);
}

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

.av-fila__nombre {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  min-width: 0;
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
  font-weight: var(--peso-enfasis);
}

.av-fila__meta {
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  color: var(--txt-3);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.av-fila__pista {
  position: relative;
  display: block;
  height: 30px;
  border-radius: var(--r-sm);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-2);
  overflow: hidden;
}

/* La barra de la etapa. --inicio y --ancho llegan en tanto por uno desde PHP,
   ya recortados: la hoja solo los multiplica por 100. */
.av-fila__barra {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: calc(var(--inicio, 0) * 100%);
  width: calc(var(--ancho, 0) * 100%);
  min-width: 8px;
  border-radius: var(--r-sm);
  background: color-mix(in oklab, var(--etapa, var(--info)) 24%, transparent);
  overflow: hidden;
}

.av-fila__hecho {
  display: block;
  width: calc(var(--pct, 0) * 1%);
  height: 100%;
  background: var(--etapa, var(--info));
}

/* Etapa sin fechas: no tiene barra, tiene una nota. Que no apareciera sería
   peor: el cliente creería que la borró. */
.av-fila__pista--sin-fecha {
  display: flex;
  align-items: center;
  padding: 0 var(--e-2);
  background: repeating-linear-gradient(
    135deg,
    var(--sup-2) 0 8px,
    var(--sup-3) 8px 16px
  );
}

.av-fila__aviso {
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  color: var(--txt-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Marcador de HOY. Se posiciona sobre la COLUMNA DE PISTAS, no sobre la fila
   entera: por eso descuenta el ancho de la columna de nombres y su hueco. */
.av-hoy {
  position: absolute;
  /* Arranca DESPUES del hueco de la etiqueta: la línea cubre las barras y la
     etiqueta se dibuja dentro de ese hueco, no fuera de la caja. */
  top: var(--e-5);
  bottom: 0;
  left: calc(var(--av-col) + var(--e-3) + (100% - var(--av-col) - var(--e-3)) * var(--pos, 0));
  width: 2px;
  background: var(--error);
  pointer-events: none;
  z-index: 2;
}

.av-hoy::before {
  content: attr(data-etiqueta);
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -100%);
  padding: 2px var(--e-2);
  border-radius: var(--r-full);
  background: var(--error);
  color: var(--n-0);
  font-size: var(--t-xs);
  line-height: 1.4;
  font-weight: var(--peso-enfasis);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   A10. Vista tabla
   -------------------------------------------------------------------------- */

/* La tabla scrollea DENTRO de su caja, nunca el body. */
.av-tabla__caja {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}

.av-tabla {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
}

.av-tabla th,
.av-tabla td {
  padding: var(--e-2) var(--e-3);
  text-align: left;
  vertical-align: middle;
  border-bottom: var(--b-fino) solid var(--borde);
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
  font-weight: var(--peso-cuerpo);
}

.av-tabla thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--sup-0);
  font-size: var(--t-xs);
  font-weight: var(--peso-titulo);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--txt-3);
}

.av-tabla tbody th { font-weight: var(--peso-enfasis); }
.av-tabla tbody tr:last-child td,
.av-tabla tbody tr:last-child th { border-bottom: 0; }
.av-tabla tbody tr:hover td,
.av-tabla tbody tr:hover th { background: var(--sup-1); }

.av-tabla td.num,
.av-tabla th.num {
  font-variant-numeric: tabular-nums;
  color: var(--txt-2);
}

.av-tabla__enlace {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  min-width: 0;
  text-decoration: none;
  color: inherit;
}

.av-tabla__enlace:hover { color: var(--p); }

/* La tabla no tiene línea vertical de HOY, así que "hoy" se marca en la fila
   cuya etapa está en curso. */
.av-tabla tr[data-hoy="1"] th:first-child {
  box-shadow: inset 3px 0 0 var(--error);
}

/* --------------------------------------------------------------------------
   A11. Etapas y tareas
   -------------------------------------------------------------------------- */

.av-etapa { gap: var(--e-3); }

.av-etapa--activa {
  border-color: var(--p);
  box-shadow: var(--sombra-2);
}

.av-etapa__cab {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--e-2) var(--e-3);
}

.av-etapa__id {
  flex: 1 1 16rem;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
}

.av-etapa__nombre {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  min-width: 0;
  font-size: var(--t-h3);
  line-height: var(--lh-h3);
  font-weight: var(--peso-titulo);
  letter-spacing: -.01em;
}

.av-etapa__nombre a { text-decoration: none; }
.av-etapa__nombre a:hover { color: var(--p); text-decoration: underline; text-underline-offset: 3px; }

.av-etapa__meta {
  width: 100%;
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  color: var(--txt-3);
  font-variant-numeric: tabular-nums;
}

.av-etapa__acc {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
  margin-left: auto;
}

.av-etapa__pct {
  font-size: var(--t-base);
  font-weight: var(--peso-cifra);
  font-variant-numeric: tabular-nums;
}

.av-tareas {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

.av-tarea {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
  padding: var(--e-2);
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
}

.av-tarea__editar {
  flex: 1 1 18rem;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
}

.av-tarea__nombre {
  flex: 1 1 10rem;
  min-width: 0;
  font-weight: var(--peso-enfasis);
}

.av-tarea--hecha .av-tarea__nombre { color: var(--txt-3); }

.av-tarea__pista {
  flex: none;
  display: block;
  width: 64px;
  height: 6px;
  border-radius: var(--r-full);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-0);
  overflow: hidden;
}

.av-tarea__hecho {
  display: block;
  width: calc(var(--pct, 0) * 1%);
  height: 100%;
  background: var(--etapa, var(--p));
}

.av-tarea__pct { flex: none; width: 5rem; }

/* El estado de la tarea es un botón: se lee y además alterna. Lleva su punto,
   así que no se distingue solo por color. */
.av-tarea__estado {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--e-1);
  min-height: 32px;
  padding: 0 var(--e-2);
  border-radius: var(--r-sm);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-0);
  color: var(--txt-2);
  font-size: var(--t-xs);
  font-weight: var(--peso-enfasis);
  white-space: nowrap;
}

.av-tarea__estado::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: var(--r-full);
  border: 2px solid currentColor;
}

.av-tarea__estado::after {
  content: "";
  position: absolute;
  inset: 50%;
  width: var(--tactil);
  height: var(--tactil);
  transform: translate(-50%, -50%);
}

.av-tarea__estado:hover { border-color: var(--borde-fuerte); color: var(--txt); }

.av-tarea__estado--hecha {
  color: var(--ok);
  background: var(--ok-suave);
  border-color: color-mix(in oklab, var(--ok) 45%, transparent);
}

.av-tarea__estado--hecha::before { background: currentColor; }

.av-tarea__estado:disabled,
.av-tarea__estado[aria-disabled="true"] { opacity: .45; }

/* Botón de solo icono. El dibujo mide 28 px y el área táctil 44. */
.av-iconobtn {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-sm);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-0);
  color: var(--txt-2);
  transition: color var(--ms-instantaneo) var(--ease-ambos),
              border-color var(--ms-instantaneo) var(--ease-ambos),
              background var(--ms-instantaneo) var(--ease-ambos);
}

.av-iconobtn svg { width: 13px; height: 13px; }

.av-iconobtn::after {
  content: "";
  position: absolute;
  inset: 50%;
  width: var(--tactil);
  height: var(--tactil);
  transform: translate(-50%, -50%);
}

.av-iconobtn:hover { color: var(--txt); border-color: var(--borde-fuerte); }
.av-iconobtn:active { transform: scale(.94); }

.av-iconobtn--peligro:hover {
  color: var(--error);
  border-color: color-mix(in oklab, var(--error) 45%, transparent);
  background: var(--error-suave);
}

.av-iconobtn:disabled,
.av-iconobtn[aria-disabled="true"] { opacity: .45; }

/* --------------------------------------------------------------------------
   A12. Plegables

   <details> nativo, no un botón con JavaScript: el formulario tiene que poder
   abrirse en un celular con la señal de una obra, con el script sin cargar.
   -------------------------------------------------------------------------- */

.av-plegable {
  border-radius: var(--r-md);
  border: var(--b-fino) dashed var(--borde-fuerte);
  background: var(--sup-1);
}

.av-plegable[open] { background: var(--sup-1); }

.av-plegable__resumen {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--e-2);
  min-height: 40px;
  padding: 0 var(--e-3);
  border-radius: inherit;
  cursor: pointer;
  font-size: var(--t-xs);
  font-weight: var(--peso-enfasis);
  color: var(--txt-2);
  list-style: none;
}

.av-plegable__resumen::-webkit-details-marker { display: none; }

.av-plegable__resumen::before {
  content: "+";
  flex: none;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: var(--r-sm);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-0);
  font-size: var(--t-xs);
  line-height: 1;
}

.av-plegable[open] > .av-plegable__resumen::before { content: "\2212"; }
.av-plegable__resumen:hover { color: var(--p); }

/* --------------------------------------------------------------------------
   A13. Formularios

   No se usa .campo de base.css: los controles del panel de avance son más
   compactos (34-38 px) porque en esta pantalla hay decenas por vista. El piso
   de 44 px de área táctil se respeta igual, con el ::after invisible.
   -------------------------------------------------------------------------- */

.av-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: var(--e-3);
  align-items: start;
  padding: var(--e-3);
  min-width: 0;
}

.av-form--caja {
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
}

.av-form__titulo {
  font-size: var(--t-xs);
  font-weight: var(--peso-titulo);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--txt-3);
}

.av-form__ancho { grid-column: 1 / -1; }

.av-form__pie {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2) var(--e-3);
}

.av-campo {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
  min-width: 0;
}

.av-campo__etiqueta {
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  font-weight: var(--peso-enfasis);
  color: var(--txt);
}

.av-campo__ayuda {
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  color: var(--txt-3);
  text-wrap: pretty;
}

/* La etiqueta va SIEMPRE arriba y visible, nunca solo el placeholder: al
   escribir, el placeholder desaparece y ya no se sabe qué campo era. */
.av-control {
  width: 100%;
  min-width: 0;
  min-height: 38px;
  padding: var(--e-2) var(--e-3);
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-0);
  color: var(--txt);
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
}

.av-control::placeholder { color: var(--txt-3); }
.av-control:hover { border-color: var(--borde-fuerte); }
.av-control:focus-visible { border-color: var(--p); }

.av-control:disabled,
.av-control[aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
  background: var(--sup-2);
}

.av-control--num {
  width: 5.5rem;
  font-variant-numeric: tabular-nums;
  font-family: var(--fuente-num);
}

.av-control--area {
  min-height: 84px;
  resize: vertical;
  line-height: var(--lh-base);
}

.av-control--color {
  width: 56px;
  padding: var(--e-1);
  cursor: pointer;
}

/* Interruptor con su explicación debajo. */
.av-conmutador {
  display: flex;
  flex-direction: column;
  gap: var(--e-1);
  padding: var(--e-3);
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
}

/* Deshabilitado a propósito y con el motivo escrito al lado: es un control que
   todavía no tiene endpoint, no un adorno. */
.av-conmutador--apagado { opacity: .82; }

/* Zona de arrastre de fotos. El <input file> nativo va encima, transparente:
   así funciona el clic, el teclado y el arrastre sin una línea de JavaScript. */
.av-suelta {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-3);
  padding: var(--e-3);
  border-radius: var(--r-md);
  border: 2px dashed var(--borde-fuerte);
  background: var(--sup-0);
}

.av-suelta__icono { width: 20px; height: 20px; color: var(--p); flex: none; }

.av-suelta__txt {
  flex: 1 1 12rem;
  min-width: 0;
  font-size: var(--t-xs);
  line-height: var(--lh-sm);
  color: var(--txt-2);
  text-wrap: pretty;
}

.av-suelta__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.av-suelta:focus-within {
  border-color: var(--p);
  outline: var(--b-grueso) solid var(--p);
  outline-offset: 2px;
}

.av-suelta__input:disabled { cursor: not-allowed; }

/* --------------------------------------------------------------------------
   A14. Bitácora
   -------------------------------------------------------------------------- */

.av-bitacora { gap: var(--e-4); }

.av-entradas {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.av-entrada {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  padding: var(--e-3);
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
}

.av-entrada__cab {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
}

.av-entrada__fecha {
  font-size: var(--t-sm);
  font-weight: var(--peso-enfasis);
  font-variant-numeric: tabular-nums;
}

.av-entrada__borrar { margin-left: auto; }

.av-entrada__titulo {
  font-size: var(--t-base);
  line-height: var(--lh-h3);
  font-weight: var(--peso-titulo);
}

.av-entrada__texto {
  font-size: var(--t-sm);
  line-height: var(--lh-base);
  white-space: pre-line;
  max-width: 72ch;
  text-wrap: pretty;
}

.av-entrada__fotos {
  display: grid;
  gap: var(--e-2);
  grid-template-columns: repeat(auto-fill, minmax(min(140px, 45%), 1fr));
}

.av-entrada__fotos img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-sm);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-2);
}

/* Una sola foto ocupa el ancho: recortarla a un cuadradito desperdicia la
   única imagen que tiene la entrada. */
.av-entrada__fotos--una { grid-template-columns: minmax(0, 1fr); }
.av-entrada__fotos--una img { aspect-ratio: 16 / 9; }

/* --------------------------------------------------------------------------
   A15. Columna lateral: detalle de la etapa
   -------------------------------------------------------------------------- */

.av-detalle { gap: var(--e-3); }

.av-detalle__titulo {
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  font-weight: var(--peso-titulo);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--txt-3);
}

/* Qué etapa está abierta en el detalle. Caja de texto normal y no la versalita
   del rótulo de arriba: el nombre lo escribe el cliente y va tal cual lo
   escribió. `anywhere` porque un nombre de 120 caracteres sin espacios no
   puede empujar la columna lateral. */
.av-detalle__cual {
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
  font-weight: var(--peso-titulo);
  letter-spacing: -.01em;
  overflow-wrap: anywhere;
}

.av-detalle .av-form { padding: 0; }

.av-detalle__borrar {
  padding-top: var(--e-3);
  border-top: var(--b-fino) solid var(--borde);
}

/* --------------------------------------------------------------------------
   A16. Telegram (panel)
   -------------------------------------------------------------------------- */

.tg-pasos {
  display: grid;
  gap: var(--e-2);
  counter-reset: paso;
  padding: 0;
  margin: 0;
  list-style: none;
}

.tg-pasos li {
  display: flex;
  gap: var(--e-3);
  align-items: flex-start;
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
}

.tg-pasos li::before {
  counter-increment: paso;
  content: counter(paso);
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  background: var(--p-suave);
  color: var(--p);
  font-size: var(--t-xs);
  font-weight: var(--peso-titulo);
}

.tg-codigo {
  align-self: flex-start;
  padding: var(--e-3) var(--e-5);
  border-radius: var(--r-md);
  border: var(--b-grueso) dashed var(--borde-fuerte);
  background: var(--sup-1);
  font-size: clamp(1.5rem, 1.1rem + 2vw, 2.25rem);
  font-weight: var(--peso-cifra);
  letter-spacing: .18em;
  font-variant-numeric: tabular-nums;
}

.tg-comando {
  display: inline-block;
  padding: 2px var(--e-2);
  border-radius: var(--r-sm);
  background: var(--sup-2);
  border: var(--b-fino) solid var(--borde);
  font-family: var(--fuente-num);
  font-size: var(--t-xs);
  /* Un comando largo no puede empujar el ancho del panel. */
  overflow-wrap: anywhere;
}

.tg-vinculo { gap: var(--e-3); }

.tg-vinculo__cab {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--e-2);
}

.tg-vinculo__datos { flex: 1 1 12rem; min-width: 0; }

.tg-vinculo__nombre {
  font-size: var(--t-base);
  font-weight: var(--peso-titulo);
  overflow-wrap: anywhere;
}

.tg-vinculo__acc {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--e-3);
}

.tg-vinculo__forma {
  flex: 1 1 16rem;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--e-2);
}

.tg-vinculo__forma .av-campo { flex: 1 1 12rem; }

.tg-comandos {
  display: grid;
  gap: var(--e-2);
  margin: 0;
}

.tg-comandos dt { min-width: 0; }
.tg-comandos dd { margin: 0; }

/* --------------------------------------------------------------------------
   A17. Tramos del panel

   Compacto (<380px): se QUITA contenido, no se encoge la letra (DISENO §6).
   -------------------------------------------------------------------------- */

@media (max-width: 640px) {
  .av { gap: var(--e-4); }
  .av-general { padding: var(--e-4); }
  .av-seccion__acc { margin-left: 0; width: 100%; }
  .av-seccion__acc.btn { justify-content: center; }
  .av-etapa__acc { margin-left: 0; width: 100%; }
  .av-tarea__pct { width: 4.5rem; }
}

@media (max-width: 380px) {
  .av { --av-col: 96px; }
  .av-tarjeta { padding: var(--e-3); }
  .av-general { padding: var(--e-3); }
  /* La escala de meses no cabe: con las barras y el marcador de HOY ya se
     entiende el calendario, y las etiquetas se pisarían unas con otras. */
  .av-gantt__escala { display: none; }
  /* Sobran: el nombre y el porcentaje de la tarea son lo que se necesita. */
  .av-tarea__pista { display: none; }
}

/* Celular acostado: solo lo imprescindible (DISENO §6). */
@media (max-height: 480px) and (orientation: landscape) {
  .av { gap: var(--e-3); }
}


/* ##########################################################################
   PARTE B — INFORME PÚBLICO Y VOCABULARIO COMPARTIDO

   Todo lo que sigue lo usa views/showroom/avance.php, que en esta entrega NO
   se toca. No borrar nada de acá sin abrir esa vista primero: cada clase de
   este bloque está escrita en ese archivo.
   ########################################################################## */

/* --------------------------------------------------------------------------
   B1. Cascarón y secciones
   -------------------------------------------------------------------------- */

.avance {
  display: flex;
  flex-direction: column;
  gap: var(--e-6);
}

.avance-seccion {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
}

.avance-seccion__cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-3);
}

.avance-seccion__titulo {
  font-size: var(--t-h2);
  line-height: var(--lh-h2);
  font-weight: var(--peso-titulo);
}

.avance-nota {
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
  color: var(--txt-2);
  max-width: 68ch;
}

/* --------------------------------------------------------------------------
   B2. Avance general
   -------------------------------------------------------------------------- */

.avance-general {
  display: grid;
  gap: var(--e-4);
  grid-template-columns: minmax(0, 1fr);
  padding: var(--e-5);
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
}

@media (min-width: 640px) {
  .avance-general { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
}

.avance-general__cifra {
  font-family: var(--fuente-num);
  font-weight: var(--peso-cifra);
  font-size: clamp(2.25rem, 1.6rem + 2.6vw, 3.25rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.avance-general__etiqueta {
  display: block;
  font-family: var(--fuente);
  font-size: var(--t-sm);
  font-weight: var(--peso-enfasis);
  color: var(--txt-2);
}

/* Barra grande del general. El valor entra por --pct desde el HTML. */
.avance-barra {
  position: relative;
  height: 12px;
  border-radius: var(--r-full);
  background: var(--sup-3);
  overflow: hidden;
}

.avance-barra__relleno {
  height: 100%;
  width: calc(var(--pct, 0) * 1%);
  border-radius: inherit;
  background: var(--ok);
  transition: width var(--ms-normal) var(--ease-ambos);
}

/* --------------------------------------------------------------------------
   B3. Selector de vista (segmentado)
   -------------------------------------------------------------------------- */

.avance-vistas {
  display: inline-flex;
  padding: 3px;
  gap: 3px;
  border-radius: var(--r-full);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-2);
}

.avance-vistas__btn {
  position: relative;
  min-height: 38px;
  padding: 0 var(--e-4);
  border-radius: var(--r-full);
  font-size: var(--t-sm);
  font-weight: var(--peso-enfasis);
  color: var(--txt-2);
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  transition: background var(--ms-instantaneo) var(--ease-ambos),
              color var(--ms-instantaneo) var(--ease-ambos);
}

/* Área táctil real de 44 px sin agrandar el dibujo (DISENO §4.2). */
.avance-vistas__btn::after {
  content: "";
  position: absolute;
  inset: 50%;
  width: var(--tactil);
  height: var(--tactil);
  transform: translate(-50%, -50%);
}

.avance-vistas__btn:hover { color: var(--txt); }

.avance-vistas__btn[aria-pressed="true"] {
  background: var(--sup-0);
  color: var(--txt);
  box-shadow: var(--sombra-1);
}

/* --------------------------------------------------------------------------
   B4. Carta Gantt — conmutación de vista
   -------------------------------------------------------------------------- */

.gantt {
  border-radius: var(--r-md);
  border: var(--b-fino) solid var(--borde);
  background: var(--sup-1);
  overflow: hidden;
}

/* Estado inicial: manda el ancho de pantalla. */
[data-vista="auto"] > .gantt-tabla { display: none; }
[data-vista="auto"] > .gantt-linea { display: block; }

@media (min-width: 1024px) {
  [data-vista="auto"] > .gantt-tabla { display: block; }
  [data-vista="auto"] > .gantt-linea { display: none; }
}

/* Estado elegido a mano: manda la persona, en cualquier ancho. */
[data-vista="linea"] > .gantt-linea { display: block; }
[data-vista="linea"] > .gantt-tabla { display: none; }
[data-vista="tabla"] > .gantt-tabla { display: block; }
[data-vista="tabla"] > .gantt-linea { display: none; }

/* --------------------------------------------------------------------------
   B5. Vista línea de tiempo
   -------------------------------------------------------------------------- */

.gantt-linea { padding: var(--e-4); }

.gantt-escala {
  display: flex;
  margin-bottom: var(--e-2);
  padding-bottom: var(--e-1);
  border-bottom: var(--b-fino) solid var(--borde);
}

.gantt-escala__mes {
  flex: 0 0 auto;
  min-width: 0;
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  color: var(--txt-3);
  text-transform: capitalize;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
  border-left: var(--b-fino) solid var(--borde);
  padding-left: var(--e-1);
  width: calc(var(--ancho, 0) * 100%);
}

.gantt-escala__mes:first-child { border-left: 0; padding-left: 0; }

.gantt-filas {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.gantt-fila {
  display: grid;
  gap: var(--e-1);
}

.gantt-fila__cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--e-2);
  min-width: 0;
}

.gantt-fila__nombre {
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
  font-weight: var(--peso-enfasis);
  min-width: 0;
}

.gantt-pista {
  position: relative;
  height: 26px;
  border-radius: var(--r-sm);
  background: var(--sup-2);
  overflow: hidden;
}

/* La barra de la etapa. --inicio y --ancho llegan en tanto por uno desde PHP,
   ya recortados: la vista solo los multiplica por 100. */
.gantt-barra {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: calc(var(--inicio, 0) * 100%);
  width: calc(var(--ancho, 0) * 100%);
  min-width: 6px;
  border-radius: var(--r-sm);
  background: color-mix(in oklab, var(--etapa, var(--info)) 28%, transparent);
  border: var(--b-fino) solid var(--etapa, var(--info));
  overflow: hidden;
}

.gantt-barra__hecho {
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(var(--pct, 0) * 1%);
  background: var(--etapa, var(--info));
}

.gantt-barra__pct {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  padding: 0 var(--e-2);
  font-size: var(--t-xs);
  font-family: var(--fuente-num);
  font-variant-numeric: tabular-nums;
  font-weight: var(--peso-enfasis);
  color: var(--txt);
  /* Sombra de texto como refuerzo: la barra puede ser de cualquier color que
     el cliente elija y no hay contraste garantizado contra el relleno. */
  text-shadow: 0 1px 2px var(--sup-0), 0 0 3px var(--sup-0);
  white-space: nowrap;
  pointer-events: none;
}

/* Etapa sin fechas: no tiene barra, tiene una nota. Que no aparezca sin más
   sería peor: el cliente creería que la borró. */
.gantt-pista--sin-fecha {
  display: flex;
  align-items: center;
  padding: 0 var(--e-2);
  background: repeating-linear-gradient(
    135deg,
    var(--sup-2) 0 8px,
    var(--sup-3) 8px 16px
  );
}

.gantt-pista--sin-fecha span {
  font-size: var(--t-xs);
  color: var(--txt-2);
}

/* Marcador de HOY. Recorre toda la columna de barras. */
.gantt-hoy {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--pos, 0) * 100%);
  width: 2px;
  background: var(--error);
  pointer-events: none;
  z-index: 2;
}

.gantt-hoy::before {
  content: attr(data-etiqueta);
  position: absolute;
  top: -2px;
  left: 50%;
  transform: translate(-50%, -100%);
  padding: 2px var(--e-2);
  border-radius: var(--r-full);
  background: var(--error);
  color: var(--n-0);
  font-size: var(--t-xs);
  font-weight: var(--peso-enfasis);
  line-height: 1.4;
  white-space: nowrap;
}

/* Sitio para que la etiqueta de HOY no se corte contra el borde de arriba. */
.gantt-linea__lienzo {
  position: relative;
  padding-top: var(--e-5);
}

/* --------------------------------------------------------------------------
   B6. Vista tabla
   -------------------------------------------------------------------------- */

.gantt-tabla { padding: var(--e-2); }

/* La tabla scrollea DENTRO de su caja, nunca el body (auditoría §7). */
.gantt-tabla__caja {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.gantt-tabla table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
}

.gantt-tabla th,
.gantt-tabla td {
  padding: var(--e-3);
  text-align: left;
  border-bottom: var(--b-fino) solid var(--borde);
  font-size: var(--t-sm);
  line-height: var(--lh-sm);
  vertical-align: middle;
}

.gantt-tabla thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--sup-1);
  font-weight: var(--peso-titulo);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--txt-2);
}

.gantt-tabla tbody tr:last-child td { border-bottom: 0; }
.gantt-tabla tbody tr:hover td { background: var(--sup-2); }

.gantt-tabla .num {
  text-align: right;
  font-family: var(--fuente-num);
  font-variant-numeric: tabular-nums;
}

.gantt-punto {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: var(--r-full);
  background: var(--etapa, var(--info));
  margin-right: var(--e-2);
  vertical-align: baseline;
}

/* Fila de hoy dentro de la tabla: la tabla no tiene línea vertical, así que el
   "hoy" se marca en la fila cuya etapa está en curso. */
.gantt-tabla tr[data-hoy="1"] td:first-child {
  box-shadow: inset 3px 0 0 var(--error);
}

/* --------------------------------------------------------------------------
   B7. Insignias de estado — color MÁS texto, nunca color solo
   -------------------------------------------------------------------------- */

.estado-etapa {
  display: inline-flex;
  align-items: center;
  gap: var(--e-1);
  padding: 2px var(--e-2);
  border-radius: var(--r-full);
  font-size: var(--t-xs);
  line-height: var(--lh-xs);
  font-weight: var(--peso-enfasis);
  white-space: nowrap;
  border: var(--b-fino) solid transparent;
}

.estado-etapa::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: var(--r-full);
  border: 2px solid currentColor;
}

.estado-etapa--pendiente  { color: var(--txt-2); background: var(--sup-2); }
.estado-etapa--en_curso   { color: var(--info);  background: var(--info-suave);  border-color: var(--info); }
.estado-etapa--completada { color: var(--ok);    background: var(--ok-suave);    border-color: var(--ok); }
.estado-etapa--atrasada   { color: var(--error); background: var(--error-suave); border-color: var(--error); }

/* Cada estado tiene además su propia FORMA de punto: quien no distingue el
   color sigue distinguiendo la etapa (1 de cada 12 hombres es daltónico). */
.estado-etapa--completada::before { background: currentColor; }
.estado-etapa--en_curso::before   { border-style: dashed; }
.estado-etapa--atrasada::before   { border-radius: 2px; }
.estado-etapa--pendiente::before  { background: transparent; }

/* --------------------------------------------------------------------------
   B8. Bitácora
   -------------------------------------------------------------------------- */

.bitacora {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
}

.bitacora-entrada {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  padding: var(--e-4);
  border: var(--b-fino) solid var(--borde);
  border-radius: var(--r-md);
  background: var(--sup-1);
}

.bitacora-entrada__cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--e-2) var(--e-3);
}

.bitacora-entrada__fecha {
  font-family: var(--fuente-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-sm);
  color: var(--txt-2);
}

.bitacora-entrada__titulo {
  font-size: var(--t-h3);
  line-height: var(--lh-h3);
  font-weight: var(--peso-titulo);
  width: 100%;
}

.bitacora-entrada__texto {
  font-size: var(--t-base);
  line-height: var(--lh-base);
  white-space: pre-line;
  max-width: 72ch;
}

.bitacora-fotos {
  display: grid;
  gap: var(--e-2);
  grid-template-columns: repeat(auto-fill, minmax(min(140px, 45%), 1fr));
}

.bitacora-fotos img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-sm);
  background: var(--sup-2);
}

/* Una sola foto ocupa el ancho: recortarla a un cuadradito desperdicia la
   única imagen que tiene la entrada. */
.bitacora-fotos--una { grid-template-columns: minmax(0, 1fr); }
.bitacora-fotos--una img { aspect-ratio: 16 / 9; }

.bitacora-entrada__pie {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2);
  align-items: center;
  font-size: var(--t-xs);
  color: var(--txt-3);
}

/* --------------------------------------------------------------------------
   B9. Informe público (/s/{slug}/avance)

   El showroom es siempre oscuro y NO usa sombras: la jerarquía se hace con
   velo, desenfoque y un borde claro (DISENO §1 y §2.3). Por eso todo lo de
   aquí abajo pisa las superficies del panel con --fg / --placa.
   -------------------------------------------------------------------------- */

.avance-publico {
  min-height: 100dvh;
  color: var(--fg-txt);
  background: var(--fg);
  padding:
    calc(var(--e-6) + env(safe-area-inset-top))
    calc(var(--borde-pantalla) + env(safe-area-inset-right))
    calc(var(--e-8) + env(safe-area-inset-bottom))
    calc(var(--borde-pantalla) + env(safe-area-inset-left));
}

.avance-publico__interior {
  max-width: 74rem;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--e-6);
}

.avance-publico__cabecera {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-3);
  align-items: flex-end;
  justify-content: space-between;
}

.avance-publico__titulo {
  font-size: var(--t-h1);
  line-height: var(--lh-h1);
  font-weight: var(--peso-titulo);
}

.avance-publico__intro {
  font-size: var(--t-base);
  line-height: var(--lh-base);
  color: var(--fg-txt-2);
  max-width: 64ch;
}

/* Superficies del informe público: placa translúcida en vez de tarjeta. */
.avance-publico .gantt,
.avance-publico .avance-general,
.avance-publico .bitacora-entrada {
  background: color-mix(in oklab, var(--fg-txt) 5%, transparent);
  border-color: var(--fg-borde);
  box-shadow: none;
}

.avance-publico .avance-nota,
.avance-publico .bitacora-entrada__fecha,
.avance-publico .bitacora-entrada__pie { color: var(--fg-txt-3); }

.avance-publico .gantt-pista { background: color-mix(in oklab, var(--fg-txt) 12%, transparent); }
.avance-publico .avance-barra { background: color-mix(in oklab, var(--fg-txt) 12%, transparent); }
.avance-publico .avance-barra__relleno { background: var(--p); }
.avance-publico .gantt-barra__pct { color: var(--fg-txt); text-shadow: var(--txt-sombra); }

.avance-publico .gantt-tabla thead th {
  background: var(--fg);
  color: var(--fg-txt-2);
}
.avance-publico .gantt-tabla th,
.avance-publico .gantt-tabla td { border-bottom-color: var(--fg-borde); }
.avance-publico .gantt-tabla tbody tr:hover td {
  background: color-mix(in oklab, var(--fg-txt) 6%, transparent);
}

.avance-publico .avance-vistas {
  background: var(--placa);
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
  border-color: var(--placa-borde);
}
.avance-publico .avance-vistas__btn { color: var(--fg-txt-2); }
.avance-publico .avance-vistas__btn[aria-pressed="true"] {
  background: color-mix(in oklab, var(--fg-txt) 14%, transparent);
  color: var(--fg-txt);
  box-shadow: none;
}

/* Doble anillo de foco sobre imagen/superficie oscura (DISENO §4.1). */
.avance-publico :focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgb(0 0 0 / .6);
}

/* --------------------------------------------------------------------------
   B10. Tramos del informe público
   -------------------------------------------------------------------------- */

@media (max-width: 380px) {
  .avance-general { padding: var(--e-4); }
  .gantt-linea { padding: var(--e-3); }
  .avance-publico { --borde-pantalla: var(--e-3); }
  /* La escala de meses no cabe: con 3 barras y el marcador de HOY ya se
     entiende el calendario, y las etiquetas se pisarían unas con otras. */
  .gantt-escala { display: none; }
}

@media (max-width: 640px) {
  .avance-publico { --borde-pantalla: var(--e-4); }
  .avance-seccion__cabecera { align-items: flex-start; }
}

/* Celular acostado: la carta ocupa casi todo y las secciones se aprietan. */
@media (max-height: 480px) and (orientation: landscape) {
  .avance-publico { padding-top: var(--e-4); padding-bottom: var(--e-4); }
  .avance-publico__interior { gap: var(--e-4); }
}


/* ##########################################################################
   MOVIMIENTO — vale para las dos partes
   ########################################################################## */

@media (prefers-reduced-motion: reduce) {
  .av-barra__relleno,
  .av-segmentado__btn,
  .av-fila,
  .av-iconobtn,
  .av-control,
  .avance-barra__relleno,
  .avance-vistas__btn {
    transition-duration: .01ms !important;
  }

  .av-segmentado__btn:active,
  .av-iconobtn:active { transform: none; }
}
