/* ═══════════════════════════════════════════════════════════════
   FIEFRE S.A. · Dashboard General de Proyectos
   Hoja de estilos. Misma paleta, tipografía y lenguaje visual que
   el resto de las vistas del sistema (public/estilo.css): ramp azul
   corporativa aclarada 15 %, degradés suaves y microanimación.

   Orden del archivo
   1. Tokens            5. KPIs
   2. Base y shell      6. Tarjetas y gráficos
   3. Menú de vistas    7. Componentes propios (matriz, planner, gantt)
   4. Filtros           8. Tablas, etiquetas, avisos y varios
   ═══════════════════════════════════════════════════════════════ */

/* ── 1. Tokens ─────────────────────────────────────────────────── */
:root {
  /* EL ALTO DE LA VENTANA, SIN EL ZOOM DEL TABLERO (03/11/2026)

     lib/escala.js pone un `zoom` sobre <html> para que el tablero se dibuje
     siempre como en 2133 px de ancho. Ese zoom achica tambien lo que se
     dibuja a lo alto: una caja pedida con 100vh se calcula con el alto entero
     de la ventana y despues se dibuja al 76 %, asi que ocupa el 76 % de la
     pantalla y abajo queda una franja muerta. Con el zoom en 0,6 la caja de
     Publicaciones usaba 343 px de 720: el 60 % de la pantalla.

     Asi que acá se descuenta. escala.js publica --escala con el factor que
     puso (1 si no escaló, y 1 por defecto para el que abra la hoja sin el
     script). Las pantallas de alto completo piden var(--alto-ventana) en vez
     de 100vh. El Resumen NO: ver su nota mas abajo. */
  --escala: 1;
  --alto-ventana: calc(100vh / var(--escala));

  /* ══ EL PISO DE LEGIBILIDAD (08/11/2026) ════════════════════════════

     El tablero se dibuja con `zoom`, asi que un texto de 11 px en un
     notebook a escala 0,68 llega al ojo como 7,5 px. Medido en la pagina
     real a 1366 x 768: la matriz tenia 43 celdas y 11 cabeceras en 7,5 px,
     y «sin informar» en 5,4.

     LO QUE NO SE HIZO, Y POR QUE. Lo primero que probe fue subir el piso de
     la escala de 0,68 a 0,82. Parecia gratis, y no lo era: yo estaba midiendo
     el scroll con document.scrollHeight, que en este tablero SIEMPRE da cero
     porque el shell es de alto fijo y el scroll vive adentro de .contenido.
     Midiendolo donde va, a 1366 x 768 con la cartera del 08/11/2026:

         escala    texto de la matriz   filas a la vista   scroll
         0,68       7,5 px              19 de 19           no
         0,76       8,4 px              18 de 19          110 px
         0,82       9,0 px              15 de 19          193 px

     O sea que subir la escala cuesta cuatro proyectos de los diecinueve. El
     0,68 estaba bien elegido.

     LO QUE SE HIZO. Que el texto chico no se achique mas alla de cierto
     punto, compensando la escala desde el CSS. `max()` se queda con el
     tamano de diseno cuando la escala es 1 o mayor, asi que en los monitores
     grandes NO cambia nada; solo crece donde hacia falta.

         10 px reales en la matriz y las tarjetas:  19 de 19 filas, 33 px de
         scroll. Contra los 193 px y 15 filas de la otra idea.

     El numero vive aca una sola vez. Se usa asi:

         font-size: max(<el tamano de diseno>, calc(var(--piso-texto) / var(--escala, 1)));

     El `, 1` del var() no es decorativo: escala.js publica --escala recien
     cuando corre, y abajo de 900 px de ancho no escala nada. */
  --piso-texto: 10px;


  /* ══════ EL ANCHO DE MAQUETADO (07/11/2026) ════════════════════════════

     Las media queries miran la VENTANA. Con el zoom del tablero puesto, el
     ancho en el que las columnas se reparten de verdad es otro -la ventana
     dividida por la escala- y los dos números no se parecen:

         notebook de 1366   la ventana dice 1366   se maqueta sobre 2133
         media pantalla,    la ventana dice 1000   se maqueta sobre 1818
         1000 px de ancho

     Así que `@media (max-width: 1100px)` entraba en una ventana de 1000 px
     teniendo 1818 px de ancho para repartir: la ficha del proyecto bajaba el
     avance por área a una fila entera y «Requieren atención» perdía la
     columna de atrasos, las dos cosas sin ninguna razón.

     CSS no puede preguntar por el zoom, así que lo contesta lib/escala.js:
     deja en <html> la clase `maqueta-1100` cuando el ancho de maquetado
     llega a 1100 px, y `maqueta-1100-1450` para el tramo angosto. Donde
     antes decía @media (min-width: 1100px) ahora dice html.maqueta-1100, y
     donde decía @media (max-width: 1100px), html:not(.maqueta-1100).

     Los cortes de 900 px para abajo (820, 780, 760, 700, 560) se quedan
     como media queries y están bien: ahí escala.js no escala nada -manda el
     responsive de esta hoja- y la ventana ES el ancho de maquetado.
     Con la escala activa, en cambio, el ancho de maquetado nunca baja de
     1636 px (900 / 0,55), así que ninguno de esos cortes puede entrar. */

  /* Ramp azul FIEFRE (aclarada 15 %) */
  --azul: #4D77C6;
  --azul-medio: #7E9ED6;
  --azul-claro: #90B6E4;
  --azul-nombre: #2F75B6;
  --azul-hondo: #3D6BBF;
  --azul-tinte: #EEF3FB;
  --azul-tinte-2: #E2EBF8;

  /* Acentos */
  --verde: #70AD47;    --verde-hondo: #558B33;
  --naranja: #ED7D31;  --naranja-oscuro: #C55A11;
  --dorado: #FFD966;   --dorado-hondo: #BF9000;
  --rojo: #E88B8B;     --rojo-hondo: #C00000;

  /* Neutros */
  --gris-fondo: #F5F7FB;
  --gris-borde: #DCE3EE;
  --gris-medio: #BFBFBF;
  /* Gris del "N/A" de la matriz. Va aparte y bastante más oscuro que
     --gris-fondo a propósito: sobre el celeste clarito de la tabla, un gris
     tenue no se distinguía de una celda vacía, que es justo lo contrario de lo
     que tiene que comunicar (acá NO hay nada que cargar). */
  --gris-na: #C7D0DE;
  --texto: #1D2432;
  --texto-suave: #5A6577;

  /* Elevación: sombras tenues teñidas de azul, nada de bordes duros */
  --sombra-1: 0 1px 2px rgba(47,117,182,.06), 0 2px 8px rgba(47,117,182,.07);
  --sombra-2: 0 2px 6px rgba(47,117,182,.10), 0 10px 24px rgba(47,117,182,.10);
  --radio: 12px;
  --transicion: .22s cubic-bezier(.4, 0, .2, 1);

  /* Estados del planner, en la misma paleta corporativa */
  --e-pendiente: #A9A9A9;
  --e-proceso: var(--naranja-oscuro);
  --e-revision: var(--azul-claro);
  --e-aprobado: var(--azul-nombre);
  --e-terminado: var(--verde-hondo);
  --e-retraso: var(--rojo-hondo);
  --e-detenido: var(--dorado-hondo);
  --e-otro: var(--gris-medio);
}

/* ── 2. Base y shell ──────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

/* Shell de altura fija (tipo consola): la página ocupa exactamente el alto de
   la ventana y NO se desplaza. El encabezado y las pestañas quedan clavados
   arriba, y el scroll aparece SOLO dentro del contenido y SOLO cuando hay más
   de lo que entra (p. ej. más proyectos que los que caben en pantalla). */
html, body { height: 100%; }

/* EL ALTO DEL SHELL EN LOS NAVEGADORES VIEJOS (06/11/2026)

   Ese 100 % vale cosas distintas segun la version del navegador, y la
   diferencia es media pantalla:

     Chrome 128 y posteriores   el 100 % se mide YA descontado el zoom que
                                pone lib/escala.js, asi que el shell tapa la
                                ventana entera. Es lo correcto y no se toca.

     Chrome anterior a 128      el 100 % es la ventana tal cual y despues se
                                dibuja a escala: con el zoom en 0,55 el
                                tablero ENTERO ocupaba el 55 % de la pantalla
                                y el 45 % de abajo quedaba en blanco.

   Visto el 06/11/2026 en un notebook de la oficina: la ventana media
   911 x 696 y <body> tambien 911 x 696 -sin dividir-. Publicaciones terminaba
   a media pantalla, con la conversacion apretada contra el campo para
   escribir y el resto de la pantalla sin usar. En el monitor grande es el
   mismo problema con el zoom en 0,9: se perdia el 10 % de abajo.

   lib/escala.js averigua cual de los dos navegadores es -midiendo, no por la
   version- y deja esta clase SOLO cuando no descuenta el zoom. Entonces se le
   pide el alto de la ventana dividido por la escala, que es exactamente lo
   que el otro navegador calcula solo. body sigue con su 100 %: ahora cuelga
   de un <html> que ya mide bien. */
html.escala-vieja { height: calc(100% / var(--escala)); }

