/* ============================================================================
   Radar de Fiscalización — hoja de estilos del panel

   Versión en blanco con la marca nueva del Colegio (CIPBA, 2026). Dos
   colores salen del logo y mandan sobre todo lo demás:

     · el verde CIPBA  #00a48a  — la identidad. Vive en el isotipo, en el
       botón principal, en los rieles y en todo lo que quiere decir "hecho".
     · el petróleo     #14484a  — el color del texto. Todo lo que se lee va
       en petróleo o en un gris verdoso que sale de él, nunca en negro puro.

   Sobre blanco, el verde de marca da 3,2:1: alcanza para cifras grandes y
   para el fondo de un botón con letra gorda, no para texto chico. Por eso
   hay un verde para texto (#007a67, 5,3:1) y uno para botones (#008571,
   4,6:1). El de marca queda para lo que se mira, no para lo que se lee.

   Tres reglas ordenan lo de abajo:

   1. Una superficie por idea. Las tarjetas son blancas sobre blanco, y lo que
      las separa es la sombra, no el color de fondo: una sombra corta para lo
      que está apoyado (tarjetas, pistas) y una larga para lo que flota
      (menús, modales, la ficha).
   2. El radio dice qué tan estable es una cosa. 16px en las superficies que
      quedan, 14px en los bloques de adentro, 11px en los controles, redondo
      del todo solo en las pastillas.
   3. El color semántico no es el color de marca. Lo urgente es coral, lo que
      espera es ámbar, lo que no se miró es azul, lo vigilado es violeta. El
      verde quiere decir resuelto. Si todo lo importante es verde, el verde
      deja de significar algo.

   El movimiento es corto y frena en seco: la interfaz tiene que sentirse con
   peso, no rebotar. La única excepción es la entrada del radar (intro.js),
   que dura tres segundos y se puede saltar con un click.
   ============================================================================ */

/* --- tipografías ---------------------------------------------------------
   Servidas desde el repo por la misma razón que Leaflet: si la red del
   Colegio bloquea Google Fonts, el panel no puede caerse a Arial.

   Archivo es de Omnibus-Type, una fundición de Buenos Aires. No es un guiño:
   es una variable con eje de ancho, así que el mismo archivo da la tipografía
   de interfaz y la condensada de los rótulos técnicos, sin una segunda
   descarga. IBM Plex Mono queda para los números, que es donde el ancho fijo
   de dígito hace falta de verdad. */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/static/vendor/tipografias/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/static/vendor/tipografias/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/vendor/tipografias/plex-mono-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/vendor/tipografias/plex-mono-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --- fichas de color ------------------------------------------------------ */

:root {
  /* El panel es claro: los controles nativos (select, date) se dibujan claros. */
  color-scheme: light;

  /* La marca, tal cual sale del logo. */
  --verde: #00a48a;
  --petroleo: #14484a;

  /* Blanco sobre blanco. Las superficies son blancas y lo que las separa es
     la sombra; los pocos grises que hay tienen una pizca de verde adentro,
     para que no se vean sucios al lado de la marca. */
  --fondo: #ffffff;
  --fondo-2: #f4f8f7;
  --superficie: #ffffff;
  --superficie-2: #eef5f3;

  --linea-suave: #e8f0ee;
  --linea: #d5e3e0;
  --linea-fuerte: #b3cbc6;
  /* El borde de lo que se completa (campos, buscador, filtros): 3:1 contra el
     blanco, lo mínimo para que un campo vacío se vea como campo. */
  --linea-control: #759690;

  /* Texto: petróleo y tres grises que salen de él. Los tres primeros pasan el
     contraste mínimo para texto (4,5:1) también sobre las superficies teñidas
     (--superficie-2, --verde-tenue), no solo sobre blanco; el cuarto es solo
     para líneas, puntos y rieles, nunca para palabras. */
  --texto: #14484a;
  --texto-2: #3f6b6a;
  --texto-3: #4c6f6d;
  --texto-4: #a7c0bc;

  /* El verde, en tres pesos. */
  --verde-texto: #007a67;    /* 5,3:1 sobre blanco: para texto chico */
  --verde-boton: #008571;    /* 4,6:1 con letra blanca: el botón principal */
  --verde-boton-hover: #00735f;
  --verde-linea: #a9e0d4;    /* el borde de una pastilla verde */
  --verde-tenue: #e6f6f2;    /* el fondo de una pastilla verde */
  --verde-brillo: rgba(0, 164, 138, .14);
  --seleccion: #bfeee3;
  --sobre-verde: #ffffff;

  /* Semánticos. Separados del verde a propósito. */
  --critico: #c2410c;
  --critico-linea: #f5c6b1;
  --critico-tenue: #fff1ea;

  --atencion: #946000;
  --atencion-linea: #f0d898;
  --atencion-tenue: #fff7e4;

  --frio: #2b57c9;
  --frio-linea: #c4d3f7;
  --frio-tenue: #edf2ff;

  --violeta: #6d3fc8;
  --violeta-linea: #dacdf6;
  --violeta-tenue: #f4efff;

  /* «Verificar visado» tiene su propio tono: el borravino de la tinta de un
     sello. Antes compartía el ámbar con la prioridad media, la apertura, lo
     histórico y los avisos, y el ámbar terminaba sin decir nada. El ámbar
     queda para lo que apura. */
  --sello: #9d2f5a;
  --sello-linea: #ebc3d3;
  --sello-tenue: #fcf0f5;

  /* El tinte de una fila de la bandeja al pasar por encima y elegida. */
  --fila-hover: #f5f9f8;
  --fila-elegida: #f3faf8;

  --tipo: "Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Las sombras llevan petróleo, no negro: un negro transparente sobre
     blanco se ve gris sucio; el petróleo se ve como una sombra de verdad. */
  --sombra-1: 0 1px 2px rgba(20, 72, 74, .05);
  --sombra-2: 0 1px 2px rgba(20, 72, 74, .05), 0 8px 20px -10px rgba(20, 72, 74, .14);
  --sombra-3: 0 12px 28px -8px rgba(20, 72, 74, .22), 0 36px 70px -24px rgba(20, 72, 74, .3);
  /* Lo que cuelga de un botón (la cuenta, el descarte, el alcance): una sombra
     corta y otra difusa, sin la caída larga de un modal. Está cerca de lo
     que lo abrió y tiene que verse así. */
  --sombra-menu: 0 2px 4px rgba(20, 72, 74, .06), 0 12px 32px -8px rgba(20, 72, 74, .22);
  /* El botón verde no brilla: un halo de color alrededor se lee como adorno.
     Lleva el canto de arriba más claro y una sombra corta, como algo que se
     aprieta. */
  --sombra-verde: inset 0 1px 0 rgba(255, 255, 255, .14), 0 1px 2px rgba(0, 92, 78, .28);

  /* El armazón: la barra lateral y el marco van en un gris verdoso apenas
     teñido, y el contenido es una hoja blanca apoyada encima. La hoja es lo
     que se trabaja; el marco no compite con ella. */
  --marco: #f2f6f5;

  /* El radio dice qué tan estable es cada objeto: cuanto más permanente,
     más redondo. Lo que aparece y desaparece es lo más cuadrado. Escalones
     cortos y distintos entre sí: con todo a 11-16px el panel parecía
     estampado de una sola matriz. */
  --r-caja: 12px;
  --r-panel: 10px;
  --r-modal: 16px;
  --r-tile: 8px;
  --r-control: 8px;
  --r-chico: 6px;
  --r-pastilla: 999px;

  /* Una sola curva para todo el panel. Arranca rápido y frena: es cómo se
     mueve algo con peso, no un rebote de sitio promocional. */
  --curva: cubic-bezier(.22, .61, .36, 1);
  --rapido: 110ms;
  --medio: 200ms;

  --lateral: 236px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--tipo);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--verde-texto); text-underline-offset: 2px; }
a:hover { color: var(--texto); }

.oculto { display: none !important; }

/* Para el lector de pantalla y nadie más: no se ve, pero sigue en el árbol de
   accesibilidad (display:none lo sacaría). Va en el h1 y en etiquetas de
   campos que ya se explican con su ícono. */
.solo-lector {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* El primer Tab de la página: salta el menú lateral y va derecho a la
   bandeja. Solo aparece con el foco. */
.saltar-al-contenido {
  position: fixed; top: 10px; left: 10px; z-index: 300;
  padding: 10px 16px;
  background: var(--petroleo); color: #fff;
  border-radius: var(--r-control);
  font-weight: 600; text-decoration: none;
  transform: translateY(-160%);
  transition: transform var(--rapido) var(--curva);
}
.saltar-al-contenido:focus-visible { transform: none; color: #fff; }
.contenido:focus { outline: none; }
.sub { color: var(--texto-3); font-size: 12px; }
.mono { font-family: var(--mono); }

::selection { background: var(--seleccion); color: var(--petroleo); }

:focus-visible {
  /* --verde-texto y no --verde: el de la marca da 2,9:1 sobre el fondo
     teñido y el anillo tiene que verse sobre cualquier superficie. */
  outline: 2px solid var(--verde-texto);
  outline-offset: 2px;
}

#hoja-iconos { position: absolute; width: 0; height: 0; overflow: hidden; }

/* --- íconos ---------------------------------------------------------------
   Un solo sprite inline: no hay pedido de red por ícono y el color lo hereda
   del texto, así que un ícono adentro de una pastilla roja sale rojo solo. */

.ico {
  width: 1em; height: 1em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: square;
  stroke-linejoin: miter;
  vertical-align: -.12em;
}

.ico.fino { stroke-width: 1.3; }
.ico.grande { width: 1.35em; height: 1.35em; }

/* El rótulo técnico: condensado, como en una carátula de plano, para decir de
   qué es el número que viene abajo sin competir con él. Iba en mayúscula con
   mucho aire entre letras, y repetido en cada métrica, tarjeta, tabla y
   acordeón era un tic de plantilla: ahora va en minúscula, y lo que lo
   separa del texto es el ancho angosto y el peso. */

.rotulo,
.dato .clave,
.marca small,
.login-caja .subtitulo,
.pista .tipo-rotulo,
.metrica .rotulo {
  font-stretch: 84%;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--texto-3);
}

/* Los títulos de pantalla van anchos: el mismo archivo de Archivo estirado
   al 112%. El rótulo angosto y el título ancho son las dos puntas del eje de
   la tipografía, y es lo que le da al panel una voz propia. */
.encabezado h2,
.panel-ficha h3,
.modal .cabecera h3,
.login-caja h1 { font-stretch: 112%; }

/* --- pantalla de entrada --------------------------------------------------
   Blanca, con el logo vertical del distrito arriba y los anillos del radar
   dibujados muy suaves de fondo: la misma imagen con la que arranca el
   panel, quieta. */

.login-pantalla {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px;
  position: relative;
  overflow: hidden;
  /* El mismo marco teñido del panel: la caja de entrada es la primera hoja
     blanca que se ve, y adentro va a seguir viéndose igual. */
  background: var(--marco);
}

/* Los anillos: cuatro círculos concéntricos, apenas visibles. */
.login-pantalla::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: min(1200px, 160vw); aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background:
    radial-gradient(circle, transparent 0 23.5%, rgba(20, 72, 74, .07) 23.5% 23.7%, transparent 23.7% 36.5%,
      rgba(20, 72, 74, .06) 36.5% 36.7%, transparent 36.7% 49.5%, rgba(20, 72, 74, .05) 49.5% 49.7%, transparent 49.7%);
  pointer-events: none;
}

.login-caja {
  position: relative;
  width: min(400px, 100%);
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-modal);
  padding: 34px 32px 30px;
  box-shadow: 0 1px 2px rgba(20, 72, 74, .05), 0 24px 48px -24px rgba(20, 72, 74, .22);
}

.login-caja h1 { font-size: 22px; font-weight: 650; margin: 0 0 4px; letter-spacing: -.03em; color: var(--petroleo); text-align: center; }
.login-caja .subtitulo { margin: 0 0 26px; text-align: center; text-wrap: balance; }

/* El logo vertical del distrito, centrado arriba de todo. */
.marca-login { display: flex; justify-content: center; margin: -4px 0 14px; }
.marca-login img { width: 128px; height: auto; display: block; }

/* --- armazón -------------------------------------------------------------- */

/* El marco teñido de fondo, la barra lateral sobre él sin borde propio, y el
   contenido como una hoja blanca con su canto y su sombra corta. Antes todo
   era blanco sobre blanco y la barra se separaba con una línea: no había
   adelante y atrás. */
.app {
  display: grid; grid-template-columns: var(--lateral) minmax(0, 1fr);
  min-height: 100vh;
  background: var(--marco);
}

aside.lateral {
  background: var(--marco);
  padding: 18px 12px 18px 14px;
  position: sticky; top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex; flex-direction: column; gap: 20px;
}

.marca { display: flex; flex-direction: column; gap: 10px; padding: 0 2px 2px; }

/* El logo del distrito, tal cual lo entrega el Colegio: no se recorta ni se
   recolorea. El archivo trae su propio aire alrededor, así que el margen
   negativo lo compensa para que el isotipo quede alineado con el resto. */
.marca .logo-cipba { display: block; width: 100%; height: auto; margin: -6px -4px -8px; max-width: 228px; }

.marca .fila-producto {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 0 0 2px;
  border-top: 1px solid var(--linea);
}

.marca .producto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.marca .producto strong { font-size: 13px; font-weight: 700; color: var(--petroleo); letter-spacing: -.01em; }
.marca .producto small { font-size: 12px; }
/* El nombre del distrito llega como va en una oración («todos los
   distritos»); solo, debajo del producto, arranca en mayúscula. */
.marca .producto small::first-letter { text-transform: uppercase; }

/* --- la cuenta ---------------------------------------------------------------
   Un círculo con las iniciales de quien mira. Es un control, así que se
   comporta como uno: se levanta al pasar y queda con un anillo mientras el
   menú está abierto. El menú cuelga del círculo y no sale de la barra: así no
   lo recorta el scroll de la barra ni tapa la bandeja. */

.cuenta { position: relative; flex: none; }

.cuenta .avatar {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  padding: 0;
  border-radius: var(--r-pastilla);
  background: var(--verde-tenue);
  border: 1px solid var(--verde-linea);
  color: var(--verde-texto);
  font: inherit; font-size: 12px; font-weight: 700;
  font-stretch: 90%;
  letter-spacing: .04em;
  cursor: pointer;
  transition: border-color var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva), transform var(--rapido) var(--curva);
}

.cuenta .avatar:hover { border-color: var(--verde); box-shadow: var(--sombra-1); transform: translateY(-1px); }
.cuenta .avatar:active { transform: none; }
.cuenta .avatar[aria-expanded="true"] { border-color: var(--verde); box-shadow: 0 0 0 3px var(--verde-brillo); transform: none; }

.menu-cuenta {
  /* Del mismo ancho que «Cargar pista», que queda justo debajo. */
  position: absolute; top: calc(100% + 8px); right: -3px;
  z-index: 30;
  width: 208px;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-panel);
  padding: 4px;
  box-shadow: var(--sombra-menu);
  transform-origin: top right;
  animation: entrar-menu 140ms var(--curva) both;
}

.menu-cuenta .quien {
  display: flex; flex-direction: column; gap: 8px;
  padding: 8px 8px 12px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--linea-suave);
}

.menu-cuenta .quien strong {
  display: block;
  font-size: 14px; font-weight: 600; line-height: 1.3;
  color: var(--petroleo);
  overflow-wrap: anywhere;
}

.menu-cuenta .quien .usuario { display: block; margin-top: 1px; font-size: 12px; color: var(--texto-3); overflow-wrap: anywhere; }
.menu-cuenta .quien .chips { display: flex; flex-wrap: wrap; gap: 5px; }
.menu-cuenta .quien .rol-chip { margin-left: 0; }

.opcion-cuenta {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  min-height: 34px;
  background: none; border: none;
  border-radius: var(--r-chico);
  padding: 7px 10px;
  color: var(--texto-2);
  font: inherit; font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

.opcion-cuenta .ico { width: 15px; height: 15px; color: var(--texto-3); transition: color var(--rapido) var(--curva); }
.opcion-cuenta:hover, .opcion-cuenta:focus-visible { background: var(--fondo-2); color: var(--petroleo); }
.opcion-cuenta:focus-visible { outline-offset: -2px; }
.opcion-cuenta:hover .ico { color: var(--texto-2); }

/* El indicador de carga: una línea verde que barre el borde superior de la
   pantalla mientras hay un pedido en vuelo. Es el único indicador de carga
   del panel. */
body.cargando::after {
  content: "";
  position: fixed; top: 0; left: 0;
  z-index: 100;
  height: 3px; width: 38vw;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(90deg, transparent, var(--verde) 40%, var(--verde));
  animation: barrido 900ms var(--curva) infinite;
}

@keyframes barrido {
  from { transform: translateX(-100%); }
  to { transform: translateX(290vw); }
}


/* El alta de pista no es una sección: es la acción que más se repite, así que
   vive arriba de todo y abre un modal sobre lo que estés mirando. */
.boton-alta {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%;
  background: var(--verde-boton);
  border: none;
  border-radius: var(--r-control);
  color: var(--sobre-verde);
  padding: 10px 12px;
  font: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer;
  box-shadow: var(--sombra-verde);
  transition: background var(--rapido) var(--curva), transform var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva);
}

.boton-alta:hover { background: var(--verde-boton-hover); }
.boton-alta:active { transform: translateY(0); box-shadow: none; }
.boton-alta .ico { width: 14px; height: 14px; }

nav.secciones { display: flex; flex-direction: column; gap: 3px; }

nav.secciones button {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  background: none;
  border: none;
  border-radius: var(--r-control);
  padding: 8px 10px;
  color: var(--texto-2);
  font: inherit; font-size: 13.5px;
  text-align: left;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

nav.secciones button .ico { width: 15px; height: 15px; color: var(--texto-3); transition: color var(--rapido) var(--curva); }
nav.secciones button:hover { background: rgba(20, 72, 74, .05); color: var(--texto); }
nav.secciones button:active { background: rgba(20, 72, 74, .09); }
nav.secciones button:hover .ico { color: var(--texto-2); }

/* La sección elegida es un pedazo de la hoja blanca asomado en el marco:
   blanco, con canto y sombra corta, igual que la hoja de la derecha. */
nav.secciones button.activo {
  background: var(--superficie);
  box-shadow: 0 0 0 1px var(--linea), var(--sombra-1);
  color: var(--petroleo);
  font-weight: 600;
}

nav.secciones button.activo .ico { color: var(--verde-texto); }

nav.secciones button .contador {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}

nav.secciones button.activo .contador { color: var(--verde-texto); }

/* --- vigiladas --------------------------------------------------------------
   Lo que se dejó mirando hasta que avance. Va en violeta porque es el color
   de lo vigilado en todo el panel (la métrica, la etiqueta de la tarjeta), y
   el violeta está solo en las marcas: el texto sigue en petróleo. Cada obra
   ocupa dos renglones de título y uno de dato; el nombre completo queda en
   el title y en la ficha. */

.vigiladas { border-top: 1px solid var(--linea); padding-top: 16px; }
.vigiladas:empty { display: none; }

.vigiladas .rotulo {
  display: flex; align-items: center; gap: 7px;
  margin: 0 0 8px; padding: 0 2px 0 10px;
}

.vigiladas .rotulo .ico { width: 14px; height: 14px; color: var(--violeta); }

.vigiladas .total-vigiladas {
  margin-left: auto;
  min-width: 22px;
  padding: 1px 7px;
  border-radius: var(--r-pastilla);
  background: var(--violeta-tenue);
  color: var(--violeta);
  font-family: var(--mono); font-size: 12px; font-stretch: 100%;
  letter-spacing: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.lista-vigiladas { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }

.atajo-vigilada {
  position: relative;
  display: flex; flex-direction: column; gap: 2px;
  width: 100%;
  text-align: left;
  background: none; border: none;
  border-radius: var(--r-chico);
  padding: 8px 10px 8px 26px;
  color: var(--texto-2);
  font: inherit;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

/* El punto violeta, a la altura del primer renglón del título. Al pasar se
   enciende con un halo: es la única pista de que la fila se abre. */
.atajo-vigilada::before {
  content: "";
  position: absolute; left: 11px; top: 15px;
  width: 6px; height: 6px;
  border-radius: var(--r-pastilla);
  background: var(--violeta);
  opacity: .55;
  transition: opacity var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva);
}

.atajo-vigilada:hover { background: var(--violeta-tenue); color: var(--texto); }
.atajo-vigilada:hover::before { opacity: 1; box-shadow: 0 0 0 3px var(--violeta-linea); }

.atajo-vigilada .titulo-vigilada {
  font-size: 13px; line-height: 1.38;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  text-wrap: pretty;
}

.atajo-vigilada .dato-vigilada {
  font-size: 12px; line-height: 1.35;
  color: var(--texto-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.atajo-vigilada .dato-vigilada .parte { color: var(--violeta); font-weight: 600; }

.ver-vigiladas {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 6px 0 0 16px;
  padding: 6px 10px;
  background: none; border: none;
  border-radius: var(--r-chico);
  color: var(--violeta);
  font: inherit; font-size: 12px; font-weight: 600;
  cursor: pointer;
  transition: background var(--rapido) var(--curva);
}

.ver-vigiladas .ico { width: 12px; height: 12px; transform: rotate(180deg); transition: transform var(--rapido) var(--curva); }
.ver-vigiladas:hover { background: var(--violeta-tenue); }
.ver-vigiladas:hover .ico { transform: rotate(180deg) translateX(-2px); }

.boton-icono {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  flex: none;
  background: none;
  border: 1px solid var(--linea-suave);
  border-radius: var(--r-chico);
  color: var(--texto-3);
  cursor: pointer;
  transition: border-color var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

.boton-icono:hover { border-color: var(--linea-fuerte); background: var(--fondo-2); color: var(--petroleo); }
.boton-icono:active { background: var(--superficie-2); }
.boton-icono .ico { width: 14px; height: 14px; }

/* --- contenido ------------------------------------------------------------ */

.contenido {
  min-width: 0;
  margin: 8px 8px 8px 0;
  padding: 32px clamp(20px, 3.2vw, 44px) 80px;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-caja);
  box-shadow: 0 1px 2px rgba(20, 72, 74, .04), 0 4px 16px -6px rgba(20, 72, 74, .06);
}

/* Lo de adentro de la hoja no se estira de punta a punta en un monitor
   ancho: las filas de la bandeja se vuelven ilegibles pasando los 1200px. */
.contenido > * { max-width: 1180px; margin-inline: auto; }

.encabezado { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; margin-bottom: 24px; }
.encabezado h2 { font-size: 28px; line-height: 1.1; margin: 0; letter-spacing: -.035em; font-weight: 650; color: var(--petroleo); }
.encabezado .sub { margin: 6px 0 0; font-size: 13px; max-width: 640px; color: var(--texto-2); }
.encabezado .espaciador { flex: 1; }

.contenido section:not(.oculto) { animation: entrar-vista 240ms var(--curva) both; }

/* El fantasma de lo que se cierra (movimiento.js): una copia inerte que se va
   mientras el original ya está cerrado. No repite las entradas de lo que
   tiene adentro, no se toca, y queda un escalón debajo de su original, así
   una ficha que se abre enseguida no aparece detrás de la que se va. */
.fantasma, .fantasma * { animation: none !important; pointer-events: none !important; }
.fantasma .velo, .fantasma .panel-ficha { z-index: 39; }
.fantasma .velo-modal { z-index: 49; }

@keyframes entrar-vista {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* --- la pastilla que viaja -------------------------------------------------
   En el menú, las pestañas y lista/mapa la opción elegida no se pinta sola: hay
   una pastilla detrás de los botones que se desliza hasta la nueva
   (movimiento.js). Sin JS, o antes de que se ubique, manda el fondo de
   .activo de siempre: .con-indicador lo apaga recién cuando la pastilla está. */
.con-indicador { position: relative; }
.con-indicador > button { position: relative; z-index: 1; }
.indicador {
  position: absolute; top: 0; left: 0; z-index: 0;
  pointer-events: none;
  opacity: 0;
}
nav.secciones > .indicador { background: var(--superficie); border-radius: var(--r-control); box-shadow: 0 0 0 1px var(--linea), var(--sombra-1); }
nav.secciones.con-indicador button.activo,
nav.secciones.con-indicador button.activo:hover { background: none; box-shadow: none; }
.pestanas > .indicador { background: var(--superficie); border-radius: 5px; box-shadow: 0 0 0 1px var(--linea), var(--sombra-1); }
.pestanas.con-indicador button.activo { background: none; box-shadow: none; }
.conmutador > .indicador { background: var(--petroleo); border-radius: 5px; box-shadow: var(--sombra-1); }
.conmutador.con-indicador button.activo { background: none; box-shadow: none; }

@media (forced-colors: active) {
  .indicador { outline: 2px solid Highlight; }
}

/* --- grupos de botones (lista/mapa, pestañas) ------------------------------
   Dos controles que hacen lo mismo se ven iguales: un riel con la opción
   elegida encendida adentro. */

.conmutador, .pestanas {
  display: inline-flex; gap: 2px;
  background: var(--fondo-2);
  border: 1px solid var(--linea);
  border-radius: var(--r-control);
  padding: 3px;
}

.conmutador button, .pestanas button {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none;
  border-radius: 5px;
  color: var(--texto-3);
  font: inherit; font-size: 13px;
  padding: 7px 16px;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

.conmutador button { padding: 6px 14px; }
.conmutador button .ico, .pestanas button .ico { width: 13px; height: 13px; }
.conmutador button:hover, .pestanas button:hover { color: var(--texto-2); }

/* La opción elegida se levanta del riel: blanca, con sombra corta. El
   conmutador lista/mapa va en petróleo porque cambia la pantalla entera. */
.conmutador button.activo { background: var(--petroleo); color: #fff; font-weight: 600; box-shadow: var(--sombra-1); }
.pestanas button.activo { background: var(--superficie); color: var(--petroleo); font-weight: 600; box-shadow: 0 0 0 1px var(--linea), var(--sombra-1); }

.pestanas { margin-bottom: 20px; }
.pestanas .contador { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; }

/* --- banda de métricas -----------------------------------------------------
   Una sola superficie dividida por líneas, no cuatro tarjetas sueltas: las
   cuatro cifras son partes de la misma foto y se leen de una pasada. */

/* Flex y no grilla, y el separador es el hueco teñido y no un borde por celda.
   Las métricas no son siempre cuatro: aparecen las nuevas desde la última
   visita y las de mención nueva solo cuando hay. Con grilla, siete métricas
   dejaban media fila vacía adentro de la caja; así la última fila se estira y
   la banda queda llena siempre. */
.metricas {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  background: var(--linea-suave);
  border: 1px solid var(--linea);
  border-radius: var(--r-caja);
  overflow: hidden;
  margin-bottom: 20px;
}

.metricas:empty { display: none; }

/* Columna pegada arriba y no bloque: un <button> centra su contenido en el
   alto, y con una celda más alta en la fila (un detalle de dos renglones,
   «recaudación, pedidos, cuentas») las cifras de las demás bajaban y la banda
   se leía torcida. */
.metrica {
  flex: 1 1 160px;
  display: flex; flex-direction: column; justify-content: flex-start;
  padding: 16px 18px 15px;
  background: var(--superficie);
  border: 0; border-radius: 0;
  color: inherit; font: inherit; text-align: left;
  cursor: pointer;
  transition: background var(--rapido) var(--curva);
}
.metrica > span { display: block; }
.metrica:focus-visible { outline-offset: -3px; }

.metrica:hover { background: var(--superficie-2); }
/* Con su filtro puesto, la métrica queda encendida: se ve qué la achicó. */
.metrica[aria-pressed="true"] { background: var(--verde-tenue); box-shadow: inset 0 -2px 0 var(--verde); }
.metrica.sin-click { cursor: default; }
.metrica.sin-click:hover { background: var(--superficie); }

.metrica .rotulo {
  display: flex; align-items: center; gap: 7px;
  margin-bottom: 12px;
}

/* El punto de color es lo que hace que la banda se lea de un vistazo: dice de
   qué estado es la cifra sin obligar a leer el rótulo. */
.metrica .rotulo::before {
  content: "";
  width: 6px; height: 6px;
  flex: none;
  border-radius: var(--r-pastilla);
  background: var(--texto-4);
}

.metrica.destacada .rotulo::before { background: var(--critico); }
.metrica.atencion .rotulo::before { background: var(--atencion); }
.metrica.verde .rotulo::before { background: var(--verde); }
.metrica.violeta .rotulo::before { background: var(--violeta); }
.metrica.frio .rotulo::before { background: var(--frio); }
.metrica.sello .rotulo::before { background: var(--sello); }

.metrica .numero {
  font-size: 30px; line-height: 1;
  font-weight: 650;
  font-stretch: 108%;
  color: var(--petroleo);
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}

.metrica .numero.monto { font-size: 21px; letter-spacing: -.03em; font-family: var(--mono); }
.metrica .detalle { color: var(--texto-3); font-size: 12px; margin-top: 6px; }
.metrica.destacada .numero { color: var(--critico); }
.metrica.frio .numero { color: var(--frio); }
/* Solo la cifra urgente va en color: con cuatro cifras de cuatro colores la
   banda parecía un semáforo y ninguna mandaba. El punto del rótulo ya dice
   de qué estado es cada una. */

@media (max-width: 560px) {
  /* En el celular la banda de la bandeja se aprieta: es lo que hay entre el
     menú y la primera pista. */
  #metricas .metrica { padding: 12px 14px; }
  #metricas .metrica .rotulo { margin-bottom: 8px; }
  #metricas .metrica .numero { font-size: 25px; }
  /* Los dos montos de Recaudación, uno por renglón: de a dos, «Corresponde al
     Distrito V» ocupaba dos renglones y la cifra de al lado quedaba más arriba. */
  #metricas-recaudacion .metrica { flex-basis: 100%; }
}

/* --- buscador y filtros ----------------------------------------------------
   Los dos quedan siempre a la vista. Un filtro puesto se enciende, para que
   nunca haya uno activo sin que se note por qué la bandeja está casi vacía. */

.barra-buscar { display: flex; align-items: center; gap: 8px; }

/* Al lado del buscador, el orden: del mismo alto, y fuera de la tira de
   filtros porque no filtra nada. */
.barra-buscar .filtro.orden { height: 40px; padding: 0 12px; flex: none; }

.buscador {
  flex: 1; min-width: 200px;
  display: flex; align-items: center; gap: 10px;
  height: 40px;
  background: var(--superficie);
  border: 1px solid var(--linea-control);
  border-radius: var(--r-control);
  padding: 0 14px;
  transition: border-color var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva);
}

.buscador .ico { width: 14px; height: 14px; color: var(--texto-3); }
.buscador input { min-height: 0; background: none; border: none; box-shadow: none; color: var(--texto); font: inherit; width: 100%; padding: 0; }
.buscador input:focus { outline: none; box-shadow: none; }
.buscador:focus-within { border-color: var(--verde); box-shadow: 0 0 0 3px var(--verde-brillo); }
.buscador:focus-within .ico { color: var(--verde); }

/* Los filtros de la bandeja, como una tira: celdas del mismo ancho pegadas
   en una sola caja, cada una con el nombre arriba y el valor abajo, como los
   casilleros de la carátula de un plano. Sueltos, cada uno medía lo que su
   opción más larga y la fila cortaba donde podía. Las líneas entre celdas
   las dibuja cada celda con una sombra de 1px que cae en el hueco: si el
   último renglón queda incompleto, lo que sobra se ve blanco y no gris. */
#filtros {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 1px;
  margin-top: 10px;
  background: var(--superficie);
  border: 1px solid var(--linea-control);
  border-radius: var(--r-control);
  overflow: hidden;
}

#filtros .filtro {
  flex-direction: column; align-items: stretch; justify-content: center; gap: 1px;
  height: auto; min-height: 50px;
  min-width: 0;
  padding: 6px 12px 7px;
  border: none; border-radius: 0;
  background: var(--superficie);
  box-shadow: 0 0 0 1px var(--linea);
}
#filtros .filtro:hover { background: var(--fondo-2); }
#filtros .filtro > span { font-size: 12px; line-height: 1.3; }
#filtros .filtro select { width: 100%; min-width: 0; padding-right: 18px; line-height: 1.4; }
#filtros .filtro:has(select:focus) { background: var(--fondo-2); }
#filtros .filtro:has(:focus-visible) { outline-offset: -2px; }
#filtros .filtro.puesto { background: var(--verde-tenue); }
#filtros .filtro.puesto:hover { background: #dcf2ec; }

/* Los dos filtros sin selector y «Limpiar filtros» no son casilleros: van
   en un renglón al pie de la tira, a lo ancho. Como casilleros partían la
   tira en dos renglones y dejaban un hueco al final. */
#filtros .filtro-extra,
#filtros .limpiar-filtros {
  grid-column: 1 / -1;
  flex-direction: row; align-items: center; gap: 6px;
  min-height: 34px; height: auto;
  padding: 0 12px;
  box-shadow: 0 0 0 1px var(--linea);
  font-size: 12.5px;
}
#filtros .filtro-extra { justify-content: flex-start; text-align: left; }
#filtros .limpiar-filtros { display: flex; justify-content: flex-end; background: var(--fondo-2); text-decoration: none; color: var(--texto-2); }
#filtros .limpiar-filtros:hover { color: var(--petroleo); text-decoration: underline; }

.filtro {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px;
  background: var(--superficie);
  border: 1px solid var(--linea-control);
  border-radius: var(--r-control);
  padding: 0 10px;
  margin: 0;
  font-size: 13px;
  color: var(--texto-2);
  transition: border-color var(--rapido) var(--curva), background var(--rapido) var(--curva);
}

/* El nombre del filtro va angosto y tenue, como el rótulo de una celda: lo
   que se lee es el valor elegido. */
.filtro > span { color: var(--texto-3); font-stretch: 88%; font-weight: 500; }
.filtro:hover { border-color: var(--texto-3); }

.filtro select,
.filtro input {
  min-height: 0;
  background-color: transparent;
  border: none;
  box-shadow: none;
  color: var(--texto);
  font: inherit;
  font-weight: 500;
  padding: 0;
  cursor: pointer;
}
.filtro select { padding-right: 20px; background-position: right 0 center; background-size: 13px; }

.filtro select:focus, .filtro input:focus { outline: none; box-shadow: none; }
.filtro:has(select:focus), .filtro:has(input:focus) { border-color: var(--verde); }
/* Con teclado, el filtro enfocado lleva el mismo anillo que el resto. */
.filtro:has(:focus-visible) { outline: 2px solid var(--verde-texto); outline-offset: 2px; }
.filtro.puesto {
  background: var(--verde-tenue);
  border-color: var(--verde-linea);
  color: var(--petroleo);
}
.filtro.puesto > span { color: var(--verde-texto); }

.limpiar-filtros {
  background: none; border: none;
  color: var(--texto-3);
  font: inherit; font-size: 13px;
  padding: 6px 4px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.limpiar-filtros:hover { color: var(--texto); }

/* Los filtros sin selector (mención nueva, también las cerradas): una
   pastilla encendida que se saca con la cruz. */
.filtro-extra { font: inherit; font-size: 13px; cursor: pointer; }
.filtro-extra .ico { width: 11px; height: 11px; color: var(--verde-texto); }

/* Debajo de la lista: las cerradas que también coinciden con la búsqueda. */
.cerradas-que-coinciden { margin: 14px 2px 0; font-size: 13px; color: var(--texto-3); }
.cerradas-que-coinciden .enlace,
.vacio .enlace { font-size: inherit; }
.vacio p { margin: 8px 0 0; }


/* --- páginas de la bandeja ------------------------------------------------ */

.paginado {
  display: flex; align-items: center; justify-content: center; gap: 6px; flex-wrap: wrap;
  margin-top: 22px;
}

.numero-pagina {
  min-width: 34px; height: 34px;
  padding: 0 8px;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  color: var(--texto-2);
  font: inherit; font-size: 13px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), border-color var(--rapido) var(--curva);
}
.numero-pagina:hover { background: var(--superficie-2); border-color: var(--linea); }
.numero-pagina.actual {
  background: var(--verde-tenue);
  border-color: var(--verde-linea);
  color: var(--petroleo);
  font-weight: 600;
  cursor: default;
}
.paginado .puntos { color: var(--texto-4); padding: 0 2px; }


/* --- barra de selección múltiple ------------------------------------------ */

.barra-seleccion {
  position: sticky; top: 14px;
  z-index: 8;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--superficie);
  border: 1px solid var(--verde-linea);
  border-radius: var(--r-control);
  padding: 10px 14px;
  margin: 14px 0 0;
  font-size: 13px;
  box-shadow: var(--sombra-3);
  animation: bajar-barra 180ms var(--curva) both;
}

@keyframes bajar-barra {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

.barra-seleccion .espaciador { flex: 1; }

/* --- la pista en la bandeja ------------------------------------------------
   Cuatro columnas: la marca de prioridad, el sello del tipo, el cuerpo y la
   columna de acciones. La marca es lo primero que se ve y no dice el estado
   sino la prioridad, que es lo que decide por dónde empezar.

   Las pistas son filas de una misma lista, no tarjetas sueltas: cincuenta
   cajas con sombra, una abajo de la otra, hacían que la bandeja se leyera
   como una pila de avisos. Ahora es una sola superficie con una línea entre
   fila y fila, como un registro. */

.lista-pistas { position: relative; display: flex; flex-direction: column; margin-top: 20px; }
.lista-pistas:has(> .pista) {
  border: 1px solid var(--linea);
  border-radius: var(--r-caja);
  background: var(--superficie);
}
/* La tarjeta que se fue (movimiento.js) queda encima mientras se apaga. */
.fantasma-tarjeta { z-index: 1; }

.pista {
  position: relative;
  display: grid;
  grid-template-columns: 3px auto 1fr auto;
  gap: 14px;
  align-items: start;
  background: var(--superficie);
  border-bottom: 1px solid var(--linea-suave);
  padding: 16px 18px 15px 12px;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva);
  animation: entrar-pista 240ms var(--curva) both;
  /* Con tope: con 50 tarjetas por página la última esperaba más de un segundo. */
  animation-delay: calc(min(var(--i, 0), 10) * 22ms);
}

@keyframes entrar-pista {
  from { opacity: 0; transform: translateY(7px); }
  to { opacity: 1; transform: none; }
}

/* Repintados después del primero (filtrar, buscar, actuar): sin entrada. */
.lista-pistas.repintada .pista { animation: none; }

/* Las esquinas de la lista las ponen la primera y la última fila: la lista
   no puede cortar lo que sobresale (el menú de descarte cuelga de la fila). */
.lista-pistas > .pista:first-child { border-top-left-radius: calc(var(--r-caja) - 1px); border-top-right-radius: calc(var(--r-caja) - 1px); }
.lista-pistas > .pista:last-of-type { border-bottom: none; border-bottom-left-radius: calc(var(--r-caja) - 1px); border-bottom-right-radius: calc(var(--r-caja) - 1px); }

/* Al pasar por encima la fila se tiñe apenas; no se levanta, porque en una
   lista de cincuenta el salto se volvía un temblor al mover el mouse.
   Elegida, verde tenue con la marca de la izquierda en verde. */
.pista:hover { background: var(--fila-hover); }
.pista.elegida { background: var(--fila-elegida); box-shadow: inset 2px 0 0 var(--verde); }

/* La prioridad, como la marca de una regla: un trazo corto a la altura del
   primer renglón, no una franja de punta a punta. La franja entera era lo
   más fuerte de la tarjeta y gritaba más que el título. */
.pista .riel {
  align-self: start;
  height: 18px;
  margin-top: 3px;
  border-radius: var(--r-pastilla);
  background: var(--texto-4);
}

.pista[data-prioridad="Alta"] .riel { background: var(--critico); }
.pista[data-prioridad="Media"] .riel { background: var(--atencion); }
.pista[data-prioridad="Baja"] .riel { background: var(--texto-4); }

/* El sello del tipo, con la casilla de selección escondida en la esquina: sin
   ella hay que abrir cada pista para actuar sobre varias, y con ella siempre
   visible la tarjeta arranca pareciendo un formulario. */
.pista .sello {
  position: relative;
  width: 34px; height: 34px;
  border-radius: var(--r-tile);
  background: var(--superficie);
  border: 1px solid var(--linea);
  display: grid; place-items: center;
  color: var(--texto-2);
  transition: border-color var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

.pista:hover .sello { border-color: var(--verde-linea); color: var(--verde-texto); }
.pista .sello .ico { width: 16px; height: 16px; }

.pista .tilde {
  position: absolute;
  top: -7px; left: -7px;
  width: 17px; height: 17px;
  margin: 0;
  appearance: none;
  border: 1px solid var(--linea-fuerte);
  border-radius: 6px;
  background: var(--fondo-2);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--rapido) var(--curva), background var(--rapido) var(--curva);
}

.pista .tilde:checked { background: var(--verde); border-color: var(--verde); }

/* El tilde, dibujado con dos bordes: no hace falta un ícono para esto. */
.pista .tilde:checked::after {
  content: "";
  position: absolute;
  left: 5px; top: 1px;
  width: 4px; height: 8px;
  border: solid var(--sobre-verde);
  border-width: 0 2px 2px 0;
  transform: rotate(42deg);
}

.pista:hover .tilde,
.pista .tilde:focus-visible,
.pista.elegida .tilde { opacity: 1; }

.pista .cuerpo { min-width: 0; }

.pista .renglon-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.pista .tipo-rotulo { margin: 0 0 10px; }

.pista .titulo {
  font-size: 16px;
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--petroleo);
  margin: 0 0 3px;
  text-wrap: pretty;
}

/* El título es el botón que abre la ficha con el teclado: se ve igual que
   un título, sin nada de botón. */
.pista .abrir-ficha {
  all: unset;
  display: inline;
  cursor: pointer;
  border-radius: 4px;
}
.pista .abrir-ficha:focus-visible { outline: 2px solid var(--verde); outline-offset: 3px; }

/* --- cápsulas de datos -------------------------------------------------------
   Cada dato de la obra en su propia cápsula, con el mismo alto que los chips
   de contacto: la tarjeta se lee como una fila de piezas ordenadas y no como
   una oración larga que corta donde puede. Las cápsulas son datos y van con
   las esquinas casi rectas, como una celda; lo redondo del todo queda para
   lo que se toca (un contacto) o dice un estado (una pastilla). */
.pista .capsulas { display: flex; flex-wrap: wrap; gap: 6px; }

.capsula {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 26px;
  max-width: 100%;
  padding: 3px 10px;
  border: 1px solid var(--linea-suave);
  border-radius: var(--r-chico);
  background: var(--fondo-2);
  color: var(--texto-2);
  font-size: 12px;
  line-height: 1.3;
}

.capsula .ico { width: 12px; height: 12px; flex: none; color: var(--texto-3); }
.capsula .tenue { color: var(--texto-3); }
.capsula .separador { color: var(--texto-4); }
.capsula.lugar { color: var(--texto); }
.capsula.monto { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; }
/* La fecha de un hecho de hace más de un año: lo que trajo el barrido
   histórico. Punteada y sin relleno para que se distinga de una pista de esta
   semana; no en ámbar, que es el color de lo que apura y esto no apura. */
.capsula.historica { color: var(--texto); border-style: dashed; border-color: var(--linea-fuerte); background: transparent; }
.capsula.partes { color: var(--texto); font: inherit; font-size: 12px; cursor: pointer; transition: border-color var(--rapido) var(--curva); }
.capsula.partes:hover { border-color: var(--linea-fuerte); }
.capsula.partes .ico.flecha { transition: transform var(--rapido) var(--curva); }
.capsula.partes[aria-expanded="true"] .ico.flecha { transform: rotate(180deg); }

/* Las partes desplegadas en la tarjeta. Las que coinciden con un filtro
   elegido llevan el borde frío, con un título que lo dice: el verde de la
   marca se leía como "esta está bien". */
.pista .partes-tarjeta { margin-top: 10px; }
.fila-parte.coincide { border-color: var(--frio-linea); }
.fila-parte .chips .estado-licitacion { font-weight: 500; }

/* Una parte suelta en la bandeja: su nombre manda y el proyecto va detrás. */
.pista .titulo .de-proyecto { margin-left: 8px; font-size: 13px; font-weight: 400; color: var(--texto-3); letter-spacing: 0; }

/* --- partes del proyecto en la ficha ---------------------------------------- */
.partes-proyecto {
  border: 1px solid var(--linea);
  border-radius: var(--r-panel);
  background: var(--superficie);
  padding: 14px 16px;
  margin-bottom: 18px;
}
.partes-proyecto.vacias { background: none; border-style: dashed; padding: 10px 14px; }
.partes-proyecto .cabeza { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.partes-proyecto .cabeza .rotulo { display: inline-flex; align-items: center; gap: 7px; color: var(--texto-2); }
.partes-proyecto .cabeza .rotulo .ico { width: 13px; height: 13px; }
.lista-partes { display: grid; gap: 6px; margin-top: 12px; }
.fila-parte {
  display: grid; grid-template-columns: minmax(80px, auto) minmax(0, 1fr) auto; align-items: center; gap: 12px;
  width: 100%; padding: 9px 12px;
  background: var(--fondo-2); border: 1px solid var(--linea-suave); border-radius: var(--r-control);
  color: var(--texto-2); font: inherit; font-size: 13px; text-align: left; cursor: pointer;
  transition: border-color var(--rapido) var(--curva);
}
.fila-parte:hover { border-color: var(--linea-fuerte); }
.fila-parte .nombre { font-weight: 600; color: var(--texto); }
/* Solo el detalle de la fila (hijo directo): el chip de licitación de adentro
   también tiene un .detalle, y con esta regla «· demorada» quedaba cortado
   con puntos suspensivos. */
.fila-parte > .detalle { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fila-parte .separador { color: var(--texto-4); margin: 0 6px; }
.fila-parte .chips { display: inline-flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.alta-parte { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--linea-suave); }
.alta-parte .acciones { margin-top: 12px; }
/* En el celular la parte va en dos renglones: el nombre con su etiqueta a la
   derecha, y la empresa debajo. En tres renglones (nombre, empresa,
   etiqueta) seis partes estiraban la tarjeta a más de una pantalla. */
@media (max-width: 520px) {
  .fila-parte {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "nombre chips" "detalle detalle";
    gap: 2px 10px;
    padding: 8px 11px;
  }
  .fila-parte .nombre { grid-area: nombre; align-self: center; }
  .fila-parte .chips { grid-area: chips; }
  .fila-parte > .detalle { grid-area: detalle; font-size: 12px; }
}

/* En la ficha de una parte, de qué proyecto es y cómo volver. */
.miga-proyecto {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  margin: 0 0 6px; padding: 0;
  background: none; border: none; color: var(--texto-3);
  font: inherit; font-size: 12px; cursor: pointer; text-align: left;
}
.miga-proyecto:hover { color: var(--texto); }
.miga-proyecto .ico { width: 12px; height: 12px; flex: none; }
.miga-proyecto span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.miga-proyecto strong { font-weight: 500; color: var(--texto-2); }

/* La miga con lo decidido sobre el proyecto al lado. Va aparte del botón para
   que, si no entra, se corte el título del proyecto y no el motivo. */
.miga { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; margin: 0 0 6px; }
.miga .miga-proyecto { margin: 0; }
.miga .decidido { font-size: 12px; color: var(--texto-3); }
.miga .boton.chico { padding: 4px 10px; font-size: 12px; }

/* La licitación es una cápsula partida: número, apertura y adjudicación son
   hitos del mismo trámite y van pegados, separados por una línea. */
.capsula-licitacion { padding: 0; gap: 0; overflow: hidden; }
.capsula-licitacion .tramo { display: inline-flex; align-items: center; gap: 6px; padding: 3px 11px; white-space: nowrap; }
.capsula-licitacion .tramo + .tramo { border-left: 1px solid var(--linea-suave); }
.capsula-licitacion .numero { font-family: var(--mono); font-size: 12px; color: var(--texto); }
.capsula-licitacion .tramo:first-child .ico { color: var(--texto-3); }
/* El primer tramo dice en qué va el trámite, con los colores de la pastilla
   de licitación: ámbar solo si la apertura se viene. */
.capsula-licitacion .estado strong { font-weight: 600; color: var(--texto); }
.capsula-licitacion .estado .detalle { color: var(--texto-3); }
.capsula-licitacion .estado.proxima-apertura { background: var(--atencion-tenue); }
.capsula-licitacion .estado.proxima-apertura strong,
.capsula-licitacion .estado.proxima-apertura .ico { color: var(--atencion); }
.capsula-licitacion .estado.apertura .ico { color: var(--atencion); }
.capsula-licitacion .estado.adjudicada .ico,
.capsula-licitacion .estado.adjudicada-en-parte .ico { color: var(--verde-texto); }
/* Con partes el estado trae su cola («del proyecto · demorada») y puede no
   entrar en el celular: ese tramo sí corta renglón. */
.capsula-licitacion { flex-wrap: wrap; }
.capsula-licitacion .tramo.estado { white-space: normal; }

/* Procedencia y responsable, al pie y en chico: importan, pero no compiten
   con los datos de la obra. */
.pista .meta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 4px 8px;
  margin-top: 10px;
  color: var(--texto-3);
  font-size: 12px;
}

.pista .meta .ico { width: 12px; height: 12px; }
.pista .meta .punto { color: var(--texto-4); }

/* La cantidad de fuentes es lo único del pie que se lee en verde: es lo que
   dice si la pista está sostenida o es una sola nota suelta. */
.pista .meta .fuentes { display: inline-flex; align-items: center; gap: 5px; color: var(--verde-texto); font-weight: 500; }
/* Sin ninguna fuente no está sostenida: el verde decía lo contrario. */
.pista .meta .fuentes.ninguna { color: var(--texto-3); }
.pista .meta .responsable { display: inline-flex; align-items: center; gap: 5px; color: var(--texto-2); }

.pista .derecha { display: flex; align-items: center; gap: 6px; justify-self: end; }

/* Las acciones se ven apenas en reposo y del todo cuando el mouse confirma
   que la tarjeta interesa. Invisibles del todo, nadie sabía que estaban hasta
   pasar por encima de casualidad. En pantalla táctil no hay hover, así que
   ahí quedan siempre puestas. */
.acciones-rapidas {
  display: flex; gap: 4px;
  opacity: .3;
  pointer-events: none;
  transition: opacity 120ms var(--curva);
}

.pista:hover .acciones-rapidas,
.pista:focus-within .acciones-rapidas { opacity: 1; pointer-events: auto; }

button.accion {
  display: grid; place-items: center;
  width: 32px; height: 32px;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-chico);
  color: var(--texto-2);
  cursor: pointer;
  transition: border-color var(--rapido) var(--curva), background var(--rapido) var(--curva), color var(--rapido) var(--curva), transform var(--rapido) var(--curva);
}

button.accion .ico { width: 15px; height: 15px; }
button.accion:hover { border-color: var(--verde-linea); background: var(--verde-tenue); color: var(--verde-texto); }
button.accion:active { transform: scale(.94); }
button.accion.peligro:hover { border-color: var(--critico-linea); background: var(--critico-tenue); color: var(--critico); }

/* El menú de descarte: la única acción de la tarjeta que pide un dato antes de
   hacerse, porque una pista descartada sin motivo no sirve de antecedente. */
.menu-descarte { position: relative; display: inline-flex; }

/* La animación de entrada deja a cada tarjeta en su propio contexto de
   apilado, así que el z-index del menú no sale de la tarjeta y la de abajo lo
   tapaba. Se levanta la tarjeta entera mientras tiene el menú abierto. */
.pista:has(.opciones-descarte:not(.oculto)) { position: relative; z-index: 5; }

.opciones-descarte {
  position: absolute; top: calc(100% + 6px); right: 0;
  z-index: 12;
  width: 262px;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-panel);
  padding: 4px;
  box-shadow: var(--sombra-menu);
  animation: entrar-menu 140ms var(--curva) both;
}