body {
  font-family: Calibri, 'Segoe UI', Arial, sans-serif;
  color: var(--texto);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  background:
    radial-gradient(1200px 380px at 50% -180px, var(--azul-tinte-2), transparent 70%),
    var(--gris-fondo);
  background-attachment: fixed;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
h1, h2, h3 { font-weight: bold; }
button, select, input { font-family: inherit; color: var(--texto); }
a { color: var(--azul-nombre); }
.oculto { display: none !important; }

/* Barra superior */
.barra {
  background: linear-gradient(120deg, var(--azul-nombre) 0%, var(--azul) 55%, var(--azul-medio) 100%);
  color: #fff;
  display: flex; align-items: center; gap: 12px;
  padding: 9px 14px;
  box-shadow: 0 2px 12px rgba(61,107,191,.28);
  position: sticky; top: 0; z-index: 50;
  flex: 0 0 auto;
}
.barra::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: linear-gradient(90deg, var(--azul-claro), #fff 45%, var(--azul-claro));
  opacity: .55;
}
/* ── Modo administrador: la barra se pone naranja ──────────────────────────
   Se activa con la clase que pone aplicarPermisos() en el <body>. El naranja
   es el de la paleta Fiefre (el mismo de "proximo compromiso" y de los avisos),
   asi que no se suma un color nuevo al tablero. */
body.modo-admin .barra {
  background: linear-gradient(120deg, var(--naranja-oscuro) 0%, var(--naranja) 55%, #F0A05E 100%);
  box-shadow: 0 2px 12px rgba(197, 90, 17, .32);
}
body.modo-admin .barra::after {
  background: linear-gradient(90deg, #F7C69B, #fff 45%, #F7C69B);
}
body.modo-admin .barra-titulo { text-shadow: 0 1px 2px rgba(120, 52, 8, .40); }
/* El candado ya abierto pasa a blanco sobre el naranja: el verde sobre naranja
   se peleaba y encima repetia lo que ya dice el color de la barra. */
body.modo-admin .btn-barra.candado.abierto {
  background: #fff; border-color: #fff; color: var(--naranja-oscuro);
}

/* La placa del logo es el boton de "volver al inicio" (04/11/2026). Se ve
   igual que siempre: lo unico que se agrega es el borde en cero -el <button>
   trae uno propio-, la manito y un realce al pasar por encima, para que se
   note que se puede apretar. */
.placa-logo {
  background: #fff; border-radius: 8px; padding: 4px 9px;
  display: flex; align-items: center;
  box-shadow: 0 2px 8px rgba(0,0,0,.14);
  border: 0; font: inherit; cursor: pointer;
  transition: box-shadow .15s, transform .15s;
}
.placa-logo:hover { box-shadow: 0 3px 12px rgba(0,0,0,.24); transform: translateY(-1px); }
.placa-logo:active { transform: translateY(0); }
.placa-logo:focus-visible { outline: 3px solid #ffc53d; outline-offset: 2px; }
.placa-logo img { height: 38px; display: block; }
.barra-titulo {
  flex: 1; text-align: left; font-weight: bold;
  text-transform: uppercase; letter-spacing: .6px; font-size: 16px;
  text-shadow: 0 1px 2px rgba(31,60,100,.35);
}
.barra-usuario { display: flex; align-items: center; gap: 10px; font-size: 14px; }

/* Estado del monitoreo, dentro de la barra */
.estado-carga { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; line-height: 1.3; }
.estado-carga .l1 { display: flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: bold; }
.estado-carga .l2 { font-size: 12px; opacity: .92; font-variant-numeric: tabular-nums; }
.estado-carga .l3 { font-size: 11.5px; opacity: .78; font-variant-numeric: tabular-nums; }
/* Nadie carga hace rato: el tablero puede estar mostrando datos viejos y nada
   mas lo indicaria. El semaforo mira el LATIDO, no la edad del dato: colorear
   por la edad del dato pondria el tablero en rojo todos los lunes por el fin de
   semana. */
.estado-carga .l3.aviso,
.estado-carga .l3.alarma { color: #fff; opacity: 1; font-weight: bold; }
/* Sin recuadro: el cartel es texto sobre la barra, no una pastilla clara. Los
   tintes ambar y rojo que habia aca se sacaron el 07/10/2026 a pedido: quedaban
   como una paleta blanca encima del azul. La severidad la marca el simbolo de
   alerta que el texto ya trae, no el color. */
.estado-carga .l3 {
  background: none; border: 0; box-shadow: none; padding: 0;
  text-shadow: 0 1px 2px rgba(31,60,100,.35);
}
.punto { width: 9px; height: 9px; border-radius: 50%; background: rgba(255,255,255,.5); flex: 0 0 auto; }
.punto.on { background: #B6F0A0; box-shadow: 0 0 0 3px rgba(182,240,160,.35); }
.punto.on.late { animation: latido 2.4s ease-in-out infinite; }
.punto.manual { background: var(--dorado); }
.punto.off { background: rgba(255,255,255,.45); }
@keyframes latido {
  0%, 100% { box-shadow: 0 0 0 3px rgba(182,240,160,.35); }
  50%      { box-shadow: 0 0 0 7px rgba(182,240,160,.10); }
}

.btn-barra {
  color: #fff; background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.55);
  padding: 5px 12px; border-radius: 20px; font-size: 13px;
  cursor: pointer; white-space: nowrap;
  transition: background var(--transicion), transform var(--transicion);
}
.btn-barra:hover { background: rgba(255,255,255,.28); transform: translateY(-1px); }
.btn-barra.icono { padding: 5px 10px; font-size: 15px; line-height: 1; }

/* ── 3. Menú de vistas ────────────────────────────────────────── */
.menu {
  background: linear-gradient(180deg, var(--azul-hondo), #35619F);
  display: flex; overflow-x: auto;
  box-shadow: var(--sombra-1);
  scrollbar-width: thin;
  position: sticky; top: 60px; z-index: 45;
  flex: 0 0 auto;
}
.menu button {
  background: none; border: 0;
  color: #fff; padding: 11px 18px; font-weight: bold; font-size: 14.5px;
  white-space: nowrap; position: relative; cursor: pointer;
  transition: background var(--transicion);
}
.menu button::after {
  content: ''; position: absolute; left: 50%; right: 50%; bottom: 0; height: 3px;
  background: #fff; border-radius: 3px 3px 0 0;
  transition: left var(--transicion), right var(--transicion);
}
.menu button:hover { background: rgba(255,255,255,.12); }
.menu button:hover::after { left: 22%; right: 22%; }
.menu button[aria-selected="true"] { background: rgba(255,255,255,.18); }
.menu button[aria-selected="true"]::after { left: 14%; right: 14%; }
/* Volver: aparece sólo cuando hay adónde volver, separado de las pestañas. */
.menu button.volver { margin-left: auto; font-size: 13.5px; opacity: .95; }
.menu button.volver::after { content: none; }
.menu button.volver:hover { background: rgba(255,255,255,.2); }

main.contenido { max-width: none; padding: 10px 16px 30px; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
section.vista[hidden] { display: none; }

/* ── 4. Filtros ───────────────────────────────────────────────── */
.barra-filtros {
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 10px;
  padding: 8px 14px; margin-bottom: 10px;
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px;
  box-shadow: var(--sombra-1);
}
.titulo-panel {
  color: var(--azul); font-weight: bold; font-size: 16px; text-transform: uppercase;
  display: flex; align-items: center; gap: 8px; margin-right: auto; padding-bottom: 6px;
}
.filtro { min-width: 120px; flex: 0 1 auto; }
.filtro.ancho { flex: 1 1 240px; min-width: 220px; }
.filtro label {
  display: block; text-align: left; font-weight: bold;
  font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--azul-nombre); margin: 0 0 2px;
}
.filtro select, .filtro input {
  width: 100%; padding: 6px 8px; font-size: 13px;
  border: 1px solid var(--gris-borde); border-radius: 6px; background: #fff;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}
.filtro select:focus, .filtro input:focus {
  outline: none; border-color: var(--azul);
  box-shadow: 0 0 0 3px rgba(77,119,198,.20);
}
.chk {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--azul-nombre); font-weight: bold; cursor: pointer;
  padding-bottom: 5px;
}
.chk input { width: auto; }
.cuenta {
  font-size: 12.5px; color: var(--texto-suave); margin-left: auto;
  font-variant-numeric: tabular-nums; padding-bottom: 6px;
}

.btn-limpiar {
  background: none; border: 1px solid var(--azul-claro); color: var(--azul);
  border-radius: 6px; padding: 6px 10px; font-size: 12px; cursor: pointer;
  transition: background var(--transicion);
}
.btn-limpiar:hover { background: var(--gris-fondo); }
.btn-excel {
  background: var(--azul); border: none; color: #fff; font-weight: bold;
  border-radius: 6px; padding: 7px 12px; font-size: 12px; cursor: pointer;
  transition: filter var(--transicion), transform var(--transicion);
}
.btn-excel:hover { filter: saturate(1.1) brightness(1.05); transform: translateY(-1px); }
.btn-excel.gris { background: var(--gris-medio); }

.boton {
  padding: 12px 18px; border: none; border-radius: 10px;
  background: linear-gradient(135deg, var(--azul), var(--azul-hondo));
  color: #fff; font-weight: bold; font-size: 15px;
  cursor: pointer; text-transform: uppercase; letter-spacing: .5px;
  box-shadow: 0 3px 10px rgba(61,107,191,.28);
  transition: transform var(--transicion), box-shadow var(--transicion), filter var(--transicion);
}
.boton:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(61,107,191,.34); filter: saturate(1.06); }
.boton:active { transform: translateY(0); }
.boton.claro {
  background: #fff; color: var(--azul); border: 1px solid var(--azul-claro);
  box-shadow: var(--sombra-1);
}
.boton.claro:hover { background: var(--azul-tinte); }

:focus-visible { outline: 2px solid var(--azul-nombre); outline-offset: 2px; }

/* ── 5. KPIs ──────────────────────────────────────────────────── */
.grilla-kpi { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 8px; margin-bottom: 10px; }
/* Las 9 áreas entran en una sola línea: tarjetas más angostas. Van sueltas
   debajo de los KPI (ya no dentro de una tarjeta con título), así que llevan el
   mismo margen inferior que la fila de arriba. */
.grilla-kpi.areas { grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); }
.grilla-kpi.areas .valor { font-size: 22px; }
.grilla-kpi.areas .nombre { font-size: 11px; letter-spacing: .4px; }
.grilla-kpi.areas .nota { font-size: 11px; font-weight: bold; }
.kpi {
  border-radius: 10px; padding: 10px 10px 11px; text-align: center; color: #fff;
  box-shadow: var(--sombra-1);
  transition: transform var(--transicion), box-shadow var(--transicion);
  /* Las dos filas de tarjetas del Resumen miden lo mismo: el alto lo mide
     igualarKpis() en app.js (la más alta de las dos filas manda) y entra por
     esta variable. El contenido queda centrado en el alto sobrante. */
  min-height: var(--kpi-alto, 0);
  display: flex; flex-direction: column; justify-content: center;
}
.kpi:hover { transform: translateY(-3px); box-shadow: var(--sombra-2); }
/* Todo el texto de la tarjeta va en blanco pleno, sin transparencias: la letra
   chica se tiene que leer igual que el número. */
.kpi .valor, .kpi .nombre, .kpi .nota { color: #fff; }
.kpi .valor { font-size: 26px; font-weight: bold; line-height: 1.1; }
.kpi .nombre { font-size: max(11px, calc(var(--piso-texto) / var(--escala, 1))); text-transform: uppercase;
  letter-spacing: .6px; margin-top: 2px; }
.kpi .nota { font-size: max(11.5px, calc(var(--piso-texto) / var(--escala, 1))); margin-top: 3px; line-height: 1.3; }
/* La bajada va con el MISMO peso en las siete tarjetas (13/10/2026). Antes las
   dos rojas la llevaban en negrita (.nota.fuerte) y se leían como "otra letra"
   al lado de las demás. Lo crítico ya se distingue por el color de la tarjeta. */

/* ── Anchos de la barra de filtros de la pestana KPI ──
   .filtro.ancho lleva flex-grow: 1, pensado para la barra de arriba, que
   tiene seis controles. Aca son cuatro, asi que el selector de PROYECTO se
   quedaba con todo el sobrante: mas de 1000 px para un nombre que entra en la
   mitad. Se le fija el ancho que hace falta y nada mas.

   Los 500 px NO son a ojo: el nombre mas largo de la lista -"OT 1089 ·
   CODELCO CHUQUICAMATA - MONORRIEL 1T 221185-TCL-006 · archivado"- mide 436 px
   a 13 px, mas el relleno, el borde y la flecha del desplegable: 474 px justos,
   y se redondea a 500 para que la ultima palabra no quede pegada a la flecha.
   Importa porque el navegador recorta las opciones al ancho del select: mas
   angosto se leeria "...221185-TC..." justo donde se distingue un proyecto de
   otro. Si algun dia entra un nombre mas largo, se sube este numero.

   El de AREA va al reves: le sobraba con el minimo de 120 px y se pedia mas
   aire. "Control de Calidad" mide 97 px, asi que 190 lo deja comodo.

   Y el titulo suelta su margin-right: auto. Era el selector de proyecto el que
   tapaba ese hueco al crecer; sin eso, los cuatro filtros se iban todos contra
   el borde derecho y quedaba un claro enorme despues de "INDICADORES". La
   cuenta de la derecha ya tiene su propio margin-left: auto (.cuenta). */
#v-kpi .titulo-panel { margin-right: 0; }
#v-kpi .filtro.ancho { flex: 0 1 500px; min-width: 300px; }
#v-kpi #kAreaCaja { flex: 0 1 190px; min-width: 150px; }

/* ── Tarjetas de la pestana KPI: se abren ──
   Un porcentaje sin la lista detras no se puede discutir. La tarjeta es un
   boton y el renglon "ver el detalle" es la unica senal de que se puede
   apretar: sin el nadie las prueba, porque en el Resumen las mismas tarjetas
   no hacen nada. */
.kpi.clicable { cursor: pointer; }
.kpi.clicable:focus-visible { outline: 0; box-shadow: 0 0 0 3px rgba(61,107,191,.55), var(--sombra-2); }
/* En el Resumen las tarjetas tambien se pinchan desde el 08/10/2026 y llevan a
   lo que estan contando. No llevan el renglon "ver el detalle" de la pestana
   KPI: son doce tarjetas en dos filas y doce renglones iguales ensucian el
   bloque. La senal es el cursor, el realce al pasar por encima -que ya
   estaba- y el title, que dice a donde va cada una. */
#v-resumen .kpi.clicable:hover { box-shadow: 0 0 0 2px var(--azul-hondo), var(--sombra-2); }
.kpi.abierta { transform: translateY(-3px); box-shadow: var(--sombra-2); }
.kpi .abrir { font-size: 11px; margin-top: 6px; font-weight: bold; letter-spacing: .3px; }

/* El panel del detalle. El rotulo de cada grupo lleva color porque son
   siempre dos listas opuestas —lo que cumple y lo que no— y leerlas sin
   distinguirlas de un vistazo obliga a volver al titulo todo el tiempo. */
.kpi-detalle-cab { font-size: 12.5px; color: var(--texto-suave); margin: 14px 0 4px; line-height: 1.5; }
.kpi-detalle-cab .btn-limpiar { margin-left: 8px; vertical-align: middle; }
.kpi-grupo {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .5px; font-weight: bold;
  margin: 14px 0 6px; padding-left: 9px; border-left: 4px solid var(--gris-medio);
}
.kpi-grupo.bien { border-left-color: var(--verde); color: var(--verde-hondo); }
.kpi-grupo.mal  { border-left-color: var(--rojo); color: var(--rojo-hondo); }
/* La tabla por persona de PRY-05 no es ni lo que cumple ni lo que no: es el
   desglose del propio indicador, y por eso no lleva color. */
.kpi-grupo.neutro { border-left-color: var(--azul); color: var(--azul-hondo); }
/* Las filas de PRY-05 tambien abren su detalle: la persona es el indicador. */
.kpi-fila { cursor: pointer; }
.kpi-fila:hover th.rw { background: var(--azul-tinte); }
.kpi-fila.abierta th.rw { background: var(--azul-tinte); font-weight: bold; }
.kpi-fila:focus-visible { outline: 2px solid var(--azul-hondo); outline-offset: -2px; }

/* Los degradés van de claro (arriba) a oscuro (abajo) a propósito: el número
   grande cae en la parte clara y la letra chica en la oscura, que es donde el
   blanco necesita contraste. El extremo inferior de cada uno queda en 4,4:1 o
   mejor contra blanco. */
/* Contraste de las tarjetas (13/10/2026). El tono claro de cada degrade daba
   entre 3.1:1 y 3.6:1 contra el texto blanco, por debajo del 4.5:1 que pide la
   norma para letra menor a 18 px. Cada degrade arranca ahora en el tono que
   antes era su final y cierra un paso mas oscuro: la misma familia de color y
   el mismo orden de intensidad entre tarjetas, pero el blanco se lee.
   Medido sobre el tono claro, que es el peor caso de cada una. */
.g1 { background: linear-gradient(170deg, #4472C4, #30569C); }   /* 4.7:1 */
.g2 { background: linear-gradient(170deg, #305496, #23406F); }   /* 7.4:1 */
.g3 { background: linear-gradient(170deg, #3F72B8, #1F4E79); }   /* 4.7:1 */
.g4 { background: linear-gradient(170deg, #305496, #17395A); }   /* 7.4:1 */
.g5 { background: linear-gradient(170deg, #548235, #3F6327); }   /* 4.5:1 */
.g6 { background: linear-gradient(170deg, #B85310, #8F3F0A); }   /* 4.9:1 */
.g-rojo { background: linear-gradient(170deg, #C00000, #9B0000); } /* 6.5:1 */

/* ── 6. Tarjetas y gráficos ───────────────────────────────────── */
.tarjeta {
  background: #fff; border: 1px solid var(--gris-borde);
  border-radius: var(--radio); padding: 18px; margin-bottom: 16px;
  box-shadow: var(--sombra-1);
  transition: box-shadow var(--transicion);
}
.tarjeta:hover { box-shadow: var(--sombra-2); }

.tarjeta-graf {
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 10px;
  padding: 10px 14px 14px; margin-bottom: 10px;
  box-shadow: var(--sombra-1);
}
/* El título de un panel: chico, en versalitas y con la raya en degradado
   debajo. Así se ven «Requieren atención», «Indicadores» y el resto del
   tablero, y así tiene que verse TAMBIÉN el que comparte renglón con un botón
   —el del Detalle, el de la Cronología, el de Usuarios—, que por estar metido
   dentro de .cabecera-graf se quedaba fuera de esta regla (el `>` sólo alcanza
   al que cuelga derecho del panel). Esos tres salían como un <h2> pelado del
   navegador: 24 px, negro y en minúsculas, que es justo lo que hacía que no
   parecieran parte del tablero. (27/10/2026) */
.tarjeta-graf > h2,
.tarjeta-graf > .cabecera-graf h2 {
  color: var(--azul); font-size: 13px; text-transform: uppercase; letter-spacing: .4px;
  margin-bottom: 6px; padding-bottom: 4px; text-align: left;
  border-bottom: 2px solid;
  border-image: linear-gradient(90deg, #1F4E79, #8FAADC) 1;
}
/* Menos uno: el de Publicaciones NO es el título del panel sino el NOMBRE DEL
   PROYECTO del que son las publicaciones -lo escribe renderMuro()-, y ahí el
   título del panel es la pestaña. Se queda grande y en azul, como estaba. */
.muro-caja > .cabecera-graf h2 {
  color: var(--azul-nombre); font-size: 24px; text-transform: none;
  letter-spacing: normal; margin-bottom: 0; padding-bottom: 0; border: 0;
}
.tarjeta-graf .cap { font-size: 12px; color: var(--texto-suave); margin: 0 0 10px; }
.cabecera-graf { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.cabecera-graf > div { flex: 1; min-width: 200px; }
.rejilla { display: grid; gap: 10px; }
.fila-graficos { display: grid; gap: 10px; margin-bottom: 10px; }
.fila-graficos > .tarjeta-graf { margin-bottom: 0; }
/* Antes era @media (min-width: 1100px); ahora lo decide el ancho de maquetado
   (ver la nota de arriba). */
html.maqueta-1100 .fila-graficos { grid-template-columns: minmax(0,1.5fr) minmax(0,1fr); }
/* Sin la columna de administrador, la matriz se queda con todo el ancho: es
   lo que mira el equipo y así entra sin scroll horizontal. */
html.maqueta-1100 .fila-graficos.solo-matriz { grid-template-columns: minmax(0, 1fr); }

/* El Resumen llena el alto de la ventana: el bloque central (matriz + salud)
   crece para que "Requieren atención" muestre varios ítems, y la carga por área
   queda pegada abajo, sin dejar un hueco vacío. En pantallas donde no alcance,
   todo vuelve a su alto natural y el scroll aparece dentro del contenido. */
#app { display: flex; flex-direction: column; min-height: 100%; }
/* OJO con el :not([hidden]): sin él, este selector con #id le gana a la regla
   section.vista[hidden]{display:none} y el Resumen queda visible en TODAS las
   pestañas. Con :not([hidden]) sólo aplica cuando el Resumen está activo. */
#v-resumen:not([hidden]) { display: flex; flex-direction: column; flex: 1 0 auto; min-height: 0; }
#v-resumen .fila-graficos { flex: 1 0 auto; min-height: 0; }

/* Barras horizontales con degradé (mismo criterio que los gráficos de barras) */
.barras { display: grid; gap: 8px; }
.barra-fila { display: grid; grid-template-columns: 132px 1fr 54px; gap: 10px; align-items: center; font-size: 13px; }
.barra-fila .nm { display: flex; align-items: center; gap: 7px; color: var(--texto); min-width: 0; }
.barra-fila .nm span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barra-fila .pista { height: 14px; background: var(--gris-fondo); border-radius: 4px; overflow: hidden; border: 1px solid var(--gris-borde); }
.barra-fila .pista > i { display: block; height: 100%; border-radius: 3px; transition: width var(--transicion); }
.barra-fila .vv { text-align: right; font-weight: bold; font-variant-numeric: tabular-nums; color: var(--azul-nombre); }
/* Segunda línea de una barra: el % de avance debajo del recuento */
.barra-fila.sec { font-size: 11.5px; color: var(--texto-suave); margin-top: 2px; }
.barra-fila.sec .pista { height: 7px; }
.cuadro { width: 10px; height: 10px; border-radius: 2px; flex: 0 0 auto; }

/* Barra de avance flat, para tablas y tarjetas */
.barra-avance {
  background: var(--gris-borde); border-radius: 3px; height: 6px;
  overflow: hidden; display: block;
}
.barra-avance > i { display: block; height: 100%; background: var(--azul-medio); transition: width var(--transicion); }
.barra-avance.completa > i { background: var(--verde); }
.barra-avance.alta { height: 9px; }
.barra-avance.en-tabla { width: 62px; display: inline-block; vertical-align: middle; margin-left: 6px; }

/* ── 7. Componentes propios ───────────────────────────────────── */

/* Matriz proyecto × área (mapa de calor de un solo tono) */
.matriz-scroll { overflow-x: auto; }
table.matriz { border-collapse: separate; border-spacing: 2px; font-size: 12.5px; min-width: 100%; }
table.matriz thead th {
  background: linear-gradient(180deg, var(--azul), var(--azul-hondo));
  color: #fff; font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  text-align: center; padding: 6px 5px; vertical-align: bottom; white-space: nowrap;
  border-radius: 6px;
}
table.matriz th.rw {
  background: #fff; color: var(--texto); font-weight: normal; text-transform: none;
  letter-spacing: 0; font-size: 13px; text-align: left; padding: 4px 8px;
  max-width: 290px; position: sticky; left: 0; z-index: 1; border-radius: 0;
  border-right: 1px solid var(--gris-borde);
}
table.matriz tbody tr:hover th.rw { background: var(--azul-tinte); }
table.matriz th.rw .ot {
  display: inline-block; min-width: 62px;
  color: var(--azul-nombre); font-weight: bold; font-variant-numeric: tabular-nums;
}
table.matriz td { padding: 0; }
table.matriz .celda {
  display: flex; align-items: center; justify-content: center;
  height: 30px; border-radius: 6px; font-variant-numeric: tabular-nums;
  font-size: 12.5px; font-weight: bold;
}
table.matriz .celda.na {
  background: var(--gris-fondo); border: 1px dashed var(--gris-medio);
  color: var(--texto-suave); font-weight: normal; font-size: 11.5px;
}
/* El extremo más oscuro de la rampa mantiene 5,5:1 con el texto, así que la
   celda nunca necesita invertir el color de la tipografía. */
table.matriz .celda.total { box-shadow: inset 0 0 0 2px rgba(47,117,182,.35); }

/* Planner (kanban) */
.calle { margin-bottom: 16px; }
.calle > h3 {
  font-size: 13.5px; color: var(--azul-nombre); text-transform: uppercase; letter-spacing: .4px;
  margin: 0 0 8px; padding-bottom: 5px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  border-bottom: 2px solid;
  border-image: linear-gradient(90deg, var(--azul-nombre), var(--azul-claro) 60%, transparent) 1;
}
.calle > h3 .cnt { font-size: 11.5px; color: var(--texto-suave); font-weight: normal; text-transform: none; letter-spacing: 0; }
.tablero { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 8px; align-items: flex-start; }
.columna {
  flex: 0 0 264px; background: #fff; border: 1px solid var(--gris-borde);
  border-radius: 10px; box-shadow: var(--sombra-1); overflow: hidden;
}
.columna > .cab {
  display: flex; align-items: center; gap: 8px; padding: 8px 11px;
  color: #fff; font-size: 12.5px; font-weight: bold;
}
.columna > .cab .n {
  margin-left: auto; font-variant-numeric: tabular-nums;
  background: rgba(255,255,255,.25); border-radius: 10px; padding: 0 7px; font-size: 11.5px;
}
/* El Resumen se queda con 62vh A PROPOSITO (03/11/2026).

   Es la pestaña que mira todo el mundo todo el día y la primera que se abre:
   que las tres columnas cambien de alto mueve de lugar lo que la gente ya sabe
   dónde está. Las demás pantallas sí descuentan el zoom (--alto-ventana). */
.columna > .cuerpo { padding: 9px; display: grid; gap: 8px; max-height: 62vh; overflow-y: auto; }

.ficha {
  background: #fff; border: 1px solid var(--gris-borde); border-left: 4px solid var(--azul-medio);
  border-radius: 8px; padding: 9px 10px;
  box-shadow: var(--sombra-1);
  transition: box-shadow var(--transicion), transform var(--transicion);
}
.ficha:hover { box-shadow: var(--sombra-2); transform: translateY(-1px); }
.ficha .proy {
  font-size: 11px; color: var(--azul-nombre); font-weight: bold;
  text-transform: uppercase; letter-spacing: .4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ficha .act { font-size: 13px; margin: 3px 0 7px; line-height: 1.3; }
.ficha .pct { font-size: 11px; color: var(--texto-suave); font-variant-numeric: tabular-nums; text-align: right; margin-bottom: 3px; }
.ficha .meta { display: flex; gap: 8px; align-items: center; font-size: 11.5px; color: var(--texto-suave); margin-top: 7px; flex-wrap: wrap; }
.ficha .meta .resp { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 128px; }
.ficha .meta .fec { margin-left: auto; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ficha .meta .fec.tarde { color: var(--rojo-hondo); font-weight: bold; }
.columna .vacia { font-size: 12.5px; color: var(--texto-suave); padding: 10px 4px; text-align: center; }

/* Grilla de las tarjetas de proyecto. El ancho mínimo lo afina la regla
   .proyectos de más abajo; acá quedan el modo grilla y el estirado, que hacen
   que todas las tarjetas de una fila midan lo mismo. */
.proyectos {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px;
  align-items: stretch;
}

/* ── Tarjetas de proyecto con anillo de avance (vista Proyectos) ──
   Reemplazaron a unas tarjetas de sólo porcentajes (.py), cuyo CSS quedó
   huérfano y se borró el 02/10/2026. Cada una lleva un anillo
   con el % global y un semáforo de salud (real vs. plan + atraso); debajo, el
   desglose de las 9 áreas con mini-barras. Todas miden lo mismo: anillo fijo,
   9-10 filas de área de alto fijo y un pie de 4 casilleros. */
.proyectos { grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); }
/* Cuando las tarjetas entran en dos filas, la cantidad de columnas y el alto
   los fija ajustarProyectos() en app.js: así las dos filas caben enteras en una
   pantalla sin bajar con el cursor. Con tres filas o más se vuelve al ancho
   cómodo y el scroll es el esperado. */
.proyectos.fijo { grid-template-columns: repeat(var(--pcard-cols, 4), minmax(0, 1fr)); }

/* Un solo proyecto a la vista (16/10/2026): la tarjeta se agranda y se centra.
   Al filtrar hasta dejar uno, la tarjeta quedaba del mismo ancho mínimo pegada
   al borde izquierdo, con toda la pantalla vacía al lado — justo cuando es la
   única que se está mirando.

   Se agranda con zoom y NO estirando la columna: la tarjeta conserva su ancho
   de siempre (el cómodo, 300 px) y se dibuja a escala, así que crece entera y
   proporcional —anillo, tipografía, barras de área y pie— como la lupa del
   navegador. Estirando sólo el ancho quedaba deforme: las barras de área
   larguísimas y finitas al lado de un anillo que seguía chico.

   Va zoom y no transform: scale() porque zoom SÍ ocupa el espacio que usa, así
   que la tarjeta alta sigue entrando en el scroll de la vista en vez de
   desbordarse. El alto queda libre para que el avance por área se lea entero. */
.proyectos.sola { display: block; }
.proyectos.sola .pcard {
  /* La escala la calcula ajustarProyectos() con el alto que queda libre, para
     que la tarjeta entre entera sin bajar con el cursor. El 1.6 es el
     respaldo por si ese cálculo no llegó a correr. */
  zoom: var(--pcard-zoom, 1.6); width: 300px; margin: 0 auto;
  height: auto; max-height: none;
}
/* El realce al pasar el mouse se anula: con la tarjeta sola no hay ninguna otra
   de la que distinguirse, y el salto de 2 px multiplicado por el zoom se nota. */
.proyectos.sola .pcard:hover { transform: none; }
/* En pantalla angosta no se agranda nada: la tarjeta ya ocupa todo el ancho y
   con zoom se saldría de la pantalla. ajustarProyectos() también se aparta por
   debajo de 640 px de grilla, así que este corte cubre el tramo intermedio. */
@media (max-width: 700px) {
  .proyectos.sola .pcard { zoom: 1; width: auto; }
}

.pcard {
  background: #fff; border: 1px solid var(--gris-borde); border-radius: var(--radio);
  border-top: 4px solid var(--azul-medio);
  padding: 9px 11px 8px; box-shadow: var(--sombra-1);
  display: flex; flex-direction: column; gap: 7px;
  height: var(--pcard-alto, auto); min-height: 0; overflow: hidden;
  transition: box-shadow var(--transicion), transform var(--transicion);
}
.pcard:hover { box-shadow: var(--sombra-2); transform: translateY(-2px); }
/* Toda la tarjeta abre el Detalle del proyecto, no sólo el nombre. */
.pcard[data-proy-clave] { cursor: pointer; }
.pcard[data-proy-clave]:hover .ident .pr,
.pcard[data-proy-clave]:focus-visible .ident .pr { text-decoration: underline; color: var(--azul); }
.pcard[data-proy-clave]:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.pcard.ok   { border-top-color: var(--verde); }
.pcard.warn { border-top-color: var(--naranja); }
.pcard.bad  { border-top-color: var(--rojo-hondo); }

/* Anillo + identificación en una fila, y las fechas de contrato en una fila
   propia debajo que cruza las dos columnas.
   Es una grilla y no un flex porque la fila de fechas tiene que ocupar TODO el
   ancho de la tarjeta: dentro de la columna angosta de la derecha el término
   salía cortado. Con align-items:center, además, el anillo queda centrado
   contra el bloque de identificación, que al quedarse sin las fechas es más
   bajo: el % de avance sube solo y queda a media altura. */
.pcard-top {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 0 10px; align-items: center; flex: 0 0 auto; min-width: 0;
}
.pcard-top > .pcard-fechas { grid-column: 1 / -1; }
.donut { position: relative; width: 74px; height: 74px; flex: 0 0 auto; }
.donut svg { transform: rotate(-90deg); display: block; }
.donut .num { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.donut .num b { font-size: 19px; line-height: 1; color: var(--azul-nombre); font-variant-numeric: tabular-nums; }
/* "Sin dato" no entra a 19 px dentro de un anillo de 74: va chico y en gris,
   que ademas es lo que es -la ausencia del numero, no un numero-. */
.donut .num b.sindato { font-size: 11px; color: var(--texto-suave); font-weight: normal; }
.donut .num small { font-size: 8.5px; color: var(--texto-suave); text-transform: uppercase; letter-spacing: .3px; }
/* El MISMO anillo dentro de una fila de tabla (la columna % AVANCE de
   Prioridades, 27/10/2026): 46 px en vez de 74, asi que el numero y el rotulo
   bajan a lo que entra adentro. El ancho y el alto los fija la hoja y no el
   SVG, para que la celda no crezca si alguna vez cambia el tamano del dibujo. */
.donut.chico { width: 46px; height: 46px; margin: 0 auto; }
.donut.chico .num b { font-size: 13px; }
.donut.chico .num b.sindato { font-size: 8px; line-height: 1.1; }
/* ADENTRO VA SOLO EL NUMERO (27/10/2026, pedido de Fiefre). El rotulo «AVANCE»
   del anillo grande acá no aporta -la columna se llama % AVANCE dos renglones
   más arriba- y a 6 px no se leía: era una mancha gris debajo de la cifra.
   Se esconde y no se saca del HTML porque el anillo es el mismo de la tarjeta,
   donde el rótulo sí hace falta: ahí no hay encabezado que lo diga. */
.donut.chico .num small { display: none; }
/* La fila de rotulos: el estado a la izquierda y la OT a la derecha.
   El margin-left:auto y no un space-between, para que la OT siga a la derecha
   aunque alguna vez no haya pildora de estado.

   EL SEPARADOR DE LA DERECHA (1 cm el 09/10/2026, despues 1,5 y por ultimo 2) va
   CEDIBLE y no como margen fijo: tiene esa base pero puede encogerse hasta cero.
   Con un margin-right duro, en las tarjetas apretadas ese espacio se quedaba
   con el que necesitaba el texto y "Al dia" partia en dos lineas; asi, lo ultimo
   que cede es el aire y nunca las letras. El calc descuenta el gap de la fila,
   que si no sumaria encima.

   CUANTO CORRE DE VERDAD. Como el separador se encoge, el numero es un tope y
   no una medida: a 340 px la pildora se corre los 2 cm enteros; a 300 y a 268 se
   corre lo que haya -unos 8 y 6 px menos- porque ahi el hueco libre se acaba.
   Lo medido con 2 cm: en los tres anchos la pildora sigue al lado del texto y
   "esperado hoy 30%" sigue en una sola linea, que era la condicion. Para
   correrla mas de esto hay que achicar la pildora o dejar que el texto parta en
   dos lineas: el ancho de la tarjeta ya no da. */
.pcard-chips { display: flex; align-items: stretch; gap: 8px; min-width: 0; flex-wrap: wrap; }
/* El estado y la linea del plan van apilados en una columna, y la OT al lado:
   asi la pildora se estira contra las dos (align-self: stretch) y llega hasta
   "esperado hoy", en vez de quedar del alto de un solo renglon.

   EL MIN-WIDTH ES EL PISO, y es el que decide si la pildora entra al lado o se
   va sola al renglon de abajo: el separador casi no influye. Medido en la
   tarjeta de 268 px (el minimo del auto-fill): con 96 o 108 px de piso la
   pildora baja; con 80 se queda al lado, y el texto sigue entrando en una sola
   linea. Es a lo que se puede bajar sin que "esperado hoy 30%" se parta.

   El piso tiene que estar igual: sin el, en las tarjetas mas apretadas -hasta
   214 px, que es lo que arma ajustarProyectos cuando hay muchos proyectos- el
   texto se cortaba en "esperado / hoy / 30%" y la pildora le pasaba por encima
   a "Atencion". Con el piso, en esos anchos la OT baja a su renglon, entera, y
   nada se superpone. */
/* `flex: 1 1 auto` y no el `flex: 1` de antes. Con `flex: 1` la base es 0: la
   columna no "encoge" nunca, solo recibe lo que sobra, asi que el separador se
   servia primero y el texto se quedaba con las migas -de ahi que "esperado hoy
   30%" partiera en dos lineas con la tarjeta ancha-. Con la base en auto, la
   columna parte midiendo su contenido y lo que cede es el separador. */
.pcard-chips .chips-izq { min-width: 80px; flex: 1 1 auto; }
.pcard-chips .chip-salud { flex: 0 0 auto; }
.pcard-chips .chip-ot { flex: 0 0 auto; align-self: stretch; }
/* El 20 es el factor de encogido, y no es decorativo: con el 1 de antes, el
   separador y la columna del texto cedian a la par, y en la tarjeta ancha con
   una OT larga ("OT 1089 +2") el que terminaba cediendo era el texto -"esperado
   hoy / 30%" partido en dos lineas- teniendo el separador 2 cm de aire al lado.
   Con 20, el aire se consume casi entero antes de que el texto ceda un pixel. */
.pcard-chips::after { content: ''; flex: 0 20 calc(2cm - 8px); }
/* Los colores son los del anillo: el numero en el azul del nombre y el "OT" en
   el gris de "AVANCE". El cuerpo, en cambio, es el del NOMBRE DEL PROYECTO
   (.ident .pr, 14,5 px) y ya no el de la pildora de estado: pedido el
   09/10/2026 para que la OT se lea desde lejos, que es como se mira la tarjeta
   en reunion. El relleno sube con la letra para que el ovalo no quede apretado. */
.chip-ot {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font-size: 14.5px; font-weight: bold; padding: 2px 11px; border-radius: 20px;
  background: var(--azul-tinte); color: var(--texto-suave);
  text-transform: uppercase; letter-spacing: .3px;
}
.chip-ot b { color: var(--azul-nombre); font-variant-numeric: tabular-nums; }

.pcard .ident { min-width: 0; flex: 1; }
.pcard .ident .cl { font-size: 11px; color: var(--texto-suave); letter-spacing: .3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-height: 13px; }
.pcard .ident .pr { font-size: 14.5px; color: var(--azul-nombre); line-height: 1.15; margin: 1px 0 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcard .ident .plan { font-size: 11px; color: var(--texto-suave); margin-top: 4px; line-height: 1.3; }
.pcard .ident .plan b { color: var(--texto); }

.chip-salud { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: bold; padding: 1px 8px; border-radius: 20px; }
.chip-salud.ok   { background: #EAF5E1; color: var(--verde-hondo); }
.chip-salud.warn { background: #FFF4E5; color: var(--naranja-oscuro); }
.chip-salud.bad  { background: #FDECEC; color: var(--rojo-hondo); }
.chip-salud.nodata { background: var(--gris-fondo); color: var(--texto-suave); }
.pcard.nodata { border-top-color: var(--gris-medio); }
/* Rendimiento HH (CPI), sólo admin. */
.pcard-cpi { font-size: 11px; color: var(--texto-suave); margin-top: 3px; }
.pcard-cpi b { color: var(--azul-nombre); font-variant-numeric: tabular-nums; }

/* Las áreas ocupan lo que sobra de la tarjeta y se reparten el espacio en
   partes iguales. El piso del renglón es holgado (15 px) y sólo lo baja
   ajustarProyectos() cuando hay que apretar las tarjetas para que las dos filas
   entren en una pantalla. */
/* El desglose por área de la tarjeta de proyecto, plegado (13/10/2026). */
.pcard-areas-caja { border-top: 1px solid var(--gris-borde); margin-top: 6px; padding-top: 5px; }
.pcard-areas-caja > summary {
  cursor: pointer; list-style: none; font-size: 11px; font-weight: bold;
  color: var(--azul-nombre); letter-spacing: .3px; display: flex;
  align-items: center; gap: 5px; padding: 2px 0; user-select: none;
}
.pcard-areas-caja > summary::-webkit-details-marker { display: none; }
.pcard-areas-caja > summary::before { content: '▸'; font-size: 11px; transition: transform var(--transicion); }
.pcard-areas-caja[open] > summary::before { transform: rotate(90deg); }
.pcard-areas-caja > summary:hover { text-decoration: underline; }
.pcard-areas-caja > summary .cu { color: var(--texto-suave); font-weight: normal; margin-left: auto; }
.pcard-areas-caja[open] .pcard-areas { margin-top: 4px; }

/* Tarjeta gris: la de "áreas sin datos" del Resumen. No compite con las que
   traen un número, porque informa una ausencia y no una medida. */
.kpi.g-gris { background: linear-gradient(170deg, #6B7684, #4C555F); }

/* Botón chico: el "Ver las siguientes" del contador del Detalle. */
.boton.chico { padding: 2px 9px; font-size: 11px; margin-left: 6px; vertical-align: baseline; }

/* La leyenda de marcas del Detalle, que antes sólo vivía en los tooltips. */
.leyenda-tabla { line-height: 1.6; }
.leyenda-tabla b { color: var(--azul-nombre); }

.pcard-areas {
  display: grid; gap: 2px; padding-top: 7px; border-top: 1px solid var(--gris-borde);
  grid-auto-rows: minmax(var(--prow-min, 15px), 1fr);
  flex: 1 1 auto; min-height: 0; overflow: hidden;
}
/* La columna del nombre eran 74 px, que daban para "Serv. Téc." y no para
   "Servicio Técnico". Desde el 08/10/2026 los nombres van completos (Fiefre
   pidió que no se abrevie nada que no haga falta), así que la columna se midió
   contra el nombre más largo. Son 106 px y no 86: estos renglones van en
   MAYÚSCULA por la regla de más abajo, y "CONTROL DE CALIDAD" mide 103 px
   a 11 px contra los 86 del mismo texto en minúscula. Los 32 px salen de la
   barra, que es la parte elástica: aun en la tarjeta más angosta que permite
   la grilla (268 px) le quedan unos 96. */
.pcard-areas .prow { display: grid; grid-template-columns: 106px minmax(0, 1fr) 34px; gap: 6px; align-items: center; font-size: 11px; line-height: 1.05; }
.pcard-areas .prow .an { color: var(--texto); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: .2px; }
/* Renglon sin dato: dice CON PALABRAS cual de los tres casos es -no interviene,
   no cargo nada, cargo sin informar-. Ocupa la barra y la cifra, que en estos
   renglones estan vacias las dos. */
.pcard-areas .prow.na .nada {
  grid-column: 2 / -1; text-align: right; font-size: 11px; color: var(--gris-medio);
  letter-spacing: .2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pcard-areas .prow.na .an { color: var(--gris-medio); }
.pcard-areas .prow .an .atr { color: var(--rojo-hondo); font-size: 11px; margin-left: 3px; vertical-align: middle; }
.pcard-areas .pista { height: 7px; background: var(--gris-fondo); border: 1px solid var(--gris-borde); border-radius: 4px; overflow: hidden; }
.pcard-areas .pista > i { display: block; height: 100%; border-radius: 3px; background: linear-gradient(90deg, var(--azul-medio), var(--azul-hondo)); transition: width var(--transicion); }
.pcard-areas .vv { text-align: right; font-weight: bold; font-variant-numeric: tabular-nums; color: var(--azul-nombre); }
.pcard-areas .vv.na { font-weight: normal; color: var(--gris-medio); }

.pcard-pie { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; font-size: 11px; color: var(--texto-suave); white-space: nowrap; border-top: 1px solid var(--gris-borde); padding-top: 6px; flex: 0 0 auto; }
.pcard-pie > span { overflow: hidden; text-overflow: ellipsis; }
.pcard-pie b { color: var(--azul-nombre); font-variant-numeric: tabular-nums; }
.pcard-pie .malo, .pcard-pie .malo b { color: var(--rojo-hondo); font-weight: bold; }

/* ── Enlace de SharePoint de la tarjeta ──
   Va debajo del avance y arriba de las áreas. Cuando el proyecto tiene enlace
   se ve el acceso a la carpeta; cuando no, un botón para pegarlo. Ni el enlace
   ni los botones abren el Detalle: hacen lo suyo. */
/* Centrada en la tarjeta: es una fila suelta entre el bloque de identificacion
   y las areas, y pegada a la izquierda quedaba colgando. */
.pcard-sp { display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 0; flex: 0 0 auto; }
.pcard-sp a {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  font-size: 11px; font-weight: bold; letter-spacing: .3px; text-transform: uppercase;
  color: var(--azul-nombre); text-decoration: none;
  background: var(--azul-tinte); border: 1px solid var(--azul-tinte-2);
  border-radius: 20px; padding: 2px 9px; transition: background var(--transicion);
}
.pcard-sp a:hover { background: var(--azul-tinte-2); text-decoration: underline; }
/* El enlace toma el color del avance de la tabla: ambar en preparacion (50%),
   verde cuando esta lista (100%). Antes era azul siempre y el estado solo lo
   decia la insignia de al lado; con quince tarjetas en pantalla el color se lee
   de una pasada y el numerito hay que ir a buscarlo. Los fondos se DERIVAN de
   los acentos del tablero, no se eligen a mano. */
.pcard-sp a.sp-50 {
  color: var(--dorado-hondo); border-color: var(--dorado);
  background: color-mix(in srgb, var(--dorado) 34%, #fff);
}
.pcard-sp a.sp-50:hover { background: color-mix(in srgb, var(--dorado) 55%, #fff); }
.pcard-sp a.sp-100 {
  color: var(--verde-hondo); border-color: var(--verde);
  background: color-mix(in srgb, var(--verde) 22%, #fff);
}
.pcard-sp a.sp-100:hover { background: color-mix(in srgb, var(--verde) 38%, #fff); }
.pcard-sp a .tx { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcard-sp a .ic { flex: 0 0 auto; font-size: 11px; }
.pcard-sp .sp-btn {
  background: none; border: 1px dashed var(--gris-borde); border-radius: 20px;
  color: var(--texto-suave); font-family: inherit; font-size: 11px; letter-spacing: .3px;
  text-transform: uppercase; padding: 2px 9px; cursor: pointer;
  transition: border-color var(--transicion), color var(--transicion);
}
.pcard-sp .sp-btn:hover { border-color: var(--azul); color: var(--azul-nombre); border-style: solid; }
.pcard-sp .sp-btn.editar { border: none; font-size: 12px; line-height: 1; padding: 2px 5px; }
.pcard-sp .fuente { font-size: 11px; color: var(--gris-medio); text-transform: uppercase; letter-spacing: .3px; }
/* Badge de % de la tabla de cubicaciones: 50 = en preparación, 100 = lista. */
.pcard-sp .sp-pct {
  font-size: 11px; font-weight: bold; letter-spacing: .3px; text-transform: uppercase;
  padding: 1px 7px; border-radius: 20px; flex: 0 0 auto; line-height: 1.5;
}
.pcard-sp .sp-pct.sp-50 { background: var(--dorado); color: var(--dorado-hondo); }
.pcard-sp .sp-pct.sp-100 { background: var(--verde); color: #fff; }
.pcard-sp .sp-btn.lista { border-color: var(--verde); color: var(--verde-hondo); border-style: solid; }
.pcard-sp .sp-btn.lista:hover { background: var(--verde); color: #fff; border-color: var(--verde); }
.pcard-sp .sp-btn.revertir { border: none; font-size: 11px; padding: 2px 6px; }

/* ── Carta Gantt: la misma píldora que las cubicaciones, un renglón más arriba
   (16/10/2026). Se deja en AZUL -el color neutro de .pcard-sp a- a propósito:
   el ámbar y el verde de la píldora de abajo significan 50 % y 100 %, y usarlos
   acá haría creer que la carta Gantt también tiene un estado. No lo tiene: está
   o no está. Lo único propio es el aire de arriba, para que las dos píldoras no
   queden pegadas al renglón de la recepción por cliente. */
.pcard-gantt { margin-top: 3px; }

/* Aviso al pie de la Cronologia: fechas que se fueron de rango y por eso no
   entran en la escala. Ambar, no rojo: hay que corregir la planilla, pero el
   tablero no esta roto. */
.gantt-aviso {
  margin: 8px 2px 0; padding: 7px 11px; border-radius: 8px;
  font-size: 12px; line-height: 1.45;
  background: color-mix(in srgb, var(--dorado) 26%, #fff);
  border: 1px solid var(--dorado); color: var(--dorado-hondo);
}

/* ── Buscador de la vista Proyectos ───────────────────────────────
   Una sola línea baja, del alto de la barra de históricos, para no comerle
   pantalla a las tarjetas: lo que se viene a mirar acá son las tarjetas. */
.barra-pcards {
  display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
  margin: 0 0 8px; padding: 6px 10px;
  background: var(--gris-fondo); border: 1px solid var(--gris-borde); border-radius: 10px;
}
.barra-pcards label { font-size: 12px; color: var(--texto-suave); margin: 0; }
.barra-pcards select {
  font-family: inherit; font-size: 12.5px; padding: 4px 7px; max-width: 220px;
  border: 1px solid var(--gris-borde); border-radius: 7px; background: #fff; color: var(--texto);
}
/* El campo de texto manda: se lleva el espacio que sobra, pero no baja de un
   ancho en el que se lea lo escrito. */
.barra-pcards .bp-buscar { position: relative; flex: 1 1 260px; min-width: 200px; display: flex; }
.barra-pcards .bp-lupa {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  font-size: 12px; opacity: .55; pointer-events: none;
}
.barra-pcards input[type="search"] {
  width: 100%; font-family: inherit; font-size: 13px; color: var(--texto);
  padding: 5px 9px 5px 28px;
  border: 1px solid var(--gris-borde); border-radius: 7px; background: #fff;
}
.barra-pcards input[type="search"]:focus {
  outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px var(--azul-tinte);
}
.barra-pcards .bp-cuenta {
  margin-left: auto; font-size: 12px; color: var(--texto-suave);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

@media (max-width: 820px) {
  /* En el teléfono la cuenta se va sola a su renglón antes que apretar el
     campo de búsqueda hasta no poder leer lo que se escribe. */
  .barra-pcards .bp-cuenta { margin-left: 0; }
}

/* ── Diálogo para pegar el enlace de SharePoint ── */
.modal {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  background: rgba(29, 36, 50, .42); padding: 20px;
}
.modal-caja {
  background: #fff; border-radius: var(--radio); box-shadow: var(--sombra-2);
  border-top: 4px solid var(--azul); padding: 18px 20px 16px;
  width: 100%; max-width: 540px;
}
.modal-caja h3 {
  color: var(--azul); font-size: 13px; text-transform: uppercase; letter-spacing: .4px;
  padding-bottom: 4px; margin-bottom: 6px;
  border-bottom: 2px solid; border-image: linear-gradient(90deg, #1F4E79, #8FAADC) 1;
}
.modal-proy { font-size: 15px; color: var(--azul-nombre); font-weight: bold; margin-bottom: 12px; }
.modal-caja label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .4px; color: var(--texto-suave); margin-bottom: 4px; }
.modal-caja input {
  width: 100%; font-family: inherit; font-size: 13px; color: var(--texto);
  border: 1px solid var(--gris-borde); border-radius: 8px; padding: 8px 10px; background: #fff;
}
.modal-caja input:focus { outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px var(--azul-tinte); }
.modal-nota { font-size: 11.5px; color: var(--texto-suave); margin-top: 8px; line-height: 1.4; min-height: 34px; }
.modal-botones { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.modal-botones .esp { flex: 1; }
.boton.claro.peligro { color: var(--rojo-hondo); border-color: var(--rojo); }
.boton.claro.peligro:hover { background: #FDECEC; }

/* Acciones de "Mi sesión": una debajo de otra y a todo el ancho, para que
   Salir se vea de una en vez de estar escondido en un menú. */
.sesion-acciones { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.sesion-acciones .boton { width: 100%; padding: 11px 18px; text-align: center; }

/* ── Salud de la cartera (Resumen ejecutivo) ──
   Al costado de la matriz de avance va la lista priorizada de los proyectos que
   requieren atención. La columna nunca queda más alta que la matriz: se estira
   a la altura de la fila y, si la lista es larga, se desplaza por dentro.

   Arriba de la lista había un anillo con los proyectos por estado de salud; se
   retiró porque repetía el semáforo que ya se ve en la matriz de al lado. La
   pila queda de una sola fila, y por eso grid-template-rows es una sola:
   con "auto minmax(0,1fr)" el único panel se quedaba en la fila "auto" y no
   llegaba a estirarse a lo alto de la columna. */
.pila-salud { display: grid; gap: 10px; }
.pila-salud > .tarjeta-graf { margin-bottom: 0; }
/* Antes era @media (min-width: 1100px); ahora, el ancho de maquetado.
   La columna sólo aporta un alto mínimo; el alto real lo manda la matriz de
   al lado. Por eso la pila va posicionada: así su contenido no empuja la fila
   hacia abajo. */
html.maqueta-1100 .col-salud { position: relative; min-height: 380px; }
html.maqueta-1100 .pila-salud { position: absolute; inset: 0; grid-template-rows: minmax(0, 1fr); }
html.maqueta-1100 .pila-salud > .tarjeta-graf { min-height: 0; display: flex; flex-direction: column; }
html.maqueta-1100 .pila-salud .lista-atencion { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 4px; }

.lista-atencion { display: grid; gap: 6px; align-content: start; }
.la-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 74px 104px 104px; gap: 10px; align-items: center;
  padding: 5px 10px; border: 1px solid var(--gris-borde); border-radius: 10px; background: #fff;
  border-left: 5px solid var(--gris-medio);
  transition: box-shadow var(--transicion), transform var(--transicion);
}
.la-row:hover { box-shadow: var(--sombra-1); transform: translateX(2px); }
.la-row.bad { border-left-color: var(--rojo-hondo); }
.la-row.warn { border-left-color: var(--naranja); }
.la-row .id { min-width: 0; }
.la-row .id .pr { font-size: 13px; color: var(--azul-nombre); font-weight: bold; line-height: 1.15; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.la-row .id .cl { font-size: 11.5px; color: var(--texto-suave); letter-spacing: .3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.la-row .av { text-align: center; }
.la-row .av .n { font-size: 16px; font-weight: bold; color: var(--azul-nombre); font-variant-numeric: tabular-nums; line-height: 1; }
.la-row .av .pista { height: 6px; background: var(--gris-fondo); border: 1px solid var(--gris-borde); border-radius: 4px; overflow: hidden; margin-top: 4px; }
.la-row .av .pista > i { display: block; height: 100%; background: linear-gradient(90deg, var(--azul-medio), var(--azul-hondo)); }
.la-row .atr { text-align: center; font-size: 11px; line-height: 1.2; color: var(--rojo-hondo); font-weight: bold; }
.la-row .atr.cero { color: var(--texto-suave); font-weight: normal; }
/* Vencido NO es lo mismo que tener actividades atrasadas, y hasta el 03/10/2026
   esta misma celda decia "sin atrasos" sobre un proyecto que llevaba 43 dias
   pasado de la fecha de entrega. Ahora lo dice fuerte y con su propio fondo:
   un proyecto vencido es el peor estado del tablero y tiene que leerse primero. */
.la-row .atr.vencido {
  color: #fff; background: var(--rojo-hondo); border-radius: 5px;
  padding: 3px 4px; font-size: 11px; letter-spacing: .2px; line-height: 1.25;
}
.la-row .ent { text-align: right; font-size: 11px; line-height: 1.25; color: var(--texto-suave); font-variant-numeric: tabular-nums; }
.la-row .ent b { color: var(--texto); display: block; font-size: 13px; }
.la-row .ent.tarde b { color: var(--rojo-hondo); }

.salud-ok-msg { background: #EAF5E1; border: 1px solid var(--verde); color: var(--verde-hondo); border-radius: 8px; padding: 14px 16px; font-size: 13.5px; font-weight: bold; }

/* ── Matriz pulida "Avance por proyecto y área" (Resumen) ──
   El color llena la celda, el N/A queda apagado (rayado tenue), el Total lleva
   barra y hay una columna Cob. con la cobertura. El nombre del proyecto es un
   enlace que abre el Detalle. */
.mtx-scroll { overflow-x: auto; }
table.mtx { border-collapse: separate; border-spacing: 3px; min-width: 100%; font-size: 13px; }
table.mtx thead th {
  background: linear-gradient(180deg, var(--azul), var(--azul-hondo)); color: #fff;
  font-size: max(11px, calc(var(--piso-texto) / var(--escala, 1))); text-transform: uppercase; letter-spacing: .4px; text-align: center;
  padding: 7px 6px; white-space: nowrap; border-radius: 6px; vertical-align: bottom;
}
table.mtx th.rw {
  background: #fff; color: var(--texto); font-weight: normal; text-align: left; text-transform: none;
  padding: 4px 10px; position: sticky; left: 0; z-index: 1; border-right: 2px solid var(--gris-borde);
  white-space: nowrap; max-width: 320px;
}
/* Los nombres de area van completos desde el 07/10/2026. Para que "CONTROL DE
   CALIDAD" y "SERVICIO TECNICO" no estiren la tabla, parten en dos lineas en
   vez de empujar el ancho. Va sobre #matrizAvance y no sobre table.mtx porque
   esa clase la reusa otra tabla, cuyos titulos son cortos y no tienen que
   cambiar. */
#matrizAvance thead th { white-space: normal; line-height: 1.15; }
/* ── Todas las areas, del mismo ancho (13/10/2026) ───────────────────────
   La matriz se armaba con el ancho automatico del navegador, que le da a cada
   columna lo que mide su contenido. Como las celdas son todas igual de cortas
   ("100%", "N/A", "S/D"), el que terminaba mandando era el TITULO: VENTAS
   salia de 48 px y CONTROL DE CALIDAD de 110, mas del doble.

   Y eso se lee mal. La matriz esta para comparar un area contra otra de un
   vistazo; con las columnas de distinto ancho el ojo compara tamanios de
   recuadro antes que porcentajes, y una fila de 100% angostos parece menos que
   una de 0% anchos.

   Con `table-layout: fixed` el ancho ya no lo decide el contenido sino la
   primera fila -la de titulos-, y las columnas que no declaran ancho se
   reparten en PARTES IGUALES lo que sobra. Asi que alcanza con declarar una
   sola: la del nombre. Las nueve, diez u once de area -cuantas haya- mas el
   Total salen todas iguales solas, sin tener que saber cuantas son.

   Hacen falta las dos lineas juntas: con `width: auto` el navegador ignora
   `table-layout: fixed` y vuelve al ancho por contenido (medido: no cambiaba
   nada hasta poner el 100 %).

   El 21 % de la columna del nombre no es un numero al azar: en un monitor de
   1920 con la escala del tablero puesta (2133 px de ancho de trabajo, ver
   lib/escala.js) da 429 px para el nombre y 147 px para cada area, que es
   justo como se venia viendo la matriz.

   Va en PORCENTAJE y no en 440 px fijos por la vista del administrador: con la
   columna "Requieren atencion" al costado, la matriz tiene 1361 px en vez de
   2057. Con un ancho rigido para el nombre, a cada area le quedaban 69 px; con
   el 21 % la del nombre cede primero -el nombre entero sigue en el globito- y
   las areas no bajan de 86 px. */
#matrizAvance { table-layout: fixed; width: 100%; }
#matrizAvance thead th.rw { width: 21%; max-width: none; }
/* Red de contencion para esa vista angosta: si un titulo largo no entra en sus
   86 px, parte en dos lineas en vez de montarse sobre el de al lado. */
#matrizAvance thead th { overflow-wrap: anywhere; }
/* En celulares no: debajo de 900 px el tablero no se escala (ese es el corte de
   lib/escala.js) y repartir 390 px entre doce columnas deja celdas de 28 px,
   donde no entra ni "100%". Ahi vuelve lo de antes: cada columna con el ancho
   de su contenido y desplazamiento lateral dentro de .mtx-scroll. */
@media (max-width: 899px) {
  #matrizAvance { table-layout: auto; width: auto; }
}


/* El encabezado "Proyecto" va igual que los de area. table.mtx th.rw lo dejaba
   en blanco, sin negrita y sin mayusculas, porque esa misma clase pinta los
   nombres de proyecto de cada fila, donde eso si corresponde. Aca se repone
   todo lo que esa clase le saca a table.mtx thead th -fondo, color, cuerpo,
   esquinas y relleno-, asi la fila de encabezados se lee como una sola pieza y
   la celda azul llega a la misma altura que ADMINISTRACION o CONTROL DE
   CALIDAD, que ocupan dos renglones. El borde derecho se saca: era el corte
   contra el fondo blanco, y con la celda pintada sobra. */
/* El nombre del proyecto se montaba encima de la columna ADMINISTRACION.
   th.rw tenia max-width: 320px y white-space: nowrap. Con esa combinacion el
   texto largo sale igual del recuadro, y como esta columna es sticky lo que
   sobresale se dibuja ENCIMA de los porcentajes, no por debajo.

   Va TODO EN UNA LINEA, pedido el 08/10/2026: el nombre no parte en dos. La
   columna crece hasta donde haga falta y el ancho que sume se lo lleva el
   desplazamiento horizontal de .mtx-scroll, que ya existe. Por eso se suelta
   el max-width de la celda: era justamente el que recortaba la columna y
   dejaba el texto afuera.

   El tope real va en el <span> de adentro, donde si se respeta (en una tabla
   de ancho automatico, max-width sobre un <th> no se honra: mismo arreglo que
   #tablaHistoricos). Son 420 px, de sobra para el nombre mas largo de hoy
   -"FINNING ANTOFAGASTA - WALL CRANE CAP. 2t (x2) NAVE 4", unos 355-. Si
   alguna vez entra uno mas largo, se corta con puntos suspensivos y el nombre
   entero sigue en el title: feo, pero nunca encima de otro dato. */
/* La celda del proyecto con su propio tinte (16/10/2026): es la que da sentido
   a toda la fila y en blanco quedaba como un hueco entre el encabezado azul y
   las diez celdas de color. Con fondo propio se lee como una columna más. El
   realce del mouse sigue distinguiéndose porque usa el tinte siguiente. */
#matrizAvance tbody th.rw { white-space: nowrap; max-width: none; background: var(--azul-tinte); }
#matrizAvance tbody th.rw .proy-link {
  /* 100% y no 420 px: con table-layout: fixed la columna ya mide 440, y si el
     navegador le reparte unos px de mas, el nombre los aprovecha. */
  display: inline-block; max-width: 100%; vertical-align: middle;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

#matrizAvance thead th.rw {
  background: linear-gradient(180deg, var(--azul), var(--azul-hondo)); color: #fff;
  font-weight: bold; text-transform: uppercase; letter-spacing: .4px; text-align: center;
  padding: 7px 6px; border-right: 0; border-radius: 6px; white-space: nowrap;
}

table.mtx tbody tr:hover th.rw { background: var(--azul-tinte); }
/* ── La fila entera se ilumina al pasar por encima (13/10/2026) ───────────
   Con 10 columnas de porcentajes, al apuntar una celda del medio no se sabia
   de que proyecto era: habia que seguir el renglon con el ojo hasta el nombre,
   a media pantalla de distancia, y un renglon mas arriba o mas abajo se abre
   el detalle de otro proyecto.

   Es un RECUADRO y no un fondo de color: la matriz se lee por el color de cada
   celda (la escala azul del avance), y cualquier tinte encima lo falsearia
   justo en la fila que se esta mirando.

   Y va con outline sobre cada celda, NO con una banda ::after sobre la fila.
   La banda se probo primero y movia la pantalla: un ::after posicionado cuenta
   como contenido desplazable de .mtx-scroll y le sumaba 3 px al ancho con solo
   pasar el mouse -medido a 12 anchos de ventana distintos-, asi que la barra
   de desplazamiento horizontal aparecia y desaparecia sola y el tablero daba
   un salto. El outline no entra en ningun calculo de tamanio: no mueve nada.
   Tampoco pisa los box-shadow que ya traen .cel.total y .cel.na.noaplica, que
   es lo que habria pasado de usar otro box-shadow. */
#matrizAvance tbody tr:hover th.rw { background: var(--azul-tinte-2); }
#matrizAvance tbody tr:hover .cel { outline: 2px solid var(--azul-hondo); outline-offset: 0; }
/* ...y la celda del NOMBRE entra en el mismo recuadro (13/10/2026). Hasta hoy
   el marco empezaba en la primera columna de porcentajes: la fila se leia
   empezada por ADMINISTRACION y el nombre, que es lo que dice de que proyecto
   es esa fila, quedaba justo afuera del marco que viene a senalarla.

   El recuadro va HACIA ADENTRO (outline-offset negativo) y no hacia afuera
   como en las celdas de color: esta columna es sticky contra el borde
   izquierdo de .mtx-scroll, asi que los 2 px dibujados por fuera caen en la
   zona que recorta el overflow y el lado izquierdo del marco no se veria.
   El redondeo de 6 px es el mismo de las celdas de porcentaje, para que el
   marco cierre igual en las dos puntas; sobre el fondo blanco de la celda no
   se nota mientras el cursor no esta encima. */
#matrizAvance tbody th.rw { border-radius: 6px; }
#matrizAvance tbody tr:hover th.rw { outline: 2px solid var(--azul-hondo); outline-offset: -2px; }
/* La celda del nombre se pincha ENTERA, no sólo sobre las letras: el cursor
   tiene que decirlo en toda su superficie, igual que en las de porcentaje. */
#matrizAvance tbody th.rw.clic-proy { cursor: pointer; }
#matrizAvance tbody th.rw.clic-proy:focus-visible {
  outline: 2px solid var(--azul-hondo); outline-offset: -2px;
}

table.mtx th.rw .ot { color: var(--azul-nombre); font-weight: bold; font-variant-numeric: tabular-nums; margin-right: 6px; }
table.mtx td { padding: 0; }

/* ── Tabla de Proyectos históricos ──
   Reusa table.mtx para verse igual que la matriz de avance, pero sus celdas
   llevan texto suelto y no el <div class="cel"> de colores, así que necesitan
   su propio relleno: table.mtx td va con padding 0 justamente porque ahí el
   que ocupa la celda entera es el recuadro de color. */
table.mtx td.hcel { padding: 6px 10px; font-size: 12.5px; color: var(--texto); white-space: nowrap; }
/* En historicos las columnas de datos se achican a su contenido (width: 1px mas
   abajo), asi que con 10 px de relleno quedaban los cinco textos pegados unos a
   otros contra el borde derecho. 34 px los separa sin estirar la tabla: lo que
   se suma sale de la columna del nombre, que es la elastica.

   Y van CENTRADAS bajo su titulo, que ya venia centrado: la fecha tiraba a la
   izquierda y el avance a la derecha, asi que ninguna de las cuatro caia debajo
   de su encabezado. El nombre del proyecto no, que es texto largo. */
/* Las reglas de #tablaHistoricos se retiraron el 27/10/2026: esa pestana pasó
   a tarjetas y la tabla ya no existe. Lo de abajo es de la matriz de avance,
   que sí la sigue usando. */
table.mtx td.hcel.num { text-align: right; font-variant-numeric: tabular-nums; }
table.mtx td.sin-datos { padding: 18px 10px; }

/* La matriz de avance reparte el ancho entre 9 columnas de área iguales; acá son
   pocas columnas de datos, así que sin esto quedaban estiradas a lo ancho de la
   pantalla con el texto perdido en el medio. El nombre del proyecto se queda con
   lo que sobra y las demás se achican a su contenido. */
/* Barra de la pestaña de históricos: a la izquierda el rango (lo usa
   cualquiera, sólo filtra la tabla), a la derecha el umbral de días (sólo el
   administrador, y cambia lo que ve todo el equipo). */
/* Centrada: se retiro el titulo "Proyectos historicos" de arriba (08/10/2026,
   lo dice la pestania) y la barra quedo sola al tope de la vista, pegada a la
   izquierda. El umbral del administrador suelta su margin-left:auto, que era lo
   que lo mandaba contra el borde derecho; con la barra centrada los dos grupos
   van juntos al medio, separados por el gap. */
.barra-hist {
  display: flex; flex-wrap: wrap; gap: 10px 22px; align-items: center;
  justify-content: center;
  margin: 2px 0 10px; padding: 8px 10px;
  background: var(--gris-fondo); border: 1px solid var(--gris-borde); border-radius: 10px;
}
.barra-hist .hgrupo { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.barra-hist label { font-size: 12px; color: var(--texto-suave); margin: 0; }
.barra-hist input[type="date"], .barra-hist input[type="number"] {
  font-family: inherit; font-size: 12.5px; padding: 4px 7px;
  border: 1px solid var(--gris-borde); border-radius: 7px; background: #fff; color: var(--texto);
}
.barra-hist input[type="number"] { width: 72px; text-align: right; font-variant-numeric: tabular-nums; }
.barra-hist .hsuf { font-size: 12px; color: var(--texto-suave); }
.barra-hist .hnota { font-size: 12px; }
.boton.chico { padding: 4px 10px; font-size: 12px; }

/* ── Proyectos históricos: UNA tabla, no dos ──────────────────────────────
   Hasta el 07/10/2026 esta tabla reusaba tal cual el estilo de la matriz de
   avance, y se veía partida en dos bloques: el nombre del proyecto en un
   recuadro blanco a la izquierda y, muy lejos, las columnas de datos con su
   propia cabecera azul. Parecían dos tablas distintas de lo mismo.

   Eran tres cosas sumadas: el ancho 100% de la columna del nombre empujaba el
   resto hasta el borde; el separado de 3 px entre celdas abría el hueco; y la
   celda "Proyecto" de la cabecera, por ser th.rw, salía blanca mientras las
   otras salían azules, así que ni siquiera se leían como una misma fila de
   títulos.

   Acá se desarma esa herencia: celdas pegadas, UNA cabecera azul entera, el
   nombre ocupando lo que sobra y las columnas de datos justas. */
/* Acá vivían las reglas de la TABLA de proyectos históricos. Se retiraron el
   27/10/2026: esa pestaña pasó a mostrar las mismas tarjetas que «Proyectos»,
   para que el archivo también tenga a mano la carta Gantt y las tablas de
   cubicaciones. El historial del repositorio las guarda si hiciera falta. */

.cel {
  display: flex; align-items: center; justify-content: center; gap: 3px;
  height: 32px; border-radius: 6px; font-weight: bold; font-variant-numeric: tabular-nums;
  font-size: max(12.5px, calc(var(--piso-texto) / var(--escala, 1)));
  /* Un filo propio para que la celda se vea como celda SIEMPRE (16/10/2026).
     El fondo sale del mapa de calor, así que un avance bajo quedaba casi
     blanco: el redondeo desaparecía y esa fila no se leía como las de al lado,
     aunque tuviera el mismo dato. El filo dibuja la forma aunque el relleno
     sea tenue. Va en inset y no en border para no correr la grilla. */
  box-shadow: inset 0 0 0 1px rgba(47, 117, 182, .22);
}
/* Area sin ninguna actividad cargada: dice "S/D" en naranja tenue.
   Antes era un punto gris claro, que a tres metros no se distinguia de una
   celda vacia de verdad y obligaba a pasar el mouse para saber que decia. El
   naranja es el del tablero, el mismo de "Atencion": no es un error ni un cero,
   es un dato que falta, y la escala azul del avance sigue siendo solo para
   avances de verdad. */
.cel.na {
  background: repeating-linear-gradient(45deg, #FBFCFE, #FBFCFE 5px, #F1F5FA 5px, #F1F5FA 10px);
  color: var(--naranja); font-weight: bold; letter-spacing: .4px;
  font-size: max(11px, calc(var(--piso-texto) / var(--escala, 1)));
}
/* El mismo rotulo en la leyenda, para que se lea igual que en la celda. */
.leyenda .ly-sd { color: var(--naranja); }
/* ── Aviso de reconectar la carpeta ──
   Va arriba de todo el contenido: es la diferencia entre ver los datos de hoy
   y ver la copia del servidor sin enterarse. */
.aviso-reconectar {
  display: flex; align-items: center; gap: 12px;
  margin: 12px 16px 0; padding: 12px 16px;
  background: #FFF7ED; border: 1px solid #FDBA74; border-left: 4px solid #EA580C;
  border-radius: 10px;
}
.aviso-reconectar .ic { font-size: 18px; color: #C2410C; flex: 0 0 auto; }
.aviso-reconectar .txt { flex: 1 1 auto; font-size: 12.5px; line-height: 1.5; color: var(--texto); }
.aviso-reconectar .txt b { color: #9A3412; }
.aviso-reconectar .boton { flex: 0 0 auto; }
@media (max-width: 700px) {
  .aviso-reconectar { flex-wrap: wrap; }
  .aviso-reconectar .boton { width: 100%; }
}

/* ── Bloques del panel de administrador (origen de datos) ── */
.bloque-admin {
  margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--gris-borde);
}
.bloque-admin h4 {
  margin: 0 0 4px; font-size: 13px; color: var(--azul-nombre); letter-spacing: .2px;
}
.bloque-admin .modal-botones { margin-top: 10px; }
/* Verde = anda, rojo = no anda. Se usa dentro de los .modal-nota del panel. */
.bloque-admin .bien { color: var(--verde-hondo, #15803D); }
.bloque-admin .mal  { color: var(--rojo-hondo, #B91C1C); }
.bloque-admin code {
  background: var(--gris-fondo); border: 1px solid var(--gris-borde);
  border-radius: 4px; padding: 0 4px; font-size: 11px;
}
/* Resultado de "Probar conexion": un paso por linea, con su pista si fallo. */
.sp-pasos { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.sp-paso {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: 12px; line-height: 1.45; padding: 7px 10px; border-radius: 8px;
  background: var(--gris-fondo); border: 1px solid var(--gris-borde);
}
.sp-paso.mal { background: #FEF2F2; border-color: #FCA5A5; }
.sp-paso .ic { flex: 0 0 auto; font-size: 12px; line-height: 1.45; }
.sp-paso b { display: block; color: var(--texto); font-weight: 600; }
.sp-paso .det { color: var(--texto-suave); word-break: break-word; }
.sp-paso .pista { display: block; margin-top: 3px; color: var(--rojo-hondo); }

/* "No aplica": se escribe N/A (no el "·" del área sin datos), en gris legible. */
/* "N/A" = el área no aplica a este proyecto. Va con fondo gris pleno, no con el
   rayado de las celdas sin dato: son dos cosas distintas y conviene que se
   distingan de un vistazo. El rayado dice "falta cargar"; el gris dice "acá no
   hay nada que cargar". */
.cel.na.noaplica {
  background: var(--gris-na);
  box-shadow: inset 0 0 0 1px #B4C0D2;
  color: var(--texto); font-weight: bold; letter-spacing: .3px;
  font-size: max(11px, calc(var(--piso-texto) / var(--escala, 1)));
}
/* "Sin informar": el area TIENE actividades, pero ninguna trae estado ni %.
   Se muestra cuantas son, para no confundirlo con un area vacia. */
/* Decia "3 s/i" en una linea. Desde el 08/10/2026 dice "3 / sin informar" en
   dos: la palabra entera mide 42 px a 8 px y al lado del numero no entraba,
   pero debajo si -la celda tiene 32 px de alto y el conjunto mide 26-. */
.cel.na.sininfo { flex-direction: column; color: var(--texto-suave); font-weight: bold;
  font-size: max(12px, calc(var(--piso-texto) / var(--escala, 1))); gap: 0; line-height: 1.05; }
/* Este llegaba al ojo en 5,4 px: directamente no se leia. Su piso es 9 y
   no 10 porque es la segunda linea de una celda de 32 px de alto. */
.cel.na.sininfo small { font-size: max(8px, calc(9px / var(--escala, 1)));
  font-weight: normal; letter-spacing: .2px; opacity: .8; }
.cel .atr-cel { color: var(--rojo-hondo); font-size: max(11px, calc(var(--piso-texto) / var(--escala, 1))); line-height: 1; }
/* Celdas que abren el detalle del área (07/10/2026). Se marcan al pasar por
   encima y no antes: un realce permanente en 9 columnas x 15 filas convertiría
   la matriz en un tablero de botones y se perdería la lectura del color, que es
   para lo que está la matriz. */
.cel.clicable { cursor: pointer; transition: box-shadow var(--transicion), transform var(--transicion); }
.cel.clicable:hover { box-shadow: 0 0 0 2px var(--azul-hondo); transform: translateY(-1px); }
.cel.clicable:focus-visible { outline: 0; box-shadow: 0 0 0 2px var(--azul-hondo), 0 0 0 4px rgba(61,107,191,.35); }
.cel.total { position: relative; overflow: hidden; background: var(--gris-fondo); box-shadow: inset 0 0 0 1px var(--gris-borde); color: var(--texto); }
.cel.total > i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 6px 0 0 6px; }
.cel.total > span { position: relative; z-index: 1; }

/* Nombre de proyecto clicable: abre el Detalle. */
.proy-link { cursor: pointer; }
.proy-link:hover { text-decoration: underline; color: var(--azul); }

@media (max-width: 780px) {
  .la-row { grid-template-columns: minmax(0, 1fr) 70px; }
  .la-row .atr, .la-row .ent { display: none; }
}
/* Columna de salud angosta (ancho de maquetado de 1100 a 1450 px): quedan el
   nombre, el avance y la fecha; los atrasos se leen en el globito de la fila.
   Antes era @media (min-width:1100px) and (max-width:1450px), y entraba en
   todo notebook: la ventana medía 1366 pero el tablero se maquetaba sobre
   2133, así que la columna perdía los atrasos teniendo ancho de sobra. */
html.maqueta-1100-1450 .pila-salud .la-row { grid-template-columns: minmax(0, 1fr) 66px 96px; }
html.maqueta-1100-1450 .pila-salud .la-row .atr { display: none; }

/* ── Avance por proyecto y área: barras por área, sin N/A (Resumen) ──
   Una fila por proyecto que muestra sólo las áreas con % cargado, más la
   cobertura (cuántas de las 9). El total manda el color del borde izquierdo. */
.lista-avance { display: grid; gap: 9px; }
.av-row {
  display: grid; grid-template-columns: 210px 62px 1fr; gap: 14px; align-items: center;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 10px; padding: 10px 12px;
  border-left: 5px solid var(--azul-medio); transition: box-shadow var(--transicion);
}
.av-row:hover { box-shadow: var(--sombra-1); }
.av-row.alto { border-left-color: var(--verde); }
.av-row.medio { border-left-color: var(--dorado-hondo); }
.av-row.bajo { border-left-color: var(--rojo-hondo); }
.av-row .id { min-width: 0; }
.av-row .id .pr { font-size: 13.5px; color: var(--azul-nombre); font-weight: bold; line-height: 1.15; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.av-row .id .cl { font-size: 11px; color: var(--texto-suave); letter-spacing: .3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.av-row .id .cob { font-size: 11px; color: var(--texto-suave); margin-top: 3px; }
.av-row .id .cob b { color: var(--azul-nombre); font-variant-numeric: tabular-nums; }
.av-row .tot { text-align: center; }
.av-row .tot .n { font-size: 22px; font-weight: bold; color: var(--azul-nombre); font-variant-numeric: tabular-nums; line-height: 1; }
.av-row .tot .t { font-size: 11px; color: var(--texto-suave); text-transform: uppercase; letter-spacing: .4px; }
.av-row .chips { display: flex; gap: 8px; flex-wrap: wrap; }
.av-chip { display: grid; gap: 3px; min-width: 72px; flex: 0 1 96px; }
.av-chip .l { display: flex; justify-content: space-between; gap: 6px; font-size: 11px; align-items: baseline; }
.av-chip .l .a { color: var(--texto-suave); letter-spacing: .2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.av-chip .l .a .atr { color: var(--rojo-hondo); font-weight: bold; }
.av-chip .l .v { font-weight: bold; color: var(--azul-nombre); font-variant-numeric: tabular-nums; }
.av-chip .p { height: 7px; background: var(--gris-fondo); border: 1px solid var(--gris-borde); border-radius: 4px; overflow: hidden; }
.av-chip .p > i { display: block; height: 100%; border-radius: 3px; }
.av-row .vacio { color: var(--texto-suave); font-size: 12px; font-style: italic; }

@media (max-width: 820px) {
  .av-row { grid-template-columns: 1fr 56px; }
  .av-row .chips { grid-column: 1 / -1; }
}

/* Cronograma */
.gantt-scroll { overflow-x: auto; }
.gantt { min-width: 860px; }
.gantt-cab, .gantt-fila { display: grid; grid-template-columns: 300px 1fr; gap: 12px; }
.gantt-cab {
  font-size: 11px; color: var(--azul-nombre); font-weight: bold;
  text-transform: uppercase; letter-spacing: .5px;
  padding-bottom: 6px; border-bottom: 2px solid var(--azul-claro);
}
.gantt-fila { align-items: center; padding: 6px 0; border-bottom: 1px solid var(--gris-borde); }
.gantt-fila:hover { background: var(--azul-tinte); }
.gantt-fila .nm { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-left: 2px; }
.gantt-fila .nm .ot { color: var(--texto-suave); }
.gantt-fila.sub .nm { padding-left: 18px; color: var(--texto-suave); font-size: 12.5px; }
/* ── La rejilla de meses (13/10/2026, como fondo desde el 18/10/2026) ───
   Era una linea gris clarisima por mes: con quince proyectos abiertos, las
   barras quedaban flotando sin referencia y no se sabia en que mes caia cada
   una sin seguir la columna con el dedo hasta el encabezado. Ahora los meses
   se alternan con una banda muy tenue -el mismo recurso que una tabla con
   renglones alternados- y la linea de cada mes se ve.

   El dibujo entra por --rejilla-gantt, un degradado con topes duros que arma
   renderGantt() UNA vez y hereda a todas las pistas. Antes era un <i> por
   linea y por banda DENTRO DE CADA FILA: unos 4.600 nodos repetidos que se
   rehacian en cada redibujo. Como fondo se pinta en el mismo lugar y por
   debajo de las barras, igual que entonces, y no cuesta un nodo. */
.pista-gantt {
  position: relative; height: 20px;
  background-image: var(--rejilla-gantt, none);
}
.viga {
  position: absolute; top: 5px; height: 11px; min-width: 3px;
  background: var(--azul-tinte-2); border-radius: 6px; overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(47,117,182,.18);
}
.viga > i { display: block; height: 100%; border-radius: 6px; background: linear-gradient(90deg, var(--azul-medio), var(--azul-hondo)); }
.viga.sub { height: 8px; top: 6px; }
.hoy { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--rojo-hondo); z-index: 2; border-radius: 2px; }

/* ── Hitos de área en la Cronología (13/10/2026) ──────────────────────────
   Un rombo por cada actividad que dice HITO en OBSERVACIONES, puesto en su
   fecha de compromiso. Es la forma estándar de dibujar un hito en un Gantt: un
   instante, no un tramo, así que no tiene ancho de barra.
   Va por encima de la viga (z-index 3) pero por debajo de la línea de hoy y de
   las flechas, que son las que ordenan la lectura. */
.pista-gantt .hito {
  position: absolute; top: 50%; width: 9px; height: 9px; margin-left: -4.5px;
  transform: translateY(-50%) rotate(45deg);
  background: #fff; border: 2px solid var(--azul-hondo);
  border-radius: 1px; z-index: 3; box-sizing: border-box;
}
.pista-gantt .hito.ok    { background: var(--verde);  border-color: var(--verde-hondo); }
.pista-gantt .hito.tarde { background: var(--rojo);   border-color: var(--rojo-hondo); }
/* El último hito del área es el que habilita a la siguiente: de él sale la
   flecha, y por eso se dibuja un punto más grande que los demás. */
.pista-gantt .hito.enlace { width: 11px; height: 11px; margin-left: -5.5px; }
/* LA APROBACION (14/10/2026). Cuando OBSERVACIONES dice APROBACION en la
   planilla de Proyectos, esa actividad es un hito -ver esHitoAprobacion()-. Se
   dibuja con el borde verde del area que ya cumplio, y hueco por dentro
   mientras no este cumplida, igual que los demas rombos: lo que la distingue es
   el color del borde, no la forma.

   La que ademas habilita el arranque de Ingenieria lleva un halo verde: de ahi
   sale la flecha que se saltea las areas del medio, y sin la marca no se
   entiende por que la flecha nace justo ahi. */
.pista-gantt .hito.aprobacion { border-color: var(--verde-hondo); }
.pista-gantt .hito.aprobacion.ok { background: var(--verde); border-color: var(--verde-hondo); }
.pista-gantt .hito.inicia-ing {
  width: 11px; height: 11px; margin-left: -5.5px;
  box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--verde) 34%, transparent);
}

/* LOS DOS HITOS PROPIOS DE CADA AREA (18/10/2026): el de INICIO, donde toma el
   trabajo, y el de FIN, donde lo entrega a la siguiente. No salen de ninguna
   columna de la planilla: son los dos extremos de la barra del area, dibujados
   como hito porque es lo que significan.

   Se distinguen de los rombos de OBSERVACIONES por la FORMA -estos no giran,
   son cuadrados chicos pegados al borde de la barra- para que de un vistazo se
   vea cual es el limite del area y cual un hito interno suyo. El de fin va un
   poco mas marcado: es el que manda la flecha al area de abajo. */
.pista-gantt .hito.borde {
  width: 8px; height: 14px; margin-left: -4px; border-radius: 2px;
  transform: translateY(-50%); border-width: 2px;
}
.pista-gantt .hito.borde.inicio { border-color: var(--azul); background: #fff; }
.pista-gantt .hito.borde.fin    { border-color: var(--azul-hondo); width: 9px; margin-left: -4.5px; }
.pista-gantt .hito.borde.ok     { background: var(--verde); border-color: var(--verde-hondo); }
.pista-gantt .hito.borde.tarde  { background: var(--rojo);  border-color: var(--rojo-hondo); }
/* El rombo chico al lado del nombre del área avisa que esa área tiene hitos
   marcados, incluso con la pista angosta o el rombo fuera de la ventana. */
.gantt-fila.sub .nm-hito { color: var(--azul-hondo); font-size: 11px; vertical-align: middle; }
.eje-gantt { position: relative; height: 18px; font-size: 11px; color: var(--texto-suave); }
/* El mes en curso, en el encabezado, con el mismo color que la linea de hoy. */
.eje-gantt span.hoy-mes { color: var(--rojo-hondo); font-weight: bold; }
.eje-gantt span { position: absolute; transform: translateX(-50%); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ── 8. Tablas, etiquetas, avisos y varios ────────────────────── */
.tabla-scroll { overflow-x: auto; border-radius: 10px; }

/* ── El Detalle usa todo el alto de la pantalla (22/10/2026) ───────────────
   La tabla de actividades tenía un alto fijo de 68vh: se cortaba a media
   pantalla y abajo quedaba una franja en blanco, así que se veían menos
   tareas de las que cabían. Ahora el alto lo pone la pantalla, no un número.
   Para eso main.contenido -que es el que scrollea- se vuelve una columna
   flexible MIENTRAS se mira el Detalle (la clase se la pone cambiarVista; en
   las otras vistas main sigue siendo un bloque normal que crece con su
   contenido). Encadenados, #app, la vista, la tarjeta y la caja de la tabla
   ceden su alto hasta que la tabla llega al borde de abajo y scrollea por
   dentro. Sirve igual en 1366×768 que en 1080 y con cualquier área filtrada,
   y el encabezado azul de la tabla ya es sticky, así que no se pierde. */
main.contenido.alto-pleno { display: flex; flex-direction: column; }
main.contenido.alto-pleno > #app { flex: 1 1 auto; min-height: 0; }
/* Los filtros y el botón que los pliega conservan su alto: lo que cede es la
   tabla, nunca los controles. */
main.contenido.alto-pleno > #app > .barra-filtros,
main.contenido.alto-pleno > #app > .btn-filtros-movil { flex: 0 0 auto; }
/* Ceden alto (flex-shrink), pero no estiran: con pocas actividades la tarjeta
   sigue midiendo lo que mide la lista, como siempre, y no se infla con una
   mancha blanca adentro. Sólo cuando la lista no cabe entra a jugar el recorte
   y la tabla pasa a scrollear por dentro.

   OJO con el :not([hidden]), la MISMA trampa que ya está anotada arriba para
   #v-resumen: un selector con #id le gana a section.vista[hidden]{display:none},
   así que sin él el Detalle de actividades se cuela DEBAJO de todas las
   pestañas -Resumen, Proyectos, Cronología- aunque esté marcado hidden. El
   Detalle se abre apretando el porcentaje de un área en el Resumen o un
   proyecto en Proyectos, y en ninguna otra parte. */
#v-detalle:not([hidden]) { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; }
#v-detalle > .tarjeta-graf {
  flex: 0 1 auto; min-height: 0; margin-bottom: 0;
  display: flex; flex-direction: column;
}
/* El título y el botón de CSV mantienen su alto; lo que cede es la tabla. El
   margen de abajo separa la cabecera del encabezado azul de la tabla: con las
   tarjetas de la ficha ahí arriba, pegadas se leían como una sola franja de
   colores y no se sabía dónde terminaba una cosa y empezaba la otra. */
#v-detalle > .tarjeta-graf > .cabecera-graf { flex: 0 0 auto; margin-bottom: 10px; }
/* La tarjeta del proyecto mantiene su alto, igual que el título: lo que cede
   es la tabla. Su propio tope está en «.ficha-detalle» más abajo; sin este
   flex, en una pantalla baja se estiraba a lo que quedara y dejaba la tabla
   en dos renglones. */
#v-detalle > .tarjeta-graf > .ficha-detalle { flex: 0 0 auto; }
#v-detalle .tabla-scroll { flex: 0 1 auto; min-height: 0; overflow: auto; }
table.datos { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13.5px; }
table.datos th {
  background: linear-gradient(180deg, var(--azul), var(--azul-hondo));
  color: #fff; font-weight: bold; padding: 9px 8px; text-align: left;
  white-space: nowrap; letter-spacing: .3px;
  position: sticky; top: 0; z-index: 2;
}
table.datos th:first-child { border-radius: 10px 0 0 0; }
table.datos th:last-child { border-radius: 0 10px 0 0; }
table.datos th.orden { cursor: pointer; user-select: none; }
table.datos th.orden:hover { filter: brightness(1.1); }
table.datos td { padding: 7px 8px; border-bottom: 1px solid var(--gris-borde); vertical-align: top; }
/* ══ LA ZEBRA EXISTIA Y NO SE VEIA (08/11/2026) ══════════════════════════

   Yo habia informado que las tablas largas «no tienen zebra». Era falso: la
   regla estaba desde siempre. Lo que pasaba es que #FAFCFF contra el blanco
   son cinco puntos de 255 —un 2 %—, y a 0,68 de escala en un notebook eso
   no lo ve nadie. Una zebra que no se distingue es exactamente lo mismo que
   no tenerla, sólo que además parece resuelta.

   El Detalle tiene 800 filas y doce columnas: seguir un renglón hasta el
   final es para lo que sirve. Se sube al 5 %, que es lo habitual, y se usa
   el gris del tablero en vez de inventar otro tono.

   No se toca el :hover, que va con --azul-tinte y tiene que seguir ganándole
   a la banda: es el que dice en qué renglón está el mouse. */
table.datos tbody tr:nth-child(even) td { background: var(--gris-fondo); }
table.datos tbody tr:hover td { background: var(--azul-tinte); }
table.datos td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.datos td.fecha { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Agrupado por disciplina (sólo con Ingeniería elegida en el filtro de área).
   La columna "Disc." lleva el código del documento -DI, EL, EC, CE, FC, ME- y
   una línea marca dónde termina un bloque y empieza el siguiente. Vale para las
   dos tablas: la del Detalle (table.datos) y la de la pestaña KPI (table.mtx).
   En la del KPI la línea sale cortada cada 3 px porque esa tabla separa sus
   celdas (border-spacing); es la misma pauta que ya tiene la matriz de avance. */
table.datos td.disc,
table.mtx td.hcel.disc {
  font-weight: bold; letter-spacing: .5px; color: var(--azul-hondo);
  white-space: nowrap; text-align: center;
}
table.datos tbody tr.corte-disc td,
table.mtx tbody tr.corte-disc > th,
table.mtx tbody tr.corte-disc > td { border-top: 2px solid var(--azul); }
table.datos .tarde { color: var(--rojo-hondo); font-weight: bold; }

/* ───── La columna "Archivos" del Detalle (21/10/2026) ─────
   Lo que cuelga de una tarea de Servicio Técnico o de Montaje: protocolos,
   informes, fotos, planos. Los archivos se apilan uno por renglón -son nombres
   largos y puestos en fila no se leen- y la columna no crece más de 260 px:
   el dato que se viene a leer en esta tabla sigue siendo la actividad de al
   lado. El nombre se recorta con puntos suspensivos y el globo del title lo
   dice entero, igual que las demás columnas anchas. */
table.datos th.sin-orden { cursor: default; }
table.datos td.arch { max-width: 260px; }
/* ── OJO: la caja es .arch-caja y la CELDA es .arch (22/10/2026) ───────────
   Las dos se llamaban "arch", así que una sola regla le pegaba a las dos y el
   <td> se quedaba con display:flex. Un <td> con display propio deja de ser
   table-cell: se descuelga de la fila, no estira hasta el alto del renglón y
   dibuja su borde de abajo donde termina SU contenido. En las filas altas
   -nombre de actividad en dos líneas- la raya quedaba 10 px más arriba que la
   de las celdas vecinas, y la columna Archivos se veía escalonada. Lo veía
   sobre todo quien no puede subir, porque su celda trae un solo guión y es la
   más baja de la fila. El tope de ancho va acá, en la caja: en la celda no lo
   respeta el reparto de columnas de la tabla. */
.arch-caja {
  display: flex; flex-direction: column; gap: 3px; align-items: flex-start;
  max-width: 260px;
}
.arch-item { display: flex; align-items: center; gap: 4px; max-width: 100%; cursor: help; }
.arch-item > a {
  color: var(--azul-hondo); text-decoration: none; font-weight: bold;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.arch-item > a:hover { text-decoration: underline; }
/* La cruz de sacar: discreta hasta que se la mira. Es una acción que borra, así
   que se pone en rojo al acercarse y pregunta antes de hacer nada. */
.arch-x {
  border: 0; background: transparent; color: var(--gris-medio);
  cursor: pointer; font-size: 11px; line-height: 1; padding: 2px; border-radius: 4px;
}
.arch-x:hover { background: #FDECEC; color: var(--rojo-hondo); }
.arch-mas {
  border: 1px dashed var(--gris-borde); background: transparent; color: var(--azul);
  cursor: pointer; font-size: 11px; padding: 2px 7px; border-radius: 999px; white-space: nowrap;
}
.arch-mas:hover { border-style: solid; background: var(--azul-tinte); }
.arch-vacio { color: var(--gris-na); }
.nombre-persona { color: var(--azul-nombre); font-weight: bold; }
.recorte { max-width: 330px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* En el Detalle el tope no es fijo: las columnas de texto largo se reparten el
   ancho que sobra para que la tabla entre en la pantalla y no aparezca la barra
   horizontal, que además de cortar el Origen contra el borde se come el alto
   del último renglón. El número lo calcula ajustarAnchoDetalle() en app.js;
   mientras no lo haya, manda el mismo 330 px de siempre. */
#tablaDetalle .recorte { max-width: var(--ancho-recorte, 330px); }
/* La celda recortada avisa que hay mas para leer: el cursor de ayuda y, al
   pasar el mouse, el globo de abajo con el texto entero (ver iniciarGlobos()
   en app.js). No se marca con subrayado ni color: son columnas enteras y
   subrayarlas todas emparejaria el ruido con el dato. */
.recorte { cursor: help; }
/* Salvo que la celda recortada viva adentro de algo que se pincha: ahi manda
   el cursor de mano, que dice lo que importa (esto lleva a otro lado). */
a .recorte, button .recorte, .proy-link .recorte, [role="button"] .recorte { cursor: inherit; }

/* ───────── El globo con la celda entera ─────────
   Fijo contra la ventana y pegado al <body>: una tabla con scroll propio lo
   recortaria igual que a la celda. El ancho maximo de 460 px es el que deja
   una observacion larga en tres o cuatro renglones; mas ancho obliga a barrer
   la pantalla con la vista para leer un renglon. pointer-events: none para que
   el globo no se interponga entre el mouse y la fila de abajo. */
.globo-celda {
  position: fixed; z-index: 9000; left: 0; top: 0;
  max-width: 460px; padding: 8px 11px;
  background: var(--texto); color: #fff;
  border-radius: 8px; box-shadow: 0 6px 22px rgba(13,22,40,.28);
  font-size: 12px; line-height: 1.45; text-align: left;
  white-space: pre-wrap; overflow-wrap: anywhere;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .12s ease;
}
.globo-celda.visible { opacity: 1; visibility: visible; }
@media print { .globo-celda { display: none; } }

/* Etiquetas de estado (píldoras) */
.etiqueta {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 10px; border-radius: 20px;
  color: #fff; font-size: 11.5px; font-weight: bold; white-space: nowrap; letter-spacing: .2px;
}
.et-pendiente { background: linear-gradient(135deg, #CFCFCF, #A9A9A9); }
.et-proceso   { background: linear-gradient(135deg, var(--naranja), var(--naranja-oscuro)); }
.et-revision  { background: linear-gradient(135deg, #9DC3E6, var(--azul-claro)); color: #14324F; }
.et-aprobado  { background: linear-gradient(135deg, #2E75B6, #1F4E79); }
.et-terminado { background: linear-gradient(135deg, var(--verde), var(--verde-hondo)); }
.et-retraso   { background: linear-gradient(135deg, var(--rojo), var(--rojo-hondo)); }
.et-detenido  { background: linear-gradient(135deg, var(--dorado), var(--dorado-hondo)); color: #4A3800; }
.et-otro      { background: linear-gradient(135deg, #E4E4E4, var(--gris-medio)); color: #3A3A3A; }
/* Variante suave, para metadatos dentro de fichas y tablas */
.etiqueta.suave {
  background: var(--azul-tinte); color: var(--azul-nombre);
  border: 1px solid var(--gris-borde); font-weight: bold; font-size: 11px; padding: 1px 8px;
}

/* Avisos */
.aviso {
  display: flex; gap: 10px; align-items: flex-start;
  border-radius: 8px; padding: 9px 12px; margin-bottom: 8px; font-size: 13.5px;
  border: 1px solid var(--gris-borde); background: #fff;
  box-shadow: var(--sombra-1);
}
.aviso .ic { flex: 0 0 auto; font-size: 15px; line-height: 1.3; }
.aviso b { font-weight: bold; }
.aviso ul { margin: 6px 0 0; padding-left: 18px; }
.aviso.info { background: var(--azul-tinte); border-color: var(--azul-claro); color: #1B3E63; }
.aviso.atencion { background: #FFF4E5; border-color: var(--naranja); color: var(--naranja-oscuro); }
.aviso.critico { background: #FDECEC; border-color: var(--rojo); color: var(--rojo-hondo); }

/* Alertas del resumen: no cuentan el detalle, llevan a la vista donde está.
   Cada una es un botón; el número manda y el texto dice adónde va. */
.alertas { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; align-items: stretch; }
.chip-alerta {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 14px 7px 12px; border-radius: 22px;
  font-size: 13px; font-weight: bold; cursor: pointer;
  border: 1px solid; background: #fff; font-family: inherit;
  box-shadow: var(--sombra-1);
  transition: transform var(--transicion), box-shadow var(--transicion), filter var(--transicion);
}
.chip-alerta:hover { transform: translateY(-2px); box-shadow: var(--sombra-2); filter: saturate(1.08); }
.chip-alerta:active { transform: translateY(0); }
.chip-alerta .n { font-size: 17px; font-variant-numeric: tabular-nums; line-height: 1; }
.chip-alerta .ir { font-weight: normal; font-size: 11px; opacity: .75; white-space: nowrap; }
.chip-alerta.critico  { border-color: var(--rojo);    color: var(--rojo-hondo);     background: #FDECEC; }
.chip-alerta.atencion { border-color: var(--naranja); color: var(--naranja-oscuro); background: #FFF4E5; }
.chip-alerta.info     { border-color: var(--azul-claro); color: var(--azul-nombre); background: var(--azul-tinte); }
.chip-alerta.quieto { cursor: default; }
.chip-alerta.quieto:hover { transform: none; box-shadow: var(--sombra-1); filter: none; }

.sin-datos {
  background: var(--gris-fondo); border: 1px dashed var(--gris-medio); border-radius: 8px;
  padding: 22px; text-align: center; color: var(--texto-suave); font-size: 14px;
}
.nota { font-size: 12px; color: var(--texto-suave); margin-top: 8px; line-height: 1.45; }
.leyenda { display: flex; gap: 12px; flex-wrap: wrap; font-size: 11.5px; color: var(--texto-suave); margin-top: 10px; align-items: center; }
.leyenda .it { display: inline-flex; align-items: center; gap: 5px; }
/* La de la matriz de avance va centrada: desde que se retiro el titulo de la
   tarjeta y la columna Cob., es lo unico que queda debajo de la tabla. */
#leyendaMtx { justify-content: center; }
/* Un solo renglón: si no entra, ese renglón se desliza, no se corta ni baja. */
.leyenda.una-linea {
  flex-wrap: nowrap; overflow-x: auto; margin-top: 0; gap: 9px;
  font-size: 11px; padding-bottom: 2px; scrollbar-width: none;
}
.leyenda.una-linea::-webkit-scrollbar { height: 0; }
.leyenda.una-linea .it { white-space: nowrap; }
.leyenda.una-linea b { color: var(--texto); }

/* Bienvenida */
.bienvenida { max-width: 780px; margin: 40px auto; text-align: center; }
.zona {
  background: #fff; border: 2px dashed var(--azul-claro); border-radius: 16px;
  padding: 32px 26px; box-shadow: var(--sombra-1);
  transition: border-color var(--transicion), background var(--transicion);
}
.zona.encima { border-color: var(--azul); background: var(--azul-tinte); }
.zona img { height: 66px; margin-bottom: 12px; }
.zona h2 { color: var(--azul-nombre); font-size: 19px; text-transform: uppercase; letter-spacing: .5px; margin-bottom: 10px; }
.zona p { color: var(--texto-suave); margin: 0 auto 18px; line-height: 1.55; max-width: 560px; }
.zona .acciones { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.pasos {
  text-align: left; font-size: 13.5px; color: var(--texto-suave);
  max-width: 580px; margin: 20px auto 0; line-height: 1.7;
  background: var(--gris-fondo); border: 1px solid var(--gris-borde);
  border-radius: 10px; padding: 14px 16px;
}
.pasos b { color: var(--azul-nombre); }
.pasos code { background: #fff; border: 1px solid var(--gris-borde); padding: 1px 5px; border-radius: 4px; font-size: 12.5px; }

/* Aviso flotante */
#aviso-flotante {
  position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 90px);
  z-index: 90; max-width: min(92vw, 580px);
  background: linear-gradient(135deg, var(--azul-nombre), var(--azul-hondo));
  color: #fff; padding: 11px 18px; border-radius: 22px; font-size: 13.5px; font-weight: bold;
  box-shadow: 0 10px 30px rgba(24,52,92,.34);
  opacity: 0; pointer-events: none;
  transition: transform var(--transicion), opacity var(--transicion);
}
#aviso-flotante.visible { transform: translate(-50%, 0); opacity: 1; }

/* Al recargar datos: se mantiene el render anterior atenuado, sin salto */
.recargando { opacity: .6; transition: opacity .15s; }

/* ══════════ Festejo: una tarea llegó al 100 % (16/10/2026) ══════════
   El cartel arriba y los papelitos encima de todo. Los dos con pointer-events
   en none: el festejo NO puede tapar un clic, aunque caiga justo cuando alguien
   iba a abrir una tarjeta. */

.festejo {
  position: fixed; left: 50%; top: 86px; transform: translate(-50%, 0);
  z-index: 96; max-width: min(92vw, 560px);
  display: flex; align-items: center; gap: 11px;
  background: linear-gradient(135deg, var(--verde), var(--verde-hondo));
  color: #fff; padding: 10px 18px; border-radius: 22px;
  box-shadow: 0 12px 34px rgba(34,72,24,.34);
  pointer-events: none;
  animation: festejoEntra .32s cubic-bezier(.2,.9,.3,1.2);
}
.festejo .fx { font-size: 22px; line-height: 1; flex: 0 0 auto; }
.festejo .ft { min-width: 0; font-size: 13.5px; font-weight: bold; line-height: 1.25; }
.festejo .ft b { font-weight: bold; }
.festejo .fm { font-weight: normal; opacity: .9; }
.festejo .ft small {
  display: block; font-weight: normal; font-size: 11.5px; opacity: .92; margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@keyframes festejoEntra {
  from { opacity: 0; transform: translate(-50%, -14px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* Los papelitos. `display:none` mientras no hay ráfaga, así el navegador no
   mantiene una capa de pantalla completa para nada. Cada <i> trae su color, su
   tamaño, su giro y su demora en el atributo style (los pone lanzarConfeti):
   acá sólo está la caída, que es una sola animación de transform y opacity y
   por eso la resuelve el compositor sin tocar el layout. */
.confeti {
  position: fixed; inset: 0; z-index: 97; overflow: hidden;
  pointer-events: none; display: none;
}
.confeti.cayendo { display: block; }
/* Sin `will-change`: con doscientos papelitos en pantalla, pedir una capa de
   compositor para cada uno es justo el caso que hay que evitar. `translate3d`
   del keyframe ya los sube a la GPU mientras dura la animación, que es lo que
   hace falta, y los suelta al terminar. */
.confeti i {
  position: absolute; top: -30px; width: 8px; height: 12px; opacity: 0;
  /* LINEAL, no una curva de suavizado. Con `cubic-bezier(.3,.6,.55,1)` -lo que
     había acá primero- el papelito recorría media pantalla en el primer tercio
     del tiempo y después quedaba estacionado abajo: en cualquier instante se
     veía una franja apretada arriba y el resto de la pantalla vacío. Lineal, la
     posición es el tiempo, así que los papelitos quedan repartidos parejo de
     arriba abajo, que es lo que se pidió. La sensación de peso la da que cada
     uno baja a su propia velocidad (ver lanzarConfeti), no la curva. */
  animation-name: confetiCae; animation-timing-function: linear;
  animation-fill-mode: forwards;
}
@keyframes confetiCae {
  0%   { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg); }
  90%  { opacity: 1; }
  100% { opacity: 0; transform: translate3d(var(--desvio, 0), 104vh, 0) rotate(var(--giro, 540deg)); }
}

/* Quien pidió menos movimiento se queda con el cartel quieto. El confeti ni se
   dibuja -lanzarConfeti() también lo corta-, pero el corte va igual acá por si
   alguna vez se lo llama desde otro lado. */
@media (prefers-reduced-motion: reduce) {
  .festejo { animation: none; }
  .confeti { display: none !important; }
}

@media (max-width: 820px) {
  /* En el teléfono la barra de arriba es más alta y el cartel le quedaba
     encima. */
  .festejo { top: 70px; max-width: calc(100% - 24px); }
}

/* ── Mayúsculas en los datos ───────────────────────────────────
   Todo lo que viene de las planillas se muestra en MAYÚSCULA, venga como venga
   escrito. Dos excepciones a propósito:
     · el NOMBRE DEL PROYECTO, porque la nomenclatura lleva el tonelaje en
       minúscula (25t-5t, 3,2t, 20t-20t) y en mayúscula se lee mal;
     · el NOMBRE DE ARCHIVO, que tiene que coincidir con el del disco.
   Se hace con text-transform, no tocando el dato: el CSV y el cruce de nombres
   siguen trabajando con el texto original. Los textos explicativos quedan en
   minúscula: son frases, no datos. */

/* Tablas: todas las celdas, menos las marcadas como tal-cual */
table.datos td { text-transform: uppercase; }
table.datos td.tal-cual { text-transform: none; }

/* Tarjetas con anillo: cliente, áreas y pie en mayúscula; producto tal cual,
   porque la nomenclatura lleva el tonelaje en minúscula (25t-5t, 3,2t). */
.pcard .ident .cl,
.pcard-areas .prow .an,
.pcard-pie { text-transform: uppercase; }
.pcard .ident .pr { text-transform: none; }

/* Lista "requieren atención" del Resumen: cliente/OT en mayúscula, producto tal cual. */
.la-row .id .cl { text-transform: uppercase; }
.la-row .id .pr { text-transform: none; }

/* Avance por proyecto y área: cliente, cobertura y nombres de área en mayúscula;
   el producto tal cual (tonelaje en minúscula). */
.av-row .id .cl, .av-row .id .cob, .av-chip .l .a { text-transform: uppercase; }
.av-row .id .pr { text-transform: none; }

/* La fila de la matriz lleva OT + nombre de proyecto: ya va tal cual, definido
   más arriba en table.matriz th.rw. */

/* Estados, etiquetas y leyendas */
.etiqueta,
.leyenda .it { text-transform: uppercase; }

/* Filtros: la lista de proyectos conserva su escritura, el resto en mayúscula */
#fBuscar,
#fArea, #fArea option,
#fResponsable, #fResponsable option,
#fEstado, #fEstado option { text-transform: uppercase; }
#fProyecto, #fProyecto option { text-transform: none; }

/* Fichas del planner, si algún día vuelve esa vista */
.ficha .act, .ficha .meta { text-transform: uppercase; }
.ficha .proy { text-transform: none; }

/* Barra de desplazamiento discreta */
::-webkit-scrollbar { height: 9px; width: 9px; }
::-webkit-scrollbar-track { background: var(--azul-tinte); border-radius: 9px; }
::-webkit-scrollbar-thumb { background: var(--azul-medio); border-radius: 9px; }
::-webkit-scrollbar-thumb:hover { background: var(--azul); }

@media (min-width: 700px) { .barra-titulo { font-size: 18px; } }
@media (max-width: 780px) {
  .menu { top: 0; position: static; }
  .barra { position: static; }
  .estado-carga { align-items: flex-start; }
  .proyectos { grid-template-columns: 1fr; }
}

/* ── El telefono (13/10/2026) ────────────────────────────────────────────
   Medido a 375 px: el bloque de estado del monitoreo ("Datos cargados solos ·
   4 archivos / Planillas guardadas: ... / Monitoreando cada 5 s ...") se
   apilaba en una columna de unos 70 px y se comia media pantalla ANTES de
   mostrar un solo dato; los botones de administrador se salian por la derecha
   y de las ocho pestanas se veian cuatro.

   Que se hace aca: la barra superior pasa a dos renglones (logo + titulo
   arriba, botones abajo), el estado del monitoreo se reduce a su primera
   linea -el semaforo y "N archivos", que es lo unico que se mira de un
   vistazo- y las pestanas se achican para que entren mas. Nada se esconde que
   no se pueda recuperar: las dos lineas de detalle del estado siguen en el
   title, y las pestanas siguen desplazandose de costado. */
@media (max-width: 780px) {
  .barra {
    flex-wrap: wrap; row-gap: 8px; padding: 8px 10px;
  }
  .barra-titulo { font-size: 14px; letter-spacing: .3px; flex: 1 1 auto; }
  .placa-logo { padding: 3px 7px; }
  .placa-logo img { height: 26px; }
  /* Los botones bajan a su propio renglon y pueden envolverse: antes el ultimo
     quedaba cortado contra el borde de la pantalla. */
  .barra-usuario {
    order: 3; flex: 1 0 100%; flex-wrap: wrap; gap: 6px;
    justify-content: flex-start;
  }
  /* Del estado del monitoreo queda la linea que resume: punto + archivos. */
  .estado-carga { flex: 0 0 auto; }
  .estado-carga .l2,
  .estado-carga .l3 { display: none; }
  .estado-carga .l1 { font-size: 12px; }
  /* Pestanas: mas chicas y mas juntas, para que entren mas de cuatro. */
  .menu button { padding: 9px 11px; font-size: 13px; }
  .menu button.volver { margin-left: 0; }
}

/* El botón "⋯" de la barra y el de filtros sólo existen en el teléfono. Va
   ANTES del bloque de abajo: si fuera después lo pisaría y no aparecerían. */
.solo-movil, .btn-filtros-movil { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   TELÉFONO  ·  reescrito el 13/10/2026
   ══════════════════════════════════════════════════════════════════════════
   El primer intento fue achicar el tablero de escritorio. No alcanzó: medido a
   375 px, entre la barra superior (200 px), las pestañas y la barra de filtros
   había unos 600 px de controles antes del primer dato, en una pantalla de 812.
   Se veía el tablero, pero no se veían los números.

   Esta versión recorta el cromo y cambia tres cosas de forma, que son las que
   de verdad hacen la diferencia en un teléfono:

     1. La BARRA SUPERIOR queda en una línea (unos 46 px). El estado del
        monitoreo se reduce a su semáforo y los botones de administrador se
        guardan detrás de un "⋯".
     2. Las PESTAÑAS bajan al pie, fijas, como en cualquier aplicación de
        teléfono: se llega con el pulgar y no gastan el alto de arriba, que es
        el que se mira.
     3. Los FILTROS se pliegan detrás de un botón que dice cuántos hay puestos.
        Lo normal es mirar sin filtrar; desplegarlos es la excepción.

   Lo demás es densidad: tipos un poco más chicos donde sobra, menos relleno,
   y las tablas anchas convertidas en fichas.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 780px) {

  /* ── 1 · La barra superior, en una línea ──────────────────────────────── */
  .barra {
    flex-wrap: wrap; row-gap: 6px; padding: 6px 10px; gap: 8px;
    align-items: center;
  }
  .placa-logo { padding: 2px 6px; }
  .placa-logo img { height: 22px; }
  .barra-titulo {
    font-size: 13px; letter-spacing: .2px; flex: 1 1 auto;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .barra-usuario { gap: 6px; flex: 0 0 auto; }
  /* Del estado del monitoreo sólo queda el semáforo: el detalle está en el
     title y, con el menú desplegado, en su renglón. */
  .estado-carga { flex: 0 0 auto; }
  .estado-carga .l1 { font-size: 0; gap: 0; }        /* deja el punto, saca el texto */
  .estado-carga .l2, .estado-carga .l3 { display: none; }
  /* Los botones que no son la campana ni el "⋯" se guardan. */
  .barra-usuario > .btn-barra:not(.campana):not(#btnBarraMas) { display: none; }
  .barra.desplegada .barra-usuario {
    flex: 1 0 100%; flex-wrap: wrap; justify-content: flex-start;
  }
  .barra.desplegada .barra-usuario > .btn-barra { display: inline-flex; }
  .barra.desplegada .estado-carga .l1 { font-size: 12px; gap: 7px; }
  .barra.desplegada .estado-carga .l2 { display: block; font-size: 11px; }
  .solo-movil { display: inline-flex; }

  /* ── 2 · Las pestañas, al pie y fijas ─────────────────────────────────── */
  .menu {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto;
    z-index: 60; box-shadow: 0 -2px 12px rgba(31, 60, 100, .22);
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  .menu button {
    padding: 11px 13px; font-size: 12px; letter-spacing: 0;
    min-height: 44px;                      /* alcance cómodo del pulgar */
  }
  .menu button::after { top: 0; bottom: auto; }   /* el subrayado va arriba */
  .menu button.volver { margin-left: 0; }
  /* El contenido no queda tapado por la barra del pie. */
  #app { padding-bottom: 64px; }

  /* ── 3 · Los filtros, plegados ────────────────────────────────────────── */
  .btn-filtros-movil {
    display: flex; align-items: center; gap: 8px; width: 100%;
    margin: 10px 0 0; padding: 11px 14px; min-height: 44px;
    background: #fff; border: 1px solid var(--gris-borde); border-radius: 10px;
    font-family: inherit; font-size: 13px; font-weight: bold;
    color: var(--azul-nombre); cursor: pointer; box-shadow: var(--sombra-1);
  }
  .btn-filtros-movil.con-filtros { border-color: var(--azul); }
  .btn-filtros-movil .ic { font-size: 14px; }
  .btn-filtros-movil .flecha { margin-left: auto; transition: transform var(--transicion); }
  .btn-filtros-movil.abierto .flecha { transform: rotate(180deg); }
  .btn-filtros-movil .cuenta-filtros {
    background: var(--azul); color: #fff; border-radius: 20px;
    padding: 1px 8px; font-size: 11px;
  }
  .barra-filtros { display: none; }
  .barra-filtros.abierta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
  .barra-filtros .filtro { flex: 1 1 calc(50% - 10px); min-width: 0; }
  .barra-filtros .filtro.ancho { flex: 1 1 100%; }
  .barra-filtros select, .barra-filtros input { width: 100%; min-height: 40px; }
  .barra-filtros .chk {
    flex: 1 1 100%; display: flex; align-items: center; gap: 10px;
    min-height: 40px; margin: 0;
  }
  .barra-filtros .chk input { flex: 0 0 auto; width: 20px; height: 20px; }
  .barra-filtros .btn-limpiar { flex: 1 1 calc(50% - 10px); justify-content: center; min-height: 40px; }

  /* ── 4 · Densidad del contenido ───────────────────────────────────────── */
  .tarjeta-graf { padding: 12px 10px; }
  /* Los tres selectores no son de más: en el teléfono TODOS los títulos crecen,
     y para eso cada uno tiene que pesar lo mismo que la regla que le pone el
     tamaño allá arriba. Con «.cabecera-graf h2» solo, el del Detalle se
     quedaba en 13 px al lado de los demás en 17. */
  .tarjeta-graf h2, .cabecera-graf h2,
  .tarjeta-graf > .cabecera-graf h2, .muro-caja > .cabecera-graf h2 { font-size: 17px; }
  .cabecera-graf { flex-wrap: wrap; gap: 8px; }
  /* Las bajadas largas, recortadas a tres renglones y desplegables de un toque. */
  .cap.cap-plegada {
    max-height: 4.4em; overflow: hidden; position: relative; cursor: pointer;
    padding-bottom: 1.2em;
  }
  .cap.cap-plegada::after {
    content: '… ver más';
    position: absolute; right: 0; bottom: 0; left: 0;
    text-align: right; font-weight: bold; color: var(--azul-nombre);
    background: linear-gradient(90deg, rgba(255,255,255,0) 0, #fff 38%);
    padding-left: 30px;
  }
  /* Tarjetas de indicador: dos por renglón, pero sin el relleno del monitor. */
  .grilla-kpi { gap: 8px; }
  .kpi { padding: 8px 8px 9px; min-height: 0 !important; }
  .kpi .valor { font-size: 21px; }
  .kpi .nombre { font-size: 11px; }
  .kpi .nota { font-size: 11px; line-height: 1.25; }
  /* Los avisos de abajo del Resumen, a ancho completo y tocables. */
  .chip-alerta { width: 100%; justify-content: flex-start; min-height: 42px; }

  /* ── 5 · El Detalle: de tabla a fichas ────────────────────────────────── */
  /* En el teléfono no hay "alto de pantalla" que llenar: las fichas se leen
     bajando la página entera, así que acá se deshace el estirado de arriba.
     El :not([hidden]) va por lo mismo que arriba: con #id suelto, el Detalle
     se vería en todas las pestañas. */
  main.contenido.alto-pleno { display: block; }
  #v-detalle:not([hidden]) { display: block; flex: 0 1 auto; }
  #v-detalle > .tarjeta-graf { display: block; margin-bottom: 10px; }
  #v-detalle .tabla-scroll { max-height: none; flex: none; overflow: visible; }
  #tablaDetalle,
  #tablaDetalle tbody,
  #tablaDetalle tr,
  #tablaDetalle td { display: block; width: auto; }
  #tablaDetalle thead { display: none; }   /* los títulos van en cada celda */
  #tablaDetalle tbody tr {
    border: 1px solid var(--gris-borde); border-radius: 10px;
    margin-bottom: 10px; padding: 8px 10px; background: #fff;
    box-shadow: var(--sombra-1);
  }
  #tablaDetalle tbody tr:nth-child(even) td { background: none; }
  #tablaDetalle tbody tr.corte-disc { border-top: 3px solid var(--azul); }
  #tablaDetalle td {
    border: 0; padding: 3px 0; text-align: left !important;
    display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 8px;
    align-items: baseline;
  }
  #tablaDetalle td::before {
    content: attr(data-col);
    font-size: 11px; font-weight: bold; color: var(--texto-suave);
    text-transform: uppercase; letter-spacing: .3px;
  }
  /* Una celda vacía no merece un renglón, ni cuando lo vacío es el div interno
     (Observaciones y Origen suelen venir así). */
  #tablaDetalle td:empty { display: none; }
  #tablaDetalle td:has(> div.recorte:empty) { display: none; }
  /* El área ya está en el filtro; la fila de disciplina y el origen, al final. */
  #tablaDetalle td:nth-child(1) { display: none; }
  #tablaDetalle td .recorte { max-width: none; white-space: normal; overflow: visible; }
  #tablaDetalle td .barra-avance.en-tabla { grid-column: 2; margin-top: 3px; width: 100%; }

  /* ── 6 · La Cronología ────────────────────────────────────────────────── */
  .gantt-scroll { max-height: calc(100vh - 230px); }
  .gantt-cab, .gantt-fila { grid-template-columns: 164px 1fr; gap: 6px; }
  .gantt-fila .nm { font-size: 11px; }
  .gantt-fila.sub .nm { padding-left: 8px; font-size: 11px; }
  .gantt-areas .gantt-fila.sub .nm { padding-left: 8px; }
  /* El nombre del proyecto, en DOS renglones: recortado a uno no identifica
     nada -"FIEFRE …" puede ser cualquiera de cuatro- y en el teléfono no hay
     tooltip que leer. El `#gantt` del selector está para ganarle al nowrap que
     la fila trae de la versión de escritorio. */
  #gantt .gantt-fila.proyecto .nm .nmtxt {
    white-space: normal; line-height: 1.2;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; flex: 1 1 auto; min-width: 0;
  }
  #gantt .gantt-desvio-lbl, #gantt .gantt-ok-lbl { flex: 0 0 auto; margin-left: 4px; }
  #gantt { min-width: 760px; }           /* siempre se desplaza de costado */
  .gantt-controles { flex-wrap: wrap; gap: 6px; width: 100%; }
  .gantt-controles .boton { font-size: 11px; padding: 6px 10px; min-height: 38px; }
  #ganttZoom button { padding: 6px 10px; }

  /* ── 7 · Tarjetas de proyecto: una por renglón, entera ────────────────── */
  .proyectos, .proyectos.fijo {
    grid-template-columns: 1fr !important;
    --pcard-cols: 1 !important; --pcard-alto: none !important;
  }
  .pcard { max-height: none; }

  /* ── 8 · La matriz de avance ──────────────────────────────────────────
     Con las columnas repartidas en 375 px, el navegador partía los títulos
     letra por letra y "ADMINISTRACIÓN" salía en vertical. Acá cada columna
     toma el ancho de su título, el nombre del proyecto se recorta, y la tabla
     se desplaza de costado dentro de su caja. */
  #matrizAvance thead th { overflow-wrap: normal; white-space: nowrap; }
  #matrizAvance thead th.rw { width: auto; }
  #matrizAvance tbody th.rw { max-width: 172px; }
  #matrizAvance tbody th.rw .proy-link { max-width: 164px; }
  .mtx-scroll, .tabla-scroll { -webkit-overflow-scrolling: touch; }

  /* ── 8-bis · El aviso flotante, por encima de la barra del pie ────────
     Aparece abajo y al centro; con las pestañas fijas al pie quedaba tapado
     justo cuando dice algo que hay que leer. */
  #aviso-flotante { bottom: 74px; max-width: calc(100% - 24px); }

  /* ── 9 · Diálogos a ancho completo: en 375 px un modal centrado con margen
           deja los botones fuera del alcance del pulgar ─────────────────── */
  .modal-caja { max-width: 100%; width: 100%; max-height: 92vh; border-radius: 12px; }
  .modal-caja .boton, .modal-caja .btn-limpiar { min-height: 42px; }
}


/* Respeta a quien pide menos movimiento en el sistema operativo */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ═══════════════════════════════════════════════════════════════
   SESIÓN, PERMISOS Y MURO DEL PROYECTO
   Quién soy y el candado de administrador viven en la barra de
   arriba; el muro es una pestaña más, con el mismo lenguaje visual
   que el resto (tarjetas blancas, ramp azul, sombras tenues).
   ═══════════════════════════════════════════════════════════════ */

/* ── Barra de arriba: quién soy, campana y candado ── */
.btn-barra.quien.puesto {
  background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .55); font-weight: bold;
}
.btn-barra.candado.abierto {
  background: var(--verde); border-color: var(--verde-hondo); color: #fff; font-weight: bold;
}
.btn-barra.campana { position: relative; }
.btn-barra.campana .globo,
/* El contador de la pestana (Proyectos historicos, Publicaciones).
   Hasta el 07/10/2026 iba en position:absolute con top:-5px, asi que asomaba
   por encima del borde de la barra azul y se leia como un globo suelto, sin
   relacion con el texto. Ahora va EN LINEA con el texto de la pestana y
   centrado con el: vertical-align:middle lo alinea con el medio de la linea,
   que es lo que se ve bien tanto en "Proyectos historicos" como en
   "Publicaciones".
   El aro blanco se mantiene: es lo que lo despega del azul. */
.globo-menu {
  display: inline-block; vertical-align: middle; margin-left: 2px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 9px; background: var(--rojo-hondo); color: #fff;
  font-size: 11px; font-weight: bold; line-height: 17px; text-align: center;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .85);
}
/* La campana late apenas al aparecer: se nota sin molestar. */
.btn-barra.campana:not(.oculto) { animation: campanea 1.6s ease-in-out 2; }
@keyframes campanea {
  0%, 100% { transform: none; }
  20% { transform: rotate(-12deg); }
  40% { transform: rotate(10deg); }
  60% { transform: rotate(-6deg); }
}
nav.menu button[data-vista="muro"] { position: relative; }

/* ── Centro de notificaciones ─────────────────────────────────── */
.panel-notif {
  position: absolute; top: calc(100% - 4px); right: 12px; z-index: 60;
  width: 360px; max-width: calc(100vw - 24px); max-height: calc(var(--alto-ventana) * .74);
  background: #fff; color: var(--texto);
  border: 1px solid var(--gris-borde); border-radius: var(--radio);
  box-shadow: var(--sombra-2); overflow: hidden;
  display: flex; flex-direction: column;
}
.pn-cab {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--gris-borde);
}
.pn-tit { font-weight: bold; font-size: 14px; margin-right: auto; }
.pn-link {
  background: none; border: 0; color: var(--azul-nombre); cursor: pointer;
  font-size: 12.5px; padding: 3px 5px; border-radius: 6px;
}
.pn-link:hover { background: var(--azul-tinte); }
#btnNotifPrefs { font-size: 15px; line-height: 1; color: var(--texto-suave); }
.pn-prefs {
  padding: 10px 12px; border-bottom: 1px solid var(--gris-borde);
  background: var(--gris-fondo); display: flex; flex-direction: column; gap: 6px;
}
.pn-prefs-tit { font-size: 11.5px; color: var(--texto-suave); text-transform: uppercase; letter-spacing: .3px; }
.pn-chk { display: flex; align-items: center; gap: 7px; font-size: 13px; cursor: pointer; }
.pn-lista { overflow-y: auto; }
.pn-vacio { padding: 26px 14px; text-align: center; color: var(--texto-suave); font-size: 13px; }

.notif-item {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; border-bottom: 1px solid var(--gris-borde);
  cursor: pointer; background: #fff; transition: background var(--transicion);
}
.notif-item:hover { background: var(--azul-tinte); }
.notif-item.no-leido { background: #F3F8FF; }
.notif-item.no-leido:hover { background: var(--azul-tinte-2); }
.ni-punto { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; background: transparent; }
.notif-item.no-leido .ni-punto { background: var(--azul-nombre); }
.ni-ic {
  flex: 0 0 26px; width: 26px; height: 26px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center; font-size: 14px;
}
.ni-cuerpo { min-width: 0; flex: 1; }
.ni-tit { font-size: 13px; line-height: 1.3; color: var(--texto); }
.ni-sub { font-size: 11.5px; color: var(--texto-suave); margin-top: 2px; display: flex; gap: 6px; flex-wrap: wrap; }
.ni-tipo { font-weight: bold; }
/* Colores por tipo (mismo criterio que el semáforo) */
.ni-ic.t-mencion { background: var(--azul-tinte-2); }
.ni-ic.t-aviso   { background: #FFF4D6; }
.ni-ic.t-vence   { background: #FFE9D6; }
.ni-ic.t-atraso  { background: #FFE9D6; }
.ni-ic.t-vencido { background: #FADBDB; }
.ni-ic.t-critico { background: #FADBDB; }
.notif-item.t-vencido .ni-tipo, .notif-item.t-critico .ni-tipo { color: var(--rojo-hondo); }
.notif-item.t-vence .ni-tipo, .notif-item.t-atraso .ni-tipo { color: var(--naranja-oscuro); }

.nota-visitante {
  font-size: 12.5px; color: var(--texto-suave); margin-top: 12px; line-height: 1.5;
  background: var(--azul-tinte); border: 1px solid var(--azul-tinte-2);
  border-radius: 8px; padding: 10px 12px;
}

/* Proyecto sin tablas de cubicaciones, visto por quien no es administrador. */
.pcard-sp .sin-enlace {
  font-size: 11px; color: var(--gris-medio); text-transform: uppercase; letter-spacing: .3px;
}

/* ── Avatar con iniciales ── */
.avatar {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, var(--azul-medio), var(--azul-hondo));
  color: #fff; font-size: 12.5px; font-weight: bold; letter-spacing: .3px;
}
.avatar.chico { width: 24px; height: 24px; font-size: 11px; }

/* ── Caja del muro ── */
.muro-caja { display: flex; flex-direction: column; }
.muro-acciones { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; }
#v-muro.encima .muro-caja { outline: 2px dashed var(--azul); outline-offset: 4px; }

/* ── Fechas y enlaces (02/11/2026) ─────────────────────────────────────────
   Una fila por proyecto, y en cada celda el campo arriba y, abajo, de dónde
   sale hoy ese dato. La nota va en gris y chica: es una explicación, no un
   dato, y tiene que leerse sólo cuando se la busca. */
.fechas-tabla td { vertical-align: top; }
.fechas-tabla .fx-proy b { display: block; }
.fechas-tabla .fx-arch {
  display: inline-block; margin-top: 3px; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .3px; color: var(--texto-suave);
  border: 1px solid var(--gris-borde); border-radius: 4px; padding: 0 5px;
}
.fechas-tabla .fx-fecha input[type="date"] { width: 142px; }
.fechas-tabla .fx-enlace { min-width: 220px; }
.fechas-tabla .fx-enlace input[type="url"] { width: 100%; }
.fechas-tabla input[type="date"], .fechas-tabla input[type="url"] {
  font-family: inherit; font-size: 12.5px; color: var(--texto);
  border: 1px solid var(--gris-borde); border-radius: 6px; padding: 5px 7px; background: #fff;
}
.fechas-tabla input:focus {
  outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px var(--azul-tinte);
}
.fechas-tabla .fx-de {
  display: block; margin-top: 4px; font-size: 10.5px; line-height: 1.35; color: var(--texto-suave);
}
.fechas-tabla .fx-de.manda b { color: var(--texto); }
.fechas-tabla .fx-pct { display: flex; align-items: center; gap: 7px; margin-top: 5px; }
.fechas-tabla .fx-chapa {
  font-size: 11px; font-weight: bold; border-radius: 4px; padding: 1px 6px;
  border: 1px solid var(--gris-borde); color: var(--texto-suave); background: #fff;
}
.fechas-tabla .fx-chapa.media { border-color: var(--dorado); background: #FFF8E1; color: var(--dorado-hondo); }
.fechas-tabla .fx-chapa.lista { border-color: var(--verde); background: #F1F8F1; color: var(--verde-hondo); }

/* ── El hilo: respuestas, citas y visto bueno (02/11/2026) ──────────────────
   La sangría la lleva cada mensaje en --sangria (0 a 3): la pone renderMuro()
   según de cuántos mensajes cuelga. Se corta en 3 porque más adentro una
   respuesta larga queda en una columna de dos palabras de ancho. */
.post.respuesta { margin-left: calc(var(--sangria, 1) * 26px); }
.post.respuesta::before {
  content: ''; position: absolute; left: -14px; top: 16px; width: 10px; height: 10px;
  border-left: 2px solid var(--gris-borde); border-bottom: 2px solid var(--gris-borde);
  border-bottom-left-radius: 5px;
}
.post { position: relative; }

/* La cita de arriba de una respuesta, y la del campo de escribir: la misma
   forma en los dos lados, porque son la misma cosa dicha en dos momentos. */
.post-cita, .redactar-cita {
  display: flex; align-items: baseline; gap: 7px; width: 100%; text-align: left;
  background: var(--azul-tinte); border: 0; border-left: 3px solid var(--azul);
  border-radius: 5px; padding: 5px 9px; margin-bottom: 8px;
  font-family: inherit; font-size: 12px; color: var(--texto-suave);
}
.post-cita { cursor: pointer; }
.post-cita:hover { background: var(--azul-tinte-2); }
.post-cita.ida { background: var(--gris-fondo); border-left-color: var(--gris-borde); font-style: italic; }
.post-cita .qa, .redactar-cita .qa { font-weight: bold; color: var(--azul-nombre); white-space: nowrap; }
.post-cita .qt, .redactar-cita .qt {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1;
}
.redactar-cita { margin-left: 12px; margin-right: 12px; width: auto; }
.redactar-cita .qr { white-space: nowrap; }
.redactar-cita .qx {
  flex: 0 0 auto; background: none; border: 0; cursor: pointer;
  color: var(--texto-suave); font-size: 12px; line-height: 1; padding: 2px 4px;
}
.redactar-cita .qx:hover { color: var(--rojo-hondo); }

/* El visto bueno de los nombrados. Verde cuando ya lo dieron todos: es la
   única pregunta que tiene esta barra. */
.post-vb {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin-top: 9px; padding-top: 8px; border-top: 1px dashed var(--gris-borde);
  font-size: 12px; color: var(--texto-suave);
}
.post-vb .esp { flex: 1; }
.post-vb .vb-cuenta b { color: var(--texto); }
.post-vb.completo .vb-cuenta b { color: var(--verde-hondo); }
.post-vb .vb-quienes {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 46%;
}
.vb-btn {
  flex: 0 0 auto; background: #fff; border: 1px solid var(--azul); border-radius: 6px;
  color: var(--azul-nombre); font-family: inherit; font-size: 12px; font-weight: bold;
  padding: 5px 11px; cursor: pointer;
}
.vb-btn:hover { background: var(--azul-tinte); }
.vb-btn.dado {
  border-color: var(--verde); background: #F1F8F1; color: var(--verde-hondo); font-weight: normal;
}
/* Ya dado: deja de ser un botón, porque no hay nada que apretar. */
.vb-dado {
  flex: 0 0 auto; border: 1px solid var(--verde); border-radius: 6px; background: #F1F8F1;
  color: var(--verde-hondo); font-size: 12px; padding: 5px 11px;
}
/* Quién lo abrió: al lado del visto bueno y más apagado, que es lo que es. */
.post-vb .vb-abrio { color: var(--texto-suave); }
.post-vb .vb-abrio b { color: var(--texto); font-weight: bold; }
.post-vb .vb-abrio.viejo b { color: var(--texto-suave); }
/* Con el candado puesto, cada nombre sale con su ✕ para sacar el visto bueno
   que se dio por error. */
.post-vb .vb-chip {
  display: inline-flex; align-items: center; gap: 3px; margin-right: 5px;
  border: 1px solid var(--gris-borde); border-radius: 10px; padding: 1px 4px 1px 7px;
  background: #fff;
}
.vb-saca {
  border: 0; background: none; cursor: pointer; color: var(--texto-suave);
  font-family: inherit; font-size: 11px; line-height: 1; padding: 2px 3px; border-radius: 6px;
}
.vb-saca:hover { background: #FDECEC; color: var(--rojo-hondo); }

/* ── Redactar ── */
.redactar {
  border: 1px solid var(--gris-borde); border-radius: 10px; background: var(--gris-fondo);
  padding: 10px 12px; margin-bottom: 14px;
}
/* ── El cursor, en la misma columna que el texto (02/11/2026) ──────────────
   El que escribía veía su nombre en una columna y el cursor doce píxeles más
   a la derecha, en otra. No era una impresión: la caja de texto es un elemento
   con borde (1 px) y relleno propio (11 px), así que su PRIMERA LETRA cae 12 px
   adentro del borde de la caja, mientras el nombre de arriba y los botones de
   abajo arrancan pegados al borde de la tarjeta.

   Se corrige moviendo lo de arriba y lo de abajo, no la caja: así nada cambia
   de tamaño ni de forma, y el nombre, el cursor y los botones quedan los tres
   sobre la misma línea vertical. Los 12 px son el borde + el relleno de la
   caja de texto; si alguno de los dos cambia, este número cambia con él. */
.redactar-quien, .redactar-pie { padding-left: 12px; }

.redactar-quien { display: flex; align-items: center; gap: 9px; font-size: 13.5px; margin-bottom: 8px; }
.redactar-quien b { color: var(--azul-nombre); }
.redactar-quien .en { font-size: 11.5px; color: var(--texto-suave); }
.redactar-quien .en.aviso { color: var(--naranja-oscuro); font-weight: bold; }

.redactar-campo { position: relative; }
/* La caja crece sola con el texto, como el Teams (06/11/2026). El alto se lo
   pone ajustarAltoRedactar() en lib/app.js a cada tecla; acá van los dos
   límites:

     min-height   los dos renglones de siempre, aunque esté vacía;
     max-height   hasta dónde puede crecer. Pasado eso deja de crecer y vuelve
                  a aparecer su barra (overflow-y), que es lo que hace el
                  Teams: la caja para escribir no se puede comer la
                  conversación. Es un tercio de la ventana, sin el zoom del
                  tablero (ver --alto-ventana arriba).

   Y `resize: none` porque ya no hay nada que arrastrar: el tirador de la
   esquina estiraba la caja y a la siguiente tecla el alto volvía a ser el del
   texto. Un control que se deshace solo confunde más de lo que sirve. */
.redactar textarea {
  width: 100%; font-family: inherit; font-size: 13.5px; line-height: 1.45; color: var(--texto);
  border: 1px solid var(--gris-borde); border-radius: 8px; padding: 9px 11px; background: #fff;
  resize: none; min-height: 62px;
  max-height: calc(var(--alto-ventana) * .33); overflow-y: auto;
}
.redactar textarea:focus { outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px var(--azul-tinte); }

/* ══════ «FULANO ESTÁ ESCRIBIENDO…» (07/11/2026) ═════════════════════════
   Ocupa su lugar SIEMPRE, aunque esté vacía: si apareciera y desapareciera,
   la conversación daría un salto de un renglón cada vez que alguien toca una
   tecla, y eso molesta más de lo que el cartel ayuda. */
.tecleando {
  flex: 0 0 auto; height: 17px; line-height: 17px; padding: 0 2px;
  font-size: 12px; font-style: italic; color: var(--texto-suave);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ══════ LLEVAR UN MENSAJE A OTRA OBRA (07/11/2026) ══════════════════════
   El diálogo es una lista de obras con su buscador: con veinte conversaciones,
   un <select> obliga a desplegar y leer de a una. */
.llevar-previa {
  background: var(--azul-tinte); border-left: 3px solid var(--azul-medio);
  border-radius: 0 7px 7px 0; padding: 7px 10px; margin: 8px 0 12px;
  font-size: 12.5px; color: var(--texto); line-height: 1.45;
  max-height: 76px; overflow: hidden;
}
.llevar-lista {
  max-height: calc(var(--alto-ventana) * .34); overflow-y: auto;
  border: 1px solid var(--gris-borde); border-radius: 9px; margin-top: 5px; padding: 4px;
}
.llevar-lista .llevar-obra {
  display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
  background: none; border: 0; border-radius: 7px; padding: 6px 9px;
  font-family: inherit; font-size: 13px; color: var(--texto); cursor: pointer;
}
.llevar-lista .llevar-obra:hover { background: var(--azul-tinte); }
.llevar-lista .llevar-obra .ot {
  font-size: 11px; font-weight: bold; color: var(--azul-nombre); white-space: nowrap;
}
.llevar-lista .llevar-obra .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.llevar-vacio { padding: 10px; font-size: 12.5px; color: var(--texto-suave); }

/* ══════ BUSCAR EN TODAS LAS OBRAS (07/11/2026) ═══════════════════════════
   El interruptor vive DENTRO del campo de búsqueda, pegado a la lupa: es un
   modo de ese buscador, no otro buscador. */
.muro-buscar .buscar-todas {
  flex: 0 0 auto; background: none; border: 1px solid var(--gris-borde);
  border-radius: 999px; padding: 2px 9px; cursor: pointer;
  font-family: inherit; font-size: 11.5px; color: var(--texto-suave); line-height: 1.4;
}
.muro-buscar .buscar-todas:hover { border-color: var(--azul); color: var(--azul-nombre); }
.muro-buscar .buscar-todas.puesto {
  background: var(--azul); border-color: var(--azul); color: #fff; font-weight: bold;
}
/* El rótulo de la obra, en los resultados, lleva a esa conversación. */
.guardado-de.ir {
  display: block; width: 100%; text-align: left; background: none;
  border: 0; padding: 0; cursor: pointer; font: inherit;
  font-size: 11px; font-weight: bold; letter-spacing: .3px; text-transform: uppercase;
  color: var(--azul-nombre);
}
.guardado-de.ir:hover { text-decoration: underline; }
/* Cuando hay más de los que se muestran. */
.buscar-tope {
  background: var(--azul-tinte); border-radius: 8px; padding: 7px 10px;
  font-size: 12px; color: var(--texto); margin-bottom: 8px;
}

/* ══════ LAS DOS VISTAS DE LA CABECERA (07/11/2026) ══════════════════════
   Guardados (de todas las obras) y Archivos (de ésta). Son botones que se
   quedan apretados, no pestañas: se vuelve tocándolos otra vez. */
.muro-vistas { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 7px; }
.muro-vistas .boton.puesto {
  background: var(--azul); border-color: var(--azul); color: #fff;
}
.muro-vistas .n { font-variant-numeric: tabular-nums; opacity: .75; margin-left: 2px; }
/* De qué obra es cada mensaje guardado: estando en otra conversación es lo
   único que no se puede deducir mirando. */
.guardado-de {
  font-size: 11px; font-weight: bold; letter-spacing: .3px; text-transform: uppercase;
  color: var(--azul-nombre); margin: 10px 0 -4px 2px;
}
.post-btn.puesto { color: var(--azul-nombre); }

/* Los archivos de la conversación, todos juntos. */
.muro-archivos {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px;
  padding: 2px;
}
.muro-archivos .arch {
  display: flex; flex-direction: column; gap: 3px; min-width: 0; text-align: left;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 9px;
  padding: 7px; font-family: inherit; color: var(--texto);
  text-decoration: none; cursor: pointer;
}
.muro-archivos .arch:hover { border-color: var(--azul); box-shadow: var(--sombra-1); }
.muro-archivos .tapa {
  display: flex; align-items: center; justify-content: center;
  height: 86px; border-radius: 6px; background: var(--azul-tinte); overflow: hidden;
}
.muro-archivos .tapa img { width: 100%; height: 100%; object-fit: cover; }
.muro-archivos .tapa .ic { font-size: 30px; }
.muro-archivos .nm {
  font-size: 12px; font-weight: bold; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.muro-archivos .de { font-size: 11px; color: var(--texto-suave); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ══════ REACCIONES (07/11/2026) ══════════════════════════════════════════
   Van debajo del mensaje y arriba del visto bueno, que es otra cosa: la
   reacción no compromete a nada y el visto bueno queda anotado con nombre. */
.post-reacciones { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-top: 7px; }
.post-reacciones .reaccion {
  display: inline-flex; align-items: center; gap: 4px;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 999px;
  padding: 1px 8px; min-height: 22px;
  font-family: inherit; font-size: 12px; line-height: 1; color: var(--texto);
  cursor: pointer;
}
.post-reacciones .reaccion:hover { border-color: var(--azul); background: var(--azul-tinte); }
.post-reacciones .reaccion[disabled] { cursor: default; opacity: .8; }
.post-reacciones .reaccion[disabled]:hover { border-color: var(--gris-borde); background: #fff; }
/* La propia, marcada: hay que poder ver de un vistazo si uno ya reaccionó. */
.post-reacciones .reaccion.mia { border-color: var(--azul); background: var(--azul-tinte); font-weight: bold; }
.post-reacciones .reaccion .n { font-variant-numeric: tabular-nums; color: var(--texto-suave); }
.post-reacciones .reaccion.mia .n { color: var(--azul-nombre); }
.post-reacciones .agregar { padding: 1px 7px; color: var(--texto-suave); }
.post-reacciones .agregar .mas { font-size: 10px; }
/* El elegir va en la misma fila, no flotando: la conversación scrollea por
   dentro y un panel posicionado a mano se despega al desplazar. */
.post-reacciones .elegir { display: inline-flex; gap: 2px; margin-left: 2px; }
.post-reacciones .elegir button {
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 7px;
  padding: 1px 5px; font-size: 14px; line-height: 1.2; cursor: pointer;
}
.post-reacciones .elegir button:hover { border-color: var(--azul); background: var(--azul-tinte); }

/* ══════ BARRITA DE FORMATO Y TEXTO CON FORMATO (07/11/2026) ══════════════
   Los botones escriben en la caja las mismas marcas que uno puede teclear,
   así que la barrita es una ayuda y no una segunda forma de hacer lo mismo. */
.redactar-formato {
  display: flex; align-items: center; gap: 2px; flex-wrap: wrap; margin-bottom: 5px;
}
.redactar-formato button {
  min-width: 26px; height: 24px; padding: 0 6px;
  background: none; border: 1px solid transparent; border-radius: 6px;
  font-family: inherit; font-size: 12px; color: var(--texto-suave);
  cursor: pointer; line-height: 1;
}
.redactar-formato button:hover { background: var(--azul-tinte); color: var(--azul-nombre); }
.redactar-formato button:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
.redactar-formato .sep {
  width: 1px; height: 15px; background: var(--gris-borde); margin: 0 4px;
}

/* Cómo se ve el formato ya publicado. Sobrio a propósito: un mensaje de obra
   con media docena de estilos distintos se lee peor, no mejor. */
.post-texto b { font-weight: 700; }
.post-texto i { font-style: italic; }
.post-texto s { opacity: .7; }
.post-texto code {
  font-family: Consolas, 'Courier New', monospace; font-size: .92em;
  background: var(--azul-tinte); border-radius: 4px; padding: 1px 5px;
  overflow-wrap: anywhere;
}
/* Las viñetas van pegadas al texto del mensaje, sin el margen enorme que les
   pone el navegador por defecto. */
.post-texto .post-lista { margin: 4px 0 4px 2px; padding-left: 18px; }
.post-texto .post-lista li { margin: 1px 0; }


/* ══════ AUTOCOMPLETAR DE MENCIONES: SE ABRE HACIA ARRIBA (07/11/2026) ════

   Se abría hacia ABAJO (top: 100%), y la caja para escribir vive pegada al
   borde de abajo de la pantalla. O sea que la lista de nombres se dibujaba
   fuera de la ventana.

   Medido el 07/11/2026 en un notebook de 1366×768: la lista mide 148 px, se
   salía 71 px por abajo y de siete nombres se veían tres. Encima tapaba los
   botones «Adjuntar» y «Publicar».

   Y NO ERA SÓLO QUE NO SE VIERA. Con la lista abierta, el Enter deja de
   hacer un renglón nuevo y elige el nombre marcado (ver el keydown de
   #muroTexto en lib/app.js, que es lo que hace cualquier chat). Como la
   lista estaba fuera de la pantalla, nadie sabía que estaba abierta ni cuál
   era el nombre marcado: se escribía una arroba, se seguía escribiendo, se
   apretaba Enter para bajar de renglón y aparecía de la nada un @nombre que
   uno no eligió, con el cursor saltado a otro lado.

   Eso es lo que el equipo reportaba como «el cursor desaparece de donde
   estoy escribiendo». Comprobado tecla por tecla: con «Hola @ca» y el
   cursor en 8, un Enter dejaba «Hola @calidad2 » y el cursor en 15.

   SE ABRE HACIA ARRIBA Y LISTO. No hace falta decidir el lado según el
   lugar que quede: en esta pantalla la caja para escribir está SIEMPRE
   abajo de todo y arriba está la conversación, que es espacio de sobra. El
   tope de alto se mide sin el zoom del tablero (--alto-ventana), como el
   resto de las pantallas de alto completo. */
.sugerencias {
  position: absolute; left: 6px; right: 6px; bottom: 100%; z-index: 20; margin-bottom: 3px;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 10px;
  box-shadow: var(--sombra-2); overflow: hidden;
  max-height: min(232px, calc(var(--alto-ventana) * .34)); overflow-y: auto;
}
.sugerencias .sug {
  display: flex; align-items: center; gap: 9px; width: 100%; padding: 6px 10px;
  background: none; border: 0; border-bottom: 1px solid var(--gris-borde);
  font-family: inherit; font-size: 13px; text-align: left; cursor: pointer; color: var(--texto);
}
.sugerencias .sug:last-child { border-bottom: 0; }
.sugerencias .sug.activa, .sugerencias .sug:hover { background: var(--azul-tinte); }
.sugerencias .sug .nm { font-weight: bold; color: var(--azul-nombre); white-space: nowrap; }
.sugerencias .sug .cg {
  font-size: 11px; color: var(--texto-suave); margin-left: auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Previa de lo que se va a adjuntar */
.adjuntos-previa { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 9px; }
.adjuntos-previa .prev {
  position: relative; width: 96px; background: #fff;
  border: 1px solid var(--gris-borde); border-radius: 8px; padding: 5px; text-align: center;
}
.adjuntos-previa .prev img,
.adjuntos-previa .prev video { width: 100%; height: 58px; object-fit: cover; border-radius: 5px; display: block; }
.adjuntos-previa .prev .ic { display: block; font-size: 30px; line-height: 58px; }
.adjuntos-previa .prev .nm {
  display: block; font-size: 11px; color: var(--texto-suave); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.adjuntos-previa .prev .quitar {
  position: absolute; top: -6px; right: -6px; width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid var(--gris-borde); background: #fff; color: var(--rojo-hondo);
  font-size: 11px; line-height: 1; cursor: pointer; box-shadow: var(--sombra-1);
}
.adjuntos-previa .prev .quitar:hover { background: #FDECEC; }

.redactar-pie { display: flex; align-items: center; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
.redactar-pie .esp { flex: 1; }
.redactar-pie .boton { padding: 7px 15px; font-size: 12.5px; }
.redactar-nota { font-size: 11.5px; color: var(--texto-suave); }

.aviso-identificarse {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: #FFF4E5; border: 1px solid var(--naranja); color: var(--naranja-oscuro);
  border-radius: 10px; padding: 12px 14px; font-size: 13px; font-weight: bold; margin-bottom: 14px;
}
.aviso-identificarse .boton { padding: 6px 14px; font-size: 12.5px; }

/* ── Lista de posteos ── */
/* align-content:start evita que, cuando hay pocos posteos (p.ej. un único aviso
   de cubicaciones), la grilla estire esa fila para llenar todo el alto del panel
   y el mensaje quede envuelto en un enorme espacio en blanco. Cada posteo ocupa
   sólo su alto natural y se apilan desde arriba. */
.muro-lista { display: grid; gap: 10px; align-content: start; }
.post {
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 10px;
  padding: 11px 13px; box-shadow: var(--sombra-1);
  transition: box-shadow var(--transicion);
}
.post:hover { box-shadow: var(--sombra-2); }
/* Posteo donde te nombraron: se distingue sin gritar.

   El relleno de la izquierda baja de 13 a 10 porque el borde sube de 1 a 4: si
   no, el posteo donde te nombraron escribe su texto 3 px más adentro que los de
   arriba y los de abajo, y la conversación queda con los renglones corridos.
   13 + 1 = 10 + 4. */
.post.mencionado {
  border-left: 4px solid var(--dorado-hondo); background: #FFFDF5; padding-left: 10px;
}

.post-cab { display: flex; align-items: center; gap: 10px; }
.post-quien { min-width: 0; flex: 1; }
.post-quien b {
  display: block; font-size: 13.5px; color: var(--azul-nombre); text-transform: uppercase;
  letter-spacing: .3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.post-meta { font-size: 11.5px; color: var(--texto-suave); }
.post-meta .pr { color: var(--texto); }
/* Editar/borrar del propio posteo: SIEMPRE visibles (antes sólo al pasar el
   mouse, así que nadie sabía que estaban, y en pantallas táctiles no salían). */
.post-acciones { flex: 0 0 auto; display: flex; gap: 4px; opacity: .85; transition: opacity var(--transicion); }
.post:hover .post-acciones, .post:focus-within .post-acciones { opacity: 1; }
.post-btn {
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 6px;
  color: var(--texto-suave); font-size: 13px; line-height: 1; padding: 4px 8px; cursor: pointer;
}
.post-btn:hover { border-color: var(--gris-borde); background: var(--azul-tinte); color: var(--azul-nombre); }
.post-btn.malo:hover { background: #FDECEC; color: var(--rojo-hondo); border-color: var(--rojo); }

.post-texto { font-size: 13.5px; line-height: 1.5; color: var(--texto); margin-top: 8px; word-break: break-word; }
.post-texto a { color: var(--azul-nombre); }
.mencion {
  background: var(--azul-tinte-2); color: var(--azul-nombre); font-weight: bold;
  border-radius: 4px; padding: 0 3px;
}
/* Cuando el mencionado sos vos, se ve de una. */
.mencion.mia { background: var(--dorado); color: #6B4E00; }

/* Fotos y videos: grilla que se adapta, y una sola sale grande. */
.post-medios {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 6px; margin-top: 9px;
}
.post-medios.uno { grid-template-columns: minmax(0, 420px); }
.post-medios .medio {
  position: relative; padding: 0; border: 1px solid var(--gris-borde); border-radius: 8px;
  overflow: hidden; background: var(--gris-fondo); cursor: zoom-in; display: block;
}
.post-medios .medio img,
.post-medios .medio video { display: block; width: 100%; height: 130px; object-fit: cover; }
.post-medios.uno .medio img,
.post-medios.uno .medio video { height: auto; max-height: 380px; object-fit: contain; }
.post-medios .medio:hover { border-color: var(--azul); }
.post-medios .medio .play {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 30px; color: #fff; text-shadow: 0 2px 10px rgba(0, 0, 0, .6);
  background: rgba(29, 36, 50, .22); pointer-events: none;
}

/* Documentos: una fila por archivo, con su ícono y su peso. */
.post-docs { display: grid; gap: 5px; margin-top: 9px; }
.post-docs .doc {
  display: flex; align-items: center; gap: 9px; text-decoration: none;
  border: 1px solid var(--gris-borde); border-radius: 8px; padding: 6px 10px;
  background: var(--gris-fondo); font-size: 12.5px; color: var(--texto);
  transition: background var(--transicion), border-color var(--transicion);
}
.post-docs .doc:hover { background: var(--azul-tinte); border-color: var(--azul-medio); }
.post-docs .doc .ic { font-size: 17px; flex: 0 0 auto; }
.post-docs .doc .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.post-docs .doc .pz {
  margin-left: auto; font-size: 11px; color: var(--texto-suave);
  font-variant-numeric: tabular-nums; flex: 0 0 auto;
}

/* ── Visor de fotos y videos ── */
.visor {
  position: fixed; inset: 0; z-index: 80; background: rgba(15, 20, 30, .93);
  display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 34px 20px 20px;
}
.visor-cuerpo { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; width: 100%; }
.visor-cuerpo img,
.visor-cuerpo video { max-width: 100%; max-height: 100%; border-radius: 8px; box-shadow: 0 10px 40px rgba(0, 0, 0, .5); }
.visor-pie {
  flex: 0 0 auto; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; justify-content: center;
  color: #E7EDF7; font-size: 12.5px; margin-top: 14px;
}
.visor-pie a { color: var(--azul-claro); }
.visor-cerrar {
  position: absolute; top: 12px; right: 16px; width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .3); background: rgba(255, 255, 255, .1);
  color: #fff; font-size: 16px; cursor: pointer;
}
.visor-cerrar:hover { background: rgba(255, 255, 255, .22); }

/* El diálogo de "quién soy" usa un desplegable ancho, como los filtros. */
.modal-caja select {
  width: 100%; font-family: inherit; font-size: 13px; color: var(--texto);
  border: 1px solid var(--gris-borde); border-radius: 8px; padding: 8px 10px; background: #fff;
}
.modal-caja select:focus { outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px var(--azul-tinte); }
.modal-nota code {
  background: var(--gris-fondo); border: 1px solid var(--gris-borde); border-radius: 4px;
  padding: 1px 5px; font-size: 11px;
}

@media (max-width: 780px) {
  .post-medios { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  .post-medios .medio img, .post-medios .medio video { height: 104px; }
}

/* ── Avisos de la conversación ──
   Un aviso es un mensaje que queda fijo arriba: lo que el equipo tiene que ver
   aunque entre la semana que viene. Se distingue por el borde y la chapa, no
   por gritar. */
.aviso-chk { white-space: nowrap; }
.post.es-aviso {
  border-left: 4px solid var(--dorado-hondo); background: #FFFBF0;
  box-shadow: var(--sombra-2);
}
/* Si además te mencionan, manda la marca de aviso: ya está destacado. */
.post.es-aviso.mencionado { background: #FFFBF0; }
.chapa-aviso {
  display: inline-block; margin-left: 8px; vertical-align: middle;
  background: var(--dorado); color: #6B4E00;
  font-size: 11px; font-weight: bold; letter-spacing: .4px; text-transform: uppercase;
  border-radius: 20px; padding: 1px 8px;
}

/* Usuario del administrador: es uno y es fijo, así que se muestra, no se pide. */
.usuario-fijo {
  font-family: inherit; font-size: 15px; font-weight: bold; letter-spacing: .6px;
  color: var(--azul-nombre); background: var(--gris-fondo);
  border: 1px solid var(--gris-borde); border-radius: 8px;
  padding: 8px 10px; margin-bottom: 12px;
}

/* ── Entrar, mi clave y usuarios ─────────────────────────────── */
.modal-caja.ancha { max-width: 860px; }
.modal-caja .chk.recordarme { margin-top: 10px; font-size: 13px; color: var(--texto); }

/* Alta de usuario: una sola línea en pantallas anchas. */
.alta-usuario {
  display: grid; grid-template-columns: 1fr 1fr 1.6fr 1fr auto; gap: 8px;
  align-items: end; margin: 12px 0 4px;
  background: var(--gris-fondo); border: 1px solid var(--gris-borde);
  border-radius: 10px; padding: 10px 12px;
}
.alta-usuario .campo { min-width: 0; }
.alta-usuario label {
  display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--texto-suave); margin-bottom: 3px;
}
.alta-usuario input {
  width: 100%; font-family: inherit; font-size: 12.5px; color: var(--texto);
  border: 1px solid var(--gris-borde); border-radius: 7px; padding: 6px 8px; background: #fff;
}
.alta-usuario input:focus { outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px var(--azul-tinte); }
.alta-usuario .boton { padding: 7px 14px; font-size: 12.5px; white-space: nowrap; }

.tabla-usuarios { max-height: calc(var(--alto-ventana) * .46); overflow-y: auto; margin-top: 6px; }
/* Acciones al pie de la pestaña Usuarios (antes iban en el pie del modal). */
.acciones-usuarios { display: flex; gap: 8px; margin-top: 12px; }
table.datos.usuarios { width: 100%; font-size: 12.5px; }
table.datos.usuarios td.correo { font-variant-numeric: tabular-nums; color: var(--azul-nombre); }
table.datos.usuarios tr.baja td { color: var(--gris-medio); text-decoration: line-through; }
table.datos.usuarios tr.baja td.acc { text-decoration: none; }
table.datos.usuarios td.acc { white-space: nowrap; text-align: right; }

/* El desplegable del @ muestra nombre y correo. */
.sugerencias .sug .co {
  font-size: 11px; color: var(--azul-nombre); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sugerencias .sug .cg { margin-left: auto; }
.sugerencias .sug .cg.sin { color: var(--naranja-oscuro); }
.sug-vacio { padding: 8px 10px; font-size: 12.5px; color: var(--texto-suave); }

/* Mención a alguien que todavía no tiene usuario: se ve, pero avisa que no le
   va a llegar el aviso. */
.mencion.sin-usuario {
  background: var(--gris-fondo); color: var(--texto-suave);
  box-shadow: inset 0 0 0 1px var(--gris-borde);
}

/* ══════════════ Fechas de contrato en la tarjeta (el recuadro) ══════════════
   Inicio → término del proyecto. Las carga el administrador (botón ✎). */
.pcard-fechas {
  display: flex; align-items: center; gap: 6px; min-width: 0; flex: 0 0 auto;
  margin-top: 6px; font-size: 11px; color: var(--texto);
  background: #EAF5E1; border: 1px solid #CDE6BC; border-radius: 8px; padding: 3px 8px;
}
/* Le falta el inicio, el termino o los dos: gris, para que la tarjeta incompleta
   se distinga de lejos de la que ya tiene las dos fechas. Hasta el 14/10/2026
   esta clase se llamaba .de-planilla y marcaba el ORIGEN de la fecha (planilla
   contra carga a mano del administrador); desde que manda la planilla, el origen
   dejo de ser una distincion util y lo que hay que ver es que falta. */
.pcard-fechas.incompleta { background: var(--gris-fondo); border-color: var(--gris-borde); color: var(--texto-suave); }
/* Centrado y COMPLETO: antes se cortaba con puntos suspensivos y la fecha de
   término quedaba a medias ("TERMINO 28-09-…"), que es justo el dato que se va
   a mirar. Ahora el texto puede bajar a una segunda línea; cada mitad
   (.pt = INICIO … / TERMINO …) no se parte, así que el salto cae entre las dos
   fechas y nunca dentro de una. En el ancho normal de la tarjeta entra en una
   sola línea; la segunda aparece sólo cuando las tarjetas se aprietan. */
.pcard-fechas .ff { flex: 1 1 auto; text-align: center; min-width: 0; }
.pcard-fechas .ff .pt { white-space: nowrap; }
.pcard-fechas .ff b { color: var(--verde-hondo); font-variant-numeric: tabular-nums; }
.pcard-fechas.incompleta .ff b { color: var(--texto); }
.pcard-fechas .fecha-btn {
  flex: 0 0 auto; background: none; border: 1px solid #CDE6BC; border-radius: 6px;
  color: var(--verde-hondo); font-family: inherit; font-size: 11px; line-height: 1;
  padding: 2px 6px; cursor: pointer;
}
.pcard-fechas .fecha-btn:hover { background: #DCEFCF; }

/* Recepción por cliente: su propia línea, entre el recuadro de fechas y las
   tablas de cubicaciones. Sin recuadro, para que no compita con el verde de
   arriba: es un dato de referencia, no el compromiso que manda el avance.
   Centrada, como el recuadro de fechas que tiene encima. */
.pcard-recepcion {
  /* Sin margen propio: el gap de .pcard ya la separa de las filas vecinas. */
  flex: 0 0 auto; min-width: 0; text-align: center;
}
.pcard-recepcion .rr {
  display: block; width: 100%; min-width: 0;
  font-family: inherit; font-size: 11px; letter-spacing: .3px; text-transform: uppercase;
  color: var(--texto-suave); text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pcard-recepcion b { color: var(--azul-nombre); font-variant-numeric: tabular-nums; letter-spacing: .2px; }
.pcard-recepcion.vacia .rr, .pcard-recepcion.vacia b { color: var(--gris-medio); }
/* Para el administrador la línea entera es el botón que abre el diálogo. Se
   mantiene como una línea de texto (nada de recuadro) y se delata al pasar por
   encima: el lápiz a la derecha ya avisa que se puede tocar. */
.pcard-recepcion button.rr {
  background: none; border: 1px solid transparent; border-radius: 6px;
  padding: 1px 4px; cursor: pointer;
  transition: background var(--transicion), border-color var(--transicion), color var(--transicion);
}
.pcard-recepcion button.rr:hover,
.pcard-recepcion button.rr:focus-visible { background: var(--azul-tinte); border-color: var(--azul-tinte-2); color: var(--azul-nombre); }
.pcard-recepcion .lapiz { margin-left: 4px; color: var(--azul-nombre); }
.pcard-recepcion.vacia button.rr { border-style: dashed; border-color: var(--gris-borde); }

/* ══════ La ficha del proyecto, arriba del Detalle (29/10/2026) ════════════
   Pedido de Fiefre: que arriba de «Detalle de actividades» esté la tarjeta
   resumen del proyecto. Es LA MISMA .pcard del Resumen y de los archivados -no
   se copia ni una regla de forma-; acá sólo se dice dónde va y cómo se reparte.

   HASTA HOY ACÁ HABÍA CINCO TARJETITAS (.ficha-tarjeta) metidas en la franja
   del título. Se fueron con la función que las dibujaba: la tarjeta de verdad
   trae esos cuatro datos y además el anillo, el estado, la OT, el rendimiento
   y el avance por área.

   ANCHA Y BAJA, NO ALTA Y ANGOSTA. En el Resumen la tarjeta es una celda de
   una grilla de seis y se lee de arriba abajo; acá está sola y arriba de la
   tabla, donde cada renglón que se lleva es un renglón de actividades que no
   se ve. Apilada contra el borde izquierdo dejaba el monitor entero en blanco
   a su derecha y empujaba la tabla fuera de la pantalla. Así que acá cambia de
   forma: el mismo contenido, en tres columnas a lo ancho de la pantalla.

     · izquierda  el anillo, el cliente, el producto, el estado, la OT, el
                  rendimiento y las fechas de contrato (eso ya es .pcard-top);
     · medio      la recepción por cliente, la carta Gantt y las tablas de
                  cubicaciones, una debajo de otra;
     · derecha    el avance de las diez áreas, en dos columnas.

   Y el pie -actividades, atrasadas, HH- cruza las tres por abajo. Los tres
   bloques se colocan por su clase y no por su posición: el orden de los hijos
   lo decide tarjetaProyecto(), y el día que se agregue una fila ahí, acá no
   hay que contar de nuevo. */
.ficha-detalle { margin: 0 0 10px; max-height: min(42vh, 380px); overflow: auto; }

.ficha-detalle .pcard.en-ficha {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(200px, .8fr) minmax(320px, 1.4fr);
  grid-template-rows: auto auto auto auto;
  column-gap: 18px; row-gap: 5px;
  align-content: start;
}
/* El anillo y la identificación, a la izquierda y ocupando los tres renglones
   de arriba: así las fechas de contrato quedan debajo del nombre, que es donde
   se leen, y no sueltas al medio. */
.ficha-detalle .pcard.en-ficha > .pcard-top { grid-column: 1; grid-row: 1 / 4; align-self: start; }
.ficha-detalle .pcard.en-ficha > .pcard-recepcion { grid-column: 2; grid-row: 1; }
.ficha-detalle .pcard.en-ficha > .pcard-gantt { grid-column: 2; grid-row: 2; }
.ficha-detalle .pcard.en-ficha > .pcard-sp:not(.pcard-gantt) { grid-column: 2; grid-row: 3; }
.ficha-detalle .pcard.en-ficha > .pcard-areas-caja { grid-column: 3; grid-row: 1 / 4; }
.ficha-detalle .pcard.en-ficha > .pcard-pie { grid-column: 1 / -1; grid-row: 4; }

/* En columna, el avance por área ya no va debajo de nada: en vez del hilo de
   arriba que lo separaba de la fila anterior, lleva uno al costado que lo
   separa de la columna del medio. */
.ficha-detalle .pcard-areas-caja { border-top: 0; margin-top: 0; padding: 0 0 0 16px; border-left: 1px solid var(--gris-borde); }
.ficha-detalle .pcard-areas { grid-template-columns: 1fr 1fr; gap: 2px 16px; border-top: 0; padding-top: 4px; }

/* Dentro de la ficha la tarjeta no es un botón: no se levanta al pasarle el
   cursor ni cambia el puntero, porque no lleva a ninguna parte. */
.ficha-detalle .pcard.en-ficha { cursor: default; }
.ficha-detalle .pcard.en-ficha:hover { transform: none; }

/* Pantalla angosta (tablet): el avance por área baja entero debajo de las
   otras dos columnas, en vez de estrujarse en un tercio.
   Antes era @media (max-width: 1100px) y se disparaba con el tablero
   escalado: en una ventana de 1000 px el maquetado tiene 1818 px de ancho y
   las tres columnas entran de sobra (ver la nota del ancho de maquetado). */
html:not(.maqueta-1100) .ficha-detalle .pcard.en-ficha {
  grid-template-columns: minmax(260px, 1fr) minmax(190px, .8fr);
}
html:not(.maqueta-1100) .ficha-detalle .pcard.en-ficha > .pcard-areas-caja {
  grid-column: 1 / -1; grid-row: 4;
  border-left: 0; padding: 5px 0 0; border-top: 1px solid var(--gris-borde);
}
html:not(.maqueta-1100) .ficha-detalle .pcard.en-ficha > .pcard-pie { grid-row: 5; }
/* En el teléfono vuelve a ser la tarjeta de siempre, una columna de arriba
   abajo: ahí no hay ancho que repartir y la pantalla se recorre entera, así
   que el alto deja de ser un problema. */
@media (max-width: 780px) {
  .ficha-detalle { max-height: none; overflow: visible; }
  .ficha-detalle .pcard.en-ficha { display: flex; }
  .ficha-detalle .pcard.en-ficha > .pcard-areas-caja {
    border-left: 0; padding: 5px 0 0; border-top: 1px solid var(--gris-borde); margin-top: 6px;
  }
}
/* Y con menos de 560 px las áreas vuelven a una columna: con dos, cada una
   queda en unos 160 px y la columna del nombre mide 106, así que «CONTROL DE
   CALIDAD» se cortaba. */
@media (max-width: 560px) {
  .ficha-detalle .pcard-areas { grid-template-columns: 1fr; }
}

/* ══════ «Qué falta cargar»: la matriz y el detalle (27/10/2026) ═══════════
   Las dos tablas son las del resto del tablero (table.datos); lo único propio
   es el semáforo de las celdas, que es de lo que trata la pantalla: ámbar =
   falta, verde = está todo, gris = a esta área no le toca. El ámbar y no el
   rojo a propósito: que a una actividad le falte la fecha de inicio es algo
   que hay que ir a pedir, no una alarma del tablero. */
.faltan-areas th.rw { text-align: left; white-space: nowrap; }
.datos td.num { text-align: right; font-variant-numeric: tabular-nums; }
.faltan-areas th.num, .faltan-detalle th.num { text-align: right; }
.datos td.falta {
  background: color-mix(in srgb, var(--dorado) 26%, #fff);
  color: var(--dorado-hondo); font-weight: bold;
}
.datos td.falta .de { font-weight: normal; opacity: .7; }
.datos td.falta[role="button"] { cursor: pointer; }
.datos td.falta[role="button"]:hover { background: color-mix(in srgb, var(--dorado) 46%, #fff); }
.datos td.falta[role="button"]:focus-visible { outline: 2px solid var(--azul); outline-offset: -2px; }
.datos td.bien { color: var(--verde-hondo); font-weight: bold; }
.datos td.vacio { color: var(--gris-medio); }
/* En el detalle, «falta» es una palabra y no un número: va centrada. */
.faltan-detalle td.falta { text-align: center; }

/* ══════ «Actividad»: una pestaña por usuario y su registro (28/10/2026) ═══
   La lista de arriba son las pestañas de las personas: una fila de botones que
   se desliza de costado cuando no entran, y no una lista vertical, para que la
   ficha del usuario elegido quede a la vista sin tener que bajar. El que está
   abierto se marca con el borde de abajo, como cualquier pestaña. */
.act-pestanas {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin-top: 10px; padding-bottom: 2px;
}
.act-pest {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 7px 13px; border-radius: 10px; cursor: pointer;
  background: #fff; border: 1px solid var(--gris-borde);
  border-bottom: 3px solid transparent;
  font-family: inherit; color: var(--texto); text-align: left;
  box-shadow: var(--sombra-1);
  transition: transform var(--transicion), box-shadow var(--transicion), border-color var(--transicion);
}
.act-pest:hover { transform: translateY(-1px); box-shadow: var(--sombra-2); }
.act-pest.puesta { border-bottom-color: var(--azul); background: var(--azul-tinte); }
.act-pest-nom { font-size: 13px; font-weight: bold; }
.act-pest-sub { font-size: 11px; color: var(--texto-suave); font-variant-numeric: tabular-nums; }

/* Las cifras de la ficha: lo que se quiere saber antes de leer línea por
   línea. Se reparten a lo ancho y bajan a dos columnas en el teléfono. */
.act-cifras {
  display: grid; gap: 10px; margin: 12px 0;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.act-cifra {
  background: var(--gris-fondo); border: 1px solid var(--gris-borde);
  border-radius: 10px; padding: 9px 12px;
}
.act-cifra-t { font-size: 11px; color: var(--texto-suave); margin-bottom: 3px; }
.act-cifra-v { font-size: 15px; font-weight: bold; font-variant-numeric: tabular-nums; }
.act-cifra-v small { font-size: 11.5px; font-weight: normal; color: var(--texto-suave); }

.datos.actividad td.nowrap { white-space: nowrap; font-variant-numeric: tabular-nums; }
.datos.actividad td.act-detalle { color: var(--texto-suave); }
/* Un intento fallido tiene que saltar a la vista: es lo que se va a buscar. */
.datos.actividad tr.mal-fila td { background: #FDECEC; }
/* Los tipos de línea, en la paleta de las etiquetas de estado. */
.et-ver    { background: linear-gradient(135deg, #9DC3E6, var(--azul-claro)); color: #14324F; }
.et-filtro { background: linear-gradient(135deg, var(--dorado), var(--dorado-hondo)); color: #4A3800; }
.et-orden  { background: linear-gradient(135deg, #E4E4E4, var(--gris-medio)); color: #3A3A3A; }
.et-accion { background: linear-gradient(135deg, #2E75B6, #1F4E79); }
.et-excel  { background: linear-gradient(135deg, var(--verde), var(--verde-hondo)); }
.et-fallo  { background: linear-gradient(135deg, var(--rojo), var(--rojo-hondo)); }
/* El aviso en rojo de la cabecera, cuando el registro no se pudo pedir. */
.cap .mal { color: var(--rojo-hondo); }

/* ══════════════ Cronología (Gantt) ══════════════ */
/* ── Que se pueda leer (13/10/2026) ──────────────────────────────────────
   Con quince proyectos expandidos había ciento veinte renglones: al bajar se
   perdía el encabezado de meses, al desplazar de costado se perdía el nombre
   del área, y no se sabía dónde terminaba un proyecto y empezaba el otro.
   Tres cosas arreglan eso: la caja tiene alto propio y scroll en los dos ejes,
   el encabezado de meses queda fijo arriba y la columna de nombres fija a la
   izquierda. */
.gantt-scroll {
  overflow: auto;
  max-height: calc(var(--alto-ventana) - 230px);
  min-height: 320px;
  border: 1px solid var(--gris-borde); border-radius: 8px;
  background: #fff;
}
#gantt { min-width: 640px; }
/* El encabezado de meses viaja con el scroll vertical. */
.gantt-cab {
  position: sticky; top: 0; z-index: 8; background: #fff;
  padding-top: 4px;
}
/* El nombre del proyecto o del área viaja con el scroll horizontal. */
.gantt-cab > div:first-child,
.gantt-fila .nm { position: sticky; left: 0; z-index: 4; background: #fff; }
.gantt-fila:hover .nm { background: var(--azul-tinte); }
/* Cada proyecto, un bloque: la franja del nombre más marcada y las áreas con
   una guía a la izquierda que dice hasta dónde llega el proyecto. */
.gantt-fila.proyecto { background: var(--azul-tinte-2); }
.gantt-fila.proyecto .nm { background: var(--azul-tinte-2); }
.gantt-fila.proyecto:hover,
.gantt-fila.proyecto:hover .nm { background: var(--azul-tinte); }
.gantt-areas { border-left: 3px solid var(--azul-claro); }
.gantt-areas .gantt-fila.sub .nm { padding-left: 15px; }

/* Los tres anchos de la pista. */
#ganttZoom { display: flex; gap: 0; }
#ganttZoom button { border-radius: 0; }
#ganttZoom button:first-child { border-radius: 7px 0 0 7px; }
#ganttZoom button:last-child { border-radius: 0 7px 7px 0; }
#ganttZoom button.activo {
  background: var(--azul-hondo); color: #fff; border-color: var(--azul-hondo);
}
.gantt-controles { display: flex; gap: 8px; flex: 0 0 auto; }
.gantt-fila.proyecto .nm { display: flex; align-items: center; gap: 6px; overflow: visible; }
.gantt-fila.proyecto .nm .nmtxt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gantt-toggle {
  flex: 0 0 auto; width: 18px; height: 18px; line-height: 15px; text-align: center;
  background: none; border: 1px solid var(--gris-borde); border-radius: 4px;
  color: var(--azul-nombre); cursor: pointer; font-size: 11px; padding: 0; font-family: inherit;
}
.gantt-toggle:hover { background: var(--azul-tinte-2); }
.gantt-toggle.vacio { border-color: transparent; background: none; cursor: default; }

/* ── Línea base vs desvío (Cronología) ──
   La barra es la base (fechas de contrato); el relleno es el avance real. El
   tramo rayado naranja es lo que debería estar hecho hoy y no está (atraso), y
   el tramo pasado el término es el desvío proyectado al ritmo actual. */
.gantt-atraso { position: absolute; top: 3px; height: 14px; border-radius: 3px; z-index: 1; pointer-events: none;
  background: repeating-linear-gradient(45deg, rgba(237,125,49,.40) 0 4px, rgba(237,125,49,.15) 4px 8px); }
.gantt-desvio { position: absolute; top: 6px; height: 8px; border-radius: 3px; z-index: 1;
  background: repeating-linear-gradient(45deg, var(--naranja) 0 3px, rgba(237,125,49,.25) 3px 6px); opacity: .75; }
.gantt-proyfin { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--naranja-oscuro); z-index: 3; }
.gantt-desvio-lbl { margin-left: 6px; font-size: 11px; font-weight: bold; color: var(--rojo-hondo); white-space: nowrap; }
.gantt-ok-lbl { margin-left: 6px; font-size: 11px; color: var(--verde-hondo); }

/* ── Dependencias entre áreas + área crítica (Cronología) ── */
.gantt-areas { position: relative; }
svg.gantt-deps { position: absolute; top: 0; left: 0; pointer-events: none; z-index: 4; overflow: visible; }
.dep-linea { fill: none; stroke: var(--gris-medio); stroke-width: 1.2; opacity: .8; }
.dep-linea.crit { stroke: var(--naranja-oscuro); stroke-width: 1.8; opacity: 1; }
/* La dependencia que nace de un hito se dibuja entera, no tenue: es un vínculo
   declarado en la planilla, no una secuencia deducida del orden de las áreas. */
.dep-linea.de-hito { opacity: 1; stroke-width: 1.6; }
.dep-flecha { fill: var(--gris-medio); opacity: .8; }
.dep-flecha.crit { fill: var(--naranja-oscuro); opacity: 1; }
/* Dos áreas que van en paralelo (la de abajo arrancó antes del hito de la de
   arriba): línea punteada, porque ahí no hay una espera que dibujar. */
.dep-linea.solapada { stroke-dasharray: 3 3; opacity: .65; }
/* LA FLECHA DE LA APROBACION (14/10/2026). No une dos areas consecutivas: va
   desde el rombo de la aprobacion hasta el arranque de Ingenieria, salteandose
   las areas del medio. Por eso se dibuja distinta -verde y mas fina- y no se
   confunde con un eslabon de la secuencia de trabajo: dice "esto es lo que
   habilito aquello", no "esto va despues de aquello".

   Gana sobre .crit y sobre .de-hito a proposito: la fuente de esta flecha es
   lo que tiene que leerse, aunque el area este en la cadena critica. */
.dep-linea.de-aprobacion { stroke: var(--verde-hondo); stroke-width: 1.3; opacity: .95; }
.dep-flecha.de-aprobacion { fill: var(--verde-hondo); opacity: .95; }
/* Al pasar el mouse por un área se enciende su cadena: la flecha que la
   habilita y la que ella manda. */
svg.gantt-deps .dep-linea.viva { stroke: var(--azul-hondo); stroke-width: 2.2; opacity: 1; stroke-dasharray: none; }
svg.gantt-deps .dep-flecha.viva { fill: var(--azul-hondo); opacity: 1; }
.gantt-fila.sub.critica .nm { color: var(--naranja-oscuro); font-weight: bold; }
.gantt-fila.sub .cuello { font-size: 11px; }
.viga.sub.critica { box-shadow: 0 0 0 1.5px var(--naranja-oscuro); }
.viga.sub.critica > i { background: linear-gradient(90deg, var(--naranja), var(--naranja-oscuro)); }

/* ══════════════ Publicaciones: columna lateral fija + chat ══════════════
   El alto es fijo (lo que queda de pantalla): el panel y la lista scrollean por
   dentro, así el campo para escribir queda siempre abajo, pegado a los mensajes. */
.muro-layout { display: flex; gap: 12px; align-items: stretch; height: calc(var(--alto-ventana) - 148px); }

/* Columna de proyectos: fija, ancha para que se lea el nombre completo, con su
   propia barra de scroll de Windows cuando no entran todos. */
.muro-panel {
  flex: 0 0 300px; align-self: stretch;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: var(--radio);
  box-shadow: var(--sombra-1); overflow: hidden; display: flex; flex-direction: column; min-height: 0;
}
.muro-panel-cab {
  font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: .4px;
  color: var(--azul); padding: 10px 12px; border-bottom: 1px solid var(--gris-borde);
  background: var(--azul-tinte); flex: 0 0 auto;
}
.muro-panel-lista { flex: 1 1 auto; overflow-y: auto; min-height: 0; padding: 6px; }
.muro-panel-vacio { padding: 14px; font-size: 12px; color: var(--texto-suave); }
.muro-proy {
  display: flex; align-items: flex-start; gap: 8px; width: 100%; text-align: left;
  background: none; border: 1px solid transparent; border-radius: 8px;
  padding: 8px 10px; margin-bottom: 2px; cursor: pointer; font-family: inherit;
  color: var(--texto); transition: background var(--transicion);
}
.muro-proy:hover { background: var(--azul-tinte); }
.muro-proy.activo { background: var(--azul-tinte-2); border-color: var(--azul-claro); }
/* OT primero (en negrita) y después el nombre, misma fuente y tamaño, para que
   la lista quede alineada y ordenada por OT. */
/* Todos los proyectos de la lista van en azul, no sólo el abierto (16/10/2026):
   es el mismo nombre de proyecto que en el resto del tablero. El elegido se
   distingue por su fondo y su borde, que para eso están. */
.muro-proy .mp-txt { flex: 1 1 auto; min-width: 0; font-size: 12.5px; line-height: 1.3;
  white-space: normal; overflow-wrap: anywhere; color: var(--azul-nombre); }
.muro-proy .mp-ot { font-weight: bold; font-variant-numeric: tabular-nums; white-space: nowrap; }
.muro-proy .mp-badge {
  flex: 0 0 auto; align-self: center;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 10px;
  background: var(--rojo-hondo); color: #fff; font-size: 11px; font-weight: bold;
  line-height: 18px; text-align: center; font-variant-numeric: tabular-nums;
}

/* Proyecto archivado en la columna: sólo se ve cuando el administrador repuso
   las publicaciones de los históricos. Va apagado y con su etiqueta, para que
   no se confunda con lo que está en curso. */
.muro-proy.archivado .mp-txt { color: var(--texto-suave); }
.muro-proy .mp-arch {
  display: inline-block; margin-left: 6px; padding: 0 5px; border-radius: 6px;
  background: var(--gris-fondo); border: 1px solid var(--gris-borde);
  font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: .3px;
  color: var(--texto-suave); white-space: nowrap; vertical-align: 1px;
}

/* Interruptor del administrador: reponer las publicaciones de los archivados.
   Va arriba a la derecha de la cabecera, fuera del flujo del título. */
.cabecera-graf > .muro-arch {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px; align-items: flex-end;
  max-width: 320px; text-align: right;
}
.muro-arch .muro-arch-lbl {
  display: flex; align-items: center; gap: 6px; margin: 0; cursor: pointer;
  font-size: 12px; color: var(--texto-suave); text-align: left;
}
.muro-arch input[type="checkbox"] { flex: 0 0 auto; margin: 0; cursor: pointer; }
.muro-arch .hnota { font-size: 11.5px; }

/* La caja de la conversación: cabecera fija arriba, mensajes scrollables en el
   medio, campo para escribir fijo abajo. */
.muro-layout .muro-caja { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.muro-layout .muro-caja > .cabecera-graf { flex: 0 0 auto; }
/* Encabezado simple: el proyecto en grande (h2) y abajo, en negrita, el rótulo. */
.muro-caja .muro-sub { font-weight: bold; font-size: 13px; color: var(--texto); margin-top: 2px; }

/* ══════ UNA EXPLICACIÓN QUE SE PLIEGA (07/11/2026) ══════════════════════
   La bajada de la Cronología hace falta la primera vez y estorba después.
   Nace abierta; quien la cierra se la encuentra cerrada la próxima. */
.cap-pliegue { margin: 0 0 8px; }
.cap-pliegue > summary {
  display: inline-flex; align-items: center; gap: 5px;
  cursor: pointer; list-style: none; width: fit-content;
  font-size: 12px; font-weight: bold; color: var(--azul-nombre);
  padding: 2px 8px 2px 4px; border-radius: 7px;
}
.cap-pliegue > summary::-webkit-details-marker { display: none; }
.cap-pliegue > summary::before {
  content: "▸"; font-size: 10px; transition: transform var(--transicion);
}
.cap-pliegue[open] > summary::before { transform: rotate(90deg); }
.cap-pliegue > summary:hover { background: var(--azul-tinte); }
.cap-pliegue > summary:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
/* Cerrada, el rótulo no deja hueco debajo; abierta, el texto respira. */
.cap-pliegue > .cap { margin-top: 5px; }

/* ══════ EL MANUAL, ADENTRO DE LA PÁGINA (07/11/2026) ════════════════════
   Índice fijo a la izquierda y el texto desplazándose al lado, que es como
   se lee un manual. El alto se mide sin el zoom del tablero
   (--alto-ventana), como el resto de las pantallas de alto completo. */
.modal-caja.ayuda {
  max-width: 920px; width: 94vw;
  display: flex; flex-direction: column;
  max-height: calc(var(--alto-ventana) * .88);
}
.ayuda-barra { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; margin-bottom: 10px; }
.ayuda-barra h3 { margin: 0; border: 0; padding: 0; }
.ayuda-cuerpo { display: flex; gap: 16px; flex: 1 1 auto; min-height: 0; }
.ayuda-indice {
  flex: 0 0 186px; display: flex; flex-direction: column; gap: 1px;
  border-right: 1px solid var(--gris-borde); padding-right: 10px;
  overflow-y: auto; min-height: 0;
}
.ayuda-indice a {
  display: block; padding: 5px 8px; border-radius: 7px;
  font-size: 12.5px; color: var(--texto); text-decoration: none; line-height: 1.25;
}
.ayuda-indice a:hover { background: var(--azul-tinte); color: var(--azul-nombre); }
.ayuda-indice a.activa { background: var(--azul); color: #fff; font-weight: bold; }

.ayuda-texto { flex: 1 1 auto; min-width: 0; overflow-y: auto; padding-right: 6px; }
.ayuda-texto section { scroll-margin-top: 4px; }
.ayuda-texto section + section { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--gris-borde); }
.ayuda-texto h4 {
  margin: 0 0 8px; font-size: 15px; color: var(--azul-nombre);
}
.ayuda-texto p { margin: 0 0 8px; font-size: 13.5px; line-height: 1.55; color: var(--texto); }
.ayuda-texto code {
  font-family: Consolas, "Courier New", monospace; font-size: .92em;
  background: var(--azul-tinte); border-radius: 4px; padding: 1px 5px;
}
/* La nota al pie de una sección: lo que conviene saber pero no es el camino
   principal. */
.ayuda-texto .ay-nota {
  background: var(--azul-tinte); border-left: 3px solid var(--azul-medio);
  border-radius: 0 7px 7px 0; padding: 7px 10px; font-size: 12.5px;
  color: var(--texto); margin: 10px 0 8px;
}
.ayuda-texto .ay-tabla { border-collapse: collapse; margin: 6px 0 10px; }
.ayuda-texto .ay-tabla td {
  padding: 4px 14px 4px 0; font-size: 13px; vertical-align: top;
  border-bottom: 1px solid var(--gris-borde);
}
.ayuda-texto .ay-tabla td:first-child { white-space: nowrap; }

@media (max-width: 780px) {
  /* En el teléfono el índice va arriba, en una fila que se desplaza de
     costado: una columna fija de 186 px se come media pantalla. */
  .ayuda-cuerpo { flex-direction: column; gap: 10px; }
  .ayuda-indice {
    flex: 0 0 auto; flex-direction: row; gap: 5px; overflow-x: auto;
    border-right: 0; border-bottom: 1px solid var(--gris-borde);
    padding: 0 0 7px;
  }
  .ayuda-indice a { white-space: nowrap; font-size: 12px; }
}

/* ══════ BUSCAR DENTRO DE LA CONVERSACIÓN (07/11/2026) ════════════════════
   Va en la cabecera de la conversación, no en la barra de filtros de arriba:
   esa busca actividades en todo el tablero y ésta mira los mensajes del
   proyecto que está abierto. Dos cosas distintas, dos lugares distintos. */
.muro-buscar {
  display: flex; align-items: center; gap: 6px; margin-top: 7px;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 8px;
  padding: 3px 9px; max-width: 420px;
}
.muro-buscar:focus-within { border-color: var(--azul); box-shadow: 0 0 0 3px var(--azul-tinte); }
.muro-buscar .ic { font-size: 12px; opacity: .65; }
.muro-buscar input {
  flex: 1 1 auto; min-width: 0; border: 0; outline: none; background: none;
  font-family: inherit; font-size: 13px; color: var(--texto); padding: 4px 0;
}
.muro-buscar .cuenta {
  flex: 0 0 auto; font-size: 11.5px; color: var(--texto-suave);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Lo encontrado, pintado adentro del mensaje. */
mark.hit { background: #ffe9a8; color: inherit; border-radius: 3px; padding: 0 1px; }

/* La marca de editado dice cuándo; la fecha entera va en el title. */
.post-editado { cursor: help; border-bottom: 1px dotted var(--gris-borde); }

/* El cliente, en azul, dentro del título del proyecto y en la línea de
   redactar (16/10/2026). Es el mismo azul de los nombres de proyecto del resto
   del tablero: separa de un vistazo DE QUIÉN es la obra de CÓMO se llama, sin
   agregar otro renglón al encabezado. */
/* El nombre del proyecto va ENTERO en azul, no sólo el cliente (16/10/2026).
   Con la OT y el suministro en el color del texto y el cliente en azul, el
   mismo título se leía partido en dos y parecía que el azul marcaba algo
   distinto. Es un solo dato: de qué proyecto son estas publicaciones. */
#muroTituloProy, #muroTituloProy .cl { color: var(--azul-nombre); }
.redactar-quien .en .pr { color: var(--azul-nombre); font-weight: bold; }
.redactar-quien .en .pr .cl { color: inherit; }
.muro-layout #muroLista { flex: 1 1 auto; overflow-y: auto; min-height: 0; padding-right: 4px; }

/* ══════ LOS MENSAJES SE APOYAN ABAJO, COMO EL TEAMS (07/11/2026) ═════════

   La conversación va de más viejo a más nuevo, y el más nuevo tiene que
   quedar PEGADO al campo para escribir. Con `align-content: start` -lo que
   había- los mensajes se apilaban ARRIBA y el hueco quedaba en el medio:
   medido el 07/11/2026 en el tablero real, un proyecto con dos mensajes
   dejaba 308 px de blanco entre el último y el campo para escribir, en una
   pantalla de 768. Justo el tipo de espacio sin información que se vino a
   buscar, sólo que en el medio en vez de abajo.

   SE HACE CON `margin-top: auto` EN EL PRIMER MENSAJE, no con
   `justify-content: flex-end` ni con `align-content: end`. Las tres empujan
   igual mientras sobra lugar, pero las dos últimas, en una caja que además
   SCROLLEA, empujan el contenido fuera del arranque de la caja cuando no
   sobra: la conversación larga se queda con los mensajes de arriba
   inalcanzables, no hay scroll que llegue. Con el margen automático eso no
   puede pasar: cuando no hay lugar libre, `auto` vale 0 y la lista se
   comporta exactamente como antes.

   Comprobado en produccion con la lista desbordada 102 px: con scrollTop en
   0 el primer mensaje arranca justo en el borde de la caja y se ve entero.

   La caja pasa a flex porque el margen automático necesita un contenedor que
   reparta el lugar sobrante; en grid, `margin-top: auto` sobre un ítem no
   empuja nada. El resultado dibujado es el mismo: una columna con el mismo
   gap y los mensajes a todo el ancho.

   LAS PANTALLAS DE «no hay nada» NO: «Todavía no hay publicaciones en este
   proyecto», «Elegí un proyecto» y la de sin servidor entran a esta misma
   caja como .sin-datos (ver renderMuro en lib/app.js). Un cartel que explica
   qué hacer se lee arriba, donde se mira; empujado contra el campo para
   escribir parece un mensaje más de la conversación. */
.muro-layout #muroLista { display: flex; flex-direction: column; }
.muro-layout #muroLista > :first-child { margin-top: auto; }
.muro-layout #muroLista > .sin-datos:first-child { margin-top: 0; }
/* Y las dos vistas que no son la conversación tampoco se apoyan abajo:
   una lista de archivos o de guardados se lee de arriba para abajo, como
   cualquier lista. El «pegado abajo» es de la conversación y nada más. */
.muro-layout #muroLista.arriba > :first-child { margin-top: 0; }
.muro-layout #redactar { flex: 0 0 auto; margin-top: 8px; border-top: 1px solid var(--gris-borde); padding-top: 10px; }
.muro-layout #avisoIdentificarse { flex: 0 0 auto; }

/* Los avisos 📌 ya no quedan fijos arriba: van en su lugar cronológico, pero
   conservan su color (.es-aviso) para que se noten en el medio de la charla. */

/* Al saltar desde la campana, el mensaje mencionado parpadea un momento. */
@keyframes flashPost { 0% { box-shadow: 0 0 0 3px var(--azul); } 100% { box-shadow: 0 0 0 0 rgba(77,119,198,0); } }
.post.flash { animation: flashPost 2.2s ease-out; border-radius: 8px; }

@media (max-width: 820px) {
  .muro-layout { flex-direction: column; height: auto; }
  .muro-panel { flex-basis: auto; width: 100%; max-height: 240px; }
  .muro-layout #muroLista { max-height: 55vh; }
}

/* ══════════════ Muro de entrada (login) ══════════════ */
body.con-gate { overflow: hidden; }
.gate {
  position: fixed; inset: 0; z-index: 55;  /* tapa header (50) y menú (45), pero debajo del modal (60) */
  display: flex; align-items: center; justify-content: center; padding: 20px;
  background: #fff;                         /* fondo blanco (por ahora) */
}
.gate-caja {
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 16px;
  box-shadow: var(--sombra-2); padding: 34px 40px; max-width: 440px; text-align: center;
}
.gate-caja img { height: 46px; width: auto; margin-bottom: 14px; }
.gate-caja h2 { margin: 0 0 8px; color: var(--azul-nombre); font-size: 20px; }
.gate-caja p { margin: 0 0 18px; color: var(--texto-suave); font-size: 13px; line-height: 1.5; }
.gate-caja .boton { font-size: 14px; padding: 9px 22px; }
/* Los dos roles, uno arriba del otro y a todo el ancho de la tarjeta. */
.gate-roles { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 2px; }
.gate-roles .boton { width: 100%; padding: 11px 22px; }
/* Acceso secundario: iniciar sesión con el correo (sistema de usuarios). */
.gate-link {
  margin-top: 14px; background: none; border: none; padding: 4px;
  color: var(--azul-nombre); font-family: inherit; font-size: 12.5px;
  cursor: pointer; text-decoration: underline;
}
.gate-link:hover { color: var(--azul-hondo); }
.gate-nota { margin-top: 16px; font-size: 11px; color: var(--gris-medio); letter-spacing: .2px; }

/* ══════════════ Entrar con Microsoft ══════════════ */
.boton.microsoft {
  width: 100%; background: #fff; color: #444; border: 1px solid #8c8c8c;
  display: flex; align-items: center; justify-content: center; font-weight: 600;
  margin: 4px 0 2px;
}
.boton.microsoft:hover { background: #f3f3f3; border-color: #666; }
.ms-logo { display: inline-block; width: 16px; height: 16px; margin-right: 8px; flex: 0 0 auto;
  background:
    linear-gradient(#f25022, #f25022) 0 0 / 7px 7px no-repeat,
    linear-gradient(#7fba00, #7fba00) 9px 0 / 7px 7px no-repeat,
    linear-gradient(#00a4ef, #00a4ef) 0 9px / 7px 7px no-repeat,
    linear-gradient(#ffb900, #ffb900) 9px 9px / 7px 7px no-repeat; }
.ms-o { display: flex; align-items: center; text-align: center; color: var(--texto-suave); font-size: 11px; margin: 12px 0 6px; }
.ms-o span { padding: 0 10px; white-space: nowrap; }
.ms-o::before, .ms-o::after { content: ''; flex: 1; height: 1px; background: var(--gris-borde); }

/* ══════════════ Quitar proyecto de la vista (solo admin) ══════════════ */
.pcard { position: relative; }
.pcard-quitar {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 20px; height: 20px; line-height: 17px; text-align: center; padding: 0;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 50%;
  color: var(--texto-suave); font-size: 12px; font-family: inherit; cursor: pointer; opacity: .5;
  transition: opacity var(--transicion), color var(--transicion), border-color var(--transicion), background var(--transicion);
}
.pcard:hover .pcard-quitar, .pcard:focus-within .pcard-quitar { opacity: 1; }
.pcard-quitar:hover { color: var(--rojo-hondo); border-color: var(--rojo-hondo); background: #FDECEC; opacity: 1; }

/* 🗂 Mandar al archivo ahora. Va al lado del ✕ y se comporta igual -aparece
   al pasar el mouse por la tarjeta- pero se tiñe de azul y no de rojo: el ✕
   esconde el proyecto, esto lo MUEVE a la pestaña de archivados. */
.pcard-archivar {
  position: absolute; top: 6px; right: 30px; z-index: 2;
  width: 20px; height: 20px; line-height: 17px; text-align: center; padding: 0;
  background: #fff; border: 1px solid var(--gris-borde); border-radius: 50%;
  color: var(--texto-suave); font-size: 11px; font-family: inherit; cursor: pointer; opacity: .5;
  transition: opacity var(--transicion), color var(--transicion), border-color var(--transicion), background var(--transicion);
}
.pcard:hover .pcard-archivar, .pcard:focus-within .pcard-archivar { opacity: 1; }
.pcard-archivar:hover { color: var(--azul-hondo); border-color: var(--azul-hondo); background: var(--azul-tinte); opacity: 1; }
/* En la pestaña de archivados: de dónde salió cada uno. */

/* Lista de proyectos ocultos (modal). */
.oculto-row { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 4px; border-bottom: 1px solid var(--gris-borde); }
.oculto-row .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--texto); }
.oculto-row .boton { padding: 4px 12px; flex: 0 0 auto; }
/* ══════════════ Prioridades de entrega ══════════════
   La tabla del orden de entrega. Reusa table.mtx para verse igual que las
   demás, con lo propio de esta vista: el número de orden apagado a la izquierda
   (es la posición que manda la balanza, no un dato que se lea), el nombre del
   proyecto quedándose con el ancho que sobra, y la fila entera teñida según el
   estado —lo que importa acá se lee de corrido: proyecto, fecha, días—. */
#tablaPrioridades { min-width: 0; }
#tablaPrioridades th.rw { max-width: none; }
#tablaPrioridades thead th:not(.rw) { width: 1px; }
#tablaPrioridades th.rw.num {
  width: 1px; text-align: right; color: var(--texto-suave);
  font-variant-numeric: tabular-nums; position: static; border-right: 0;
}
/* La segunda columna (el proyecto) es la que crece. */
#tablaPrioridades tr > th.rw + th.rw { width: 100%; }

#tablaPrioridades tr.prio-vencido > th.rw,
#tablaPrioridades tr.prio-vencido > td.hcel { background: #FDECEC; }
#tablaPrioridades tr.prio-proximo > th.rw,
#tablaPrioridades tr.prio-proximo > td.hcel { background: #FFF2E4; }
#tablaPrioridades tr.prio-sinfecha > th.rw,
#tablaPrioridades tr.prio-sinfecha > td.hcel { background: var(--gris-fondo); color: var(--texto-suave); }
#tablaPrioridades tbody tr:hover > th.rw,
#tablaPrioridades tbody tr:hover > td.hcel { background: var(--azul-tinte); }

/* El ✎ de cada fila abre el mismo diálogo de fechas que la tarjeta del
   proyecto. Va apagado hasta que el cursor pasa por la fila: es una acción de
   administrador, no el dato que se viene a leer. */
#tablaPrioridades .fecha-btn {
  background: none; border: 1px solid #CDE6BC; border-radius: 6px;
  color: var(--verde-hondo); font-family: inherit; font-size: 11px; line-height: 1;
  padding: 1px 5px; margin-left: 6px; cursor: pointer; opacity: .45;
  transition: opacity var(--transicion), background var(--transicion);
}
#tablaPrioridades tr:hover .fecha-btn, #tablaPrioridades .fecha-btn:focus { opacity: 1; }
#tablaPrioridades .fecha-btn:hover { background: #DCEFCF; opacity: 1; }

/* Fecha que no es un compromiso cargado, sino la actividad más tardía de la
   planilla. Se marca, porque tomarla por un compromiso con el cliente es
   exactamente el error que esta pestaña tiene que evitar. */
.prio-aviso { color: var(--naranja-oscuro); font-weight: bold; cursor: help; }

/* Riesgo: barra + número. La barra se lee de un vistazo cuando la balanza está
   del lado del riesgo y hay que ver por qué subió cada proyecto; el número
   queda para comparar dos que se parecen. */
.prio-riesgo { display: inline-flex; align-items: center; gap: 7px; cursor: help; }
.prio-barra {
  display: inline-block; width: 64px; height: 8px; border-radius: 5px;
  background: var(--gris-borde); overflow: hidden;
}
.prio-barra i {
  display: block; height: 100%; border-radius: 5px;
  background: linear-gradient(90deg, var(--dorado), var(--naranja), var(--rojo-hondo));
}
.prio-rnum { font-variant-numeric: tabular-nums; font-size: 11.5px; color: var(--texto-suave); min-width: 20px; }

/* ── La balanza ──
   Un deslizador entre dos extremos con nombre. Va dentro de la tarjeta, arriba
   de la tabla, porque es lo que explica el orden que se está viendo. Misma caja
   gris que la barra de Proyectos históricos: los dos son controles de mirar,
   no de datos. */
.balanza {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 2px 0 10px; padding: 8px 12px;
  background: var(--gris-fondo); border: 1px solid var(--gris-borde); border-radius: 10px;
}
.balanza .bz-ext { font-size: 12px; color: var(--texto-suave); white-space: nowrap; }
.balanza input[type="range"] {
  flex: 1 1 180px; min-width: 140px; max-width: 320px; accent-color: var(--azul); cursor: pointer;
}
.balanza .bz-val {
  font-size: 12px; color: var(--texto); white-space: nowrap;
  padding: 3px 9px; background: #fff; border: 1px solid var(--gris-borde); border-radius: 999px;
}
.balanza #prioBalanzaReset { margin-left: auto; }
@media (max-width: 760px) {
  .balanza #prioBalanzaReset { margin-left: 0; }
}

/* ══════ PRIORIDADES EN EL TELEFONO (08/11/2026) ═════════════════════════

   Medido en la pagina real a 375 px: esta pestaña no se podia usar. Dos
   cosas, y las dos arregladas acá.

   1. LAS TARJETAS DE ARRIBA. `.rep-tiles` pedia `repeat(5, 1fr)` -cinco
      columnas fijas- y hay siete hijos: las seis tarjetas quedaban de 25 px
      de ancho, con el titulo partido a una letra por renglon ("N° / PRO",
      "SIN / FEC"). Cinco columnas fijas estan bien en el informe impreso,
      que mide 1.040 px; en un telefono no.

   2. LA TABLA. Medía 496 px dentro de un contenedor de 334, y los cuatro
      contenedores de arriba tenian `overflow-x: visible`. No se desplazaba:
      un tercio de la tabla -incluida la columna de dias restantes- quedaba
      cortado y no habia forma de llegar.

   La pestaña es la que mas sentido tiene mirar desde el telefono, en
   terreno, y el Resumen en el mismo telefono ya se veia bien: las reglas
   existian, lo que faltaba era aplicarselas a esta.

   LA IMPRESION NO SE TOCA, y conviene decir por que no hizo falta: la hoja
   de impresion de mas abajo esconde TODO menos #reporteKpi, que es el informe
   para Gerencia y tiene su propio HTML. #prioInforme no se imprime, asi que
   la caja con scroll que se agrega aca no puede cortar ningun papel.

   OJO: estas tarjetas NO son la grilla de .rep-tiles. Prioridades la pasa a
   `display: flex` a proposito -lo dice el comentario de ese bloque: la fila
   lleva un elemento que no es una tarjeta y no tiene que medir lo mismo-, y
   cada tarjeta va con `flex: 1 1 0; min-width: 0`, que es justamente la
   receta para que se achiquen hasta desaparecer. Tocar grid-template-columns
   aca no hace absolutamente nada; lo probe y las tarjetas siguieron en 25 px.
   Se arregla en el eje que corresponde: que la fila pueda cortarse y que cada
   tarjeta tenga un ancho base del que no baje. */
/* La caja que deja desplazar la tabla de costado. No va dentro del @media:
   `overflow-x: auto` no hace NADA mientras la tabla entre, asi que en el
   monitor grande es invisible, y asi no hay dos reglas que mantener de
   acuerdo. */
.rep-scroll { overflow-x: auto; }

/* ══════════════════ Reporte de indicadores para gerencia ══════════════════
   Se abre con "Exportar para Gerencia" en la pestaña KPI's: primero se ve cómo
   queda y recién después se baja.

   EL PDF LO ARMA EL NAVEGADOR, con "Guardar como PDF" en el diálogo de
   impresión. No se sumó una librería de PDF a propósito: son varios cientos de
   KB que habría que subir por FTP y meter en la CSP —que desde el 02/10/2026 va
   con hash y sin 'unsafe-inline'—, y el resultado sería el mismo documento. Lo
   que se ve en la vista previa es exactamente lo que sale impreso, porque es el
   MISMO HTML: la hoja de impresión de más abajo sólo esconde el resto.

   LA PALETA ES LA DEL TABLERO. Lo primero fue el azul marino y el dorado
   fuerte del informe de Prioridades, pero el documento sale del dashboard y se
   mira al lado del dashboard: con dos azules distintos parecían dos sistemas.
   Desde el 08/10/2026 los tonos del reporte NO son valores propios sino los
   mismos tokens del bloque 1, así que el día que cambie la paleta de la empresa
   cambia también el informe sin que haya que acordarse de este bloque. */
#modal-reporte .modal-caja.reporte {
  max-width: 1180px; width: 100%; max-height: calc(var(--alto-ventana) * .92);
  display: flex; flex-direction: column; padding: 14px 16px 16px;
  border-top-color: var(--rep-navy);
}
.rep-barra { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.rep-barra .esp { flex: 1; }
.rep-aviso {
  font-size: 11.5px; color: var(--texto-suave); background: var(--gris-fondo);
  border: 1px solid var(--gris-borde); border-radius: 6px; padding: 6px 10px; margin-bottom: 10px;
}
/* El lienzo desplaza; la hoja de adentro mide lo que mide una A4 apaisada, para
   que lo que se ve sea del mismo ancho que lo que se imprime. */
.rep-lienzo { overflow: auto; background: var(--gris-fondo); padding: 14px; border-radius: 8px; }

:root {
  --rep-navy:  var(--azul-hondo);
  --rep-navy2: var(--azul);
  --rep-oro:   var(--dorado);
  --rep-tenue: var(--azul-tinte-2);     /* texto secundario sobre el azul */
  --rep-fila:  var(--azul-tinte);
  /* Los fondos de los semáforos se DERIVAN de los acentos del tablero y no se
     eligen a mano: así el verde del informe es el mismo verde del tablero,
     aclarado, y no un verde parecido. */
  --rep-ok-f:  color-mix(in srgb, var(--verde) 26%, #fff);   --rep-ok-t:  var(--verde-hondo);
  --rep-med-f: color-mix(in srgb, var(--dorado) 50%, #fff);  --rep-med-t: var(--dorado-hondo);
  --rep-mal-f: color-mix(in srgb, var(--rojo) 38%, #fff);    --rep-mal-t: var(--rojo-hondo);
  --rep-nd-f:  var(--gris-fondo);        --rep-nd-t:  var(--texto-suave);
}

.rep {
  width: 1040px; margin: 0 auto; background: #fff; color: var(--texto);
  font-size: 11px; line-height: 1.35;
  box-shadow: 0 2px 10px rgba(0,0,0,.12);
}

/* ── Encabezado ── */
.rep-cab {
  background: var(--rep-navy); color: #fff; padding: 16px 20px;
  display: flex; align-items: center; gap: 18px;
}
.rep-cab h1 { font-size: 22px; margin: 0; letter-spacing: .5px; font-weight: bold; }
.rep-cab .rep-sub { font-size: 10.5px; color: var(--rep-tenue); margin-top: 3px; }
.rep-cab .esp { flex: 1; }
/* El logo va arriba a la izquierda, delante del titulo, como en el resto del
   tablero. Sobre la banda azul necesita su recuadro blanco: el logo es azul. */
.rep-logo { background: #fff; border-radius: 6px; padding: 6px 10px; height: 38px; flex: 0 0 auto; }
/* Sobre el dorado del tablero -más claro que el del informe original- el
   texto va en el gris oscuro y no en azul: en azul no llegaba a contraste. */
.rep-periodo {
  background: var(--rep-oro); color: var(--texto);
  font-size: 13px; font-weight: bold; letter-spacing: 1px; text-align: center;
  padding: 6px; text-transform: uppercase;
}
.rep-meta {
  display: flex; flex-wrap: wrap; gap: 4px 22px; padding: 8px 20px;
  background: var(--rep-navy2); color: var(--rep-tenue); font-size: 10.5px;
}
.rep-meta b { color: var(--rep-oro); font-weight: bold; margin-right: 5px; text-transform: uppercase; font-size: 9.5px; letter-spacing: .4px; }

/* ── Las cinco tarjetas ── */
.rep-tiles { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; padding: 14px 20px 4px; }
/* Mismas esquinas y misma sombra que las tarjetas .kpi del tablero: son la
   misma pieza y antes una salia redondeada y la otra cuadrada en la misma
   pantalla. El radio y la sombra se toman de los tokens, no se repiten. */
.rep-tile {
  background: var(--rep-navy2); color: #fff; border-radius: 10px; padding: 10px 8px 9px;
  text-align: center; border-top: 3px solid var(--rep-oro); box-shadow: var(--sombra-1);
}
.rep-tile.cumple  { border-top-color: var(--verde); }
.rep-tile.falla   { border-top-color: var(--rojo); }
.rep-tile.sindato { border-top-color: var(--gris-medio); }
.rep-tile-id  { font-size: 9px; letter-spacing: 1px; color: var(--rep-oro); font-weight: bold; }
.rep-tile-val { font-size: 25px; font-weight: bold; line-height: 1.1; margin: 1px 0 2px; }
.rep-tile-nom { font-size: 9px; text-transform: uppercase; letter-spacing: .3px; color: var(--rep-tenue); min-height: 24px; }
.rep-tile-pie { font-size: 9px; color: #fff; margin-top: 4px; border-top: 1px solid rgba(255,255,255,.22); padding-top: 4px; }

/* ── Títulos de bloque y tablas ── */
.rep-h2 {
  background: var(--rep-navy); color: #fff; font-size: 11px; font-weight: bold;
  text-transform: uppercase; letter-spacing: .8px; padding: 5px 20px; margin: 14px 0 0;
}
.rep-tabla { width: 100%; border-collapse: collapse; font-size: 10px; }
.rep-tabla thead th {
  background: var(--rep-navy2); color: #fff; font-size: 9px; text-transform: uppercase;
  letter-spacing: .4px; padding: 6px 8px; text-align: left; border-bottom: 2px solid var(--rep-oro);
}
.rep-tabla td { padding: 5px 8px; border-bottom: 1px solid var(--gris-borde); vertical-align: top; }
.rep-tabla tbody tr:nth-child(even) td { background: var(--rep-fila); }
.rep-tabla .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rep-tabla .prin { font-weight: bold; color: var(--rep-navy); }
.rep-tabla .formula { color: var(--texto-suave); font-size: 9px; }
.rep-chip {
  display: inline-block; border-radius: 3px; padding: 2px 7px; font-size: 9px;
  font-weight: bold; text-transform: uppercase; letter-spacing: .3px; white-space: nowrap;
}
.rep-chip.ok  { background: var(--rep-ok-f);  color: var(--rep-ok-t); }
.rep-chip.med { background: var(--rep-med-f); color: var(--rep-med-t); }
.rep-chip.mal { background: var(--rep-mal-f); color: var(--rep-mal-t); }
.rep-chip.nd  { background: var(--rep-nd-f);  color: var(--rep-nd-t); }
/* Celda del desglose: el color dice de un vistazo si ese mes llegó a la meta. */
.rep-cel-ok  { background: var(--rep-ok-f)  !important; color: var(--rep-ok-t);  font-weight: bold; }
.rep-cel-mal { background: var(--rep-mal-f) !important; color: var(--rep-mal-t); font-weight: bold; }
.rep-cel-nd  { background: var(--rep-nd-f)  !important; color: var(--rep-nd-t); }

.rep-pie {
  background: var(--rep-navy); color: var(--rep-tenue); font-size: 9.5px;
  padding: 7px 20px; display: flex; justify-content: space-between;
}

/* ── La hoja impresa ───────────────────────────────────────────────────────
   Se esconde todo menos el reporte con visibility y no con display: display
   reflowea el documento entero y en Chrome deja la primera pagina en blanco.
   Las tablas se parten entre paginas, pero nunca por la mitad de una fila. */
@media print {
  @page { size: A4 landscape; margin: 9mm; }
  body * { visibility: hidden !important; }
  #reporteKpi, #reporteKpi * { visibility: visible !important; }

  /* Los contenedores del dialogo tienen que dejar de ser dialogo. El modal es
     position: fixed y el lienzo lleva overflow: auto con alto maximo: si se
     dejan asi, lo que se imprime es UNA pagina con el trozo que estaba a la
     vista y el resto recortado, que es el error clasico de imprimir desde un
     modal. Volviendolos estaticos y sin recorte, el reporte se pagina entero. */
  #modal-reporte, #modal-reporte .modal-caja.reporte, .rep-lienzo {
    position: static !important; display: block !important;
    overflow: visible !important; max-height: none !important; max-width: none !important;
    padding: 0 !important; margin: 0 !important; border: 0 !important;
    background: none !important; box-shadow: none !important;
  }
  /* La barra de botones y el aviso son de la pantalla, no del documento. Se
     sacan del flujo ademas de esconderse: con visibility igual ocupan lugar. */
  .rep-barra, .rep-aviso { display: none !important; }

  /* Fuera del flujo y pegado al borde: todo lo demas de la pagina sigue
     ocupando su lugar aunque este invisible, y sin esto el reporte arrancaria
     varias paginas mas abajo, en blanco. Al no quedar ningun ancestro
     posicionado, se ubica contra la pagina. */
  #reporteKpi { position: absolute; left: 0; top: 0; width: 100%; }
  .rep { width: 100%; box-shadow: none; }
  .rep-tabla tr, .rep-tile { break-inside: avoid; }
  .rep-h2 { break-after: avoid; }
  /* Los fondos de color SON el reporte: sin esto Chrome los descarta y sale en
     blanco y negro. El usuario igual tiene que dejar "Graficos de fondo"
     marcado en el dialogo, asi que la vista previa lo recuerda. */
  .rep, .rep * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ── La pestana Prioridades de entrega ──
   Reusa las clases .rep-* del reporte de gerencia: es el mismo informe, con
   el mismo formato, y tenerlo dos veces escrito terminaria con dos azules
   distintos. Lo propio es el ancho -el reporte de los KPI mide una hoja A4
   porque se imprime; este se mira en pantalla y usa lo que haya-, que la tabla
   no recorta el nombre del proyecto, y lo que viene abajo. */
#prioInforme .rep.rep-ancho { width: 100%; max-width: none; }
/* La letra de la tabla es la MISMA que la de la matriz del Resumen -13 px-, y
   desde el 08/10/2026 el ENCABEZADO tambien: los titulos de columna iban a
   10,5 y se leian como letra chica encima de un cuerpo de 13. La pildora del
   estado sube igual: a 9 px quedaba perdida al lado de un renglon de 13. */
#prioInforme .rep-tabla { font-size: 13px; }
#prioInforme .rep-tabla td { padding: 7px 10px; }
#prioInforme .rep-tabla thead th { padding: 8px 10px; font-size: 13px; }
#prioInforme .rep-chip { font-size: 10.5px; padding: 2px 9px; }

/* La celda del anillo no lleva el relleno de las demas: el dibujo ya trae su
   propio aire y, sumados, la fila quedaba el doble de alta. */
#prioInforme .rep-tabla td.av { padding: 1px 10px; }

/* Todas las columnas van CENTRADAS menos el nombre del proyecto, que es texto
   largo y se lee desde la izquierda (08/10/2026). Antes convivian tres
   alineaciones -la OT a la izquierda, la fecha y los dias a la derecha, el
   estado al medio- y la columna de la OT ni siquiera era pareja consigo misma:
   la que se completa desde el tablero cae a la derecha y las demas a la
   izquierda. Se centra desde aca y no sacandole la clase .num a cada celda,
   porque esa clase ademas da las cifras de ancho fijo, que si hacen falta. */
#prioInforme .rep-tabla th,
#prioInforme .rep-tabla td { text-align: center; }
#prioInforme .rep-tabla th.proy,
#prioInforme .rep-tabla td.proy { text-align: left; }

/* La OT va PEGADA al nombre, en su insignia, como en la matriz y en la columna
   de Publicaciones: "OT 1025  FIEFRE - NAVE GRANALLADORA". El conjunto es el
   enlace al detalle del proyecto. */
#prioInforme .rep-tabla .ot {
  color: var(--azul-nombre); font-weight: bold; font-variant-numeric: tabular-nums;
  margin-right: 6px;
}
/* La OT que no esta en la planilla de Gerencia y si en la del area. Se marca
   con el punteado de "esto no sale de aca", no con un color: un numero en otro
   color se lee como una alarma, y no lo es. */
#prioInforme .rep-tabla .ot.prestada {
  text-decoration: underline dotted var(--azul-claro); text-underline-offset: 3px; cursor: help;
}
#prioInforme .rep-tabla .proy-link { color: var(--azul-nombre); font-weight: 600; }
#prioInforme .rep-tabla .proy-link:hover { color: var(--azul); }

/* ── Esquinas redondas, como el resto del tablero ─────────────────────
   Era la unica pieza con los cantos rectos: la hoja del informe nacio como una
   A4 para imprimir -ahi los angulos rectos estan bien- y esta pestania la
   reuso tal cual. En pantalla, al lado de tarjetas, filtros y botones
   redondeados, cantaba.

   El informe de Gerencia NO se toca: ese si se imprime, y va por su propio
   .rep sin este bloque. */
/* Sin overflow:hidden a proposito. Recortarlo redondearia las esquinas igual,
   pero una tabla que no entrara se cortaria sin que nadie pueda llegar a la
   ultima columna. No hace falta: la banda del titulo y la tabla van metidas
   20 px, asi que ningun hijo toca los cantos de la hoja. */
#prioInforme .rep { border-radius: var(--radio); }
/* La tabla se mete para adentro los mismos 20 px que ya tienen las tarjetas de
   arriba, asi las dos piezas quedan alineadas y las esquinas redondas del
   encabezado se ven contra el blanco de la hoja. */
/* Y NO SE ESTIRA MAS ALLA DE SU CONTENIDO (27/10/2026). Con el ancho clavado
   en calc(100% - 40px), en una pantalla ancha el sobrante se repartia entre las
   seis columnas y quedaban cuatro columnas de numeros separadas por
   centimetros de nada: para saber a que proyecto pertenecia el estado habia que
   recorrer la fila con el dedo. Ahora cada columna mide lo que mide su
   contenido y el aire sobrante queda DESPUES de la ultima, que es donde no
   molesta. El min-width evita el otro extremo -una tabla angosta perdida debajo
   de una fila de tarjetas que si ocupa todo- y el max-width deja que en una
   pantalla chica vuelva a aparecer el desplazamiento horizontal de siempre.

   Y VA CENTRADA (27/10/2026): el margin:auto reparte el sobrante a los dos
   lados. Pegada a la izquierda, debajo de una fila de tarjetas que si ocupa
   todo el ancho, se leia como si la pantalla se hubiera cortado. Con el
   max-width, cuando la tabla ocupa todo lo que puede ese auto son los mismos
   20 px de antes, asi que sigue alineada con las tarjetas. */
#prioInforme .rep-tabla {
  width: auto; min-width: min(calc(100% - 40px), 1180px); max-width: calc(100% - 40px);
  margin: 4px auto 20px;
}
#prioInforme .rep-tabla thead th:first-child { border-top-left-radius: 10px; border-bottom-left-radius: 10px; }
#prioInforme .rep-tabla thead th:last-child { border-top-right-radius: 10px; border-bottom-right-radius: 10px; }

/* ── Lo que pidio Fiefre el 08/10/2026 ───────────────────────────────────
   Nada de dorado y todo el texto en blanco sobre el azul. Va TODO acotado a
   #prioInforme y no se tocan las clases .rep-* de arriba: las comparte el
   reporte de Gerencia -que si lleva el dorado y la banda del periodo- y
   cambiarlas alla seria cambiar dos informes de una. */

/* Las tarjetas y el boton en la misma linea. Pasa de grilla a flex porque
   ahora la fila tiene un elemento que NO es una tarjeta y no tiene que medir
   lo mismo que ellas. */
#prioInforme .rep-tiles { display: flex; align-items: stretch; padding: 14px 20px; }
#prioInforme .rep-tile { flex: 1 1 0; min-width: 0; }

/* ══ Y EN EL TELEFONO, QUE NO SE ACHIQUEN HASTA DESAPARECER (08/11/2026) ══

   `flex: 1 1 0` con `min-width: 0` es justamente la receta para que las seis
   tarjetas queden de 25 px en 375 px de pantalla, con el titulo partido a una
   letra por renglon: «N° / PRO», «SIN / FEC». Medido en la pagina real.

   VA ACA ABAJO Y NO CON LAS OTRAS REGLAS DE TELEFONO, y es a proposito: la
   linea de arriba tiene la misma especificidad que estas, asi que gana la que
   va DESPUES en el archivo. Puesto mas arriba -que es donde lo escribi la
   primera vez- el bloque entero no hacia nada y las tarjetas seguian en 25 px.
   Un @media no agrega especificidad. */
@media (max-width: 760px) {
  #prioInforme .rep-tiles { flex-wrap: wrap; }
  /* 132 px de base: en 334 entran dos por renglon, en una tablet tres o
     cuatro. `1 1` para que repartan el sobrante y no queden desparejas. */
  #prioInforme .rep-tile { flex: 1 1 132px; }
  /* El boton de bajar el Excel se llevaba una columna al lado de las
     tarjetas. En renglon propio, de lado a lado, que es donde se toca. */
  #prioInforme .rep-bajar { flex: 1 0 100%; }
}
/* El filo de arriba era dorado. En blanco sigue separando la tarjeta del
   fondo; el verde y el rojo quedan, que ahi el color ES el dato. */
#prioInforme .rep-tile { border-top-color: #fff; }
#prioInforme .rep-tile-id { color: #fff; }

/* El boton: mismo cuerpo que una tarjeta -azul y texto blanco- para que la
   fila se lea como una sola pieza. Antes era blanco con letra azul, dentro
   de la banda del encabezado que ya no existe. */
#prioInforme .rep-bajar {
  flex: 0 0 auto; align-self: stretch; white-space: nowrap; cursor: pointer;
  background: var(--rep-navy); color: #fff; font: inherit; font-size: 12px; font-weight: bold;
  border: 1px solid rgba(255,255,255,.55); border-radius: 10px; padding: 0 18px;
  box-shadow: var(--sombra-1); transition: background var(--transicion);
}
#prioInforme .rep-bajar:hover { background: var(--azul-nombre); }
#prioInforme .rep-bajar:focus-visible { outline: 2px solid var(--azul-claro); outline-offset: 2px; }

/* El titulo bajo a quedar pegado a la tabla: arriba ya estan las tarjetas,
   que son lo primero que se mira. El periodo lo acompana a la derecha. */
/* Hubo una banda azul con el titulo "PRIORIDADES DE ENTREGA" entre las
   tarjetas y la tabla. Se retiro el 08/10/2026: lo dice la pestania desde la
   que se llega. Con ella se fueron su periodo y su centrado. */

/* Las tarjetas se miden contra la tabla que tienen debajo: el rotulo y el pie
   iban a 9 px sobre un cuerpo de tabla de 13, y se leian como letra al margen.
   A 11 px acompanian al numero sin competir con el. */
#prioInforme .rep-tile-id { font-size: 11px; letter-spacing: .6px; }
#prioInforme .rep-tile-pie { font-size: 11px; }

/* El filo dorado de abajo del encabezado de la tabla, en blanco. */
#prioInforme .rep-tabla thead th { border-bottom-color: rgba(255,255,255,.55); }
/* El pie iba en el azul palido de --rep-tenue. */
#prioInforme .rep-pie { color: #fff; }

/* ── Los dos graficos del reporte ──
   Marcas finas y ejes recesivos: en un informe el dato es el numero, la tinta
   esta para ordenarlo. Los colores salen de los acentos del tablero; el par
   verde/rojo de la variacion esta validado para daltonismo (deltaE 16,2 en
   deuteranopia), pero ademas el signo lo dice la POSICION respecto del cero y
   cada barra lleva su numero escrito, asi que se lee igual en blanco y negro. */
.rep-graf { padding: 14px 20px 6px; }
.rep-graf-tit {
  font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: .5px;
  color: var(--rep-navy); margin-bottom: 8px;
}
.rep-graf-tit span {
  display: block; font-weight: normal; text-transform: none; letter-spacing: 0;
  font-size: 10px; color: var(--texto-suave); margin-top: 1px;
}
.rep-graf-grilla { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
.rep-graf-chico { border: 1px solid var(--gris-borde); border-radius: 10px; padding: 6px 8px 2px; }
.rep-graf-sub {
  font-size: 9px; font-weight: bold; letter-spacing: .5px; color: var(--texto-suave);
  display: flex; justify-content: space-between; align-items: baseline;
}
.rep-graf-sub b { font-size: 12px; color: var(--rep-navy); }
.g-nodata { font-size: 9.5px; color: var(--texto-suave); padding: 30px 0; text-align: center; }

/* Texto del grafico: siempre tinta de texto, nunca el color de la marca. */
.rep-graf text { font-family: inherit; }
.g-id   { font-size: 11px; font-weight: bold; fill: var(--rep-navy); }
.g-sub  { font-size: 9.5px; fill: var(--texto-suave); }
.g-val  { font-size: 11px; font-weight: bold; fill: var(--texto); }
.g-nd   { font-size: 10px; fill: var(--texto-suave); }
.g-tick { font-size: 8.5px; fill: var(--texto-suave); }
.g-meta-t { font-size: 8px; fill: var(--texto-suave); }

.g-cero { stroke: var(--gris-medio); stroke-width: 1; }
.g-eje  { stroke: var(--gris-borde); stroke-width: 1; }
.g-meta { stroke: var(--gris-medio); stroke-width: 1; stroke-dasharray: 3 3; }
/* Las dos barras de la variacion: el periodo anterior recesivo y el actual en
   el azul fuerte, el mismo de la linea del acumulado. Son dos VALORES, no una
   polaridad: quien dice si mejoro o empeoro es el numero del encabezado. */
.g-antes { fill: var(--azul-claro); }
.g-ahora { fill: var(--azul-nombre); }
/* La variacion del encabezado. Lleva flecha y signo ademas del color, asi que
   no depende de distinguir verde de rojo. */
.rep-graf-sub b.g-dsube  { color: var(--verde-hondo); }
.rep-graf-sub b.g-dbaja  { color: var(--rojo-hondo); }
.rep-graf-sub b.g-digual { color: var(--texto-suave); font-size: 10px; }
.rep-graf-sub b.g-dnd    { color: var(--texto-suave); font-size: 10px; }
.g-linea{ fill: none; stroke: var(--azul-nombre); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.g-punto{ fill: var(--azul-nombre); stroke: #fff; stroke-width: 1.5; }

/* Al imprimir, cada grafico entero en una pagina y no partido al medio. */
@media print {
  .rep-graf, .rep-graf-chico { break-inside: avoid; }
}



/* ═══════════ Carta Gantt: el programa .mpp dibujado ═══════════════════════
   El boton de la tarjeta y el visor. Toma los mismos tokens que el resto del
   tablero; lo unico propio es la tabla, que imita el esquema de Project:
   sangria por nivel, flecha en las fases y la barra de avance al final. */

/* En la tarjeta: boton con la misma forma que el enlace de al lado, para que
   la fila se lea pareja aunque uno abra el visor y el otro el documento. */
.pcard-sp .gantt-ver {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  font-size: 11px; font-weight: bold; letter-spacing: .3px; text-transform: uppercase;
  color: var(--azul-nombre); font-family: inherit; cursor: pointer;
  background: var(--azul-tinte); border: 1px solid var(--azul-tinte-2);
  border-radius: 20px; padding: 2px 9px; transition: background var(--transicion);
}
.pcard-sp .gantt-ver:hover { background: var(--azul-tinte-2); text-decoration: underline; }
.pcard-sp .gantt-ver .tx { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcard-sp .gantt-pct {
  font-size: 11px; font-weight: bold; letter-spacing: .3px; line-height: 1.5;
  color: var(--azul-nombre); background: var(--azul-tinte);
  border-radius: 20px; padding: 1px 7px;
}
.pcard-sp .gantt-doc { font-size: 11px; padding: 2px 6px; }

/* LAS DOS PILDORAS DE LA TARJETA MIDEN LO MISMO (27/10/2026). Carta Gantt y
   Tablas de cubicaciones van una debajo de la otra: con textos de largo
   distinto quedaban de anchos distintos y se leia como un error de
   alineacion. El ancho lo manda la mas larga -«Tablas de cubicaciones»-, y
   las insignias de % tambien se igualan para que las dos filas corten
   parejas. Si manana cambia alguno de los dos textos, hay que volver a medir. */
.pcard-sp a, .pcard-sp .gantt-ver { min-width: 140px; justify-content: center; line-height: 1.5; }
.pcard-sp .sp-pct, .pcard-sp .gantt-pct { min-width: 52px; text-align: center; }

/* El visor. Mas ancho que los demas dialogos: son cinco columnas y nombres
   largos, y leerlos en una caja angosta obliga a cortar lo que importa. */
.modal-caja.gantt-caja { max-width: 1100px; width: 94vw; }
.gantt-barra {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 4px 0 10px;
}
/* Los datos del programa, uno por tarjetita. Mismo azul de la cabecera de la
   tabla pero en claro, para que se lean como parte de ella y no compitan con
   los números de las filas. */
.gantt-meta { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.g-chip {
  display: inline-block; background: var(--azul-tinte-2); color: var(--azul-nombre);
  border: 1px solid color-mix(in srgb, var(--azul-medio) 35%, transparent);
  border-radius: 20px; padding: 3px 11px; font-size: 11px; font-weight: 600;
  white-space: nowrap;
}
.g-chip b { font-size: 12px; font-weight: bold; }
.gantt-wrap { max-height: 62vh; overflow: auto; border: 1px solid var(--borde); border-radius: 8px; }

.g-tabla { width: 100%; border-collapse: collapse; font-size: 12px; }
.g-tabla th {
  position: sticky; top: 0; z-index: 2; background: var(--azul-medio); color: #fff;
  font-size: 10px; text-transform: uppercase; letter-spacing: .4px;
  padding: 7px 9px; text-align: right; white-space: nowrap;
}
.g-tabla th.g-nom { text-align: left; }
.g-tabla td {
  padding: 5px 9px; border-bottom: 1px solid var(--borde); text-align: right;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.g-tabla td.g-nom { text-align: left; white-space: normal; min-width: 320px; }
.g-tabla tr:last-child td { border-bottom: none; }
.g-tabla tbody tr:hover td { background: var(--azul-tinte); }
/* Las fases, en negrita y con fondo propio: es el esqueleto del programa. */
.g-tabla tr.g-res td { background: var(--gris-suave); font-weight: bold; }
/* Los hitos no llevan marca propia (27/10/2026): acá estaban su color y su
   rombo. Una fila es una fila. */
.g-tog {
  display: inline-block; width: 15px; margin-right: 3px; padding: 0;
  background: none; border: none; cursor: pointer; color: var(--azul-medio);
  font-size: 10px; line-height: 1; font-family: inherit;
}
.g-tog.vacia { cursor: default; }
.g-pista {
  display: inline-block; width: 70px; height: 7px; border-radius: 4px;
  background: var(--gris-suave); overflow: hidden; vertical-align: middle; margin-right: 7px;
}
.g-pista i { display: block; height: 100%; background: var(--azul-medio); border-radius: 4px; }
.g-tabla td.g-p b { min-width: 34px; display: inline-block; text-align: right; }


/* La linea del archivo, dentro de la tarjeta en «Proyectos historicos»: cuando
   se entrego, hace cuanto y como llego. Es lo que daba la tabla que habia
   antes en esa pestana. Discreta a proposito: en el archivo lo que se viene a
   mirar es el proyecto, no cuando entro. */
.pcard-archivo {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  flex-wrap: wrap; font-size: 11px; color: var(--gris-texto);
  background: var(--gris-suave); border-radius: 8px; padding: 4px 10px;
}
.pcard-archivo b { color: var(--texto); font-weight: bold; }
.pcard-archivo .como {
  font-size: 10px; text-transform: uppercase; letter-spacing: .4px; opacity: .75;
}

/* ── ¿Los avisos de mención llegan de verdad? (Usuarios, 07/11/2026) ─────
   Dos renglones, uno por canal, con su chapa de activo/apagado. Es una lista
   de dos elementos: no merece una tabla. */
.lista-avisos { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 6px; }
.lista-avisos li { font-size: 12.5px; color: var(--texto); line-height: 1.5; }
.lista-avisos .etiqueta { margin-right: 6px; }
.modal-nota .mal { color: var(--rojo-hondo); }