@keyframes entrar-menu {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

.opciones-descarte.arriba { top: auto; bottom: calc(100% + 6px); animation-name: entrar-menu-arriba; }

@keyframes entrar-menu-arriba {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

/* El encabezado del menú va separado de las opciones por una línea: es la
   pregunta, y abajo están las respuestas. */
.opciones-descarte .rotulo { margin: 0 -4px 4px; padding: 8px 14px 9px; border-bottom: 1px solid var(--linea-suave); }

.opciones-descarte button {
  display: block; width: 100%;
  min-height: 34px;
  text-align: left;
  background: none; border: none;
  border-radius: var(--r-chico);
  padding: 7px 10px;
  color: var(--texto);
  font: inherit; font-size: 13px;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

/* Descartar es la acción que saca una pista de la bandeja: la opción elegida
   se tiñe del coral de lo destructivo, no del verde de lo resuelto. */
.opciones-descarte button:hover,
.opciones-descarte button:focus-visible { background: var(--critico-tenue); color: var(--critico); }
.opciones-descarte button:focus-visible { outline-offset: -2px; }

/* La pregunta de a qué partes abiertas baja una decisión sobre el proyecto.
   Flota como el menú de descarte, pero colgada del body y no de la tarjeta:
   adentro de la ficha o de una tarjeta la recortaban el panel y el apilado de
   la entrada. El velo es transparente: está para que tocar afuera cancele sin
   tocar de paso lo que hay abajo. */
.velo-alcance { position: fixed; inset: 0; z-index: 70; }

.alcance {
  position: fixed; z-index: 71;
  width: min(340px, calc(100vw - 32px));
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-panel);
  padding: 12px;
  box-shadow: var(--sombra-menu);
  color: var(--texto);
  font-size: 13px;
  animation: entrar-menu 140ms var(--curva) both;
}
/* La caja toma el foco solo para que Escape y Tab sigan pasando por ella
   (tabindex -1): no es un control y no lleva anillo. */
.alcance:focus { outline: none; }
.alcance .rotulo { margin-bottom: 8px; padding: 0 4px; }
.alcance p { margin: 0 4px 8px; line-height: 1.5; }
.alcance .advertencia { color: var(--atencion); font-weight: 600; }

.partes-alcance { list-style: none; margin: 0 0 8px; padding: 0; }
.partes-alcance label {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 4px;
  border-radius: var(--r-chico);
  cursor: pointer;
}
.partes-alcance label:hover { background: var(--fondo-2); }
.partes-alcance input { width: auto; flex: none; margin: 0; accent-color: var(--verde); }
.partes-alcance .nombre { flex: 1; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.partes-alcance input:disabled ~ .nombre { color: var(--texto-3); }
.partes-alcance .etiqueta { flex: none; }

.acciones-alcance { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }

/* En un celular, al lado del botón no entra una lista de seis zonas: va abajo
   de todo y a lo ancho, con el margen de la página. */
.alcance.abajo {
  left: 16px; right: 16px; top: auto;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  width: auto;
  max-height: 70vh;
}

/* --- pastillas de estado --------------------------------------------------- */

.etiqueta {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2.5px 10px;
  border-radius: var(--r-pastilla);
  font-size: 12px;
  color: var(--texto-2);
  border: 1px solid var(--linea);
  background: var(--superficie-2);
  white-space: nowrap;
}

.etiqueta .ico { width: 11px; height: 11px; }

.etiqueta.alta { color: var(--critico); border-color: var(--critico-linea); background: var(--critico-tenue); }
.etiqueta.media { color: var(--atencion); border-color: var(--atencion-linea); background: var(--atencion-tenue); }
.etiqueta.baja { color: var(--texto-3); border-color: var(--linea); background: var(--superficie-2); }

.etiqueta.sin-revisar { color: var(--frio); border-color: var(--frio-linea); background: var(--frio-tenue); }
.etiqueta.verificar-visado { color: var(--sello); border-color: var(--sello-linea); background: var(--sello-tenue); }
.etiqueta.a-fiscalizar { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.etiqueta.vigilada { color: var(--violeta); border-color: var(--violeta-linea); background: var(--violeta-tenue); }
/* "Nueva mención" no es un estado: es un aviso. Ámbar y sin relleno, con el
   borde punteado, para que no se lea como una pastilla más de fiscalización. */
.etiqueta.mencion { color: var(--critico); border: 1px dashed var(--critico-linea); background: transparent; }
.etiqueta.fiscalizada { color: var(--sobre-verde); border-color: var(--verde-boton); background: var(--verde-boton); }
.etiqueta.descartada, .etiqueta.unida { color: var(--texto-3); border-color: var(--linea); background: var(--superficie-2); }
.etiqueta.pendiente { color: var(--frio); border-color: var(--frio-linea); background: var(--frio-tenue); }
.etiqueta.en-curso { color: var(--atencion); border-color: var(--atencion-linea); background: var(--atencion-tenue); }
.etiqueta.lista { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.etiqueta.proyectada { color: var(--atencion); border-color: var(--atencion-linea); background: var(--atencion-tenue); }
.etiqueta.cobrada { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.etiqueta.oficial { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.etiqueta.prensa { color: var(--texto-2); border-color: var(--linea); background: var(--superficie-2); }
.etiqueta.ok-cuenta { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
/* En la fila de una parte: se cargó después de que se decidió sobre el
   proyecto. Es un dato, no un estado: gris y punteado. */
.etiqueta.llego-despues { color: var(--texto-3); border-style: dashed; background: transparent; }

/* --- la etiqueta de una obra con partes ------------------------------------
   Un tramo por estado de sus contratos, pegados como una sola pastilla: «4
   sin revisar · 2 descartadas» se lee como un todo y cada tramo conserva el
   color de su estado. Solo los extremos van redondos. Si no entra, corta
   renglón entre tramos en vez de salirse de la tarjeta y correr la página de
   costado. */
.etiqueta-obra { display: inline-flex; align-items: center; flex-wrap: wrap; row-gap: 3px; max-width: 100%; }
.etiqueta-obra .tramo { border-radius: 0; margin-left: -1px; }
.etiqueta-obra .tramo:first-child { margin-left: 0; border-radius: var(--r-pastilla) 0 0 var(--r-pastilla); }
.etiqueta-obra .tramo:last-child { border-radius: 0 var(--r-pastilla) var(--r-pastilla) 0; }
/* El estado elegido en el filtro lleva un anillo de su propio color. */
.etiqueta-obra .tramo.coincide { position: relative; box-shadow: inset 0 0 0 1.5px currentColor; }
/* El verde lleno quiere decir "terminado": adentro de una obra que todavía
   tiene otras partes, la fiscalizada va con el verde tenue. */
.etiqueta-obra .tramo.fiscalizada { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }

/* En una pantalla angosta y en el globo del mapa (Leaflet lo limita a 300 px)
   la pastilla partida corta renglón: cada tramo va como su propia pastilla,
   porque un tramo con las esquinas rectas al principio de un renglón parecía
   cortado. */
@media (max-width: 520px) {
  .etiqueta-obra { column-gap: 3px; }
  .etiqueta-obra .tramo,
  .etiqueta-obra .tramo:first-child,
  .etiqueta-obra .tramo:last-child { margin-left: 0; border-radius: var(--r-pastilla); }
}
#mapa .chips-popup .etiqueta-obra { column-gap: 3px; }
#mapa .chips-popup .etiqueta-obra .tramo { margin-left: 0; border-radius: var(--r-pastilla); }

/* Lo decidido sobre el proyecto entero, al lado de la etiqueta de la obra. Es
   una nota y se tiene que ver como tal: texto tenue, sin relleno, borde
   punteado. */
.estado-proyecto {
  display: inline-block;
  max-width: 100%;
  padding: 2px 10px;
  border: 1px dashed var(--linea-fuerte);
  border-radius: var(--r-pastilla);
  background: none;
  color: var(--texto-2);
  font: inherit; font-size: 12px; line-height: 1.45;
  text-align: left;
}
.estado-proyecto .tenue { color: var(--texto-3); }
button.estado-proyecto { cursor: pointer; text-decoration: underline; text-decoration-color: var(--texto-4); text-underline-offset: 2px; }
button.estado-proyecto:hover { color: var(--texto); border-color: var(--texto-3); }

.rol-chip {
  display: inline-flex; align-items: center;
  margin-left: 6px;
  padding: 1.5px 9px;
  border: 1px solid var(--linea);
  border-radius: var(--r-pastilla);
  font-size: 12px;
  font-stretch: 86%;
  font-weight: 600;
  color: var(--texto-3);
}

.rol-chip.admin { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.rol-chip.consejo { color: var(--violeta); border-color: var(--violeta-linea); background: var(--violeta-tenue); }
.rol-chip.jefe { color: var(--frio); border-color: var(--frio-linea); background: var(--frio-tenue); }
.rol-chip.distrito { color: var(--texto-2); border-color: var(--linea-fuerte); text-transform: none; letter-spacing: 0; font-size: 12px; }

/* El selector de distrito de la barra lateral: solo para quien ve todos. */
.selector-distrito {
  display: flex; align-items: center; gap: 8px;
  margin: 2px 4px 10px;
  font-size: 12px;
  color: var(--texto-3);
}
.selector-distrito select { flex: 1; min-width: 0; min-height: 32px; padding: 5px 28px 5px 9px; font-size: 12px; background-position: right 8px center; background-size: 12px; }

/* El cuadro de distritos: una fila por distrito, con sus partidos adentro. */
/* Cerrado, cada distrito es un renglón: nombre, sede, estado y el botón a
   la derecha. La flecha dice que se abre; el botón no la tapa. */
.tarjeta.distrito-fila { padding: 12px 18px; margin-bottom: 8px; }
.tarjeta.distrito-fila[open] { padding: 14px 18px 18px; }
.distrito-fila summary { cursor: pointer; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-weight: 600; min-height: 34px; list-style: none; }
.distrito-fila summary::-webkit-details-marker { display: none; }
.distrito-fila summary::before {
  content: "";
  width: 14px; height: 14px; flex: none;
  background: var(--texto-3);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform var(--medio) var(--curva);
}
.distrito-fila[open] summary::before { transform: rotate(90deg); }
.distrito-fila[open] summary { margin-bottom: 8px; }
.distrito-fila summary .espaciador { flex: 1; }
.distrito-fila summary .sub { font-weight: 400; }
.distrito-fila .etiqueta.activo { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.distrito-fila .etiqueta.inactivo { color: var(--texto-3); border-color: var(--linea); background: var(--superficie-2); }
.distrito-fila .etiqueta.publica { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.distrito-fila .etiqueta.no-publica { color: var(--texto-3); border-color: var(--linea); background: var(--superficie-2); }
.distrito-fila .etiqueta.inactivo-sibom { color: var(--atencion); border-color: var(--atencion-linea); background: var(--atencion-tenue); }
.distrito-fila td input, .distrito-fila td textarea { width: 100%; min-height: 32px; font-size: 12px; padding: 5px 8px; }
.distrito-fila td textarea { min-height: 48px; }
.distrito-fila .ojo { font-size: 12px; color: var(--atencion); margin-top: 4px; line-height: 1.4; }
.distrito-ficha { font-size: 13px; color: var(--texto-2); margin: 0 0 12px; line-height: 1.6; }
.distrito-fila .etiqueta.pausado { color: var(--atencion); border-color: var(--atencion-linea); background: var(--atencion-tenue); }

/* El barrido histórico del distrito: una caja adentro de su fila, con la
   barra de cuánto va. Verde porque es lo hecho; lo que falta queda en la
   línea de fondo. */
.historico-distrito {
  margin: 0 0 14px;
  padding: 12px 14px;
  border: 1px solid var(--linea);
  border-radius: 10px;
  background: var(--superficie-2);
  font-size: 13px;
  color: var(--texto-2);
}
.historico-distrito .historico-cabecera { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.historico-distrito .historico-cabecera strong { color: var(--texto); }
.historico-distrito .sub { margin: 8px 0 0; line-height: 1.6; }
.historico-distrito .fallidas-texto { color: var(--critico); }
.historico-distrito ul.fallidas { margin: 8px 0 0; padding-left: 18px; font-size: 12px; line-height: 1.6; }
.barra-progreso { height: 6px; border-radius: 3px; background: var(--linea); overflow: hidden; margin-top: 10px; }
.barra-progreso > span { display: block; height: 100%; background: var(--verde); border-radius: 3px; transition: width .4s ease; }

/* Las acciones de una cuenta, una debajo de la otra y sin partirse. */
.acciones-cuenta { white-space: nowrap; }
.acciones-cuenta .boton-texto { display: block; font-size: 12px; }

/* El aviso de la pista: lo que el radar no pudo confirmar. Va en ámbar y en
   una línea: es una advertencia, no un error. */
.badge-aviso {
  display: flex; align-items: center; gap: 6px;
  margin-top: 9px;
  font-size: 12px;
  color: var(--texto-2);
}

/* El ícono va en ámbar y el texto no: dos avisos largos en ámbar eran lo más
   fuerte de la tarjeta, por encima del título. */
.badge-aviso .ico { width: 12px; height: 12px; flex: none; color: var(--atencion); }
.badge-aviso span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- estado de licitación --------------------------------------------------
   Esquinas rectas a propósito: lo que cambia solo es lo más cuadrado, y este
   chip cambia con el calendario. Así no se confunde con la pastilla redonda
   del estado de gestión que va al lado. */
.estado-licitacion {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2.5px 9px 2.5px 7px;
  border: 1px solid var(--linea);
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--texto-3);
  background: var(--superficie-2);
}

.estado-licitacion .ico { width: 11px; height: 11px; }
.estado-licitacion .prefijo,
.estado-licitacion .detalle { font-weight: 400; opacity: .85; }
/* Solo la apertura que se viene lleva color: es la fecha que apura. La que ya
   pasó y la adjudicada son hechos, y van en neutro con el ícono teñido. Antes
   la próxima apertura era azul como «Sin revisar» y la adjudicada verde como
   «A fiscalizar», y las dos pastillas se leían como estados de la pista. */
.estado-licitacion.proxima-apertura { color: var(--atencion); border-color: var(--atencion-linea); background: var(--atencion-tenue); }
.estado-licitacion.apertura { color: var(--texto); }
.estado-licitacion.apertura .ico { color: var(--atencion); }
.estado-licitacion.adjudicada,
.estado-licitacion.adjudicada-en-parte { color: var(--texto); }
.estado-licitacion.adjudicada .ico,
.estado-licitacion.adjudicada-en-parte .ico { color: var(--verde-texto); }

/* Con partes, la licitación («Adjudicada en 1 de 6 · del proyecto · demorada»)
   y la mención («Nueva mención en el proyecto y ZONA 1 - …») traen textos que
   no entran en una línea de celular: cortan renglón dentro del chip en vez de
   salirse. La licitación baja por piezas (prefijo, estado, detalle). */
.renglon-chips > .etiqueta.mencion,
.renglon-chips > .estado-licitacion,
.fila-parte .chips .estado-licitacion,
#mapa .chips-popup .estado-licitacion { white-space: normal; max-width: 100%; text-align: left; }
.renglon-chips > .estado-licitacion,
.fila-parte .chips .estado-licitacion,
#mapa .chips-popup .estado-licitacion { flex-wrap: wrap; row-gap: 1px; }

/* La licitación que abrió sobres hace mucho y sigue sin adjudicar. Va en
   coral y no en ámbar: el ámbar ya es el estado Apertura de al lado. */
.aviso-demora {
  display: flex; align-items: flex-start; gap: 7px;
  margin-top: 10px;
  padding: 7px 11px;
  border: 1px solid var(--critico-linea);
  border-radius: var(--r-chico);
  background: var(--critico-tenue);
  color: var(--texto-2);
  font-size: 12px;
}

.aviso-demora .ico { width: 13px; height: 13px; flex: none; margin-top: 2px; color: var(--critico); }
.aviso-demora strong { color: var(--critico); font-weight: 600; }

/* El aviso de la ficha cuando lo decidido sobre el proyecto y sus partes no
   dice lo mismo. Ámbar como lo que espera una decisión, con los botones
   abajo: es lo primero que tiene que leer quien abre la ficha. */
.aviso-partes {
  margin: 0 0 14px;
  padding: 11px 14px;
  border: 1px solid var(--atencion-linea);
  border-radius: var(--r-control);
  background: var(--atencion-tenue);
  color: var(--texto);
  font-size: 13px;
}
.aviso-partes p { display: flex; align-items: flex-start; gap: 8px; margin: 0; line-height: 1.5; }
.aviso-partes p .ico { width: 14px; height: 14px; flex: none; margin-top: 2px; color: var(--atencion); }
.aviso-partes .sub { display: block; margin-top: 3px; }
.aviso-partes .acciones-aviso { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0 22px; }
/* Todas las partes cerradas no pide nada: solo explica por qué la obra no
   está en «Abiertas». */
.aviso-partes.tranquilo { border-color: var(--linea); background: var(--superficie-2); color: var(--texto-2); }
.aviso-partes.tranquilo p .ico { color: var(--texto-3); }


/* La licitación se distingue por su borde ámbar entero, no por una franja
   de un costado: la franja curvada contra el radio se veía como un error. */
.bloque-licitacion {
  border: 1px solid var(--atencion-linea);
  border-radius: var(--r-panel);
  padding: 14px 16px 16px;
  margin-bottom: 14px;
}

.bloque-licitacion > .rotulo {
  display: flex; align-items: center; gap: 7px;
  margin-bottom: 12px;
  color: var(--atencion);
}

.bloque-licitacion > .rotulo .ico { width: 13px; height: 13px; }
.bloque-licitacion .grilla { margin-bottom: 0; }
.grupo-form + .bloque-licitacion { margin-top: 16px; }

/* Cómo va a quedar la tarjeta, antes de guardar. */
.vista-licitacion { margin-top: 12px; }
.vista-licitacion .pie-campo { margin: 0; }
.asi-se-ve { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 12px; }
.aviso-licitacion { margin: 8px 0 0; font-size: 12px; line-height: 1.5; }
.aviso-licitacion.info { color: var(--texto-3); }
.aviso-licitacion.alerta { color: var(--critico); }

/* --- la licitación en la ficha -----------------------------------------------
   Tres pasos en línea, como un trámite: lo hecho queda tildado, el paso en el
   que está se enciende con el color de su estado y lo que falta queda apagado. */
.panel-ficha .aviso-demora { margin: 0 0 12px; }

.resumen-licitacion {
  border: 1px solid var(--linea);
  border-radius: var(--r-panel);
  background: var(--superficie);
  padding: 14px 16px 16px;
  margin-bottom: 18px;
}

.resumen-licitacion .cabeza {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-bottom: 14px;
}

/* El título del recuadro en el color de los rótulos: en ámbar se sumaba a lo
   que apura sin apurar nada. */
.resumen-licitacion .cabeza .rotulo { display: inline-flex; align-items: center; gap: 7px; color: var(--texto-2); }
.resumen-licitacion .cabeza .rotulo .ico { width: 13px; height: 13px; }

.pasos-licitacion {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.paso {
  position: relative;
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding-right: 10px;
}

/* La línea que une un paso con el siguiente. */
.paso::before {
  content: "";
  position: absolute;
  top: 10px; left: 24px; right: 0;
  height: 2px;
  background: var(--linea);
}

.paso:last-child::before { display: none; }
.paso.hecho::before { background: var(--linea-fuerte); }

.paso .marca {
  position: relative;
  width: 22px; height: 22px;
  border: 2px solid var(--linea-fuerte);
  border-radius: 50%;
  background: var(--superficie);
  display: grid; place-items: center;
  margin-bottom: 6px;
}

.paso .marca .ico { width: 11px; height: 11px; stroke-width: 2.4; }
.paso .nombre { font-size: 13px; font-weight: 600; color: var(--texto-3); }
.paso .cuando { font-size: 12px; color: var(--texto-3); font-variant-numeric: tabular-nums; }

.paso.hecho .marca { border-color: var(--texto-3); background: var(--superficie-2); color: var(--texto-2); }
.paso.hecho .nombre { color: var(--texto-2); }
.paso.hecho .cuando { color: var(--texto-3); }

.paso.actual .cuando { color: var(--texto-2); }
.paso.actual.proxima-apertura .marca { border-color: var(--frio); background: var(--frio-tenue); box-shadow: 0 0 0 4px var(--frio-tenue); }
.paso.actual.proxima-apertura .nombre { color: var(--frio); }
.paso.actual.apertura .marca { border-color: var(--atencion); background: var(--atencion-tenue); box-shadow: 0 0 0 4px var(--atencion-tenue); }
.paso.actual.apertura .nombre { color: var(--atencion); }
.paso.actual.adjudicada .marca { border-color: var(--verde); background: var(--verde-tenue); box-shadow: 0 0 0 4px var(--verde-tenue); color: var(--verde-texto); }
.paso.actual.adjudicada .nombre { color: var(--verde-texto); }

.datos-licitacion {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px 16px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--linea-suave);
}

.dato-licitacion { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dato-licitacion .clave {
  font-stretch: 84%; font-size: 12px; font-weight: 600;
  letter-spacing: .01em;
  color: var(--texto-3);
}
.dato-licitacion .valor { font-size: 13px; color: var(--texto); overflow-wrap: anywhere; }

/* --- el formulario de edición, por temas --------------------------------- */
.grupo-form { padding-top: 16px; margin-top: 16px; border-top: 1px solid var(--linea-suave); }
.grupo-form:first-child { padding-top: 0; margin-top: 0; border-top: none; }
/* El título de un grupo de campos (Fuente citada, Ubicación…) es un título
   y no un rótulo de dato: en el tamaño del cuerpo, en petróleo. */
.grupo-form > .rotulo,
.modal .bloque-fuente > .rotulo { margin-bottom: 4px; font-size: 13.5px; font-stretch: 100%; letter-spacing: -.005em; color: var(--petroleo); }
.grupo-form > .rotulo { margin-bottom: 12px; }
.grupo-form .grilla { margin-bottom: 0; }
.grupo-form > .campo { margin: 14px 0 0; }
.grilla .campo.ancho { grid-column: 1 / -1; }

/* --- superficies, formularios y botones ------------------------------------ */

.tarjeta {
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-caja);
  padding: 20px 22px;
  margin-bottom: 16px;
}

.tarjeta:last-child { margin-bottom: 0; }

.tarjeta h3 {
  display: flex; align-items: center; gap: 8px;
  font-size: 16px;
  font-weight: 650;
  margin: 0 0 14px;
  letter-spacing: -.015em;
  color: var(--petroleo);
}

.tarjeta h3 .ico { color: var(--texto-3); width: 15px; height: 15px; }
.tarjeta > .sub:first-of-type { margin-top: -8px; }
/* Una tarjeta que arranca con un rótulo («Cargar un expediente»,
   «Composición del período») lo usa de título: va en petróleo y al tamaño
   del cuerpo, no como la etiqueta chica de un dato. */
.tarjeta > .rotulo:first-child { font-size: 15px; font-stretch: 100%; font-weight: 650; letter-spacing: -.015em; color: var(--petroleo); }

/* La etiqueta de un campo se lee antes que el campo: va en petróleo y con
   algo de peso, no en el gris de una nota al pie. */
label, .rotulo-campo { display: block; font-size: 12.5px; font-weight: 500; color: var(--texto); margin-bottom: 6px; }
/* El asterisco de obligatorio, en el verde de texto: se distingue del rótulo
   sin el coral, que en el panel quiere decir «urgente» o «error». */
label > span[aria-hidden="true"], .marca-obligatorio { color: var(--verde-texto); font-weight: 600; }

/* El error de un campo, debajo del campo (marcarCampo en panel.js). Entra
   desde arriba, cerca de lo que lo causó, y con el ícono de alerta para que no
   dependa solo del color. */
.error-campo {
  display: flex; align-items: flex-start; gap: 6px;
  margin: 6px 0 0;
  font-size: 12.5px; line-height: 1.45;
  color: var(--critico);
  animation: entrar-error 180ms var(--curva) both;
}
.error-campo .ico { width: 13px; height: 13px; flex: none; margin-top: 2px; }
@keyframes entrar-error {
  from { opacity: 0; transform: translateY(-3px); }
  to { opacity: 1; transform: none; }
}

/* Varios comitentes: nombre ancho, CUIT angosto y la cruz para sacarlo. */
.filas-comitentes { display: grid; gap: 8px; margin-bottom: 8px; }
.fila-comitente { display: grid; grid-template-columns: minmax(0, 1fr) 150px auto; gap: 8px; align-items: center; }
.fila-comitente .boton-icono { width: 32px; height: 32px; }
@media (max-width: 520px) {
  .fila-comitente { grid-template-columns: minmax(0, 1fr) auto; }
  .fila-comitente .c-cuit { grid-column: 1; grid-row: 2; }
  .fila-comitente .boton-icono { grid-column: 2; grid-row: 1; }
}

/* Lo opcional va plegado: un renglón que se abre si hace falta. «Dar de alta a
   alguien» (.plegable) es lo mismo y llevaba el triángulo del sistema. */
details.opcional > summary, details.plegable > summary {
  cursor: pointer; list-style: none; font-size: 12.5px; font-weight: 500; color: var(--verde-texto);
  padding: 4px 0; width: fit-content;
  border-radius: 4px;
}
details.opcional > summary:hover, details.plegable > summary:hover { color: var(--petroleo); }
details.opcional > summary::-webkit-details-marker, details.plegable > summary::-webkit-details-marker { display: none; }
details.opcional > summary::before, details.plegable > summary::before { content: "+ "; }
details.opcional[open] > summary::before, details.plegable[open] > summary::before { content: "− "; }
details.opcional > summary .tenue { color: var(--texto-3); }
details.opcional[open] > summary { margin-bottom: 6px; }

/* Las partes en el alta: nombre, contrato y la cruz; abajo, sus comitentes. */
.filas-partes { display: grid; gap: 8px; margin: 10px 0 8px; }
.filas-partes:empty { margin: 4px 0 0; }
.fila-parte-alta {
  display: grid; grid-template-columns: minmax(0, 1fr) 140px auto; gap: 8px; align-items: center;
  padding: 10px; border: 1px solid var(--linea); border-radius: var(--r-panel);
}
/* Los comitentes de la parte van abajo, a lo ancho: pueden ser varios. */
.fila-parte-alta .editor-comitentes { grid-column: 1 / -1; }
.fila-parte-alta .boton-icono { width: 32px; height: 32px; }
@media (max-width: 720px) {
  .fila-parte-alta { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; }
  .fila-parte-alta > .pa-nombre { grid-column: 1 / 3; }
  .fila-parte-alta > .boton-icono { grid-column: 3; grid-row: 1; }
}

/* En la carátula, un comitente por línea con su CUIT al lado. */
.valor .comitente { display: block; }
.valor .comitente + .comitente { margin-top: 3px; }

input, select, textarea {
  width: 100%;
  min-height: 38px;
  background: var(--superficie);
  border: 1px solid var(--linea-control);
  border-radius: var(--r-control);
  color: var(--texto);
  padding: 8px 12px;
  font: inherit;
  box-shadow: inset 0 1px 1px rgba(20, 72, 74, .04);
  transition: border-color var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva);
}

input::placeholder, textarea::placeholder { color: var(--texto-3); opacity: .8; }

/* Los selects llevan su propia flecha: la del sistema cambiaba de dibujo y
   de lugar entre Windows, Mac y el celular, y al lado de los íconos del panel
   era la única pieza que no era de acá. Es la misma flecha del sprite. */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234c6f6d' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 14px;
  text-overflow: ellipsis;
  cursor: pointer;
}
select[multiple] { background-image: none; padding-right: 12px; }

/* Los que no se pueden tocar se ven apagados de verdad, no solo grises. */
input:disabled, select:disabled, textarea:disabled {
  background-color: var(--fondo-2);
  color: var(--texto-3);
  border-color: var(--linea);
  box-shadow: none;
  cursor: not-allowed;
}

/* Una casilla no es un campo de texto: sin el ancho entero ni el relleno de
   los campos. Con el relleno, la casilla de cada fila de la bandeja medía
   26×18 en vez de 17×17 y al pasar el mouse aparecía como un recuadro roto
   encima del sello. */
input[type="checkbox"], input[type="radio"] { width: auto; min-height: 0; padding: 0; box-shadow: none; }

/* El color-scheme de :root no alcanza: algunos navegadores viejos lo ignoran
   en la lista que se despliega, la pintan con fondo blanco y el texto claro
   que heredan las opciones queda invisible. El color puesto en cada <option>
   lo respetan todos, así que va explícito y con fondo sólido. */
option, optgroup {
  background-color: var(--superficie);
  color: var(--texto);
}
option:disabled { color: var(--texto-3); }

input:not(:disabled):hover, select:not(:disabled):hover, textarea:not(:disabled):hover { border-color: var(--texto-3); }

/* Un campo con error lo dice en el borde y no solo en el aviso de arriba. */
[aria-invalid="true"] { border-color: var(--critico) !important; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--verde);
  box-shadow: 0 0 0 3px var(--verde-brillo);
}
/* Con error, el halo del foco también es coral: borde coral con halo verde
   se leía como «está bien y está mal» a la vez. */
[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--critico) 16%, transparent); }

/* En alto contraste de Windows las sombras desaparecen: ahí el foco vuelve a
   ser un contorno. */
@media (forced-colors: active) {
  input:focus, select:focus, textarea:focus, .buscador:focus-within { outline: 2px solid CanvasText; outline-offset: 1px; }
}

input[inputmode="numeric"], input[inputmode="decimal"], input.mono {
  font-family: var(--mono);
  font-size: 13px;
}

textarea { min-height: 84px; resize: vertical; line-height: 1.5; }
.campo { margin-bottom: 16px; }
.grilla { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px 16px; margin-bottom: 16px; }
.grilla .campo { margin-bottom: 0; }
.pie-campo { margin: 6px 0 0; font-size: 12px; color: var(--texto-3); line-height: 1.5; text-wrap: pretty; }

.boton {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--verde-boton);
  color: var(--sobre-verde);
  border: none;
  border-radius: var(--r-control);
  padding: 9px 16px;
  font: inherit; font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--sombra-verde);
  transition: background var(--rapido) var(--curva), transform var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva);
}

.boton .ico { width: 14px; height: 14px; }
.boton:hover { background: var(--verde-boton-hover); }
.boton:active { transform: translateY(1px); box-shadow: none; }
.boton:disabled { opacity: .5; cursor: default; transform: none; }

/* Ocupado: mandó algo al servidor y espera (conBotonOcupado en panel.js). No
   se ve apagado como un deshabilitado: está trabajando. El círculo aparece
   recién a los 150ms, así un guardado rápido no parpadea, y ocupa el lugar
   del ícono para que el botón no cambie de ancho. Sin ícono, tapa el texto. */
.boton[aria-busy="true"] { position: relative; opacity: 1; cursor: progress; }
.boton[aria-busy="true"]::after {
  content: "";
  position: absolute;
  top: calc(50% - 7px); left: calc(50% - 7px);
  width: 14px; height: 14px;
  box-sizing: border-box;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  opacity: 0;
  animation: girar 700ms linear infinite, aparecer 120ms var(--curva) 150ms forwards;
}
.boton[aria-busy="true"]:has(> .ico)::after { left: 18px; }
.boton.chico[aria-busy="true"]:has(> .ico)::after { left: 14px; }
.boton[aria-busy="true"] > .ico { visibility: hidden; transition: visibility 0s 150ms; }
.boton[aria-busy="true"]:not(:has(> .ico)) { -webkit-text-fill-color: transparent; transition: -webkit-text-fill-color 0s 150ms; }

@keyframes girar { to { rotate: 360deg; } }

.boton.secundario {
  background: var(--superficie);
  border: 1px solid var(--linea-fuerte);
  color: var(--texto);
  box-shadow: var(--sombra-1);
}

.boton.secundario:hover { background: var(--fondo-2); color: var(--petroleo); border-color: var(--texto-3); }
.boton.secundario:active { background: var(--superficie-2); box-shadow: none; }
/* Deshabilitado no reacciona al mouse: si se oscurece al pasar, parece que
   anda. */
.boton:disabled:hover { background: var(--verde-boton); }
.boton.secundario:disabled:hover { background: var(--superficie); color: var(--texto); border-color: var(--linea-fuerte); }
.boton.peligro:hover { border-color: var(--critico-linea); color: var(--critico); }
.boton.chico { padding: 8px 14px; font-size: 13px; }

/* Lo guardado, confirmado por el servidor (confirmarEnBoton en panel.js): el
   tilde del botón entra de nuevo y el botón se aclara un momento. */
.boton.listo { animation: boton-listo 1.2s var(--curva); }
.boton.listo .ico { animation: tilde-listo 360ms var(--curva) both; }
@keyframes boton-listo {
  0%, 35% { box-shadow: var(--sombra-verde), 0 0 0 4px var(--verde-brillo); }
  100% { box-shadow: var(--sombra-verde), 0 0 0 0 transparent; }
}
@keyframes tilde-listo {
  from { transform: scale(.4) rotate(-12deg); opacity: 0; }
  to { transform: none; opacity: 1; }
}

.acciones { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-top: 16px; }

.aviso {
  border: 1px solid var(--linea);
  border-radius: var(--r-control);
  background: var(--superficie);
  padding: 11px 14px;
  line-height: 1.45;
  margin-bottom: 14px;
  font-size: 13px;
  color: var(--texto-2);
  display: flex; align-items: center; gap: 8px;
  animation: entrar-aviso 180ms var(--curva) both;
}

@keyframes entrar-aviso {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

.aviso .ico { width: 14px; height: 14px; flex: none; }
.aviso.error { color: var(--critico); border-color: var(--critico-linea); background: var(--critico-tenue); }
.aviso.ok { color: var(--verde-texto); border-color: var(--verde-linea); background: var(--verde-tenue); }
.aviso.info { color: var(--atencion); border-color: var(--atencion-linea); background: var(--atencion-tenue); }
/* Un aviso que trae el botón que lo resuelve («Abrir la ficha», «Descartarla
   con el mismo motivo»). En pantalla angosta el botón baja a su renglón. */
.aviso.con-boton { flex-wrap: wrap; }
.aviso.con-boton > span { flex: 1 1 240px; line-height: 1.5; }

.vacio {
  text-align: center;
  color: var(--texto-3);
  font-size: 13px;
  padding: 34px 20px;
  border: 1px dashed var(--linea);
  border-radius: var(--r-panel);
}

.vacio .ico { display: block; margin: 0 auto 10px; width: 26px; height: 26px; color: var(--texto-4); }
/* La salida de una bandeja vacía: borrar la búsqueda, limpiar los filtros. */
.vacio .salidas { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 14px; }
.vacio .salidas .boton .ico { display: inline; margin: 0; width: 13px; height: 13px; color: inherit; }

.enlace {
  background: none; border: none; padding: 0;
  color: var(--verde-texto);
  font: inherit; font-size: 12px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

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

.casilla {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px;
  color: var(--texto-2);
  cursor: pointer;
  margin-bottom: 0;
}

.casilla input { width: auto; accent-color: var(--verde); }
.casillas { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 6px; }

/* --- la ficha, como panel lateral ------------------------------------------
   Antes reemplazaba la bandeja entera y había que volver con un botón. Ahora
   entra por el costado y deja la lista atrás: se abren tres pistas seguidas
   sin perder de vista en qué parte de la bandeja se estaba. */

.velo {
  position: fixed; inset: 0;
  background: rgba(20, 72, 74, .28);
  z-index: 40;
  animation: aparecer 160ms var(--curva) both;
}

@keyframes aparecer { from { opacity: 0; } to { opacity: 1; } }

.panel-ficha {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(580px, 92vw);
  background: var(--superficie);
  border-left: 1px solid var(--linea);
  z-index: 41;
  display: flex; flex-direction: column;
  box-shadow: -24px 0 60px rgba(20, 72, 74, .18);
  animation: entrar-panel 220ms var(--curva) both;
}

@keyframes entrar-panel {
  from { transform: translateX(28px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

.panel-ficha .cabecera {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 22px 22px 14px;
}

.panel-ficha .cabecera .titulos { flex: 1; min-width: 0; }
.panel-ficha .cabecera .renglon-chips { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.panel-ficha h3 { font-size: 21px; line-height: 1.2; font-weight: 650; margin: 0; letter-spacing: -.03em; text-wrap: balance; color: var(--petroleo); }
.panel-ficha .cabecera .sub { margin: 6px 0 0; font-size: 13px; }

.panel-ficha .boton-icono { width: 32px; height: 32px; }

/* Las cuatro decisiones que se toman sobre una pista, arriba de todo: si hay
   que bajar a buscarlas, la ficha se convierte en un formulario. */
.acciones-ficha {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: 0 22px 18px;
  border-bottom: 1px solid var(--linea);
}

.acciones-ficha .boton { padding: 7px 12px; font-size: 13px; }

/* El estado en el que ya está la pista: se ve marcado y no se vuelve a elegir. */
.acciones-ficha .boton.actual,
.acciones-ficha .boton.actual:disabled {
  opacity: 1; cursor: default;
  background: var(--verde-tenue);
  border: 1px solid var(--verde-linea);
  color: var(--verde-texto);
}
.acciones-ficha .boton.peligro.actual { background: var(--critico-tenue); border-color: var(--critico-linea); color: var(--critico); }

.panel-ficha .cuerpo { flex: 1; overflow-y: auto; padding: 18px 22px 40px; }
.panel-ficha .resumen { margin: 0 0 18px; font-size: 14px; color: var(--texto); }

/* --- acordeones de la ficha ------------------------------------------------
   Trece campos, las fuentes, el formulario de gestión y el historial no entran
   a la vez en 560px. Cada bloque dice cuánto tiene adentro antes de abrirse,
   así se sabe si vale la pena. */

/* Cada bloque es una sección de la ficha, no una tarjeta adentro de otra: los
   separa una línea de punta a punta y el título de la sección. Cinco cajas
   con borde y sombra apiladas en 560px hacían de la ficha una pila de
   formularios. */
.acordeon {
  border-top: 1px solid var(--linea-suave);
  margin: 0 -22px;
}

.acordeon > summary {
  display: flex; align-items: center; gap: 10px;
  background: var(--superficie);
  padding: 14px 22px;
  font-size: 13px;
  color: var(--texto);
  cursor: pointer;
  list-style: none;
  transition: background var(--rapido) var(--curva);
}

.acordeon > summary::-webkit-details-marker { display: none; }
.acordeon > summary:hover { background: #f8fbfa; }
/* El título de la sección se lee como título, no como rótulo de un dato. */
.acordeon > summary .rotulo { flex: 1; font-size: 13px; font-stretch: 100%; font-weight: 600; letter-spacing: -.005em; color: var(--petroleo); }
.acordeon > summary .cuanto { color: var(--texto-3); font-size: 12px; }
.acordeon > summary .cuanto.verde { color: var(--verde); }

.acordeon > summary .ico.flecha {
  width: 13px; height: 13px;
  color: var(--texto-3);
  transition: transform var(--medio) var(--curva);
}

.acordeon[open] > summary .ico.flecha { transform: rotate(180deg); }
.acordeon .contenido-acordeon { background: var(--superficie); padding: 2px 22px 20px; }
.acordeon[open] .contenido-acordeon { animation: abrir-acordeon 180ms var(--curva) both; }
.acordeon.moviendo .contenido-acordeon { animation: none; }

@keyframes abrir-acordeon {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

/* Los datos de la pista: dos columnas, línea entre celdas, sin relleno de
   tarjeta. Es una tabla de carátula, no trece tarjetitas. */
.datos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: var(--superficie);
  border-top: 1px solid var(--linea-suave);
}

.dato {
  position: relative;
  padding: 12px 22px;
  border-bottom: 1px solid var(--linea-suave);
  min-width: 0;
}

/* El lápiz de cada dato, arriba a la derecha de la celda. Tenue en reposo y
   entero cuando el mouse pasa por la celda: trece lápices a pleno color eran
   trece botones compitiendo con los datos. En pantalla táctil va entero. */
.dato .lapiz {
  position: absolute; top: 8px; right: 12px;
  display: grid; place-items: center;
  width: 28px; height: 28px;
  padding: 0;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-chico);
  color: var(--texto-4);
  cursor: pointer;
  transition: color var(--rapido) var(--curva), border-color var(--rapido) var(--curva), background var(--rapido) var(--curva);
}
.dato .lapiz .ico { width: 14px; height: 14px; }
.dato:hover .lapiz, .dato .lapiz:focus-visible { color: var(--texto-2); border-color: var(--linea); }
.dato .lapiz:hover { color: var(--petroleo); border-color: var(--linea-fuerte); background: var(--fondo-2); }
@media (hover: none) { .dato .lapiz { color: var(--texto-3); } }
/* El valor no pasa por debajo del lápiz. */
.dato:has(> .lapiz) .clave { padding-right: 30px; }
.dato.editando .lapiz { display: none; }

/* El dato que se está editando: el campo y sus dos botones en un renglón. */
.editar-en-lugar { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
.editar-en-lugar input {
  flex: 1; min-width: 0;
  height: 32px; padding: 4px 9px;
  font: inherit; font-size: 13px;
  color: var(--texto);
  background: var(--superficie);
  border: 1px solid var(--linea-control);
  border-radius: var(--r-control);
}
.editar-en-lugar input:focus-visible { outline: 2px solid var(--verde); outline-offset: 1px; border-color: var(--verde); }
.editar-en-lugar .boton-icono { width: 32px; height: 32px; }
.editar-en-lugar .guardar { color: var(--verde-texto); border-color: var(--verde-linea); }
.editar-en-lugar .guardar:hover { background: var(--verde-tenue); color: var(--verde-texto); border-color: var(--verde-texto); }

.dato:nth-child(odd) { border-right: 1px solid var(--linea-suave); }

/* Debajo de la grilla: el botón que lleva a Editar pista y qué falta. */
.completar-datos {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 22px;
  border-top: 1px solid var(--linea-suave);
  font-size: 13px;
}
.dato:last-child, .dato:nth-last-child(2):nth-child(odd) { border-bottom: none; }
.dato .clave { margin-bottom: 3px; display: block; }
.dato .valor { font-size: 13px; overflow-wrap: anywhere; }
.dato .valor.mono { font-family: var(--mono); }
.sin-dato { color: var(--texto-3); font-style: italic; }

.fuente { border-left: 2px solid var(--linea); padding-left: 12px; margin-bottom: 16px; }
.fuente:last-child { margin-bottom: 0; }
.fuente .encabezado-fuente { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.fuente .encabezado-fuente strong { font-size: 13px; }
.fuente .encabezado-fuente .cuando { color: var(--texto-3); font-size: 12px; font-family: var(--mono); }
.fuente blockquote { margin: 0 0 8px; color: var(--texto-2); font-size: 13px; font-style: italic; }
.fuente .meta { font-size: 12px; }

/* En la ficha de un proyecto, las fuentes de sus partes, agrupadas por parte
   y con el nombre de la parte como rótulo. */
.fuentes-sin-propia { margin: 0 0 14px; }
.fuentes-de-parte { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--linea-suave); }
.fuentes-sin-propia + .fuentes-de-parte { margin-top: 0; padding-top: 0; border-top: none; }
.fuentes-de-parte > .rotulo { margin-bottom: 8px; }

/* El historial de la ficha, como línea de tiempo (lineaDeTiempoDeLaFicha).
   Un punto por movimiento y una línea que lo une con el siguiente; los cambios
   de estado, con punto lleno en verde, son los hitos que se buscan con la
   vista. Mismo lenguaje que el Historial de la administración, más chico. */
.linea-tiempo { list-style: none; margin: 0; padding: 4px 0 0; }
.lt-hito {
  position: relative;
  display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 10px;
  padding-bottom: 14px;
}
.lt-hito:last-child { padding-bottom: 0; }
/* De centro a centro: los puntos tapan la línea con su fondo. */
.lt-hito:not(:last-child)::before {
  content: ""; position: absolute;
  left: 7.5px; top: 10px; bottom: -10px;
  width: 1px; background: var(--linea);
}
.lt-punto {
  position: relative; z-index: 1;
  width: 9px; height: 9px; margin: 5px 0 0 3.5px;
  border-radius: 50%;
  border: 1.5px solid var(--texto-4);
  background: var(--superficie);
}
.lt-hito.estado .lt-punto {
  width: 11px; height: 11px; margin: 4px 0 0 2.5px;
  border-color: var(--verde); background: var(--verde);
  box-shadow: 0 0 0 3px var(--verde-tenue);
}
.lt-cuerpo { min-width: 0; }
.lt-que { margin: 0; font-size: 13px; line-height: 1.6; color: var(--texto-2); overflow-wrap: anywhere; }
.lt-que strong { color: var(--petroleo); font-weight: 600; }
.lt-valor { color: var(--texto); }
.lt-paso { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 5px; vertical-align: middle; }
.lt-paso .flecha { color: var(--texto-3); }
.lt-cuando { margin: 2px 0 0; font-family: var(--mono); font-size: 12px; color: var(--texto-3); }

/* --- comunicaciones con la obra -------------------------------------------
   La línea de tiempo de la ficha. Un riel con un nodo por comunicación, y el
   dibujo del nodo es el canal. Dos cosas tienen color y nada más:

   · la última vigente va con el nodo lleno, en petróleo: es "dónde estamos".
   · la carta documento va en coral siempre. Es el paso formal, la intimación
     con fecha cierta, y tiene que encontrarse de un vistazo entre veinte
     llamadas. Si cada canal tuviera su color, el coral dejaría de decir algo.

   El "+" es el único verde: es la acción del bloque. */

.acordeon-con-accion { position: relative; }
.acordeon-con-accion > .acordeon > summary .cuanto { margin-right: 40px; }

.boton-mas {
  position: absolute; top: 8px; right: 20px;
  width: 31px; height: 31px;
  display: grid; place-items: center;
  border: none; border-radius: var(--r-pastilla);
  background: var(--verde-boton);
  color: var(--sobre-verde);
  box-shadow: var(--sombra-verde);
  cursor: pointer;
  transition: background var(--rapido) var(--curva), transform var(--medio) var(--curva);
}
.boton-mas .ico { width: 15px; height: 15px; stroke-width: 2; }
/* Se levanta como "Cargar pista". No gira: a mitad de un giro el "+" es una
   "×", y en este panel la "×" cierra. */
.boton-mas:hover { background: var(--verde-boton-hover); transform: translateY(-1px); }
.boton-mas:active { transform: translateY(0); box-shadow: none; }

.comunicaciones { --nodo: 34px; --hueco: 14px; }

.linea-tiempo, .linea-tiempo ol { list-style: none; margin: 0; padding: 0; }
.linea-tiempo { position: relative; }

/* El riel: una sola línea detrás de todos los nodos. Arranca en el centro del
   primero y termina en el último, no sigue de largo hacia la nada. */
.linea-tiempo::before {
  content: "";
  position: absolute;
  left: calc(var(--nodo) / 2 - 1px);
  top: 30px; bottom: 32px;
  width: 2px;
  background: var(--linea);
  border-radius: 2px;
}

.dia-rotulo {
  position: relative;
  margin: 2px 0 10px calc(var(--nodo) + var(--hueco));
  font-stretch: 84%;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--texto-3);
}

.hito {
  position: relative;
  display: grid;
  grid-template-columns: var(--nodo) minmax(0, 1fr);
  gap: var(--hueco);
  padding-bottom: 12px;
}
.dia:last-child .hito:last-child { padding-bottom: 0; }

.nodo {
  position: relative; z-index: 1;
  width: var(--nodo); height: var(--nodo);
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--superficie);
  border: 1.5px solid var(--linea);
  color: var(--texto-2);
  /* El aro blanco separa el nodo del riel: sin él la línea parece atravesarlo. */
  box-shadow: 0 0 0 4px var(--superficie);
  margin-top: 4px;
}
.nodo > .ico { width: 15px; height: 15px; }

/* Quién la inició, en la esquina del nodo: sale del Colegio o entra. */
.nodo .sentido {
  position: absolute; right: -5px; bottom: -4px;
  width: 16px; height: 16px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--superficie);
  border: 1px solid var(--linea);
  color: var(--texto-3);
}
.nodo .sentido .ico { width: 9px; height: 9px; stroke-width: 2.4; }

.hito.ultima .nodo {
  background: var(--petroleo); border-color: var(--petroleo); color: #fff;
  box-shadow: 0 0 0 4px var(--superficie), 0 6px 14px -5px rgba(20, 72, 74, .55);
}

.hito.canal-carta-documento .nodo { background: var(--critico-tenue); border-color: var(--critico-linea); color: var(--critico); }
.hito.canal-carta-documento.ultima .nodo {
  background: var(--critico); border-color: var(--critico); color: #fff;
  box-shadow: 0 0 0 4px var(--superficie), 0 6px 14px -5px rgba(194, 65, 12, .55);
}
/* El nodo ya dice que es carta documento; la tarjeta lo acompaña con su borde. */
.hito.canal-carta-documento .hito-tarjeta { border-color: var(--critico-linea); }

.hito-tarjeta {
  min-width: 0;
  background: var(--superficie);
  border: 1px solid var(--linea-suave);
  border-radius: var(--r-tile);
  padding: 11px 14px 9px;
  box-shadow: var(--sombra-1);
}

.hito-cabeza { display: flex; align-items: baseline; gap: 10px; }
.hito-titulo { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; color: var(--texto); letter-spacing: -.005em; }
.hito-hora { font-family: var(--mono); font-size: 12px; color: var(--texto-3); font-variant-numeric: tabular-nums; }

.hito-con { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 13px; color: var(--texto-2); min-width: 0; }
.hito-con .ico { width: 12px; height: 12px; color: var(--texto-3); }
.hito-con span { overflow-wrap: anywhere; }

.hito-nota {
  margin: 8px 0 0;
  font-size: 13px; line-height: 1.55;
  color: var(--texto-2);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.hito-pie {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 9px; padding-top: 8px;
  border-top: 1px solid var(--linea-suave);
  font-size: 12px; color: var(--texto-3);
}
.hito-pie .anular { margin-left: auto; color: var(--texto-3); text-decoration: none; opacity: 0; transition: opacity var(--rapido) var(--curva); }
.hito:hover .anular, .hito-pie .anular:focus-visible { opacity: 1; }
.hito-pie .anular:hover { color: var(--critico); text-decoration: underline; }
/* En una pantalla táctil no hay "pasar el mouse": el botón queda a la vista. */
@media (hover: none) { .hito-pie .anular { opacity: 1; } }
.marca-anulada { margin-left: auto; color: var(--critico); }

/* Anulada: sigue a la vista, pero se lee como lo que es. */
.hito.anulada .nodo { opacity: .5; box-shadow: 0 0 0 4px var(--superficie); }
.hito.anulada .hito-tarjeta { background: var(--fondo-2); border-style: dashed; border-color: var(--linea); box-shadow: none; }
.hito.anulada .hito-titulo, .hito.anulada .hito-con span, .hito.anulada .hito-nota {
  color: var(--texto-3);
  text-decoration: line-through;
  text-decoration-color: var(--texto-4);
}

/* Entre dos días con más de uno de distancia, el riel se corta en puntos y
   dice cuántos pasaron. */
.pausa {
  position: relative;
  padding: 0 0 14px calc(var(--nodo) + var(--hueco));
}
.pausa::before {
  content: "";
  position: absolute; z-index: 1;
  left: calc(var(--nodo) / 2 - 1px);
  top: -10px; bottom: 2px;
  width: 2px;
  background: repeating-linear-gradient(to bottom, var(--linea-fuerte) 0 3px, var(--superficie) 3px 7px);
}
.pausa span {
  display: inline-block;
  font-family: var(--mono); font-size: 12px;
  color: var(--texto-3);
  background: var(--fondo-2);
  border: 1px solid var(--linea-suave);
  border-radius: var(--r-pastilla);
  padding: 1px 9px;
}

.ver-anteriores { display: inline-flex; align-items: center; gap: 6px; margin: 14px 0 0 calc(var(--nodo) + var(--hueco)); font-size: 12px; }
.ver-anteriores .ico { width: 12px; height: 12px; }

.vacio-comunicaciones .boton { margin-top: 14px; }
/* El ícono grande es el del vacío, no el del botón. */
.vacio-comunicaciones .boton .ico { display: inline; width: 14px; height: 14px; margin: 0; color: inherit; }

/* Lo que se acaba de anotar entra desde arriba y se ilumina un momento. */
.hito.recien .hito-tarjeta { animation: hito-recien 1100ms var(--curva) both; }
.hito.recien .nodo { animation: nodo-recien 420ms var(--curva) both; }
@keyframes hito-recien {
  0% { opacity: 0; transform: translateY(-6px); box-shadow: 0 0 0 4px var(--verde-brillo), var(--sombra-1); }
  30% { opacity: 1; transform: none; box-shadow: 0 0 0 4px var(--verde-brillo), var(--sombra-1); }
  100% { box-shadow: var(--sombra-1); }
}
@keyframes nodo-recien { from { transform: scale(.55); } to { transform: none; } }

/* --- el formulario del "+" ---------------------------------------------- */

.com-nueva {
  display: grid;
  grid-template-columns: var(--nodo) minmax(0, 1fr);
  gap: var(--hueco);
  margin-bottom: 20px;
  animation: abrir-acordeon 180ms var(--curva) both;
}
.nodo-nuevo {
  border: 1.5px dashed var(--verde);
  background: var(--verde-tenue);
  color: var(--verde-texto);
}
.nodo-nuevo > .ico { stroke-width: 2; }

.com-tarjeta {
  min-width: 0;
  border: 1px solid var(--verde-linea);
  border-radius: var(--r-tile);
  padding: 14px 14px 12px;
  background: var(--superficie);
  box-shadow: 0 0 0 4px var(--verde-tenue), var(--sombra-2);
}
.com-tarjeta fieldset { border: 0; padding: 0; margin: 0 0 14px; min-width: 0; }
.com-tarjeta legend { padding: 0; }
.com-tarjeta .campo:last-of-type { margin-bottom: 0; }
.com-tarjeta .acciones { margin-top: 14px; }
.com-tarjeta .aviso { margin: 12px 0 0; }
.opcional { color: var(--texto-3); font-size: 12px; margin-left: 4px; }

/* Los canales: cinco teclas con su dibujo. La elegida se enciende en
   petróleo; la carta documento, en coral. */
.canales { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.canal { position: relative; margin: 0; cursor: pointer; font-size: inherit; color: inherit; }
.canal input, .sentidos input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.canal-caja {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  height: 100%;
  padding: 11px 4px 9px;
  border: 1px solid var(--linea);
  border-radius: var(--r-control);
  background: var(--superficie);
  color: var(--texto-2);
  font-size: 12px; line-height: 1.2; text-align: center;
  transition: background var(--rapido) var(--curva), border-color var(--rapido) var(--curva), color var(--rapido) var(--curva), transform var(--rapido) var(--curva);
}
.canal-caja .ico { width: 18px; height: 18px; }
.canal:hover .canal-caja { border-color: var(--linea-fuerte); color: var(--texto); background: var(--superficie-2); }
.canal input:checked + .canal-caja {
  background: var(--petroleo); border-color: var(--petroleo); color: #fff;
  box-shadow: 0 6px 14px -6px rgba(20, 72, 74, .55);
  transform: translateY(-1px);
}
.canal-carta-documento input:checked + .canal-caja {
  background: var(--critico); border-color: var(--critico);
  box-shadow: 0 6px 14px -6px rgba(194, 65, 12, .55);
}
.canal input:focus-visible + .canal-caja, .sentidos input:focus-visible + span { outline: 2px solid var(--verde); outline-offset: 2px; }

/* Quién la inició y cuándo, en un renglón si entran. Los rótulos cambian con
   el canal ("Nos escribieron" es más largo que "La obra"), así que la fecha
   baja sola al renglón de abajo antes de quedar cortada. */
.com-fila { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-end; margin-bottom: 14px; }
.com-fila fieldset, .com-fila .campo { margin: 0; }
.com-fila .campo { flex: 1 1 215px; min-width: 0; }

/* Quién la inició: el mismo riel que el conmutador lista/mapa. */
.sentidos {
  display: inline-flex; gap: 2px;
  background: var(--superficie-2);
  border: 1px solid var(--linea-suave);
  border-radius: var(--r-control);
  padding: 3px;
}
.sentidos label { position: relative; margin: 0; cursor: pointer; font-size: inherit; color: inherit; }
.sentidos label > span {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px;
  border-radius: 5px;
  color: var(--texto-3);
  font-size: 13px; white-space: nowrap;
  transition: background var(--rapido) var(--curva), color var(--rapido) var(--curva);
}
.sentidos label > span .ico { width: 12px; height: 12px; stroke-width: 2; }
.sentidos label:hover > span { color: var(--texto-2); }
.sentidos input:checked + span { background: var(--superficie); color: var(--petroleo); font-weight: 600; box-shadow: var(--sombra-1); }

@media (max-width: 560px) {
  .canales { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .comunicaciones { --nodo: 30px; --hueco: 11px; }
}

/* El último contacto con la obra va en la misma tira pero no es una pastilla:
   es un dato, no una acción, y con borde se leía como un botón más. Neutro,
   salvo la carta documento, que va en coral como en la línea de tiempo de la
   ficha. El padding es el de adentro de una pastilla (borde incluido): el
   texto queda en la línea del de al lado, y cuando la tira no entra y baja
   a otro renglón, el ícono cae debajo de los íconos de las pastillas. */
.ultimo-contacto {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 0 5px 12px;
  font-size: 12px;
  color: var(--texto-3);
}
.ultimo-contacto .ico { width: 12px; height: 12px; flex: none; }
.ultimo-contacto.canal-carta-documento { color: var(--critico); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .hito.recien .hito-tarjeta, .hito.recien .nodo, .com-nueva { animation: none; }
  .boton-mas:hover, .boton-mas:active { transform: none; }
}

/* --- modal -----------------------------------------------------------------
   Cargar una pista dejó de ser una sección: se hace encima de lo que estabas
   mirando y te devuelve ahí. */

.velo-modal {
  position: fixed; inset: 0;
  background: rgba(20, 72, 74, .34);
  z-index: 50;
  display: flex; align-items: flex-start; justify-content: center;
  --aire-abajo: 48px;
  padding: 48px 24px var(--aire-abajo);
  overflow-y: auto;
  animation: aparecer 160ms var(--curva) both;
}

.modal {
  width: min(760px, 100%);
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-modal);
  box-shadow: var(--sombra-3);
  animation: entrar-modal 200ms var(--curva) both;
}

@keyframes entrar-modal {
  from { opacity: 0; transform: translateY(12px) scale(.99); }
  to { opacity: 1; transform: none; }
}

.modal .cabecera {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 22px 24px 16px;
  border-bottom: 1px solid var(--linea-suave);
}

.modal .cabecera div { flex: 1; }
.modal .cabecera h3 { font-size: 21px; font-weight: 650; margin: 0; letter-spacing: -.03em; color: var(--petroleo); }
.modal .cabecera .sub { margin: 4px 0 0; font-size: 13px; color: var(--texto-2); }
.modal .boton-icono { width: 32px; height: 32px; }
.modal .cuerpo { padding: 20px 24px 0; }

/* Los botones del alta quedan pegados al pie mientras se baja por el
   formulario: con «Más datos» abierto, «Cargar pista» quedaba a dos
   pantallas de los campos que se acababan de completar. */
.modal .cuerpo > .acciones {
  /* El sticky se frena antes del relleno de abajo del velo: el negativo lo
     baja hasta el borde de la pantalla. */
  position: sticky; bottom: calc(-1 * var(--aire-abajo, 0px)); z-index: 2;
  margin: 20px -24px 0;
  padding: 14px 24px;
  background: var(--superficie);
  border-top: 1px solid var(--linea);
  border-radius: 0 0 var(--r-modal) var(--r-modal);
}
.modal .bloque-fuente {
  border-top: 1px solid var(--linea-suave);
  border-bottom: 1px solid var(--linea-suave);
  padding: 18px 0 4px;
  margin: 4px 0 18px;
}

/* "Más datos": lo que casi nunca se carga en el alta, plegado al final. */
.modal .mas-datos { margin-top: 6px; }
.modal .mas-datos[open] > summary { margin-bottom: 14px; }

/* --- tablas ----------------------------------------------------------------
   Van adentro de una caja sin relleno propio: el borde de la caja hace de
   marco y las líneas de adentro separan filas. */

.tabla-envoltorio {
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--r-caja);
  overflow: hidden;
  overflow-x: auto;
}

.tarjeta .tabla-envoltorio { border: none; border-radius: 0; background: none; box-shadow: none; }

table { width: 100%; border-collapse: collapse; }

th {
  text-align: left;
  padding: 10px 14px;
  background: var(--fondo-2);
  border-bottom: 1px solid var(--linea-suave);
  font-stretch: 84%;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--texto-3);
  white-space: nowrap;
}

td { padding: 12px 14px; border-bottom: 1px solid var(--linea-suave); vertical-align: middle; font-size: 13px; }
tbody tr:last-child td { border-bottom: none; }
/* Las celdas van más juntas que antes (14px y no 20px): con nueve columnas,
   el período y el origen se partían en dos renglones. Los bordes de la tabla
   conservan el aire. */
th:first-child, td:first-child { padding-left: 20px; }
th:last-child, td:last-child { padding-right: 20px; }
/* En los expedientes, el período (2026-08) y la instancia son cortos y no se
   parten: el que cede ancho es el nombre del comitente. */
#lista-recaudacion td.sub { white-space: nowrap; }
#lista-recaudacion td:last-child .sub { white-space: nowrap; }
tbody tr { transition: background var(--rapido) var(--curva); }
tbody tr:hover { background: #f8fbfa; }

.tarjeta th, .tarjeta td { padding-left: 0; padding-right: 10px; }

td.der, th.der { text-align: right; }
td.der { font-variant-numeric: tabular-nums; white-space: nowrap; font-family: var(--mono); font-size: 12px; }
td.mono { font-family: var(--mono); font-size: 12px; color: var(--texto-2); }
tr.fila-total td { border-top: 1px solid var(--linea); border-bottom: none; font-weight: 600; }

/* --- recaudación: el cálculo ----------------------------------------------- */

.calculo:not(:empty) {
  margin: 18px 0;
  padding: 16px 18px;
  background: var(--fondo-2);
  border: 1px solid var(--linea-suave);
  border-radius: var(--r-panel);
}

.renglon-calculo {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 5px 0;
  font-size: 13px;
  color: var(--texto-2);
}

.renglon-calculo strong { font-variant-numeric: tabular-nums; font-family: var(--mono); font-size: 12px; color: var(--texto); }

.renglon-calculo.total {
  margin-top: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--linea);
  font-size: 14px;
  color: var(--texto);
}

.renglon-calculo.total strong { color: var(--verde-texto); font-size: 14px; }

/* La barra del mes: la proporción se lee antes que el número. */
.barra-mes { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 8px 0; border-bottom: 1px solid var(--linea-suave); font-size: 13px; }
.barra-mes:last-child { border-bottom: none; }
.barra-mes .clave { width: 62px; flex: none; color: var(--texto-2); }
/* Hasta dos renglones y no uno cortado: «COOPERATIVA DE ELECTRICIDAD Y OTROS
   SERVICI…» no decía de qué cooperativa era, y el nombre no estaba en ningún
   otro lado de la fila. */
.barra-mes .nombre {
  flex: 1; min-width: 0;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden; overflow-wrap: anywhere; line-height: 1.35;
}
.barra-mes .porcentaje, .barra-mes .importe { flex: none; font-variant-numeric: tabular-nums; }
.barra-mes .riel { flex: 1; height: 6px; border-radius: var(--r-pastilla); background: var(--superficie-2); overflow: hidden; }
.barra-mes .riel span { display: block; height: 100%; background: var(--verde); border-radius: var(--r-pastilla); }
.barra-mes .porcentaje { color: var(--texto-3); font-size: 12px; }
/* Cada fila tiene su detalle en un globo (conectarGlobos en panel.js): la
   fila lo dice al pasar por encima tiñendo su barra y su importe. */
.barra-mes[data-detalle] { border-radius: 6px; transition: background var(--rapido) var(--curva); }
.barra-mes[data-detalle]:hover .riel span { background: var(--verde-boton); }
.barra-mes[data-detalle]:hover .importe { color: var(--petroleo); }
.barra-mes .riel span { transition: background var(--rapido) var(--curva); }
.barra-mes .importe { transition: color var(--rapido) var(--curva); }

.globo {
  position: fixed; top: 0; left: 0; z-index: 80;
  max-width: min(340px, calc(100vw - 16px));
  padding: 8px 11px;
  background: var(--petroleo);
  color: #fff;
  border-radius: var(--r-chico);
  box-shadow: var(--sombra-3);
  font-size: 12px; line-height: 1.45;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.barra-mes .importe { font-family: var(--mono); font-variant-numeric: tabular-nums; width: 108px; text-align: right; font-size: 12px; }

/* minmax(0, 1fr) y no 1fr: con 1fr la columna de la derecha (nombres de
   comitentes largos, sin corte de línea) empujaba su mínimo y dejaba a la de
   la izquierda en 130px, con el riel de cada barra medido en cero. */
.dos-columnas { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }

/* --- mapa ------------------------------------------------------------------ */

#mapa {
  height: 560px;
  border: 1px solid var(--linea);
  border-radius: var(--r-caja);
  background: var(--fondo-2);
  overflow: hidden;
  margin-top: 20px;
}

#mapa .leaflet-popup-content-wrapper, #mapa .leaflet-popup-tip {
  background: var(--superficie);
  color: var(--texto);
  border: 1px solid var(--linea-suave);
  border-radius: var(--r-panel);
  box-shadow: var(--sombra-3);
}

#mapa .leaflet-popup-content { margin: 13px 15px; font-family: var(--tipo); }
#mapa .leaflet-popup-content .titulo-popup { font-weight: 600; font-size: 14px; margin-bottom: 5px; }
#mapa .leaflet-popup-content .nota-popup { color: var(--texto-3); font-size: 12px; margin-top: 6px; }
#mapa .leaflet-popup-close-button { color: var(--texto-3); }
#mapa .partes-popup { display: grid; gap: 4px; margin-top: 8px; }
#mapa .partes-popup button {
  display: flex; justify-content: space-between; gap: 10px; padding: 5px 8px;
  background: var(--fondo-2); border: 1px solid var(--linea-suave); border-radius: var(--r-control);
  color: var(--texto); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
#mapa .partes-popup button:hover { border-color: var(--linea-fuerte); }
#mapa .partes-popup .tenue { color: var(--texto-3); white-space: nowrap; }
#mapa .partes-popup button { align-items: center; }
#mapa .partes-popup button.coincide { border-color: var(--frio-linea); font-weight: 600; }
#mapa .chips-popup { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
#mapa .leaflet-container { font-family: inherit; }
#mapa .leaflet-control-attribution { background: rgba(255, 255, 255, .86); color: var(--texto-3); }
#mapa .leaflet-control-attribution a { color: var(--texto-3); }
#mapa .leaflet-bar a { background: var(--superficie); color: var(--texto); border-color: var(--linea); }
#mapa .leaflet-bar a:hover { background: var(--superficie-2); }

/* El mosaico de OpenStreetMap, apenas desaturado para que los puntos de
   color (que son la información) se lean por encima del dibujo. */
#mapa .leaflet-tile-pane.mosaico-claro { filter: saturate(.55) contrast(.95); }

#nota-mapa { margin: 8px 2px 0; }

/* La leyenda, debajo del mapa: color, relleno y tamaño de los puntos. */
.leyenda-mapa { display: flex; flex-wrap: wrap; gap: 6px 22px; margin: 12px 2px 0; font-size: 12px; color: var(--texto-2); }
.leyenda-mapa:empty { display: none; }
.leyenda-mapa > div { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.leyenda-mapa .muestra {
  display: inline-block; width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid var(--c); background: var(--c);
}
.leyenda-mapa .muestra.grande { width: 14px; height: 14px; }
.leyenda-mapa .muestra.translucida { background: rgba(126, 156, 147, .35); }

/* --- contacto --------------------------------------------------------------

   El correo y el teléfono son el medio por el que el fiscalizador habla con la
   obra. Van en pastilla, neutros, y recién se encienden cuando el mouse
   confirma que se los va a usar: no dicen nada sobre la pista, son una acción.
   El texto va completo, con el interno y la anotación tal como se cargaron;
   el número que se marca lo arma el panel aparte. */

.contacto-rapido { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }

.chip-contacto {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--linea);
  border-radius: var(--r-pastilla);
  background: var(--fondo-2);
  color: var(--texto-2);
  font: inherit; font-size: 12px;
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--rapido) var(--curva), color var(--rapido) var(--curva);
}

.chip-contacto:hover { border-color: var(--linea-fuerte); color: var(--texto); }
.chip-contacto .ico { width: 12px; height: 12px; color: var(--texto-3); }
.chip-contacto:hover .ico { color: var(--verde); }

.panel-ficha .contacto-rapido { margin: 0 0 18px; }
.panel-ficha .chip-contacto { padding: 7px 13px; font-size: 12px; background: var(--superficie); }
.panel-ficha .chip-contacto.lapiz-contacto { padding: 7px 9px; }

/* Confirmación de que el correo quedó copiado: verde un segundo y vuelve. Sin
   esto hay que ir a pegar a otro lado para saber si funcionó. */
.chip-contacto.copiado,
.boton.copiado {
  border-color: var(--verde-linea);
  background: var(--verde-tenue);
  color: var(--verde-texto);
}

.chip-contacto.copiado .ico, .boton.copiado .ico { color: var(--verde-texto); }

/* --- aviso de versión nueva --------------------------------------------------
   Abajo a la derecha, encima de todo, con el verde de la marca: no es una
   alarma, es una novedad. No tapa nada importante y no se va solo. */
.aviso-version {
  position: fixed;
  right: 24px;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: flex; align-items: center; gap: 14px;
  width: min(460px, calc(100vw - 32px));
  padding: 14px 16px;
  border: 1px solid var(--verde-linea);
  border-radius: var(--r-panel);
  background: var(--superficie);
  box-shadow: var(--sombra-3);
  animation: entrar-modal 200ms var(--curva) both;
}

.aviso-version .icono-version {
  flex: none;
  width: 36px; height: 36px;
  border-radius: var(--r-tile);
  background: var(--verde-tenue);
  color: var(--verde-texto);
  display: grid; place-items: center;
}

.aviso-version .icono-version .ico { width: 17px; height: 17px; }
.aviso-version .texto-version { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.aviso-version .texto-version strong { font-size: 14px; font-weight: 600; }
.aviso-version .texto-version span { font-size: 12px; color: var(--texto-2); }
.aviso-version .botones-version { flex: none; display: flex; flex-direction: column; align-items: stretch; gap: 4px; }

.boton-texto {
  background: none; border: none;
  padding: 4px 6px;
  color: var(--texto-3);
  font: inherit; font-size: 12px;
  cursor: pointer;
}

.boton-texto:hover { color: var(--texto); }
.boton-texto:focus-visible { outline: 2px solid var(--verde); outline-offset: 2px; border-radius: 6px; }

/* En la tabla de cuentas, «Nueva contraseña» y «Dar de baja» son acciones y se
   leían como una nota gris al margen. Dar de baja se tiñe de coral al pasar:
   deja a alguien sin entrar (y pide confirmación). */
#lista-cuentas .boton-texto { color: var(--verde-texto); font-weight: 500; }
#lista-cuentas .boton-texto:hover { color: var(--petroleo); text-decoration: underline; text-underline-offset: 3px; }
#lista-cuentas .boton-texto[data-cuenta="baja"]:hover { color: var(--critico); }

@media (max-width: 560px) {
  .aviso-version { right: 16px; left: 16px; width: auto; flex-wrap: wrap; }
  .aviso-version .botones-version { flex-direction: row; width: 100%; justify-content: flex-end; }
}

/* --- responsive ------------------------------------------------------------ */

@media (max-width: 980px) {
  .app { grid-template-columns: minmax(0, 1fr); }

  /* Sin altura fija la barra no scrollea, y así el menú de la cuenta puede
     colgar por debajo de ella. */
  aside.lateral {
    position: static; height: auto;
    overflow: visible;
    flex-direction: row; align-items: center; flex-wrap: wrap;
    gap: 12px; padding: 12px 16px;
  }

  /* El logo, el producto y la cuenta pasan a ser parte de la fila de la
     barra: la cuenta se va a la punta derecha, después de «Cargar pista». */
  .marca, .marca .fila-producto { display: contents; }
  .marca .logo-cipba { width: 168px; margin: -4px -3px; }
  .marca .producto { flex: none; }
  .marca .producto strong { font-size: 13px; }
  .boton-alta { width: auto; order: 2; margin-left: auto; }
  .cuenta { order: 3; }
  /* Las secciones van en una sola fila que se desliza de costado: en dos
     renglones el menú ocupaba media pantalla antes de llegar a la bandeja. */
  nav.secciones {
    flex-direction: row; flex-wrap: nowrap; gap: 3px; order: 4;
    overflow-x: auto; scrollbar-width: none;
    margin: 0 -16px; padding: 2px 16px; width: calc(100% + 32px);
  }
  nav.secciones::-webkit-scrollbar { display: none; }
  nav.secciones button { width: auto; flex: none; font-size: 13px; padding: 7px 10px; white-space: nowrap; }
  aside.lateral .vigiladas { display: none; }

  .contenido { margin: 0 6px 6px; padding: 22px 16px 56px; }
  .encabezado h2 { font-size: 23px; }
  .dos-columnas { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 760px) {
  /* En celular la columna de acciones no entra al lado del texto: baja a una
     fila propia debajo de la tarjeta. */
  .pista { grid-template-columns: 3px auto 1fr; gap: 12px; padding: 14px; }
  .pista .derecha { grid-column: 1 / -1; justify-self: stretch; justify-content: flex-start; flex-wrap: wrap; }

  /* Los filtros, de a dos por renglón: uno por renglón eran siete renglones
     antes de la primera pista. Los que no tienen selector van a lo ancho. */
  #filtros { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* El orden baja debajo del buscador, a lo ancho. */
  .barra-buscar { flex-wrap: wrap; }
  .barra-buscar .filtro.orden { flex: 1 1 100%; }
  .barra-buscar .filtro.orden select { flex: 1; min-width: 0; }
  .opciones-descarte { right: auto; left: 0; width: min(262px, calc(100vw - 72px)); }
  .datos { grid-template-columns: 1fr; }
  .dato:nth-child(odd) { border-right: none; }
  .velo-modal { --aire-abajo: 40px; padding: 16px 12px var(--aire-abajo); }
  .panel-ficha .cuerpo, .panel-ficha .cabecera, .acciones-ficha { padding-left: 16px; padding-right: 16px; }
  /* Las cinco decisiones llenan cada renglón: de tres y dos con su ancho
     natural, los bordes de la derecha quedaban serruchados. */
  .acciones-ficha .boton { flex: 1 1 auto; justify-content: center; }
  .acordeon { margin: 0 -16px; }

  /* Las pestañas, en una fila que se desliza como el menú: «Corridas y
     cuentas» se partía en tres renglones y la barra empujaba la página de
     costado (medía 439px en una pantalla de 390). La elegida se trae a la
     vista al tocarla (elegidoALaVista). */
  .pestanas, .conmutador.relojes { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
  .pestanas::-webkit-scrollbar, .conmutador.relojes::-webkit-scrollbar { display: none; }
  .pestanas button, .conmutador.relojes button { flex: none; white-space: nowrap; }
  /* Una fila que sigue a la derecha lo dice con una flecha pegada al borde
     (la clase la pone filaQueSigue en panel.js). Sin ella, si el corte caía
     justo entre dos pestañas («…Corridas y cuentas|»), Distritos y Uso no
     existían para quien no deslizara. Al llegar al final se va. */
  .sigue::after {
    content: ""; flex: none;
    position: sticky; right: 0; z-index: 2;
    width: 34px; margin-left: -34px;
    pointer-events: none;
    background:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234c6f6d' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E") right 4px center / 13px no-repeat,
      linear-gradient(to right, transparent, var(--fondo-2) 55%);
  }
  /* El menú tiene 16px de relleno a los costados, y lo pegajoso se pega
     adentro del relleno: se corre hasta el borde de la pantalla. */
  nav.secciones.sigue::after {
    right: -16px;
    background:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234c6f6d' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E") right 4px center / 13px no-repeat,
      linear-gradient(to right, transparent, var(--marco) 55%);
  }

  /* Las fechas del encabezado (Recaudación) se reparten la fila: con el
     espaciador, «Desde» quedaba a la derecha y «Hasta» bajaba sola a la
     izquierda. */
  .encabezado .espaciador:has(+ .filtro) { display: none; }
  .encabezado > .filtro { flex: 1 1 140px; }
  .encabezado > .filtro input { min-width: 0; }
  .acordeon > summary, .acordeon .contenido-acordeon, .dato { padding-left: 16px; padding-right: 16px; }
  .modal .cabecera, .modal .cuerpo { padding-left: 16px; padding-right: 16px; }
  .modal .cuerpo > .acciones { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; }
  th, td { padding-left: 14px; padding-right: 14px; }

  /* La cápsula de licitación no entra en una línea: los hitos bajan enteros,
     sin la línea divisoria, que en un renglón nuevo quedaría colgando. */
  .capsula-licitacion { flex-wrap: wrap; }
  .capsula-licitacion .tramo + .tramo { border-left: none; }
  .capsula-licitacion .tramo { padding: 3px 10px; }
}

/* En pantalla táctil no hay mouse que revele nada: lo que en escritorio
   aparece al pasar por encima, acá queda puesto siempre. */
@media (hover: none) {
  .acciones-rapidas { opacity: 1; pointer-events: auto; }
  .pista .tilde { opacity: 1; }
}

/* Con el dedo, todo lo que se toca mide al menos 44px. Los controles que
   crecen (botones, pestañas, filtros) crecen de verdad; los que están
   encajados en una esquina (la casilla, los íconos) mantienen el dibujo y
   agrandan la zona que responde con un ::before invisible alrededor. */
@media (pointer: coarse) {
  .boton, .boton.chico, .miga .boton.chico,
  nav.secciones button, .pestanas button, .conmutador button,
  .filtro, .numero-pagina, .chip-contacto, .limpiar-filtros { min-height: 44px; }
  .boton-icono, button.accion { width: 40px; height: 40px; }

  .pista .tilde { width: 24px; height: 24px; top: -10px; left: -10px; }
  .pista .tilde:checked::after { left: 8px; top: 3px; width: 5px; height: 11px; }

  /* .pista .tilde y .boton-mas ya van con position: absolute. */
  .boton-icono, button.accion, .numero-pagina { position: relative; }
  .boton-icono::before, button.accion::before, .boton-mas::before,
  .pista .tilde::before, .numero-pagina::before {
    content: "";
    position: absolute;
    inset: -8px;
  }

  /* El mapa en el celular: más bajo que la pantalla, para que siempre quede
     página arriba o abajo donde apoyar el dedo y seguir bajando. Adentro del
     mapa, el dedo mueve el mapa: es lo que se espera de un mapa. */
  #mapa { height: min(420px, 60vh); }
}

/* --- quien pidió que no se mueva nada --------------------------------------
   No es un detalle de accesibilidad opcional: hay gente a la que el
   movimiento le da náuseas o le dispara una migraña. El panel tiene que
   quedar completamente utilizable, así que se apaga todo, incluido el
   barrido del radar. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }

  body.cargando::after { animation: none; width: 100vw; opacity: .6; }
}

/* --- la entrada del radar --------------------------------------------------
   Un velo blanco sobre todo, con el canvas de intro.js adentro. La clase
   "intro" en <html> la pone un script en el <head> antes de pintar nada, y
   solo si la persona no pidió que no se mueva nada; sin la clase, el velo
   no se muestra y el panel aparece como siempre. Cuando intro.js termina,
   "intro" se cambia por "intro-saliendo": el velo se funde y el panel entra
   desde abajo, apenas. */

html.intro body { overflow: hidden; }
/* visibility y no solo opacity: con el panel transparente, Tab caía en
   botones que no se veían detrás del velo. */
html.intro .app { opacity: 0; visibility: hidden; }
html.intro-saliendo .app { animation: revelar-app 760ms var(--curva) both; }

@keyframes revelar-app {
  from { opacity: 0; transform: translateY(12px) scale(.992); }
  to { opacity: 1; transform: none; }
}

#intro-radar {
  position: fixed; inset: 0;
  z-index: 200;
  display: none;
  background: #fff;
  cursor: pointer;
  user-select: none;
}

html.intro #intro-radar, html.intro-saliendo #intro-radar { display: block; }
html.intro-saliendo #intro-radar { opacity: 0; transition: opacity 600ms var(--curva); pointer-events: none; }

#intro-radar canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

#intro-radar .intro-logo {
  position: absolute;
  top: 26px; left: 28px;
  width: 150px; height: auto;
  animation: aparecer 600ms var(--curva) 200ms both;
}

#intro-radar .intro-texto {
  position: absolute;
  left: 50%; bottom: max(7vh, 40px);
  transform: translateX(-50%);
  width: min(620px, 92vw);
  text-align: center;
  animation: aparecer 600ms var(--curva) 350ms both;
}

#intro-radar .rotulo { color: var(--verde-texto); margin-bottom: 10px; }

#intro-radar .estado {
  margin: 0;
  font-size: 15px;
  color: var(--petroleo);
  letter-spacing: -.01em;
  text-wrap: balance;
}

#intro-radar .estado.cambia { animation: subir-texto 360ms var(--curva) both; }

@keyframes subir-texto {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

#intro-radar .contador {
  margin: 8px 0 0;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}

#intro-radar .contador span { color: var(--critico); font-weight: 600; }

#intro-radar .saltar {
  margin: 26px 0 0;
  font-size: 12px;
  color: var(--texto-3);
  letter-spacing: .08em;
  text-transform: uppercase;
}

@media (max-width: 600px) {
  #intro-radar .intro-logo { width: 118px; top: 18px; left: 18px; }
  #intro-radar .estado { font-size: 14px; }
}

/* --- papelera ------------------------------------------------------------- */

/* Cada fila es un antecedente: quién la sacó, por qué, y qué se puede hacer.
   Va en gris tenue a propósito: es lo que ya no está en la bandeja. */
/* Como la bandeja: una lista con una línea entre fila y fila, no una pila
   de cajas. */
.lista-papelera { display: flex; flex-direction: column; margin-top: 16px; }
.lista-papelera:has(> .fila-papelera) { border: 1px solid var(--linea); border-radius: var(--r-caja); background: var(--superficie); }

.fila-papelera {
  background: var(--superficie);
  border-bottom: 1px solid var(--linea-suave);
  padding: 16px 20px;
  transition: background var(--rapido) var(--curva);
}
.lista-papelera > .fila-papelera:first-child { border-top-left-radius: calc(var(--r-caja) - 1px); border-top-right-radius: calc(var(--r-caja) - 1px); }
.lista-papelera > .fila-papelera:last-of-type { border-bottom: none; border-bottom-left-radius: calc(var(--r-caja) - 1px); border-bottom-right-radius: calc(var(--r-caja) - 1px); }
.fila-papelera:hover { background: #f8fbfa; }
.fila-papelera .cabeza { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 15px; color: var(--petroleo); }
.fila-papelera p { margin: 6px 0 0; font-size: 13px; }
.fila-papelera .quien { display: flex; align-items: center; gap: 6px; color: var(--texto-2); }
.fila-papelera .quien .ico { width: 14px; height: 14px; flex: none; color: var(--texto-3); }
.fila-papelera .porque { color: var(--texto); }
/* El renglón del partido y el tipo comparte nombre con la grilla de datos de
   la ficha (.datos), que le ponía dos columnas y una raya arriba: quedaba una
   línea cruzando la fila entre el motivo y el lugar. */
.fila-papelera .datos { display: block; border-top: 0; background: none; }
.fila-papelera .acciones { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.fila-papelera .acciones .boton { padding: 6px 11px; font-size: 12.5px; }
.fila-papelera .restaurar { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.fila-papelera .restaurar textarea { width: 100%; font: inherit; }
.fila-papelera .restaurar .botones { display: flex; gap: 8px; flex-wrap: wrap; }

.proteccion-papelera { display: flex; align-items: center; gap: 8px; margin: 14px 0 0; font-size: 12.5px; color: var(--texto-3); }
.proteccion-papelera .ico { width: 14px; height: 14px; color: var(--verde-texto); }

.mas-papelera { display: flex; justify-content: center; margin-top: 16px; }

/* --- historial de movimientos ------------------------------------------------
   Lo que hizo cada persona, para la administración. Los cinco colores de los
   grupos salen de la marca y están probados para que dos vecinos del gráfico
   se distingan también con daltonismo, en este orden: verde, azul, ámbar,
   violeta, magenta. El ámbar tiene poco contraste sobre blanco, así que nunca
   va solo: el gráfico lleva leyenda y globo, y cada cifra se escribe. Lo que
   se lee (íconos, texto) va en la versión oscura de cada uno (--g-tinta). */

:root {
  --g-decision: #00a48a;
  --g-comunicacion: #2b57c9;
  --g-alta: #d39a1c;
  --g-edicion: #8a5bd6;
  --g-otros: #d0628f;
}
.g-decision { --g: var(--g-decision); --g-tinta: var(--verde-texto); --g-fondo: var(--verde-tenue); }
.g-comunicacion { --g: var(--g-comunicacion); --g-tinta: var(--frio); --g-fondo: var(--frio-tenue); }
.g-alta { --g: var(--g-alta); --g-tinta: var(--atencion); --g-fondo: var(--atencion-tenue); }
.g-edicion { --g: var(--g-edicion); --g-tinta: var(--violeta); --g-fondo: var(--violeta-tenue); }
.g-otros { --g: var(--g-otros); --g-tinta: #a23a68; --g-fondo: #fdf0f5; }
.g-ingreso { --g: var(--texto-4); --g-tinta: var(--texto-3); --g-fondo: var(--superficie-2); }
.g-todos { --g: var(--petroleo); }

/* Siete cifras en una fila: más angostas que las de la bandeja. */
#metricas-historial .metrica { flex-basis: 118px; padding: 14px 16px; }
#metricas-historial .metrica .rotulo::before { background: var(--g, var(--texto-4)); }
#metricas-historial .metrica .detalle { line-height: 1.35; }

.muestra {
  display: inline-block; flex: none;
  width: 10px; height: 10px;
  border-radius: 3px;
  background: var(--g);
}

.historial-cuerpo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 18px;
  align-items: start;
}
.historial-principal { min-width: 0; }
.historial-principal > .tarjeta { margin-bottom: 18px; }

/* --- el gráfico ---------------------------------------------------------- */

.cabeza-grafico {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 8px 16px;
  margin-bottom: 18px;
}
.cabeza-grafico h3 { margin: 0; }
.leyenda-grafico {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 4px 14px;
  font-size: 12px; color: var(--texto-2);
}
.leyenda-grafico li { display: inline-flex; align-items: center; gap: 6px; }

.grafico {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 10px;
}
/* El eje: tres números redondos, apenas visibles. Las guías son una línea
   de pelo y no se cortan: el dato es lo único que tiene peso. */
.grafico .eje { position: relative; height: 160px; }
.grafico .eje span {
  position: absolute; right: 0;
  transform: translateY(50%);
  font-family: var(--mono); font-size: 11px;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}
.grafico .plano {
  position: relative;
  height: 160px;
  margin-bottom: 26px;
  border-bottom: 1px solid var(--linea-fuerte);
}
.grafico .guia { position: absolute; left: 0; right: 0; height: 1px; background: var(--linea-suave); }
.grafico .columnas { position: absolute; inset: 0; display: flex; }

/* Cada columna es todo el alto: se apunta a un día, no a una barrita. */
.grafico .col {
  position: relative;
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: flex-end; justify-content: center;
  padding: 0; border: 0; border-radius: 6px 6px 0 0;
  background: none;
  font: inherit; color: inherit;
  cursor: pointer;
  transition: background var(--rapido) var(--curva);
}
.grafico .col:hover, .grafico .col:focus-visible { background: var(--superficie-2); }
.grafico .col:focus-visible { outline-offset: -2px; }

/* Columnas finas y con aire: nunca llenan el lugar. Entre un grupo y otro,
   un hueco blanco de 2px; la punta redondeada, la base recta. */
.grafico .pila {
  width: min(24px, 68%);
  display: flex; flex-direction: column-reverse; gap: 2px;
  transform-origin: bottom;
}
.grafico .pila .seg { flex: 1 1 0; min-height: 1px; background: var(--g); }
.grafico .pila .seg:last-child { border-radius: 4px 4px 0 0; }
.grafico .rotulo-col {
  position: absolute; top: 100%; left: 50%;
  margin-top: 7px;
  transform: translateX(-50%);
  font-size: 11px; white-space: nowrap;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}
.grafico .col.hoy .rotulo-col { color: var(--petroleo); font-weight: 600; }

.globo-grafico { min-width: 180px; }
.globo-grafico ul { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 3px; }
.globo-grafico li, .globo-grafico .total { display: flex; align-items: center; gap: 7px; }
.globo-grafico .muestra { box-shadow: 0 0 0 1px rgba(255, 255, 255, .55); }
.globo-grafico .n { margin-left: auto; padding-left: 16px; font-family: var(--mono); }
.globo-grafico .total { margin-top: 6px; padding-top: 5px; border-top: 1px solid rgba(255, 255, 255, .22); font-weight: 600; }
.globo-grafico .tenue-claro { margin-top: 4px; opacity: .75; }

/* --- la lista ------------------------------------------------------------ */

.movimientos { --nodo: 30px; --hueco: 12px; --hora: 42px; list-style: none; margin: 18px 0 0; padding: 0; }
.movimientos .vacio { list-style: none; }
.dia-historial + .dia-historial { margin-top: 22px; }
.dia-historial > ol { position: relative; list-style: none; margin: 0; padding: 0; }

/* El riel une los nodos del día, como la línea de tiempo de comunicaciones. */
.dia-historial > ol::before {
  content: "";
  position: absolute;
  left: calc(var(--hora) + var(--hueco) + var(--nodo) / 2 - 1px);
  top: 16px; bottom: 16px;
  width: 2px;
  background: var(--linea-suave);
  border-radius: 2px;
}

.movimientos .dia-rotulo {
  display: flex; align-items: baseline; gap: 10px;
  margin: 0 0 6px;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--linea-suave);
}
.movimientos .dia-rotulo .cuantos {
  margin-left: auto;
  font-family: var(--mono); font-size: 11px; font-weight: 400;
  letter-spacing: 0; text-transform: none;
  color: var(--texto-3);
}

.mov {
  position: relative;
  display: grid;
  grid-template-columns: var(--hora) var(--nodo) minmax(0, 1fr);
  gap: 0 var(--hueco);
  align-items: start;
  padding: 8px 0;
}
.mov-hora {
  padding-top: 7px;
  text-align: right;
  font-family: var(--mono); font-size: 12px;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}
.mov-nodo {
  position: relative; z-index: 1;
  width: var(--nodo); height: var(--nodo);
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--g-fondo);
  color: var(--g-tinta);
  /* El aro blanco separa el nodo del riel. */
  box-shadow: 0 0 0 4px var(--superficie);
}
.mov-nodo .ico { width: 14px; height: 14px; }
.mov.carta-documento .mov-nodo { background: var(--critico-tenue); color: var(--critico); }

.mov-cuerpo { min-width: 0; padding-top: 4px; }
.mov-frase { margin: 0; line-height: 1.55; color: var(--texto-2); overflow-wrap: anywhere; }
/* Centrada en el renglón: con -6px la cara quedaba medio renglón más abajo que
   el nombre que acompaña. */
.mov-frase .cara.chica { margin-right: 6px; vertical-align: middle; position: relative; top: -1px; }
.mov-quien, .mov-obra {
  padding: 0; border: 0; background: none;
  font: inherit; font-weight: 600;
  cursor: pointer;
  text-align: left;
  text-underline-offset: 2px;
}
.mov-quien { color: var(--petroleo); }
.mov-obra { color: var(--verde-texto); }
.mov-quien:hover, .mov-obra:hover { text-decoration: underline; }

.mov-paso { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 7px; font-size: 12.5px; }
.flecha { color: var(--texto-3); }
.mov-cambios {
  list-style: none;
  display: grid; gap: 4px;
  margin: 7px 0 0; padding: 8px 11px;
  background: var(--fondo-2);
  border-radius: var(--r-chico);
  font-size: 12.5px;
}
.mov-cambios li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 7px; }
.mov-cambios .campo { min-width: 112px; color: var(--texto-3); }
.mov-cambios .antes { color: var(--texto-3); text-decoration: line-through; text-decoration-color: var(--linea-fuerte); }
.mov-cambios .despues { color: var(--petroleo); font-weight: 500; }
.mov-texto { margin: 6px 0 0; font-size: 13px; color: var(--texto-2); overflow-wrap: anywhere; }
.mov-texto.tachada { text-decoration: line-through; color: var(--texto-3); }
.mov-nota { margin: 7px 0 0; padding-left: 9px; border-left: 2px solid var(--linea); font-size: 12.5px; color: var(--texto-2); }

/* Entrar al panel no es trabajo: una línea chica, sin tarjeta ni color. */
.mov.g-ingreso { padding: 3px 0; }
.mov.g-ingreso .mov-hora { padding-top: 2px; }
.mov.g-ingreso .mov-nodo { height: 22px; background: var(--superficie); }
.mov.g-ingreso .mov-nodo .ico { width: 12px; height: 12px; color: var(--texto-4); }
.mov.g-ingreso .mov-frase { padding-top: 1px; font-size: 12.5px; color: var(--texto-3); }
.mov.g-ingreso .mov-quien { font-weight: 500; color: var(--texto-2); }
.mov.g-ingreso .cara { display: none; }

.mas-historial { display: flex; justify-content: center; margin-top: 16px; }

/* La fila de filtros llena el ancho del buscador de arriba: eran pastillas
   sueltas en un renglón de texto y terminaban antes, con los dos bordes
   derechos sin coincidir. */
.historial-principal > .filtros { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.historial-principal > .filtros > .filtro { flex: 1 1 auto; }

/* Las dos fechas en una sola pastilla: es un solo filtro, el período. */
.filtro-fechas input { flex: 1 1 118px; width: 118px; min-width: 0; }

/* --- las personas ---------------------------------------------------------- */

.cara {
  display: inline-grid; place-items: center; flex: none;
  width: 36px; height: 36px;
  border-radius: 50%;
  font-size: 13px; font-weight: 700; letter-spacing: .02em;
}
.cara.chica { width: 22px; height: 22px; font-size: 9.5px; }
.cara.tinte-0 { background: var(--verde-tenue); color: var(--verde-texto); }
.cara.tinte-1 { background: var(--frio-tenue); color: var(--frio); }
.cara.tinte-2 { background: var(--violeta-tenue); color: var(--violeta); }
.cara.tinte-3 { background: var(--atencion-tenue); color: var(--atencion); }
.cara.tinte-4 { background: var(--superficie-2); color: var(--petroleo); }

.personas-historial { position: sticky; top: 20px; padding: 18px 12px 12px; }
.personas-historial > h3, .personas-historial > .sub { margin-left: 10px; margin-right: 10px; }
.personas-historial > .sub { margin-bottom: 10px; }

.persona {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  gap: 11px;
  align-items: start;
  width: 100%;
  padding: 10px;
  border: 0; border-radius: var(--r-panel);
  background: none;
  font: inherit; color: inherit; text-align: left;
  cursor: pointer;
  transition: background var(--rapido) var(--curva), box-shadow var(--rapido) var(--curva);
}
.persona:hover { background: var(--superficie-2); }
.persona[aria-pressed="true"] { background: var(--verde-tenue); box-shadow: inset 3px 0 0 var(--verde); }
.persona-cuerpo { display: grid; gap: 6px; min-width: 0; }
.persona-nombre { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 0; min-width: 0; line-height: 1.3; }
.persona-nombre strong { color: var(--petroleo); font-weight: 650; overflow-wrap: anywhere; }
.persona-nombre .rol-chip { font-size: 10.5px; padding: 0 7px; }
.persona-pie { font-size: 12px; line-height: 1.4; color: var(--texto-3); }
.persona-cifra {
  padding-top: 1px;
  font-size: 21px; font-weight: 700; line-height: 1;
  letter-spacing: -.03em;
  color: var(--petroleo);
}

/* De qué fue lo que hizo, en proporción; el largo dice cuánto, contra el
   que más hizo en el período. */
.mezcla { display: flex; gap: 2px; height: 6px; }
.mezcla .seg { flex: 1 1 0; min-width: 2px; background: var(--g); }
.mezcla .seg:first-child { border-radius: 3px 0 0 3px; }
.mezcla .seg:last-child { border-radius: 0 3px 3px 0; }
.mezcla .seg:only-child { border-radius: 3px; }

/* Un día por rayita: si trabaja todos los días o en tandas. */
.huella { display: flex; align-items: flex-end; gap: 1px; height: 16px; border-bottom: 1px solid var(--linea); }
.huella span { flex: 1 1 0; min-width: 0; background: var(--linea-control); border-radius: 1px 1px 0 0; }
.persona[aria-pressed="true"] .huella span { background: var(--verde-linea); }

.personas-quietas { margin-top: 10px; padding-top: 12px; border-top: 1px solid var(--linea-suave); }
.personas-quietas > .rotulo { margin: 0 10px 2px; }
.persona.quieta { grid-template-columns: 36px minmax(0, 1fr); }
.persona.quieta .cara { opacity: .65; }

/* Angosto: una sola columna, y las personas entre el gráfico y la lista. */
@media (max-width: 1100px) {
  .historial-cuerpo { grid-template-columns: minmax(0, 1fr); }
  .historial-principal { display: contents; }
  .historial-principal > .tarjeta { order: 1; margin-bottom: 0; }
  .personas-historial { order: 2; position: static; }
  .historial-principal > .barra-buscar { order: 3; }
  .historial-principal > .filtros { order: 4; margin-top: -8px; }
  .movimientos { order: 5; margin-top: 0; }
  .mas-historial { order: 6; margin-top: 0; }
  .historial-cuerpo { gap: 14px; }
}

@media (max-width: 560px) {
  /* En el celular, las cifras sin su explicación: tres por fila. */
  /* Sin el detalle, la cifra va al pie: si un rótulo ocupa dos renglones
     («Comunicaciones», «Licitaciones demoradas») las cifras de la fila siguen
     en la misma línea. */
  #metricas-historial .metrica { flex-basis: 30%; padding: 12px 14px; justify-content: space-between; }
  #metricas-historial .metrica .rotulo { margin-bottom: 6px; font-size: 11px; letter-spacing: .06em; }
  #metricas-historial .metrica .numero { font-size: 22px; }
  #metricas-historial .metrica .detalle { display: none; }
  .movimientos { --hora: 36px; --hueco: 9px; --nodo: 26px; }
  .grafico { grid-template-columns: 20px minmax(0, 1fr); gap: 6px; }
  .grafico .eje, .grafico .plano { height: 130px; }
  .mov-cambios .campo { min-width: 0; width: 100%; }
}

/* --- control de distritos --------------------------------------------------
   El tablero del Consejo Superior. Tres bloques sobre la hoja: la fila por
   distrito, los tiempos de cada obra y lo que se sacó. El color va solo
   donde algo apura (aviso en ámbar, atraso en coral): el resto es petróleo
   sobre blanco, para que lo que pide una decisión se vea sin buscarlo. */

nav.secciones button .contador.alerta { color: var(--critico); font-weight: 600; }
nav.secciones button.activo .contador.alerta { color: var(--critico); }

#vista-control .tenue { color: var(--texto-3); }
#vista-control .critico { color: var(--critico); font-weight: 600; }

.control-bloque { padding: 0; overflow: hidden; scroll-margin-top: 16px; }
.control-bloque:focus { outline: none; }
.control-bloque:focus-visible { outline: 2px solid var(--verde-texto); outline-offset: 2px; }
.cabeza-bloque { padding: 18px 22px 14px; }
.cabeza-bloque h3 { margin-bottom: 4px; }
.cabeza-bloque .sub { margin: 0; max-width: 760px; font-size: 12.5px; color: var(--texto-2); }
.pie-bloque { margin: 0; padding: 12px 22px 16px; border-top: 1px solid var(--linea-suave); }

/* La tabla de los distritos: el nombre a la izquierda, fijo al correrla de
   costado; cada celda con su número y una aclaración chica abajo. */
.tabla-control { border: none; border-radius: 0; border-top: 1px solid var(--linea-suave); }
.tabla-control th { white-space: nowrap; cursor: help; }
/* Doce columnas no entran con los nombres en un renglón: se parten en dos,
   alineados abajo, como en una planilla. */
.tabla-control thead th { white-space: normal; line-height: 1.25; vertical-align: bottom; min-width: 64px; }
.tabla-control thead th:first-child {
  position: sticky; left: 0; z-index: 2;
  min-width: 140px;
  background: var(--fondo-2);
  box-shadow: 1px 0 0 var(--linea-suave);
}
.tabla-control th, .tabla-control td { padding-left: 7px; padding-right: 7px; }
.tabla-control tr > :first-child { padding-left: 22px; }
.tabla-control tr > :last-child { padding-right: 22px; }
.tabla-control thead th:first-child { cursor: default; }
.tabla-control td { vertical-align: top; padding-top: 12px; padding-bottom: 12px; }
.tabla-control .cifra-celda { display: block; font-size: 15px; font-family: var(--tipo); font-weight: 600; color: var(--petroleo); letter-spacing: -.01em; }
.tabla-control .cifra-celda { white-space: nowrap; }
/* La aclaración se parte antes de que la tabla tenga que correrse de costado. */
.tabla-control .aclaracion { display: block; margin-top: 3px; font-family: var(--tipo); font-size: 11.5px; line-height: 1.3; color: var(--texto-3); white-space: normal; }
.tabla-control td.con-alerta .cifra-celda { color: var(--critico); }
.tabla-control .etiqueta { padding: 0 7px; font-size: 11px; vertical-align: 1px; }

.distrito-celda {
  position: sticky; left: 0; z-index: 1;
  min-width: 150px;
  text-align: left;
  background: var(--superficie);
  font-size: 13px; font-weight: 600; letter-spacing: 0; color: var(--petroleo);
  border-bottom: 1px solid var(--linea-suave);
  box-shadow: 1px 0 0 var(--linea-suave);
}
tbody tr:hover .distrito-celda { background: #f8fbfa; }
.distrito-celda .aclaracion { font-weight: 400; }
.mirar-distrito {
  padding: 0; border: 0; background: none;
  font: inherit; font-size: 14px; font-weight: 650; color: var(--petroleo);
  text-align: left; cursor: pointer;
  text-decoration: underline; text-decoration-color: var(--linea-fuerte); text-underline-offset: 3px;
  transition: text-decoration-color var(--rapido) var(--curva), color var(--rapido) var(--curva);
}
.mirar-distrito:hover { color: var(--verde-texto); text-decoration-color: currentColor; }
.mirar-distrito:disabled { cursor: default; text-decoration: none; color: var(--petroleo); }
.tabla-control tr.no-activo .cifra-celda,
.tabla-control tr.no-activo .mirar-distrito { color: var(--texto-3); }
.tabla-control tfoot td, .tabla-control tfoot th {
  border-top: 1px solid var(--linea); border-bottom: none;
  background: var(--fondo-2);
}
.tabla-control tfoot .distrito-celda { background: var(--fondo-2); }

/* Los relojes: el conmutador dice cuántas obras hay en cada uno. */
.control-bloque > .conmutador { margin: 0 22px 4px; max-width: calc(100% - 44px); overflow-x: auto; scrollbar-width: none; }
.relojes button { white-space: nowrap; }
.relojes .contador { font-family: var(--mono); font-size: 11.5px; color: var(--texto-3); font-variant-numeric: tabular-nums; }
.relojes button.activo .contador { color: rgba(255, 255, 255, .78); }

.lista-tiempos { list-style: none; margin: 12px 0 0; padding: 0; border-top: 1px solid var(--linea-suave); }
.lista-tiempos > .vacio { margin: 0; border: 0; border-radius: 0; }
.obra-reloj {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 112px;
  gap: 16px;
  padding: 14px 22px 14px 25px;
  border-bottom: 1px solid var(--linea-suave);
  transition: background var(--rapido) var(--curva);
}
.obra-reloj:last-child { border-bottom: none; }
.obra-reloj:hover { background: #f8fbfa; }
/* El canto izquierdo dice cuánto apura, como el riel de la tarjeta de la
   bandeja dice la prioridad. */
.obra-reloj::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: transparent; }
.obra-reloj.nivel-aviso::before { background: var(--atencion); }
.obra-reloj.nivel-atraso::before { background: var(--critico); }

.or-cuerpo { min-width: 0; }
.or-cuerpo .renglon-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 6px; font-size: 12px; }
.or-titulo {
  display: block; max-width: 100%;
  padding: 0; border: 0; background: none;
  font: inherit; font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--petroleo);
  text-align: left; cursor: pointer;
  overflow-wrap: anywhere;
}
.or-titulo:hover { color: var(--verde-texto); text-decoration: underline; text-underline-offset: 3px; }
.or-cuerpo > .sub { margin: 2px 0 8px; }
.or-relojes { list-style: none; margin: 0; padding: 0; display: grid; gap: 3px; }
.or-relojes li { display: flex; align-items: flex-start; gap: 7px; font-size: 12.5px; color: var(--texto-2); line-height: 1.45; }
.or-relojes li .ico { flex: none; width: 13px; height: 13px; margin-top: 2px; color: var(--texto-4); }
.or-relojes li.nivel-aviso { color: var(--atencion); }
.or-relojes li.nivel-aviso .ico { color: var(--atencion); }
.or-relojes li.nivel-atraso { color: var(--critico); font-weight: 500; }
.or-relojes li.nivel-atraso .ico { color: var(--critico); }

.or-cifra { text-align: right; padding-top: 2px; }
.or-cifra .numero {
  display: block;
  font-size: 30px; line-height: 1; font-weight: 650; font-stretch: 108%;
  letter-spacing: -.04em; font-variant-numeric: tabular-nums;
  color: var(--petroleo);
}
.or-cifra .unidad { display: block; margin-top: 5px; font-size: 11.5px; line-height: 1.3; color: var(--texto-3); }
.nivel-aviso .or-cifra .numero { color: var(--atencion); }
.nivel-atraso .or-cifra .numero { color: var(--critico); }

#mas-tiempos:not(:empty) { padding: 0 22px 18px; }

/* Lo que se sacó: el resumen a la izquierda y los movimientos a la derecha,
   con la misma línea de tiempo que el Historial. */
.bajas-cuerpo {
  display: grid;
  grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
  border-top: 1px solid var(--linea-suave);
}
.bajas-resumen { padding: 16px 22px 18px; border-right: 1px solid var(--linea-suave); background: var(--fondo-2); }
.bajas-resumen h4 { margin: 18px 0 8px; font-size: 12.5px; font-weight: 600; color: var(--texto); }
.bajas-resumen ul { list-style: none; margin: 0; padding: 0; }
.bajas-por-clase li { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; font-size: 13px; color: var(--texto-2); }
.bajas-por-clase li .n, .barras-motivo .n, .quienes-sacaron .n { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; color: var(--petroleo); }
.bajas-por-clase li.en-cero { color: var(--texto-3); }
.bajas-por-clase li.en-cero .n { color: var(--texto-4); }
.bajas-por-clase li.aparte { margin-top: 6px; padding-top: 8px; border-top: 1px dashed var(--linea); }
.barras-motivo li { display: grid; grid-template-columns: minmax(0, 1fr) 60px 22px; align-items: center; gap: 8px; padding: 3px 0; font-size: 12.5px; }
.barras-motivo .nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--texto-2); }
.barras-motivo .riel { height: 6px; border-radius: 3px; background: var(--linea-suave); overflow: hidden; }
.barras-motivo .riel > span { display: block; height: 100%; border-radius: 3px; background: var(--texto-4); }
.barras-motivo .n { text-align: right; }
.persona-baja {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 8px;
  width: 100%; margin: 0 -6px; padding: 5px 6px;
  border: 0; border-radius: var(--r-chico); background: none;
  font: inherit; font-size: 13px; color: var(--texto); text-align: left; cursor: pointer;
  transition: background var(--rapido) var(--curva);
}
.persona-baja:hover { background: var(--superficie); }
.persona-baja .nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bajas-cuerpo > .movimientos { margin: 0; padding: 14px 22px 18px; min-width: 0; }
.bajas-cuerpo > .movimientos > .vacio { margin: 0; }
.mas-en-historial { list-style: none; margin-top: 14px; font-size: 12.5px; color: var(--texto-3); }
.pie-bajas { display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 22px 16px; border-top: 1px solid var(--linea-suave); }

@media (max-width: 980px) {
  .bajas-cuerpo { grid-template-columns: minmax(0, 1fr); }
  .bajas-resumen { border-right: none; border-bottom: 1px solid var(--linea-suave); }
}

/* En el celular la tabla de distritos deja de ser tabla: cada distrito es
   una tarjeta con sus cifras de a dos, con el nombre de cada una al lado. */
@media (max-width: 720px) {
  .cabeza-bloque { padding: 16px 16px 12px; }
  .pie-bloque, .pie-bajas { padding-left: 16px; padding-right: 16px; }
  .control-bloque > .conmutador { margin-left: 16px; margin-right: 16px; max-width: calc(100% - 32px); }
  .tabla-control { overflow: visible; }
  .tabla-control thead { display: none; }
  .tabla-control tbody, .tabla-control tfoot { display: block; }
  .tabla-control tr { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; padding: 14px 16px; border-bottom: 1px solid var(--linea-suave); }
  .tabla-control tbody tr:last-child { border-bottom: none; }
  .tabla-control tfoot tr { border-top: 1px solid var(--linea); }
  .tabla-control th, .tabla-control td,
  .tabla-control tr > :first-child, .tabla-control tr > :last-child { display: block; padding: 0; border: 0; text-align: left; }
  .tabla-control .distrito-celda { position: static; grid-column: 1 / -1; box-shadow: none; background: none; }
  .tabla-control tfoot .distrito-celda { background: none; }
  .tabla-control td::before { content: attr(data-rotulo); display: block; margin-bottom: 1px; font-family: var(--tipo); font-size: 11px; color: var(--texto-3); }
  .tabla-control .aclaracion { white-space: normal; }
  .obra-reloj { grid-template-columns: minmax(0, 1fr) 76px; gap: 10px; padding: 14px 16px 14px 19px; }
  .or-cifra .numero { font-size: 24px; }
  .bajas-resumen, .bajas-cuerpo > .movimientos { padding-left: 16px; padding-right: 16px; }
  #mas-tiempos:not(:empty) { padding: 0 16px 16px; }
}

@media (max-width: 560px) {
  #metricas-control .metrica { flex-basis: 30%; padding: 12px 14px; justify-content: space-between; }
  #metricas-control .metrica .rotulo { margin-bottom: 6px; font-size: 11px; }
  #metricas-control .metrica .numero { font-size: 22px; }
  #metricas-control .metrica .detalle { display: none; }
}

/* --- la cuenta de consulta ---------------------------------------------------
   El Consejo Superior ve todo y no cambia nada (lo hace cumplir el servidor).
   Los controles que escribirían no se muestran: un botón que contesta 403 es
   peor que no tenerlo. */

body.solo-lectura #abrir-alta,
body.solo-lectura .escribe,
body.solo-lectura .acciones-rapidas,
body.solo-lectura .sello .tilde,
body.solo-lectura #barra-seleccion,
body.solo-lectura [data-restaurar],
body.solo-lectura .pestanas[data-grupo="recaudacion"] [data-tab="cargar"],
body.solo-lectura #vista-recaudacion [data-panel="cargar"],
body.solo-lectura #ficha [data-nueva-comunicacion],
body.solo-lectura #ficha [data-anular-comunicacion],
body.solo-lectura #ficha #com-nueva,
body.solo-lectura #ficha #pedir-contacto,
body.solo-lectura #ficha #abrir-alta-parte,
body.solo-lectura #ficha #alta-parte,
body.solo-lectura #ficha [data-editar-licitacion],
body.solo-lectura #ficha [data-completar-datos],
body.solo-lectura #ficha .lapiz,
body.solo-lectura #ficha .lapiz-contacto,
body.solo-lectura #ficha [data-descartar-como-proyecto],
body.solo-lectura #ficha [data-aviso-partes],
body.solo-lectura #ficha .solo-consulta .acciones,
body.solo-lectura #ficha .solo-consulta [data-agregar-comitente],
body.solo-lectura #ficha .solo-consulta [data-quitar-comitente] { display: none !important; }

fieldset.solo-consulta { margin: 0; padding: 0; border: 0; min-width: 0; }
fieldset.solo-consulta :is(input, select, textarea):disabled {
  opacity: 1;
  color: var(--texto);
  -webkit-text-fill-color: var(--texto);
  background-color: var(--fondo-2);
  cursor: default;
}

/* Va donde estarían los botones de decisión de la ficha, con el mismo aire. */
.nota-consulta {
  display: flex; align-items: center; gap: 8px;
  margin: 0 22px 14px; padding: 10px 14px;
  border: 1px solid var(--linea); border-radius: var(--r-panel);
  background: var(--fondo-2);
  font-size: 12.5px; color: var(--texto-2);
}
.nota-consulta .ico { flex: none; width: 14px; height: 14px; color: var(--texto-3); }
@media (max-width: 760px) { .nota-consulta { margin-left: 16px; margin-right: 16px; } }
