:root {
  --ink: #3B0A20;
  --ink-2: #5E2238;
  --muted: #6B5560;
  --bg: #F2EEF0;
  --surface: #FFFFFF;
  --line: #E2D8DD;
  --vino: #691B3C;
  --vino-2: #9D2449;
  --vino-soft: #F4E4EA;
  --vino-zebra-notable: #F7EBF0;
  --vino-zebra-fuerte: #F0D9E3;
  --vino-zebra-hover: #E3B8CB;
  --oro: #A87C36;
  --oro-soft: #F4ECDB;
  --verde: #1F7A52;
  --verde-soft: #E2F1EA;
  --pd-gris: #55585C;
  --pd-verde: #1E5C46;
  --ambar: #C77D00;
  --ambar-soft: #FBEFD8;
  --rojo: #C0334B;
  --rojo-soft: #FAE4E8;
  --azul: #2C5C8A;
  --azul-soft: #E5EEF6;
  --gest-semarnat: #8BC34A;
  --gest-conagua: #549CBD;
  --gest-cfe: #1B5E20;
  --gest-pemex: #A6CE39;
  --gest-gnn: #fcc23a;
  --gest-ferreas: #D4AF37;
  --gest-ductos: #17A2B8;
  --gest-otros: #9AA0A6;
  --gris: #9E9E9E;
  --shadow: 0 1px 2px rgba(59, 10, 32, .06), 0 6px 20px rgba(59, 10, 32, .08);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0
}

html {
  -webkit-text-size-adjust: 100%
}

body {
  font-family: 'Inter', system-ui, sans-serif;
  background: var(--bg);
  color: var(--ink);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased
}

/* header y nav.tabs quedan pegados ambos como un solo bloque sticky (ver
   .header-tabs-fijo) — antes cada uno tenía su propio position:sticky con
   un "top" en píxeles fijo (nav.tabs asumía que el header medía 59px), y en
   celular el header real mide un poco menos, dejando un hueco en blanco de
   ~2-3px entre los dos. Envolviéndolos juntos, el offset de nav.tabs deja
   de depender de adivinar la altura exacta del header en cada breakpoint. */
header {
  background: var(--vino);
  color: #fff;
}

.header-tabs-fijo {
  position: sticky;
  top: 0;
  z-index: 40;
}

.header-in {
  max-width: 1200px;
  margin: 0 auto;
  padding: 13px 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  justify-content: space-between
}

.header-right-group {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 16px;
  margin-left: auto;
}

.header-right {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: #fff;
  text-decoration: none;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .2px;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1.5px solid var(--oro);
  border-radius: 8px;
  padding: 7px 14px;
  background-color: var(--vino);
  transition: all .15s;
}

.header-right:hover {
  background: var(--oro);
  border-color: var(--oro);
  color: var(--vino);
}

.header-right-logo img {
  width: auto;
  height: 35px;
  transition: height 0.3s;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.brand h1 {
  font-family: 'Archivo';
  font-weight: 800;
  font-size: 17px;
  letter-spacing: .3px;
  line-height: 1.05;
}

.brand p {
  font-size: 11px;
  color: #E0BFCC;
  font-weight: 500;
  letter-spacing: .4px;
  text-transform: uppercase;
}

nav.tabs {
  background: var(--ink);
}

.tabs-in {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none
}

.tab {
  flex: none;
  background: none;
  border: none;
  color: #D2A9B9;
  font-weight: 600;
  font-size: 13.5px;
  padding: 13px 17px;
  cursor: pointer;
  white-space: nowrap;
  border-bottom: 3px solid transparent;
  display: flex;
  align-items: center;
  gap: 7px;
  transition: .15s
}

.tab-icon {
  width: 18px;
  height: 18px;
  object-fit: contain;
  flex-shrink: 0;
}

.tab:hover,
.tab:active {
  color: #fff;
}

.tab.active {
  border-bottom-color: var(--oro)
}

main {
  max-width: 1200px;
  margin: 0 auto;
  padding: 22px 18px 60px
}

.view {
  display: none;
  animation: fade .25s ease
}

.view.active {
  display: block
}

@keyframes fade {
  from {
    opacity: 0;
    transform: translateY(6px)
  }

  to {
    opacity: 1;
    transform: none
  }
}


.view-head {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 18px
}

.view-head h2 {
  font-family: 'Archivo';
  font-weight: 700;
  font-size: 22px;
  letter-spacing: -.2px
}

.view-head p {
  color: var(--muted);
  font-size: 13.5px;
  margin-top: 2px;
  max-width: 600px
}

.periodo {
  font-size: 13px;
  color: var(--vino);
  text-align: right;
  line-height: 1.3;
  flex: none
}

.periodo b {
  color: #000000;
  font-weight: 600;
  font-size: 13px;
  display: block
}

@media (max-width: 700px) {
  .header-right-logo img {
    height: 16px;
  }

  .header-in {
    padding: 11px 14px;
    gap: 10px;
  }

  .brand h1 {
    font-size: 15px;
  }

  .brand p {
    font-size: 10px;
  }

  .view-head h2 {
    font-size: 19px;
  }

  .view-head p {
    font-size: 12.5px;
  }

  /* "Corte al..." + botón Inicio: en vez de acomodarse abajo del
     título (donde antes se movían de lugar), se quedan fijos en la
     esquina superior derecha del encabezado en todas las secciones. */
  .view-head {
    padding-right: 100px;
  }

  .header-right-group {
    position: absolute;
    top: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
  }

  .header-right {
    padding: 5px 10px;
    font-size: 10.5px;
    gap: 5px;
  }

  .periodo {
    font-size: 10.5px;
  }

  .periodo b {
    font-size: 10.5px;
  }

  /* "Avance de obra" no trae un h2 dentro de .view-head (ahí solo vive
     el badge "Corte al / Inicio") — sus dos títulos ("Avance financiero
     de obra" / "Avance físico de obra") están afuera, en su propio
     renglón. Sin contenido normal, .view-head colapsaba a 0 de alto y
     el badge (position:absolute) quedaba flotando encima de esos
     títulos. Se le da alto mínimo para que el badge quepa sin taparlos. */
  #v-obra>.view-head {
    min-height: 70px;
  }
}

/* ===== KPIs: grid de 4, con "Etapa de contratación" más ancho ===== */
.kpis {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin-bottom: 18px
}

/* Tramitología tiene 4 KPIs (Derecho de vía, CFE, CONAGUA, Cruce
   ferroviario), distinto a los 3 del Tablero ejecutivo, así que usa
   su propio número de columnas en vez de heredar repeat(3, 1fr). */
#kpisTram {
  grid-template-columns: repeat(4, 1fr);
}

/* Las 4 tarjetas (incluida k-v, "Etapa de contratación") tienen el
   mismo ancho: una columna cada una, sin excepciones. */

.kpi {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 18px;
  box-shadow: var(--shadow);
  position: relative;
  overflow: hidden
}

.kpi::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--vino-2)
}

.kpi.k-v::before {
  background: var(--verde)
}

.kpi.k-b::before {
  background: var(--azul)
}

.kpi.k-a::before {
  background: var(--ambar)
}

.kpi .lbl {
  font-size: 11.5px;
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .4px
}

.kpi .lblMunicip {
  font-size: 13px;
  line-height: 1.15;
  color: var(--muted);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
}

.kpi .val {
  font-family: 'Archivo';
  font-weight: 800;
  font-size: 28px;
  margin-top: 8px;
  letter-spacing: -.5px
}

.kpi .val small {
  font-size: 14px;
  color: var(--muted);
  font-weight: 600
}

.kpi .val small.lblMunicip {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  line-height: 1.2;
  text-transform: none;
  font-weight: 500;
  letter-spacing: normal;
}

.kpi .sub {
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px
}

/* ===== KPIs "Permisos requeridos" (Tramitología): SEMARNAT / CONAGUA / CFE /
   ATTRAPI / GNN / PEMEX / INAH / MUNICIPIO / SAASCAEM / TELMEX ===== */
.kpis-permisos {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 14px;
  margin-bottom: 18px
}

.kpi-permiso {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 16px;
  box-shadow: var(--shadow);
  cursor: pointer;
  font-family: 'Archivo';
  font-weight: 700;
  font-size: 14px;
  color: var(--ink);
  transition: transform .15s, box-shadow .15s, border-color .15s;
}

.kpi-permiso:hover {
  transform: translateY(-2px);
  border-color: var(--vino-2);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .12);
}

.kpi-permiso img {
  height: 32px;
  max-width: 90px;
  object-fit: contain;
}

/* ===== Modal "Permisos Requeridos": mapa + tabla lado a lado ===== */
.modal-card-permisos {
  max-width: 1200px;
  --modal-w: 1200px;
}

/* Columna: leyenda arriba, luego la fila mapa+tabla, luego la tabla
   duplicada de ancho completo. */
.permisos-layout {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Título + botón de imprimir, uno junto al otro dentro del modal-top
   (fondo vino). */
.permisos-titulo-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

/* Fondo "fantasma" (blanco translúcido) en vez del sólido vino de
   antes -- ahora vive sobre el propio fondo vino del modal-top, así que
   un botón vino-sobre-vino se volvería invisible. */
.permisos-print-btn {
  background: rgba(255, 255, 255, .15);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .45);
  border-radius: 8px;
  padding: 6px 12px;
  font-weight: 700;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}

.permisos-print-btn:hover {
  background: rgba(255, 255, 255, .28);
}

/* Fila mapa+tabla: la tabla crece libremente según su contenido (sin
   scroll interno, sin recortarse) -- eso hace que SEMARNAT/CONAGUA/CFE
   puedan tener distinto alto de tabla entre sí (por las filas "Por
   tramitar" con fecha). El mapa, en cambio, se queda SIEMPRE fijo en
   480px y se centra verticalmente contra la tabla, para que se vea
   igual sin importar cuál de los 3 KPIs se abra. */
/* align-items:stretch (default) hace que "permisos-map-group" tome la
   misma altura que la tabla vecina (la más alta de las dos filas). */
.permisos-row {
  display: flex;
  flex-direction: row;
  gap: 20px;
}

/* Logo grande + leyenda + mapa van juntos como un solo bloque, centrados
   uno respecto al otro, ocupando el alto de la tabla vecina (ver
   .permisos-row). El mapa (flex:1 1 auto) se lleva todo el espacio que
   sobra después del logo y la leyenda. */
.permisos-map-group {
  flex: 1 1 auto;
  min-width: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.permisos-logo-grande {
  height: 44px;
  max-width: 70%;
  object-fit: contain;
  flex: 0 0 auto;
  margin: 0;
}

/* .view-porcentaje (compartida con la leyenda del modal de gestiones)
   trae "margin: 16px 0 20px" -- eso, sumado al gap del contenedor,
   dejaba mucho hueco entre el logo/leyenda y el mapa. Aquí se anula
   para que queden pegados y el mapa se lleve ese espacio de más. */
#permisosLeyenda {
  justify-content: center;
  flex: 0 0 auto;
  margin: 0 0 10px;
}

/* position:relative + iframe en position:absolute (en vez de height:100%
   a secas) porque un iframe es un elemento "reemplazado": flexbox no lo
   estira de forma confiable, así que se queda con un alto menor y deja
   hueco vacío debajo. Con inset:0 el iframe siempre llena exactamente
   el alto real del contenedor. */
.permisos-map {
  width: 100%;
  flex: 1 1 auto;
  min-height: 320px;
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #eee;
}

.permisos-map iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* La regla global "iframe { max-height:480px }" (pensada para otros
     mapas del sitio) le pone tope a CUALQUIER iframe, incluido este; sin
     anularla aquí, el mapa nunca puede pasar de 480px aunque el
     contenedor sea más alto, dejando un hueco en blanco abajo. */
  max-height: none;
  border: 0;
  display: block;
}

/* La fila estira "permisos-tbl-wrap" a la misma altura que
   "permisos-map-group" (align-items:stretch), pero eso solo agranda la
   CAJA -- la <table> de adentro seguía con su alto natural (según sus
   10 filas), dejando hueco vacío debajo. Encadenar height:100% hasta la
   tabla hace que el navegador reparta ese espacio de más entre las
   filas, para que la tabla sí llegue hasta abajo. */
/* flex:0 0 auto (en vez de un %) para que la tabla de al lado del mapa
   solo ocupe lo que en verdad necesitan sus 3 columnas angostas (No/
   Puente/Estatus), sin estirarse a la fuerza ni dejar hueco en blanco;
   el mapa (permisos-map-group, flex:1 1 auto) se lleva todo lo que
   sobra. */
.permisos-row .permisos-tbl-wrap {
  flex: 0 0 auto;
  width: 282px;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.permisos-row .permisos-tbl-wrap .tbl-scroll {
  flex: 1 1 auto;
  min-height: 0;
  /* La tabla es angosta a propósito (276px fijos): no necesita ni debe
     mostrar scroll horizontal propio, aunque redondeos de borde la
     pasen por 1-2px. */
  overflow-x: hidden;
}

.permisos-row .permisos-tbl-wrap .tbl-scroll table {
  height: 100%;
}

.permisos-tbl-wrap {
  width: 100%;
  margin-bottom: 0;
}

.tbl-permisos th:last-child,
.tbl-permisos td:last-child {
  text-align: center;
}

/* Tabla de abajo (detalle): todas las columnas de captura (Canal de
   Cruzamiento/Tipo de Trámite/Área Evaluadora/No. de Bitácora/Fecha de
   Ingreso -- de la 3 en adelante) centradas; "Puente" (columna 2) se
   queda a la izquierda como siempre. */
.tbl-permisos th:nth-child(n+3),
.tbl-permisos td:nth-child(n+3) {
  text-align: center;
}

.tbl-permisos {
  table-layout: fixed;
}

/* La tabla de abajo (detalle, 7 columnas) SÍ necesita el min-width de
   la tabla base -- si no, en celular "table-layout:fixed" la comprime
   hasta que el texto de los encabezados se encima y se vuelve
   ilegible, en vez de simplemente hacer scroll horizontal como el
   resto de las tablas del sitio (el min-width:700px de la regla base
   ya resuelve esto solo). Solo la tabla compacta (No/Puente/Estatus,
   junto al mapa) necesita min-width:0 -- ahí sí caben sus 3 columnas
   angostas sin scroll. */
.tbl-permisos--compacta {
  min-width: 0;
}

/* Columna "No" justo del ancho de su contenido, "Puente" con espacio
   fijo razonable, y las 5 columnas de captura (Canal de Cruzamiento/Tipo
   de Trámite/Área Evaluadora/No. de Bitácora/Fecha de Ingreso) se
   reparten el resto por partes iguales. */
.tbl-permisos th:first-child,
.tbl-permisos td:first-child {
  width: 34px;
  padding-left: 8px;
  padding-right: 8px;
}

.tbl-permisos th:nth-child(2),
.tbl-permisos td:nth-child(2) {
  width: 18%;
}

/* Tabla junto al mapa (No/Puente/Estatus): la caja que la contiene
   (.permisos-row .permisos-tbl-wrap) ya está fijada a 276px -- la suma
   exacta de estos 3 anchos -- así "table-layout:fixed" no tiene nada de
   sobra que repartir/estirar entre columnas. */
.tbl-permisos--compacta th:first-child,
.tbl-permisos--compacta td:first-child {
  width: 36px;
}

.tbl-permisos--compacta th:nth-child(2),
.tbl-permisos--compacta td:nth-child(2) {
  width: 100px;
}

.tbl-permisos--compacta th:last-child,
.tbl-permisos--compacta td:last-child {
  width: 140px;
}

/* "Canal de Cruzamiento" solo aplica a CONAGUA; en SEMARNAT y CFE la
   columna se oculta por completo (ver openPermisosModal). */
.tbl-permisos--sin-canal .col-canal-cruzamiento {
  display: none;
}

/* Todo el texto de las tablas de Permisos Requeridos (encabezados y
   celdas), en 10px. Los encabezados además dejan de heredar el
   white-space:nowrap de la regla base "th": con columnas repartidas en
   partes iguales (table-layout:fixed), textos largos como "Infraestructura
   que interfiere" no cabían en una sola línea y se salían por encima de
   la columna vecina; ahora se envuelven en varias líneas dentro de su
   propia celda. */
.tbl-permisos,
.tbl-permisos th {
  font-size: 10px;
}

.tbl-permisos th {
  white-space: normal;
}

.permiso-estatus-cell {
  padding-top: 10px;
  padding-bottom: 10px;
}

/* Nombre del puente en negritas, municipio en cursivas (en vez del
   peso/tamaño que traen por default las clases .puente-name/.puente-mun
   compartidas con el resto del sitio). */
.tbl-permisos .puente-name {
  font-weight: 800;
  font-style: normal;
}

.tbl-permisos .puente-mun {
  font-style: italic;
}

/* Pastilla de estatus: el color de fondo/texto/borde llega inline desde
   ESTATUS_PERMISO (mismos colores que el semáforo del modal de
   gestiones), esta clase solo define la forma. */
.permiso-estatus {
  display: inline-block;
  font-weight: 800;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .3px;
  white-space: normal;
  line-height: 1.25;
  padding: 5px 10px;
  border-radius: 14px;
}

.permiso-estatus-gris {
  font-weight: 700;
  text-transform: none;
}

.permiso-fecha {
  display: block;
  font-weight: 700;
  font-size: 11.5px;
  margin-top: 4px;
  color: var(--ink);
}

@media (max-width: 860px) {
  .permisos-row {
    flex-direction: column;
    height: auto;
  }

  /* min-width:0 -- sin esto, "permisos-map-group" seguía forzando su
     mínimo de escritorio (300px) en pantallas angostas y desbordaba el
     modal horizontalmente. */
  .permisos-map-group,
  .permisos-row .permisos-tbl-wrap {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
  }

  .permisos-map {
    height: 320px;
  }

  /* La tabla de Estatus (junto al mapa en escritorio) está calibrada en
     px a un contenedor de 282px -- en móvil el contenedor pasa a 100%
     del ancho de pantalla, más ancho que esos 282px. "width:auto" dejaba
     la tabla en su tamaño de escritorio (276px) DENTRO de un contenedor
     ya estirado a 100%, y ese sobrante quedaba como una mancha blanca a
     la derecha (la caja blanca redondeada del wrap, más ancha que la
     tabla de adentro). Acá se pasa a columnas en % que ya suman 100%,
     para que la tabla llene su contenedor sin estirarse de más (mismo
     truco que evita el "stretch" de escritorio) ni dejar hueco. */
  .tbl-permisos--compacta {
    width: 100%;
  }

  .tbl-permisos--compacta th:first-child,
  .tbl-permisos--compacta td:first-child {
    width: 14%;
  }

  .tbl-permisos--compacta th:nth-child(2),
  .tbl-permisos--compacta td:nth-child(2) {
    width: 42%;
  }

  .tbl-permisos--compacta th:last-child,
  .tbl-permisos--compacta td:last-child {
    width: 44%;
  }

  .kpis-permisos {
    grid-template-columns: 1fr;
  }
}

/* ===== Fila de gráficas: Obras por estatus (30%) / Inversión por Puentes (70%) ===== */
.grid-2 {
  display: grid;
  grid-template-columns: 30fr 70fr;
  gap: 16px;
  margin-bottom: 20px
}

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 18px;
  box-shadow: var(--shadow);
  min-width: 0;
}

.panel h3 {
  font-family: 'Archivo';
  font-weight: 700;
  font-size: 15px;
  margin-bottom: 2px
}

.panel .ph-sub {
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 14px
}

.chart-box {
  position: relative;
  height: 230px;
}

/* Inversión por Puentes: 18 barras con etiquetas largas rotadas
   45° necesitan más alto que el chart-box estándar para no
   cortarse contra el borde del panel. */
.chart-box-inv {
  height: 350px;
  width: auto;
}

.tbl-wrap {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  overflow: visible;
  position: relative;
  margin-bottom: 18px;
}

/* overscroll-behavior-x:contain evita el bug de iOS Safari donde, al
   llegar al límite de un contenedor con scroll horizontal, el gesto
   "encadena" hacia la página completa (permite seguir arrastrando más
   allá del final/inicio de la tabla, dejando ver el fondo detrás).
   Android/Chrome ya bloquea esto por defecto; iOS no, sin esta regla. */
.tbl-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

/* ===== Flechas táctiles de scroll horizontal =====
   Botones reales (no solo un hint) para desplazar tablas anchas en
   móvil. Se inyectan por JS (ver inicializarFlechasTactiles) dentro de
   cualquier contenedor con overflow-x, y su JS las mantiene
   verticalmente centradas en lo que se ve en pantalla del contenedor:
   si la tabla es más alta que la ventana y el usuario hace scroll
   hacia abajo, la flecha "seguirá viendo" en vez de quedarse arriba
   fuera de vista. Pensado como ayuda para personas mayores u otros
   usuarios a quienes cuesta notar que una tabla se puede deslizar. */
.tbl-flechas {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 0;
  pointer-events: none;
  z-index: 6;
}

.tbl-flecha {
  position: absolute;
  top: 0;
  transform: translateY(-50%);
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid rgba(105, 27, 60, 0.25);
  background: rgba(255, 255, 255, 0.95);
  color: var(--vino);
  font-size: 20px;
  font-weight: 700;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 3px 10px rgba(105, 27, 60, 0.18);
  pointer-events: auto;
  cursor: pointer;
  transition: opacity 0.15s, transform 0.1s;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.tbl-flecha:active {
  transform: translateY(-50%) scale(0.92);
}

.tbl-flecha-prev {
  left: 6px;
}

.tbl-flecha-next {
  right: 6px;
}

.tbl-flecha.oculta {
  display: none;
}

@media (min-width: 861px) {
  .tbl-flechas {
    display: none;
  }
}

@media (max-width: 860px) {
  .tbl-wrap {
    margin-top: 50px;
  }

}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  min-width: 700px
}

th {
  text-align: left;
  font-weight: 600;
  color: #fff;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .4px;
  padding: 11px 13px;
  background: var(--vino);
  white-space: nowrap
}

td {
  padding: 11px 13px;
  border-bottom: 1px solid #EFE9EC;
  vertical-align: middle
}

/* Cabecera fija (tablas de más de 5 filas): NO se puede usar
   position:sticky en el <thead> porque .tbl-scroll necesita
   overflow-x:auto para el scroll horizontal, y por especificación CSS
   eso obliga a overflow-y:auto también (no hay forma de dejarlo en
   "visible"), lo cual rompe sticky. En su lugar, JS clona el <thead> y lo
   muestra en position:fixed sincronizado con el scroll (ver
   inicializarCabecerasFijas/actualizarCabecerasFijas): el thead original
   se oculta con visibility:hidden (sin perder su lugar en el flujo, así
   la tabla no da un salto) mientras el clon fijo está visible. z-index
   por encima de ".modal" (80): si la tabla está dentro de un modal, el
   clon necesita ganarle al overlay del modal para no quedar tapado
   detrás (se veía en blanco). */
.tbl-cabecera-fija-clon {
  z-index: 500;
  pointer-events: none;
  visibility: hidden;
}

.tbl-cabecera-fija-clon table {
  border-collapse: collapse;
  margin: 0;
}

tr:last-child td {
  border-bottom: none
}

/* Zebra en tono vino: la fila impar usa el vino "notable" y la par el
   "fuerte" (ambos suaves, se notan pero sin pasarse). El hover usa un
   tercer tono, distinto de los dos de reposo, igual para impares y
   pares. Los selectores de hover repiten el mismo :nth-child()/:not()
   que su versión sin hover para igualar la especificidad y así SÍ
   ganarle al color base (ver nota de especificidad más abajo). */
tbody tr:nth-child(odd):not(.row-total):not(.row-Subtotal) td {
  background: var(--vino-zebra-notable)
}

tbody tr:nth-child(even):not(.row-total):not(.row-Subtotal) td {
  background: var(--vino-zebra-fuerte)
}

tbody tr:nth-child(odd):not(.row-total):not(.row-Subtotal):hover td,
tbody tr:nth-child(even):not(.row-total):not(.row-Subtotal):hover td {
  background: var(--vino-zebra-hover)
}

.row-total td {
  background: var(--vino-soft);
  color: var(--vino);
  font-weight: 700;
  border-bottom: 1px solid #832042;
}

.row-total .puente-name {
  color: var(--vino);
}

.row-total:hover td {
  background: var(--vino-soft);
}

.row-Subtotal td {
  background: rgb(255, 249, 251);
  color: #8B3A53;
  font-weight: 700;
  border-bottom: 1px solid #916a77;
}

.row-Subtotal .puente-name {
  color: #8B3A53;
}

.row-Subtotal:hover td {
  background: rgb(255, 249, 251);
}

/* Filas clickeables de la tabla resumen (Tablero ejecutivo) */
.seleccion {
  cursor: pointer;
  transition: background .12s, box-shadow .12s;
}

.colorSel {
  border-left: 4px solid var(--verde);
}

.nocolorSel {
  border-left: 4px solid var(--rojo);
}

.seleccion:hover {
  background: var(--vino-soft);
}

.seleccion:active {
  background: var(--oro-soft);
}

.puente-name {
  font-weight: 600;
  color: var(--ink);
}

.puente-mun {
  font-size: 11.5px;
  color: var(--muted)
}

.descargar-kmz {
  font-size: 10.5px;
  color: var(--muted)
}

.num {
  font-variant-numeric: tabular-nums
}

.rowno {
  font-family: 'Archivo';
  font-weight: 700;
  color: var(--vino-2);
  width: 26px
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 20px;
  white-space: nowrap
}

.chip::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor
}

.c-v {
  background: var(--verde-soft);
  color: #155F3F
}

.c-r {
  background: var(--rojo-soft);
  color: #9A2738
}

.c-b {
  background: var(--azul-soft);
  color: #1F4569
}

.c-o {
  background: var(--oro-soft);
  color: #7A5A1E
}

.c-g {
  background: #9E9E9E;
  color: #ffffff;
}

.c-prog {
  background: #EFE9EC;
  color: #6B5560
}

.prog {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 120px
}

.prog .bar {
  flex: 1;
  height: 8px;
  background: #EEE6EA;
  border-radius: 6px;
  overflow: hidden
}

.prog .fill {
  height: 100%;
  border-radius: 6px;
  background: var(--vino-2)
}

.prog.pe .fill {
  background: var(--oro)
}

.prog .pct {
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  width: 38px;
  text-align: right
}

/* Gallery */
.gal {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: .18s;
  display: flex;
  flex-direction: column
}

.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 28px rgba(59, 10, 32, .16)
}

.card .thumb {
  position: relative;
  aspect-ratio: 16/9;
  background: #EDE6EA;
  overflow: hidden
}

.card .thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block
}

.card .badge {
  position: absolute;
  top: 10px;
  left: 10px;
  background: rgba(59, 10, 32, .86);
  color: #fff;
  font-family: 'Archivo';
  font-weight: 700;
  font-size: 11.5px;
  min-width: 26px;
  height: 26px;
  padding: 0 8px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  white-space: nowrap;
  max-width: calc(100% - 80px);
  overflow: hidden;
  text-overflow: ellipsis
}

.card .estb {
  position: absolute;
  top: 10px;
  right: 10px
}
/* ===== Header de color dentro de la tarjeta (body-top) ===== */
.card .body-top {
  background: #691B3C;
  width: 100%;
  padding: 12px 14px;
  color: #fff;
  height: 130px;
  display: flex;
  flex-direction: column;
}

.card .body-top h4 {
  font-family: 'Archivo';
  font-weight: 700;
  font-size: 14.5px;
  line-height: 1.2;
  color: #fff;
}

.card .body-top .mun {
  font-size: 14px;
  color: #E0BFCC;
  margin-top: 2px;
}

/* Un escalón por debajo del municipio: dorado en vez del rosa de .mun,
   para que se note (no es un dato menor, es la empresa ganadora) pero
   sin competir con él. margin-top:auto lo manda siempre casi al borde
   de abajo de la tarjeta, sin importar cuánto ocupen el nombre/municipio
   arriba (2 líneas, 1 línea, etc.) */
.card .body-top .emp {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #3B0A21;
  width: calc(100% + 28px);
  height: 65px;
  margin: auto -14px -12px -14px;
  padding: 0 14px;
  font-size: 11px;
  font-weight: 600;
  color: #dcc9a5;
  text-align: start;
}

/* Modal */
.modal {
  position: fixed;
  inset: 0;
  background: rgba(40, 8, 22, .78);
  z-index: 80;
  display: none;
  padding: 20px;
  overflow-y: auto
}

.modal.open {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  animation: fade .2s
}

.modal-card {
  max-width: 960px;
  --modal-w: 960px;
  width: 100%;
  margin: 0 auto;
  background: var(--surface);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .4);
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 40px);
}

.modal-card-gest {
  max-width: 1200px;
  --modal-w: 1200px;
}

/* Encabezado del modal: ahora es un elemento normal dentro del flujo
   (flex column del .modal-card), en vez de quedar "flotando" fijo
   respecto a la pantalla. Así siempre se ve pegado a la tarjeta,
   nunca se desalinea, y el cuerpo del modal (.modal-body /
   .gest-modal-body) hace su propio scroll interno por debajo,
   sin que el encabezado tape nada. */
.modal-top {
  background: var(--vino);
  color: #fff;
  position: relative;
  flex: 0 0 auto;
  padding: 20px 76px 20px 24px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 14px;
}

.modal-top h3 {
  font-family: 'Archivo';
  font-weight: 700;
  font-size: 18px;
  line-height: 1.15
}

.modal-top .mt-mun {
  font-size: 12.5px;
  color: #E0BFCC;
  margin-top: 3px
}

/* Botón de cerrar (X): posicionado dentro del encabezado (que ya no
   se mueve porque no forma parte del área con scroll), así que no
   necesita quedar fijo respecto a la pantalla ni recalcular su
   posición a partir del ancho del modal. */
.modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 10px;
  background: var(--ink);
  color: #fff;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  z-index: 5;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .28);
  transition: background .15s;
}

.modal-close:hover {
  background: var(--vino)
}

.viewer {
  background: #1a0610;
  position: relative
}

.viewer img {
  width: 100%;
  display: block;
  max-height: 540px;
  object-fit: contain;
  background: #1a0610
}

.vnav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(0, 0, 0, .5);
  color: #fff;
  border: none;
  width: 42px;
  height: 60px;
  cursor: pointer;
  font-size: 22px;
  display: grid;
  place-items: center
}

.vnav:hover {
  background: rgba(0, 0, 0, .75)
}

.vprev {
  left: 0;
  border-radius: 0 8px 8px 0
}

.vnext {
  right: 0;
  border-radius: 8px 0 0 8px
}

.vlabel {
  position: absolute;
  bottom: 12px;
  left: 12px;
  background: rgba(59, 10, 32, .85);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  padding: 5px 11px;
  border-radius: 7px
}

.modal-body {
  padding: 18px 0 24px;
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
}

/* Botones "Primera Etapa (2026)" / "Segunda Etapa (2027)" que aparecen
   justo debajo del mapa, para puentes cuya ficha técnica combina dos
   años de datos en un mismo modal (en vez de mostrarlos apilados). */
.etapa-toggle-bar {
  display: flex;
  gap: 10px;
  padding: 12px 20px;
  background: #fff;
  border-bottom: 1px solid var(--vino-soft);
  flex-wrap: wrap;
}

.etapa-toggle-btn {
  flex: 1 1 auto;
  min-width: 160px;
  background: var(--vino-soft);
  color: var(--vino);
  border: 1.5px solid var(--vino-soft);
  border-radius: 10px;
  padding: 10px 16px;
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  text-align: center;
  transition: .15s;
}

.etapa-toggle-btn:hover {
  border-color: var(--vino-2);
}

.etapa-toggle-btn.active {
  background: var(--vino);
  color: #fff;
  border-color: var(--vino);
}

.etapa-pane.hidden {
  display: none;
}

/* En el modal de Ficha Técnica, el mapa (.viewer) y el cuerpo
   (.modal-body) comparten un solo contenedor con scroll, para que el
   mapa se desplace junto con el resto del contenido en vez de quedar
   fijo junto al título como si fuera parte del encabezado. */
.modal-scroll-area {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
}

.modal-scroll-area .modal-body {
  flex: none;
  overflow: visible;
  min-height: auto;
}

.mbody-pad {
  padding: 0 80px;
}

.mbody-group {
  padding-top: 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

.mbody-group:first-child {
  padding-top: 0;
}

.mbody-group:last-of-type {
  border-bottom: none;
}

.render-grid-pad {
  padding: 0 80px;
  margin-top: 6px;
}

.gest-modal-body {
  padding: 24px 28px;
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
}

.blk {
  margin-bottom: 25px
}

.pNuEx {
  display: flex;
  gap: 5px
}

.blk h5 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--vino-2);
  font-weight: 700;
  margin-bottom: 5px;
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Títulos con ícono + franja dorada en "Avance de Obra" (.msegbody-pad).
   Orden: ícono, franja, texto (no franja-ícono-texto) — el ícono va
   suelto, fuera de la franja, y la franja+padding viven en el
   <span class="h5-oro-texto"> que envuelve solo el texto. Inline (no
   absoluto como .ficha-icono) porque acá el padding lateral del
   contenedor es chico (20px) y no alcanza para sacar el ícono fuera del
   flujo sin que se recorte contra el modal — mismo criterio que
   .render-label-row. La franja solo abarca el alto del título (no el
   párrafo de abajo), a propósito: son varios pares título+valor
   apretados dentro de una sola grid, no un bloque único como
   "Datos técnicos". */
.h5-oro img {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
  border: none;
  border-radius: 0;
  background: none;
}

.h5-oro-texto {
  border-left: 3px solid var(--oro);
  padding-left: 8px;
}

/* Pares "título + valor" (Inicio/fecha, Monto Contratado/monto, etc.): la
   franja dorada bordea título Y valor juntos (el icono se queda fuera, a la
   izquierda), a diferencia de .h5-oro/.h5-oro-texto de arriba —esas son
   encabezados de bloques grandes (Larguillo, Rendimiento de Obra) donde la
   franja a propósito solo abarca el título. Mismo criterio que
   .ficha-row/.ficha-row-body: un solo contenedor envuelve título+valor para
   que el border-left mida el alto de ambos sin calcular nada a mano. */
.h5-oro-fila {
  display: flex;
  align-items: center;
  gap: 6px;
}

.h5-oro-fila > img {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
  border: none;
  border-radius: 0;
  background: none;
}

.h5-oro-fila > .h5-oro-cuerpo {
  flex: 1 1 auto;
  min-width: 0;
  border-left: 3px solid var(--oro);
  padding-left: 8px;
}

.h5-oro-fila > .h5-oro-cuerpo > h5 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--vino-2);
  font-weight: 700;
  margin: 0 0 5px;
}

/* En celular el icono entra DENTRO de la franja dorada, junto al título
   (renglón 1); el valor va abajo, ocupando todo el ancho (renglón 2):
     | icono título
     | texto
   display:contents en .h5-oro-cuerpo "desaparece" ese contenedor de la caja
   (no de las reglas de estilo) para que su h5/h6/p pasen a ser hijos
   directos de la rejilla de .h5-oro-fila y puedan colocarse en celdas
   distintas — si no, quedarían atrapados dentro de una sola celda. */
@media (max-width: 640px) {
  .h5-oro-fila {
    display: grid;
    grid-template-columns: 40px 1fr;
    column-gap: 6px;
    row-gap: 2px;
    border-left: 3px solid var(--oro);
    padding-left: 8px;
  }

  .h5-oro-fila > img {
    grid-column: 1;
    grid-row: 1;
  }

  .h5-oro-fila > .h5-oro-cuerpo {
    display: contents;
  }

  .h5-oro-fila > .h5-oro-cuerpo > h5 {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
    margin: 0;
  }

  .h5-oro-fila > .h5-oro-cuerpo > p,
  .h5-oro-fila > .h5-oro-cuerpo > h6 {
    grid-column: 1 / -1;
  }
}

/* Fila de Ficha Técnica (Edomex). El título (h5) vive DENTRO de
   .ficha-row-body, junto con el párrafo/chip que le sigue, para que la
   franja dorada (el border-left de .ficha-row-body) mida el alto de
   ambos juntos — el borde de un elemento siempre abarca toda su caja,
   así que no hace falta calcular nada a mano. La franja sí convive
   dentro del área del modal (no ocupa mucho espacio en blanco).
   El ÍCONO, en cambio, se saca del todo del flujo (position:absolute)
   y se manda -32px hacia la franja blanca del padding del modal — así
   no "vive" dentro del div con el resto del contenido, y como ya no es
   parte del flex, .ficha-row-body no se mueve ni un pixel por su
   ausencia. top:50%+translateY(-50%) lo centra según el alto real de
   .ficha-row (que es el alto de .ficha-row-body, título+párrafo). */
.ficha-row {
  position: relative;
  display: flex;
  align-items: center;
}

.ficha-row>.ficha-icono {
  position: absolute;
  left: -45px;
  top: 50%;
  transform: translateY(-50%);
}

.ficha-row>.ficha-row-body {
  flex: 1 1 auto;
  min-width: 0;
  border-left: 3px solid var(--oro);
  padding-left: 12px;
}

.ficha-icono {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
}

.blk p {
  font-size: 13.5px;
  color: var(--ink-2);
  text-align: justify;
}

/* ===== Estatus con proyectista / licitación (modal de ficha) ===== */
.dt-estatus {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.dt-estatus-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 13px;
  color: var(--ink-2);
}

.dt-estatus-info b {
  color: var(--ink);
  font-weight: 600;
}

/* ===== Datos técnicos (modal de ficha) =====
   Layout: tabla de 2 columnas (etiqueta | valor), un campo por fila —
   ya no 2 campos por fila. El marcado es una lista plana de <div>
   alternados (etiqueta, valor, etiqueta, valor...); nth-child(odd)/
   (even) los distingue sin necesitar una clase por celda. En móvil
   colapsa a 1 columna (etiqueta arriba, valor abajo). */
.dt {
  display: grid;
  /* La columna de etiquetas se ajusta a su contenido (la etiqueta más
     larga, "Longitud de Estructura"), dejando el resto del ancho para
     el valor. */
  grid-template-columns: auto 1fr;
  background: #FBF7F9;
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
}

.dt>div {
  display: flex;
  align-items: center;
  padding: 10px 16px;
  border-bottom: 1px dashed var(--line);
}

.dt>div:nth-child(odd) {
  border-right: 1px dashed var(--line);
  color: var(--ink-2);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .3px;
  justify-content: flex-end;
  text-align: right;
}

.dt>div:nth-child(even) {
  font-family: 'Archivo', sans-serif;
  font-weight: 700;
  font-size: 14px;
  color: var(--ink);
  text-align: left;
}

/* Quita el borde inferior de la última fila (sus 2 celdas). */
.dt>div:nth-last-child(-n+2) {
  border-bottom: none;
}

@media (max-width: 640px) {
  .dt {
    grid-template-columns: 1fr;
  }

  .dt>div:nth-child(odd) {
    border-right: none;
    border-bottom: none;
    padding-bottom: 2px;
    justify-content: flex-start;
    text-align: left;
  }

  .dt>div:nth-last-child(-n+2) {
    border-bottom: 1px dashed var(--line);
  }

  .dt>div:last-child {
    border-bottom: none;
  }
}

/* ===== Parámetros de Diseño (matriz de ejes/ramas por PSV) =====
   A diferencia de .dt (2 columnas fijas etiqueta|valor), aquí el número
   de columnas varía por puente (2 a 5 ejes/ramas). Para que quepa sin
   scroll horizontal dentro del modal (800px útiles a lo mucho, bastante
   menos en móvil), la tabla es table-layout:fixed con ancho fijo por
   columna y el texto hace wrap en vez de forzar el ancho — nunca se deja
   una sola línea "8 tipo cajón en cada claro" empujando la tabla. El
   overflow-x:auto en .pd-wrap queda solo como red de seguridad, no como
   mecanismo esperado. */
.pd-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 10px;
}

.pd-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 11px;
}

.pd-table th:first-child,
.pd-table td:first-child {
  width: 25%;
}

.pd-table th {
  color: #fff;
  padding: 7px 6px;
  line-height: 1.3;
  text-align: center;
  vertical-align: middle;
  overflow-wrap: break-word;
}

.pd-th-title {
  display: block;
  font-size: 9.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .02em;
}

.pd-th-sub {
  display: block;
  font-size: 9.5px;
  font-weight: 600;
  opacity: .92;
  margin-top: 1px;
}

.pd-th-sub-solo {
  margin-top: 0;
  font-size: 10.5px;
}

.pd-th-label {
  background: var(--pd-gris);
  text-align: left;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .02em;
}

.pd-th-gris { background: var(--pd-gris); }
.pd-th-verde { background: var(--pd-verde); }
.pd-th-vino { background: var(--vino); }
.pd-th-oro { background: var(--oro); }

.pd-table td {
  padding: 6px 6px;
  text-align: center;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  overflow-wrap: break-word;
  line-height: 1.25;
}

.pd-table tbody tr:last-child td {
  border-bottom: none;
}

.pd-table tbody tr:nth-child(even) {
  background: #FAF8F5;
}

.pd-td-label {
  text-align: left;
  font-weight: 700;
  color: var(--ink-2);
  font-size: 10.5px;
}

.pd-dash {
  color: var(--muted);
}

/* Secciones transversales debajo de la tabla de Parámetros de Diseño:
   imagen-1.png a imagen-x.png de .../puente-{carpeta}/parametros/, tantas
   como el puente tenga cargadas (por ahora solo Barrio V). El bloque se
   pinta vacío en parametrosDisenoHTML() y solo toma tamaño cuando llegan
   imágenes (pintarSeccionesTransversales), así que empieza sin :empty
   para no dejar un hueco/margen huérfano si el puente no tiene carpeta
   "parametros". Slider de 1 imagen visible (no apiladas: con varias
   secciones por puente alargaba mucho la ficha) — mismo patrón visual
   que .render-viewer/.vnav, pero con object-fit:contain en vez de cover:
   son planos técnicos con texto hasta el borde, cover los recortaría.
   Alto fijo en el visor (a diferencia de .render-viewer, que sí puede
   variar con height:auto): cada sección trae una altura distinta
   (algunas traen 2 ejes apilados, otras 1 solo), y con height:auto el
   contenedor cambiaba de alto en cada click — las flechas (position:
   absolute, top:50%) se corrían de lugar y el siguiente click ya no les
   caía encima. Con height fijo + object-fit:contain, la imagen se
   acomoda adentro sin recortarse y las flechas no se mueven nunca. */
.pd-secciones:not(:empty) {
  margin-top: 16px;
}

.pd-viewer {
  position: relative;
  height: 320px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #fff;
}

.pd-viewer img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  cursor: zoom-in;
}

@media (max-width: 640px) {
  .pd-viewer { height: 220px; }
}

.pd-viewer .vnav {
  width: 30px;
  height: 44px;
  font-size: 17px;
}

.pd-viewer .vprev { border-radius: 0 7px 7px 0; }
.pd-viewer .vnext { border-radius: 7px 0 0 7px; }

.pd-viewer-count {
  position: absolute;
  bottom: 8px;
  right: 10px;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
}

@media (max-width: 640px) {
  .pd-table { font-size: 9.5px; }
  .pd-table th, .pd-table td { padding: 5px 4px; }
  .pd-th-title, .pd-th-sub { font-size: 8.5px; }
  .pd-th-sub-solo { font-size: 9px; }
  .pd-td-label { font-size: 9px; }
  .pd-th-label { font-size: 9px; }
}

/* ===== Render / Proyecto Ejecutivo / Estudio de Tránsito. El grid solo
   tiene 1 columna: cada .render-item ocupa su propia fila, uno debajo
   del otro (mismo criterio que el video de Reconocimiento con Dron).
   Dentro de cada .render-item, el título va arriba y la imagen/video
   abajo, con UNA sola franja dorada continua a la izquierda que cubre
   ambos (ver .render-item más abajo). El ícono va del lado de afuera,
   sacado del flujo con position:absolute, igual que en "Datos técnicos" /
   "Estatus" / "Problemática" / "Solución" (ver .render-item>.ficha-icono
   y compárese con .ficha-row>.ficha-icono, mismo criterio). */
.render-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
  margin-bottom: 14px;
}

.render-grid-solo {
  grid-template-columns: 1fr;
}

/* La franja dorada va en .render-item mismo (no en la leyenda ni en la
   imagen/video por separado), así el border-left abarca TODA la caja
   —título e ícono y la imagen/video de abajo juntos, de una sola franja
   continua— igual criterio que .ficha-row-body con "Datos técnicos".
   El padding-left es mínimo (solo el aire justo para no pegar el
   texto al borde) para que la imagen/video no se achique: debe ocupar
   el mismo ancho que el resto de los bloques del modal.
   position:relative porque es el ancla del ícono absoluto (ver abajo). */
.render-item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-left: 3px solid var(--oro);
  padding-left: 8px;
}

.render-item-full {
  grid-column: 1 / -1;
  width: 100%;
}

/* Mismo -45px/centrado vertical que .ficha-row>.ficha-icono: el ícono
   queda del lado izquierdo del bloque completo (título+imagen/video),
   centrado según el alto total de .render-item.
   Repite width/height/etc. de .ficha-icono (no solo la posición):
   ".render-item img" (la regla de la foto/video grande, width:100% +
   aspect-ratio:16/9) tiene más especificidad que ".ficha-icono" sola
   (1 clase + 1 elemento vs. 1 clase) y si no se repite acá, ese ícono
   de 40x40 se estira al ancho completo de la tarjeta. Selector con 2
   clases (.render-item>.ficha-icono) para ganarle. */
.render-item>.ficha-icono {
  position: absolute;
  left: -45px;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  aspect-ratio: auto;
  object-fit: contain;
}

.render-viewer {
  position: relative;
  border-radius: 10px;
  overflow: hidden;
}

.render-viewer-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16/9;
  background: #EDE6EA;
  border: 1px solid var(--line);
}

.render-spinner {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 3px solid var(--line);
  border-top-color: var(--vino);
  animation: sicopue-girar .8s linear infinite;
}

@keyframes sicopue-girar {
  to { transform: rotate(360deg); }
}

/* Videos: se muestran en negro mientras cargan (con el spinner encima) y
   se revelan solo cuando el navegador ya tiene datos suficientes para
   reproducirlos, para que nunca se vea un frame roto o en blanco. */
.video-loading-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 4/3;
  border-radius: 10px;
  overflow: hidden;
  background: #000;
}

.video-loading-wrap video {
  width: 100%;
  height: 100%;
  aspect-ratio: 4/3;
  object-fit: cover;
  border-radius: 10px;
  display: block;
  opacity: 0;
  transition: opacity .3s ease;
}

.video-loading-wrap.video-listo video {
  opacity: 1;
}

.video-loading-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 3px solid rgba(255,255,255,.25);
  border-top-color: #fff;
  animation: sicopue-girar .8s linear infinite;
  opacity: 1;
  transition: opacity .2s ease;
}

.video-loading-wrap.video-listo::after {
  opacity: 0;
  pointer-events: none;
}

/* Variante "natural": conserva la proporción real del video (como el de
   reconocimiento con dron, que no es 4/3), sin recortar con object-fit:
   cover. Solo mantiene el fondo negro mientras carga. */
.video-loading-wrap-natural {
  aspect-ratio: auto;
  min-height: 200px;
}

.video-loading-wrap-natural video {
  width: 100%;
  height: auto;
  aspect-ratio: auto;
  object-fit: contain;
}

/* Variante "altura fija": para Estudio de Tránsito y Render Video. En vez
   de recortar el video para llenar un aspect-ratio 4/3 fijo (object-fit:
   cover), usa el mismo aspect-ratio 16/9 que la imagen de "Render"
   (.render-item img) — como ambos comparten el mismo ancho de columna,
   les queda la misma altura exacta sin necesidad de un valor en px, y
   el video se ve completo, sin recortar (object-fit: contain, con
   barras negras arriba/abajo si su proporción real no es 16:9).
   Selector calificado con 2 clases a propósito: así le gana en
   especificidad a ".render-item video" (la regla 4:3/cover de los
   videos normales) sin importar el orden en el archivo. */
.video-loading-wrap-alto-fijo {
  aspect-ratio: 16/9;
  height: auto;
}

.video-loading-wrap.video-loading-wrap-alto-fijo video {
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  object-fit: contain;
}

/* Leyenda de cada render/video, arriba del contenido (solo texto: el
   ícono ya no vive acá, se movió afuera del bloque como
   .render-item>.ficha-icono, ver más arriba). La franja dorada tampoco
   vive acá: vive en .render-item (el padre), para que sea una sola
   franja continua que cubra título y la imagen/video de abajo, no dos
   franjas cortadas por separado. */
.render-label-row {
  display: flex;
  align-items: center;
  padding: 4px 0;
}

.render-label {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--vino-2);
  text-align: left;
}

.render-item video,
.render-viewer video {
  width: 100%;
  aspect-ratio: 4/3;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #EDE6EA;
  display: block;
}

/* Los renders son imágenes 1600x900 (16:9) — con 4:3 se veían recortadas
   y más altas de lo real, tipo 600x800. */
.render-item img,
.render-viewer img {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #EDE6EA;
  display: block;
}

.render-viewer .vnav {
  width: 30px;
  height: 44px;
  font-size: 17px;
}

.render-viewer .vprev {
  border-radius: 0 7px 7px 0;
}

.render-viewer .vnext {
  border-radius: 7px 0 0 7px;
}

.pdf-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--vino-2);
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  padding: 4px 10px;
  background: var(--vino-soft);
  border-radius: 6px;
  transition: background 0.15s, color 0.15s;
  margin: 2px 4px 2px 0;
}

.pdf-link:hover {
  background: var(--vino-2);
  color: #fff;
}

/* ===== Tarjetas de archivos (Seguimiento y Supervisión de Obra) ===== */
.pdf-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* ===== Tabla de Supervisión: "Antecedentes de Validación" fija en
   270px, y "Archivos de Seguimiento" con el resto del ancho -- ahí, en
   vez de que las tarjetas de PDF se acomoden en varias filas cuando no
   caben, se quedan en una sola línea con su propio scroll horizontal. */
#tblSupervision .col-antecedentes {
  width: 270px;
}

#tblSupervision .col-archivos-seg {
  width: auto;
}

#tblSupervision td.col-archivos-seg .pdf-cards,
#tblSupervision td.col-antecedentes .pdf-cards {
  flex-wrap: nowrap;
  overflow-x: auto;
  padding-bottom: 4px;
}

#tblSupervision td.col-archivos-seg .pdf-card,
#tblSupervision td.col-antecedentes .pdf-card {
  flex: 0 0 auto;
}

/* En celular, "Antecedentes de Validación" ya no necesita los 270px fijos
   de escritorio: se angosta al ancho de ~2 tarjetas de archivo (el tamaño
   típico de lo que se sube ahí), en vez de dejar un hueco vacío grande
   cuando dice "Sin archivos". Si algún día hay más de 2, las tarjetas
   siguen su propio scroll horizontal (regla de arriba). */
@media (max-width: 640px) {
  #tblSupervision .col-antecedentes {
    width: 200px;
  }
}

.pdf-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 84px;
  padding: 8px 6px 6px;
  background: var(--vino-soft);
  border: 2px solid var(--vino);
  border-radius: 10px;
  text-decoration: none;
  color: var(--ink);
  box-shadow: 0 2px 6px rgba(105, 27, 60, 0.18);
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.1s;
}

.pdf-card:hover {
  background: var(--vino-2);
  border-color: var(--vino-2);
  color: #fff;
  box-shadow: 0 4px 10px rgba(105, 27, 60, 0.3);
  transform: translateY(-2px);
}

.pdf-card:hover .pdf-card-fecha {
  color: #fff;
}

.pdf-card-icono {
  width: 18px;
  height: 18px;
  object-fit: contain;
  margin-bottom: 4px;
}

.pdf-card-desc {
  font-size: 10px;
  font-weight: 400;
  line-height: 1.25;
  display: -webkit-box;
  line-clamp: 2;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.pdf-card-fecha {
  font-size: 9.5px;
  font-weight: 700;
  color: var(--vino-2);
  margin-top: 4px;
}

@media (max-width: 480px) {
  .pdf-card {
    width: 74px;
    padding: 7px 5px 5px;
  }
}

#tblSupervision {
  table-layout: fixed;
}

#tblSupervision th:nth-child(1),
#tblSupervision td:nth-child(1) {
  width: 40px;
}

#tblSupervision th:nth-child(2),
#tblSupervision td:nth-child(2) {
  width: 15%;
  /* Los "th" del sitio son white-space:nowrap por default -- "Puente /
     Municipio" no cabe en el 15% de la tabla y se salía de su columna
     por encima de las de al lado. Con normal + wrap, si no cabe en una
     línea se parte en dos en vez de desbordarse. */
  white-space: normal;
  overflow-wrap: break-word;
}

/* Línea vertical vino (suave) solo entre "Antecedentes de Validación" y
   "Archivos de Seguimiento" -- las demás columnas (#, Puente/Municipio)
   no la necesitan. En el encabezado, más tenue todavía porque el "th" ya
   tiene fondo vino sólido detrás. */
#tblSupervision th.col-antecedentes {
  border-right: 2px solid rgba(255, 255, 255, 0.25);
}

#tblSupervision td.col-antecedentes {
  border-right: 2px solid rgba(105, 27, 60, 0.35);
}

/* La regla vieja de acá (th/td:nth-child(3)) ya no aplica: desde que el
   encabezado "Archivos" se partió en dos con colspan/rowspan, la fila 2
   del thead solo tiene 2 celdas (Antecedentes/Archivos de Seguimiento,
   posiciones 1 y 2 dentro de ESA fila), mientras que el tbody tiene 4
   (#/Puente/Antecedentes/Archivos de Seguimiento) -- nth-child ya no
   cae parejo entre ambas filas del encabezado y el cuerpo, así que el
   ancho de esas 2 columnas se controla con .col-antecedentes/
   .col-archivos-seg (ver más abajo), no por posición. */

/* ===== Leyenda de avance por color ===== */
.view-porcentaje {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 16px 0 20px;
}

.view-porcentaje p {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
  margin-right: 4px;
  flex: 1 1 100%;
}

@media (min-width: 560px) {
  .view-porcentaje p {
    flex: none;
  }
}

.porcentaje {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 20px;
  font-size: 12.5px;
  font-weight: 600;
  font-family: 'Inter', sans-serif;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line);
}

.cuadrito-1,
.cuadrito-2,
.cuadrito-3,
.cuadrito-4 {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  margin-right: 8px;
  flex-shrink: 0;
}

.cuadrito-1 {
  background-color: var(--rojo);
}

.cuadrito-2 {
  background-color: var(--ambar);
}

.cuadrito-3 {
  background-color: var(--verde);
}

.cuadrito-4 {
  background-color: var(--gris);
}

/* ===== Botones de gestión por avance ===== */
.gchips-gest {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.btn-gest-item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-right: 9px solid transparent;
  border-radius: 20px;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  padding: 6px 14px;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: 11.5px;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, transform 0.1s;
  white-space: nowrap;
  box-sizing: border-box;
  background: var(--gest-bg, #fff);
  color: var(--gest-text, var(--ink));
}

.btn-gest-item:hover {
  background: var(--gest-hover-bg, var(--gest-bg));
  color: var(--gest-hover-text, var(--gest-text));
}

.btn-gest-item:active {
  transform: scale(0.97);
}

/* Color de fondo (pastel): representa la dependencia/gestión */
.btn-gest-cat-semarnat {
  --gest-bg: #E6F4D9;
  --gest-text: var(--ink);
}

.btn-gest-cat-conagua {
  --gest-bg: #DCEEF6;
  --gest-text: var(--ink);
}

.btn-gest-cat-cfe {
  --gest-bg: #DCEEE0;
  --gest-text: var(--ink);
  --gest-hover-bg: #7FC79A;
  --gest-hover-text: #fff;
}

.btn-gest-cat-pemex {
  --gest-bg: #EFF6D6;
  --gest-text: var(--ink);
}

.btn-gest-cat-gas {
  --gest-bg: #FBE7D4;
  --gest-text: var(--ink);
  --gest-hover-bg: #E8A464;
  --gest-hover-text: #fff;
}

.btn-gest-cat-attrapi {
  --gest-bg: #E4E1F7;
  --gest-text: var(--ink);
  --gest-hover-bg: #8B7FD1;
  --gest-hover-text: #fff;
}

.btn-gest-cat-saascaem {
  --gest-bg: #D7F0EA;
  --gest-text: var(--ink);
  --gest-hover-bg: #4FAF95;
  --gest-hover-text: #fff;
}

.btn-gest-cat-ferreas {
  --gest-bg: #F7ECD2;
  --gest-text: var(--ink);
}

.btn-gest-cat-ductos {
  --gest-bg: #D9F0F2;
  --gest-text: var(--ink);
}

.btn-gest-cat-otros {
  --gest-bg: #ECEBEC;
  --gest-text: var(--ink);
}

/* Dependencias adicionales (puentes con datos capturados: 5 y 6) */
.btn-gest-cat-telmex {
  --gest-bg: #DCE8F7;
  --gest-text: var(--ink);
  --gest-hover-bg: #6FA0DE;
  --gest-hover-text: #fff;
}

.btn-gest-cat-gas {
  --gest-bg: #FBE7D4;
  --gest-text: var(--ink);
  --gest-hover-bg: #E8A464;
  --gest-hover-text: #fff;
}

.btn-gest-cat-pemex {
  --gest-bg: #EFF6D6;
  --gest-text: var(--ink);
  --gest-hover-bg: #a7be74;
  --gest-hover-text: #fff;
}

.btn-gest-cat-conagua {
  --gest-bg: #DCEEF6;
  --gest-text: var(--ink);
  --gest-hover-bg: #7FC9E8;
  --gest-hover-text: #fff;
}

.btn-gest-cat-municipal {
  --gest-bg: #F3E9D8;
  --gest-text: var(--ink);
  --gest-hover-bg: #C9A25E;
  --gest-hover-text: #fff;
}

.btn-gest-cat-pordefinir {
  --gest-bg: #ECE3F5;
  --gest-text: var(--ink);
  --gest-hover-bg: #A97AD1;
  --gest-hover-text: #fff;
}

.btn-gest-cat-inah {
  --gest-bg: #F5E6D3;
  --gest-text: var(--ink);
  --gest-hover-bg: #C88A4C;
  --gest-hover-text: #fff;
}

/* Color del borde derecho: representa el estatus/avance de la gestión.
   En hover, ese mismo color llena todo el botón. Mismos colores que la
   leyenda "Estatus:" del modal de gestiones (Sin trámite / Por tramitar
   y En proceso (naranja, un solo escalón) / En trámite e Ingresado
   (amarillo) / Liberado), para que todo hable el mismo lenguaje de
   color. */
.btn-gest-estatus-rojo {
  border-right-color: #C0392B;
  --gest-hover-bg: #C0392B;
  --gest-hover-text: #fff;
}

.btn-gest-estatus-amarillo {
  border-right-color: #F5C518;
  --gest-hover-bg: #F5C518;
  --gest-hover-text: #3B0A20;
}

.btn-gest-estatus-ambar {
  border-right-color: #F2994A;
  --gest-hover-bg: #F2994A;
  --gest-hover-text: #fff;
}

.btn-gest-estatus-verde {
  border-right-color: #2A9D8F;
  --gest-hover-bg: #2A9D8F;
  --gest-hover-text: #fff;
}

.btn-gest-estatus-gris {
  border-right-color: #9AA0A6;
  --gest-hover-bg: #9AA0A6;
  --gest-hover-text: #fff;
}

/* ===== Botones de gestión dentro de Tramitología =====
   Sin borde derecho (solo color de dependencia como fondo) pero con
   un borde izquierdo de estatus (semáforo) y, para los puentes que
   aún no tienen datos capturados, en gris y sin click. */
.btn-gest-tram {
  border-right: none !important;
  border-radius: 8px !important;
  padding: 3px 6px !important;
  border-left: 5px solid transparent;
}

.btn-gest-tram.btn-gest-estatus-rojo {
  border-left-color: #C0392B;
}

.btn-gest-tram.btn-gest-estatus-amarillo {
  border-left-color: #F5C518;
}

.btn-gest-tram.btn-gest-estatus-ambar {
  border-left-color: #F2994A;
}

.btn-gest-tram.btn-gest-estatus-verde {
  border-left-color: #2A9D8F;
}

.btn-gest-tram.btn-gest-estatus-gris {
  border-left-color: #9AA0A6;
}

.btn-gest-tram.btn-gest-disabled {
  --gest-bg: #ECEBEC !important;
  --gest-text: #9AA0A6 !important;
  --gest-hover-bg: #ECEBEC !important;
  --gest-hover-text: #9AA0A6 !important;
  cursor: not-allowed;
  pointer-events: none;
}

/* Logo de la dependencia dentro de la etiqueta de Tramitología */
.btn-gest-tram .btn-gest-logo {
  display: block;
  height: 28px;
  width: auto;
  max-width: 140px;
  object-fit: contain;
}

/* ===== Semáforo de estatus dentro del modal de gestiones ===== */
.estatus-badge {
  display: inline-block;
  padding: 3px 0 3px 10px;
  border-left: 4px solid var(--gest-otros);
}

.estatus-badge.estatus-rojo {
  border-left-color: var(--rojo);
}

.estatus-badge.estatus-ambar {
  border-left-color: var(--ambar);
}

.estatus-badge.estatus-verde {
  border-left-color: var(--verde);
}

.estatus-badge.estatus-gris {
  border-left-color: #9AA0A6;
  color: #9AA0A6;
}

/* Variante con ícono (Estado de México): sustituye la barra de color por
   un ícono de recursos/utils, en vez del indicador de color. */
.estatus-badge.estatus-badge--icono {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-left: none;
  padding: 3px 0;
}

.estatus-icono {
  width: 16px;
  height: 16px;
  object-fit: contain;
  flex-shrink: 0;
  vertical-align: middle;
}

/* Punto de color del semáforo (modal de gestiones): reemplaza los
   iconos por estatus, para poder afinar el color exacto de cada uno
   (p. ej. "Por tramitar"/"En proceso" en naranja, "En trámite"/
   "Ingresado" en amarillo) sin depender de un archivo de imagen por
   estatus. El color/borde llega inline (ver dotStyle() en edomex.html),
   ya que el blanco de "No aplica" necesita borde propio para no
   perderse sobre fondo blanco. */
.estatus-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* ===== Ícono de Ubicación (descarga KMZ) ===== */
.kmz-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  font-size: 16px;
  text-decoration: none;
  background: #c93850;
  cursor: pointer;
  transition: background 0.15s;
}

.kmz-link img {
  width: 16px;
  height: 16px;
  display: block;
}

.kmz-link:hover {
  background: var(--vino-soft);
}

.kmz-link-disabled {
  background: #ECEBEC;
  cursor: not-allowed;
  opacity: .6;
}


.avance-general {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 16px;
  margin-bottom: 16px;
  font-family: 'Archivo', sans-serif;
}

.avance-general .ag-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-2);
}

.avance-general .ag-valor {
  font-size: 18px;
  font-weight: 800;
}

/* ===== Tabla de archivos por gestión (modal) =====
   Dos capas: .tbl-archivos-gest-wrap (estático, position:relative,
   sostiene el indicador de flecha) y .tbl-archivos-gest-scroll (el que
   de verdad hace scroll horizontal). Si el scroll fuera el mismo
   elemento que tiene position:relative, overflow-x:auto recorta
   también el eje vertical y la flecha (que vive fuera de su caja)
   desaparecería. */
.tbl-archivos-gest-wrap {
  position: relative;
}

.tbl-archivos-gest-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.tbl-archivos-gest {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-family: 'Inter', sans-serif;
}

.tbl-scroll table thead tr th {
  text-align: center;
  vertical-align: middle;
  border: 1px solid var(--vino-2);
}

.tbl-scroll table tbody tr .num, .rowtotal {
  text-align: center;
  vertical-align: middle;
}

.tbl-archivos-gest thead th {
  text-align: left;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: #fff;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
}

.tbl-archivos-gest thead th:last-child {
  width: 260px;
}

.tbl-archivos-gest tbody td {
  padding: 10px 10px;
  font-size: 13.5px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
  word-break: break-word;
}

.tbl-archivos-gest tbody tr:last-child td {
  border-bottom: none;
}

.tbl-archivos-gest tbody td:first-child {
  font-weight: 600;
  color: var(--ink-2);
}

/* ============================================================
   RESPONSIVO
   ============================================================ */

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

  #kpisTram {
    grid-template-columns: 1fr 1fr;
  }

  /* "Etapa de contratación" ya no necesita un trato especial: las 4
     tarjetas siempre tienen el mismo ancho. */

  .grid-2 {
    grid-template-columns: 1fr
  }

  main {
    padding: 18px 14px 50px
  }

  .mbody-pad {
    padding: 0 32px;
  }

  .render-grid-pad {
    padding: 0 32px;
  }

  .msegbody-pad {
    padding: 0 32px;
  }
}

@media (max-width: 400px) {

  .tbl-archivos-gest thead th:first-child,
  .tbl-archivos-gest tbody td:first-child {
    font-size: 12px;
  }

  .tbl-archivos-gest thead th:last-child {
    width: 110px;
  }

  .pdf-link span.pdf-text {
    display: none;
  }

  .header-right-logo img {
    height: 10px;
  }
}

.map-crop {
  width: 100%;
  max-width: 100%;
}

iframe {
  width: 100%;
  max-width: 100%;
  display: block;
  max-height: 480px;
  border: none;
}
.map-vista-individual iframe {
  max-height: none;
  height: 550px;
}

@media (max-width: 768px) {
  .kpis {
    grid-template-columns: repeat(3, 1fr);
  }

  #kpisTram {
    grid-template-columns: 1fr 1fr;
  }

  .gal {
    grid-template-columns: repeat(2, 1fr);
  }

  .header-in {
    padding: 14px 14px;
    gap: 10px;
  }

  .header-right-logo img {
    height: 30px;
  }

  .brand h1 {
    font-size: 16px;
  }

  .brand p {
    font-size: 14px;
  }

  .view-head h2 {
    font-size: 19px;
  }

  .mbody-pad {
    padding: 0 32px;
  }

  .render-grid-pad {
    padding: 0 32px;
  }

  .seg-avance-grid {
    grid-template-columns: 1fr;
    gap: 24px;
  }

  .seg-datos-grid {
    grid-template-columns: 1fr;
    gap: 14px;
  }

  .dash-kpi-top {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }

  .dash-kpi-inv,
  .dash-kpi-right,
  .dash-kpi-vacio {
    grid-column: 1;
    grid-row: auto;
  }

  .seg-historial-layout {
    grid-template-columns: 1fr;
  }

  .seg-historial-list {
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    gap: 8px;
    padding-bottom: 4px;
  }

  .seg-historial-item {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .seg-foto-img {
    width: 100%;
    max-width: 100%;
    aspect-ratio: 4 / 3;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--line);
    background: #EDE6EA;
    flex: none;
  }

  .seg-video-item video {
    width: 100%;
    max-width: 100%;
    height: auto;
  }
}

@media (max-width: 560px) {
  /* Aquí .mbody-pad baja a 16px de padding: ya no cabe el ícono en
     -32px sin salirse del modal (se recortaría contra .modal-card,
     que tiene overflow:hidden). Vuelve al flujo normal, en línea junto
     a la franja. */
  .ficha-row>.ficha-icono {
    position: static;
    transform: none;
    margin-right: 12px;
  }

  /* Mismo motivo que arriba, pero acá .render-item es columna (título
     arriba, imagen/video abajo): el ícono vuelve al flujo normal como
     primer elemento, arriba del todo, en vez de a la izquierda. */
  .render-item>.ficha-icono {
    position: static;
    transform: none;
    margin: 0 0 4px;
  }

  .gal {
    grid-template-columns: 1fr
  }

  .kpis {
    grid-template-columns: 1fr;
  }

  .kpi {
    padding: 12px;
  }

  .kpi .val {
    font-size: 21px
  }

  .kpi .lbl {
    font-size: 10.5px;
  }

  .modal {
    margin: 10px;
  }

  .modal-card {
    border-radius: 0px;
  }

  .modal-top {
    padding: 13px 16px;
    padding-right: 58px;
  }

  .modal-top h3 {
    font-size: 15.5px;
  }

  .modal-close {
    top: 12px;
    right: 12px;
    width: 34px;
    height: 34px;
    font-size: 16px;
  }

  .mbody-pad {
    padding: 0 16px;
  }

  .render-grid-pad {
    padding: 0 16px;
  }

  .dt {
    grid-template-columns: 1fr;
  }

  .dt>div {
    border-right: none !important;
    border-bottom: 1px dashed var(--line);
  }

  .dt>div:last-child {
    border-bottom: none;
  }

  .blk p {
    text-align: left;
  }

  .header-right-logo img {
    height: 21px;
  }

  .brand h1 {
    font-size: 12px;
  }

  .brand p {
    font-size: 8px;
  }

  .msegbody-pad {
    padding: 0 16px;
  }

  .seg-avance-col {
    grid-template-columns: 1fr;
    height: auto;
  }

  .seg-avance-chart {
    min-height: 180px;
    width: 100%;
  }

  .seg-historial-list {
    width: 100%;
    justify-content: flex-start;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 4px;
  }

  .seg-historial-item {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .seg-fotos {
    width: 100%;
  }

  .seg-historial-layout {
    grid-template-columns: 1fr;
  }

  .seg-historial-list {
    flex-direction: row;
  }
}

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

  .header-right-logo img {
    height: 21px;
  }

  header {
    padding: 2px 18px;
  }

  .brand h1 {
    font-size: 12px;
  }

  .brand p {
    font-size: 8px;
  }
}

/* ===== Responsivo: Modal de Gestiones ===== */
@media (max-width: 640px) {
  .modal {
    padding: 0;
    margin: 0;
  }

  .modal-card,
  .modal-card-gest,
  .modal-card1 {
    max-width: 100%;
    width: 100%;
    --modal-w: 100vw;
    min-height: 100vh;
    border-radius: 0;
    display: flex;
    flex-direction: column;
  }

  .modal-top {
    padding: 14px 60px 14px 16px;
    flex-wrap: wrap;
  }

  .modal-close {
    right: 12px;
    top: 12px;
    width: 40px;
    height: 40px;
    font-size: 16px;
  }

  .modal-card-gest .modal-top h3 {
    font-size: 15.5px;
    line-height: 1.25;
  }

  .gest-modal-body {
    padding: 16px;
    flex: 1;
    overflow-y: auto;
  }

  .avance-general {
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 14px;
  }

  .avance-general .ag-label {
    font-size: 12px;
  }

  .avance-general .ag-valor {
    font-size: 16px;
  }

  .tbl-archivos-gest thead th,
  .tbl-archivos-gest tbody td {
    padding: 8px 6px;
    font-size: 12.5px;
  }

  .tbl-archivos-gest thead th:last-child {
    width: 90px;
  }

  .pdf-link {
    font-size: 12px;
    padding: 4px 8px;
    white-space: normal;
    text-align: center;
  }

  .gchips-gest {
    gap: 5px;
  }

  .btn-gest-item {
    font-size: 11px;
    padding: 5px 11px;
  }

  header {
    padding: 2px 18px;
  }

  .header-right-logo img {
    height: 21px;
  }

  .brand h1 {
    font-size: 12px;
  }

  .brand p {
    font-size: 8px;
  }
}

/* ============================================================
   MODAL SEGUIMIENTO DE OBRA
   ============================================================ */

/* Avance Físico / Avance Financiero: 2 columnas en desktop, cada
   una con su texto (Programado/Real/Semanal apilados) a la
   izquierda y 1 sola gráfica a la derecha ocupando la altura
   completa de esas 3 filas. */
.seg-avance-grid {
  display: grid;
  grid-template-columns: 1fr;
}

.seg-avance-col {
  display: grid;
  grid-template-columns: minmax(180px, 2%) 1fr;
  gap: 14px;
  align-items: stretch;
  height: 250px;
}

.seg-avance-datos {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.seg-avance-datos h5 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--vino-2);
  font-weight: 700;
  margin-bottom: 4px;
  white-space: nowrap;
}

.seg-avance-fila {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 13px;
  color: var(--ink-2);
}

.seg-avance-fila b {
  color: var(--ink);
  font-family: 'Archivo', sans-serif;
}

.seg-avance-chart {
  position: relative;
  min-height: 140px;
}

/* Colima: gráfica única de avance (Físico Programado, Físico Real,
   Financiero Real) a todo el ancho del modal, con los datos de texto
   (Meta) debajo. */
.seg-avance-datos-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

.seg-avance-chart-full {
  position: relative;
  width: 100%;
  min-height: 340px;
  margin-bottom: 14px;
}

@media (max-width: 640px) {
  .seg-avance-datos-row {
    gap: 10px;
  }

  .seg-avance-chart-full {
    min-height: 260px;
  }
}

/* "Meta" ya no es una lista de filas sueltas: son 2 tablas reales
   separadas (Avance Físico / Avance Financiero), una junto a la otra en
   escritorio y apiladas en móvil. Cada una lleva encima su encabezado
   (Meta Total / Monto Contratado) -- ver .seg-meta-col/.seg-meta-encabezado. */
.seg-meta-tablas {
  display: flex;
  justify-content: center;
  gap: 40px;
  flex-wrap: wrap;
}

.seg-meta-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 300px;
}

/* El icono va a la izquierda, y la franja dorada ya no se queda solo
   junto al título/valor: ahora envuelve también la tabla de abajo (todo
   el bloque -- título, valor y tabla -- es una sola franja continua),
   con el icono centrado verticalmente respecto a esa altura completa.
   ".seg-meta-marco { flex:1 }" + "align-items:stretch" es lo que hace
   que la columna de Avance Financiero (menos filas) crezca hasta igualar
   la altura de la de Avance Físico: al ser ambas columnas hijas de un
   mismo flex-row (.seg-meta-tablas), por default ya se estiran a la
   altura de la más alta -- aquí nomás se deja que ese alto extra se lo
   quede la tabla en vez de sobrar como espacio vacío. */
.seg-meta-marco {
  display: flex;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  flex: 1 1 auto;
}

.seg-meta-marco > img {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
  /* Centrado respecto al título+valor (no respecto a todo el bloque
     incluida la tabla, que lo dejaría flotando muy abajo). */
  align-self: flex-start;
  margin-top: 4px;
}

.seg-meta-cuerpo {
  flex: 1 1 auto;
  min-width: 0;
  border-left: 3px solid var(--oro);
  padding-left: 8px;
  display: flex;
  flex-direction: column;
}

.seg-meta-cuerpo > h5 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--vino-2);
  font-weight: 700;
  margin: 0 0 5px;
}

.seg-meta-cuerpo > p {
  font-size: 14px;
  color: var(--ink);
  font-family: 'Archivo', sans-serif;
  font-weight: 600;
  margin: 0 0 10px;
}

.seg-meta-tbl {
  /* La regla base "table { min-width:700px }" del sitio (pensada para
     tablas grandes con scroll horizontal) hacía que esta tabla angosta
     terminara igual de ancha que las demás -- aquí se anula. flex+height
     100% es lo que hace que, si esta tabla tiene menos filas que la de
     al lado (Avance Financiero vs Avance Físico), crezca para ocupar
     el mismo alto en vez de dejar espacio vacío debajo. */
  flex: 1 1 auto;
  width: 100%;
  height: 100%;
  min-width: 0;
  table-layout: fixed;
  border-collapse: collapse;
  border: 1px solid var(--line);
}

.seg-meta-tbl td:first-child {
  width: 62%;
  white-space: nowrap;
}

.seg-meta-tbl th {
  background: var(--vino);
  color: #fff;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  font-weight: 700;
  padding: 8px 12px;
  text-align: center;
}

.seg-meta-tbl td {
  padding: 7px 12px;
  font-size: 13px;
  color: var(--ink-2);
  border-top: 1px solid var(--line);
}

.seg-meta-tbl tr:nth-child(even) td {
  background: var(--vino-soft);
}

.seg-meta-tbl td:last-child {
  text-align: right;
  font-weight: 700;
  color: var(--ink);
  font-family: 'Archivo', sans-serif;
}

.seg-Tabla-Rendimiento {
  margin-bottom: 0;
}

@media (max-width: 640px) {
  .seg-Tabla-Rendimiento {
    position: relative;
    padding-top: 24px;
  }

}

.seg-rend-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--ink-2);
}

.seg-rend-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border: 1px solid var(--line);
  border-radius: 10px;
}

.seg-rend-table {
  width: 100%;
  min-width: 980px;
  border-collapse: collapse;
  font-size: 12.5px;
  table-layout: auto;
}

.seg-rend-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

.seg-rend-table tbody td {
  vertical-align: top;
}

.seg-rend-table tbody td:first-child {
  min-width: 220px;
  font-weight: 600;
}

.seg-rend-table tbody td:last-child {
  min-width: 180px;
}

.seg-larguillo {
  margin-top: 10px;
}

/* Un único panel contenedor: todas las secciones (Claros, Diafragmas, Trabes,
   Cabezal, Columna, Vigas de Atado, Pilas) viven dentro de él, una debajo de
   otra, separadas solo por una línea divisoria (no por tarjetas/gaps sueltos). */
.seg-lg-layout-nuevo {
  width: 100%;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.05);
  overflow: hidden;
}

/* Contratista/Contrato: arriba de todo el larguillo, antes que la leyenda
   y las secciones — se muestra aunque todavía no haya datos de avance. */
.seg-lg-info-contrato {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 24px;
  padding: 2px 2px 12px;
  font-size: 12.5px;
  color: var(--ink-2);
}

.seg-lg-info-contrato p {
  margin: 0;
}

.seg-lg-info-contrato strong {
  color: var(--vino-2);
  font-weight: 700;
  margin-right: 4px;
}

/* Leyenda de colores del larguillo: qué significa cada color que aparece
   en las celdas de todas las secciones de abajo. Una sola vez, arriba de
   todo (no se repite por sección). */
.seg-lg-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  padding: 8px 10px;
  font-size: 11px;
  font-weight: 600;
  color: #333;
  border-bottom: 1px solid var(--line);
  background: #fafbfe;
}

.seg-lg-leyenda-item {
  display: flex;
  align-items: center;
  gap: 5px;
}

.seg-lg-leyenda-muestra {
  width: 12px;
  height: 12px;
  border: 1px solid #111;
  border-radius: 2px;
  flex-shrink: 0;
}

.seg-lg-seccion {
  width: 100%;
  border-bottom: 1px solid var(--line);
  padding: 8px 8px 10px;
  /* Todo debe caber en el ancho del modal: nada de scroll horizontal,
     las celdas se encogen (fr) en vez de forzar un min-width grande. */
  overflow-x: hidden;
  box-sizing: border-box;
}

.seg-lg-seccion:last-child {
  border-bottom: none;
}

.seg-lg-seccion-titulo {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #4c5566;
  text-align: center;
}

.seg-lg-grid-barras {
  display: grid;
  row-gap: 2px;
  column-gap: 2px;
  align-items: stretch;
  width: 100%;
}

.seg-lg-cab-columna {
  font-size: 8.5px;
  font-weight: 700;
  text-align: center;
  color: #333;
  padding-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Números de Diafragmas/Trabes: girados 90° para que quepan números de 2
   dígitos en columnas angostas sin encimarse (antes se veían truncados
   tipo "1..1..2.." al llegar al 10). writing-mode deja que el propio grid
   calcule el alto de la fila según el texto girado, sin necesidad de fijar
   una altura a mano. */
.seg-lg-cab-numero {
  writing-mode: vertical-rl;
  font-size: 8.5px;
  font-weight: 700;
  color: #333;
  justify-self: center;
  padding-bottom: 2px;
  white-space: nowrap;
}

.seg-lg-fila-etiqueta {
  font-size: 8.5px;
  font-weight: 600;
  color: #333;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2px 3px;
  /* Etiquetas largas (p. ej. "Juntas de Dilatación") envuelven en vez de
     recortarse: la columna de etiquetas tiene un ancho fijo compartido con
     las secciones por apoyo (no se puede ensanchar sin desalinear todo),
     así que se deja crecer la fila hacia abajo en su lugar. */
  white-space: normal;
  overflow-wrap: break-word;
  line-height: 1.15;
}

.seg-lg-celda {
  border: 1px solid #111;
  box-sizing: border-box;
  min-height: 12px;
  min-width: 0;
  background-color: #ffffff;
  transition: background-color 0.15s ease;
}

.seg-lg-celda-na {
  border: none;
  background: transparent;
}

/* Columna / Pilas: 3 unidades por apoyo, más delgadas que el ancho del apoyo
   y repartidas a lo largo (la de la izquierda pegada a la izquierda, la de
   en medio centrada, la de la derecha pegada a la derecha), en vez de un
   bloque compacto centrado. */
.seg-lg-grupo-unidades {
  display: flex;
  justify-content: space-between;
  align-items: stretch;
  min-width: 0;
}

.seg-lg-grupo-unidades .seg-lg-celda {
  flex: 0 0 26%;
  min-width: 0;
}

/* Secciones por apoyo (Cabezal, Columna, Vigas de Atado, Pilas): sin separación
   entre filas para que la columna-divisor se vea como una sola línea completa,
   de la cabecera hasta la última fila. */
.seg-lg-grid-apoyo {
  row-gap: 0;
}

.seg-lg-grid-apoyo > .seg-lg-cab-columna,
.seg-lg-grid-apoyo > .seg-lg-fila-etiqueta {
  padding-top: 2px;
  padding-bottom: 2px;
}

/* Columna-divisor entre apoyos: al ser una columna real de la rejilla (no un
   borde pegado a la celda), queda completa de arriba a abajo en toda la sección.
   Más ancha y oscura que un simple borde para que la separación entre apoyos
   se note claramente, incluso contra las barras verdes. */
.seg-lg-divisor-apoyo {
  width: 4px;
  margin: 0 auto;
  background: #4c5566;
  border-radius: 2px;
  align-self: stretch;
}

@media (max-width: 980px) {
  .seg-lg-seccion {
    padding: 6px 5px 8px;
  }

  .seg-lg-seccion-titulo {
    font-size: 10px;
  }

  .seg-lg-cab-columna,
  .seg-lg-cab-numero,
  .seg-lg-fila-etiqueta {
    font-size: 7.5px;
  }

  .seg-lg-divisor-apoyo {
    width: 3px;
  }

  .seg-lg-celda {
    min-height: 9px;
  }
}

/* Datos principales / Habitantes: 2 columnas. */
.seg-datos-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

@media (max-width: 640px) {
  .seg-avance-col {
    grid-template-columns: 1fr;
    height: auto;
  }

  .seg-avance-chart {
    min-height: 180px;
    width: 100%;
  }

  .seg-datos-grid {
    grid-template-columns: 1fr;
  }

  .seg-lg-seccion {
    padding: 6px 4px 8px;
  }

  .seg-lg-cab-columna,
  .seg-lg-cab-numero,
  .seg-lg-fila-etiqueta {
    font-size: 7px;
  }

  .seg-lg-celda {
    min-height: 8px;
  }

  .seg-historial-layout {
    grid-template-columns: 1fr;
  }

  .seg-historial-list {
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    gap: 8px;
    padding-bottom: 4px;
  }

  .seg-historial-item {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .seg-fotos {
    width: 100%;
  }

  .seg-foto-img {
    width: 100%;
    max-width: 100%;
    aspect-ratio: 4 / 3;
  }

  .seg-video-item video {
    width: 100%;
    max-width: 100%;
    min-height: 220px;
  }
}

.seg-principal,
.seg-ciudadania {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.seg-principal h5,
.seg-ciudadania h5,
.seg-trabajadores-col h5 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--vino-2);
  font-weight: 700;
  margin-top: 10px;
}

.seg-principal h5:first-child,
.seg-ciudadania h5:first-child,
.seg-trabajadores-col h5:first-child {
  margin-top: 0;
}

.seg-principal p,
.seg-ciudadania p,
.seg-trabajadores-col p {
  font-size: 14px;
  color: var(--ink);
  font-family: 'Archivo', sans-serif;
  font-weight: 600;
}

/* Fuerza de trabajo y Maquinaria: ahora van una al lado de la otra
   dentro de .seg-datos-grid (2 columnas en pc, 1 en celular). */
.seg-trabajadores-col {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Empleos Generados: Directos/Indirectos uno al lado del otro en vez de
   apilados. */
.seg-empleos-cols {
  display: flex;
  gap: 24px;
}

/* Historial (quincenas) + Fotografías/Videos, según el boceto:
   columna angosta de quincenas a la izquierda, y a la derecha
   Fotografías arriba / Videos abajo. */
.seg-historial-layout {
  display: grid;
  grid-template-columns: 0.3fr 1.7fr;
  gap: 16px;
  align-items: start;
}

.seg-historial-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.seg-historial-item {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: 10px;
  padding: 10px 14px;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}

.seg-historial-item:hover {
  border-color: var(--vino-2);
}

.seg-historial-item.activo {
  background: var(--vino-2);
  border-color: var(--vino-2);
  color: #fff;
}

.seg-historial-contenido {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.seg-historial-bloque h5 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--vino-2);
  font-weight: 700;
  margin-bottom: 8px;
}

/* Ícono de foto de la dependencia, primera columna de la tabla de
   trámites (tramitología). Al hacer clic abre el lightbox ampliado. */
.tram-foto-cell {
  text-align: center;
  vertical-align: middle;
  width: 64px;
}

.tram-foto-icono {
  position: relative;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: #EDE6EA;
  cursor: pointer;
  display: block;
  margin: 0 auto;
}

.tram-foto-icono img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tram-foto-badge {
  position: absolute;
  bottom: 2px;
  right: 2px;
  background: var(--vino);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 6px;
}

.tram-foto-vacia {
  color: var(--muted);
  font-size: 11px;
}

/* Lightbox: imagen ampliada al hacer clic en el ícono de foto.
   Necesita quedar por encima de cualquier otro modal desde el que se
   abra (p. ej. el de Seguimiento/Avances), así que sube su z-index en
   vez de depender del orden en el DOM. */
.lightbox-modal {
  z-index: 90;
}

.lightbox-modal.open {
  align-items: center;
}

/* Ancho/alto fijos (no dependen de la imagen): las fotos que llegan de
   obra no siempre traen el mismo formato (retrato, paisaje, cuadradas...),
   así que sin un tamaño fijo el "marco" del lightbox cambiaba de tamaño
   con cada imagen. Con object-fit:contain en #lightboxImg, cada foto se
   ajusta dentro de este mismo marco sin deformarse. */
.lightbox-card {
  position: relative;
  width: min(90vw, 900px);
  height: min(80vh, 650px);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lightbox-card #lightboxImg {
  width: 100%;
  height: 100%;
  border-radius: 10px;
  display: block;
  object-fit: contain;
  background: #1a0610;
}

/* Barra superior del lightbox: el "Tipo" del trámite (u otro título) a la
   izquierda y el botón de cerrar a la derecha, superpuestos sobre la
   imagen para no depender del tamaño del contenedor. */
.lightbox-topbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 14px 32px;
  background: linear-gradient(to bottom, rgba(0, 0, 0, .65), rgba(0, 0, 0, 0));
  border-radius: 10px 10px 0 0;
}

.lightbox-title {
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Solo en el lightbox de fotos (Tramitología): el título ("Tipo") va
   sobre la propia foto, con el degradado de .lightbox-topbar de fondo.
   Si la foto es clara, el texto blanco se pierde; un fondo propio lo
   hace legible sin importar qué haya detrás. En el modal de PDF no hace
   falta (su barra ya tiene fondo sólido). */
#modalLightbox .lightbox-title {
  background: rgba(0, 0, 0, .6);
  padding: 5px 12px;
  border-radius: 8px;
}

.lightbox-topbar .lightbox-close {
  position: static;
  flex: none;
  width: 36px;
  height: 36px;
  font-size: 15px;
}

.lightbox-prev,
.lightbox-next {
  z-index: 5;
}

.lightbox-prev {
  left: -21px;
  border-radius: 8px;
}

.lightbox-next {
  right: -21px;
  border-radius: 8px;
}

@media (max-width: 640px) {
  /* En vez de forzar 100vw x 100vh (un marco muy alto y angosto: en un
     teléfono de 375x812 eso es relación 0.46), una foto en formato
     paisaje quedaba con enormes franjas negras arriba/abajo por el
     object-fit:contain. Un marco más cuadrado (limitado por el ancho)
     deja mucho menos espacio muerto sin importar el formato de la foto. */
  .lightbox-card {
    width: 94vw;
    height: min(70vh, 94vw);
    margin: 0 auto;
    background: transparent;
  }

  .lightbox-card #lightboxImg {
    width: 100%;
    height: 100%;
  }

  .lightbox-prev {
    left: 4px;
  }
  .lightbox-next {
    right: 4px;
  }
}

/* Modal para ver PDFs embebidos (en vez de abrir una pestaña externa).
   A diferencia del lightbox de fotos, aquí la barra de título NO va
   flotando encima del contenido: el propio visor de PDF del navegador
   trae su propia barra de herramientas (zoom, descargar, imprimir...) y
   si la nuestra queda superpuesta se ven las dos chocando. Por eso el
   card es una columna: título arriba (fijo, con fondo sólido) y el PDF
   abajo ocupando el resto de la altura. */
.pdf-modal-card {
  width: min(94vw, 960px);
  height: calc(100vh - 40px);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  background: #fff;
  border-radius: 10px;
  overflow: hidden;
}

.pdf-modal-card .lightbox-topbar {
  position: static;
  flex: none;
  background: var(--vino);
  padding: 14px 16px;
  border-radius: 0;
}

.pdf-modal-card #pdfFrame {
  /* La regla global "iframe { max-height: 480px }" (pensada para los
     mapas embebidos) le pone tope a CUALQUIER iframe del sitio; sin
     anularla aquí, el visor de PDF se queda fijo en 480px de alto sin
     importar el tamaño del modal. */
  max-height: none;
  flex: 1 1 0%;
  width: 100%;
  height: 100%;
  min-height: 0;
  border: none;
  background: #fff;
  display: block;
}

@media (max-width: 640px) {
  .pdf-modal-card {
    width: 100vw;
    height: 100vh;
    border-radius: 0;
  }
}

/* Reset: los enlaces de PDF ahora son <button> que abren el visor en
   modal, así que quitan los estilos de botón nativo del navegador. */
.pdf-link,
.pdf-card {
  border: none;
  cursor: pointer;
  font-family: inherit;
}

.seg-fotos {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 14px;
}

.seg-foto-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
  width: 100%;

}

.seg-foto-img {
  width: 100%;
  max-width: 100%;
  margin: 0 auto;
  aspect-ratio: 4 / 3;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #EDE6EA;
  cursor: pointer;
}

.seg-foto-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  
}

.seg-foto-desc {
  width: 100%;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.3;
  text-align: center;
}

/* Videos: lista vertical, cada uno con su reproductor y descripción. */
.seg-videos {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.seg-video-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.seg-video-item video {
  width: 100%;
  max-width: 100%;
  height: auto;
  min-height: 220px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: #000;
  display: block;
}

.seg-video-desc {
  display: block;
  width: 100%;
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
  text-align: center;
}

.seg-vacio {
  font-size: 13px;
  color: var(--muted);
  font-style: italic;
}

/* Un poco de aire arriba cuando se llega aquí por el botón de
   "ir a" larguillo / tabla de rendimiento (scrollIntoView). */
.seg-larguillo,
.seg-Tabla-Rendimiento {
  scroll-margin-top: 16px;
}

@media (max-width: 768px) {
  .seg-historial-layout {
    grid-template-columns: 1fr !important;
    gap: 16px !important;
  }

  .seg-historial-list {
    width: 100% !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    gap: 8px !important;
    margin-bottom: 12px;
    padding-bottom: 4px;
  }

  .seg-historial-item {
    flex: 0 0 auto !important;
    min-width: 0 !important;
    white-space: nowrap;
  }

  .seg-historial-contenido {
    width: 100% !important;
  }

  .seg-fotos,
  .seg-videos {
    width: 100% !important;
  }

  .seg-fotos {
    grid-template-columns: 1fr !important;
  }

  .seg-foto-img {
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 auto !important;
  }

  .seg-video-item video {
    width: 100% !important;
    max-width: 100% !important;
    min-height: 220px !important;
  }
}

@media (max-width: 640px) {
  .apexcharts-toolbar,
  .apexcharts-menu {
    display: none !important;
    opacity: 0 !important;
    visibility: hidden !important;
  }
}

/* estilos.css — agregar después de .mbody-group:last-of-type */
.modal-card1 {
  max-width: 1200px;
  --modal-w: 1200px;
  width: 100%;
  margin: 0 auto;
  background: var(--surface);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .4);
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 40px);
}

.msegbody-pad {
  padding: 0 20px;
}

.msegbody-group {
  padding-top: 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

.msegbody-group:first-child {
  padding-top: 0;
}

.msegbody-group:last-of-type {
  border-bottom: none;
}

/* ===== Responsivo: modal de Seguimiento de obra ===== */

/* ===== Modal Chat Seguimiento ===== */
.chat-mensajes {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 20px;
}

.chat-msg {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.chat-avatar-placeholder {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--vino-2);
  color: #fff;
  font-family: 'Archivo', sans-serif;
  font-weight: 700;
  font-size: 15px;
  display: grid;
  place-items: center;
  flex: none;
}

.chat-bubble {
  background: #FBF7F9;
  border: 1px solid var(--line);
  border-radius: 0 12px 12px 12px;
  padding: 10px 14px;
  max-width: 85%;
}

.chat-bubble .cb-nombre {
  font-family: 'Archivo', sans-serif;
  font-weight: 700;
  font-size: 13px;
  color: var(--vino-2);
}

.chat-bubble .cb-rol {
  font-size: 11px;
  color: var(--muted);
  margin-bottom: 5px;
}

.chat-bubble .cb-texto {
  font-size: 13.5px;
  color: var(--ink);
  line-height: 1.4;
}

.chat-bubble .cb-fecha {
  font-size: 11px;
  color: var(--muted);
  margin-top: 5px;
  text-align: right;
}

.chat-input-row {
  display: flex;
  gap: 8px;
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.chat-input {
  flex: 1;
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 9px 16px;
  font-family: 'Inter', sans-serif;
  font-size: 13.5px;
  color: var(--ink);
  outline: none;
  transition: border-color .15s;
}

.chat-input:focus {
  border-color: var(--vino-2);
}

.chat-send {
  background: var(--vino-2);
  color: #fff;
  border: none;
  border-radius: 20px;
  padding: 9px 18px;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  transition: background .15s;
  white-space: nowrap;
}

.chat-send:hover {
  background: var(--vino);
}

.chat-historial {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.chat-historial-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  cursor: pointer;
  transition: background .15s;
}

.chat-historial-item:hover {
  background: var(--vino-soft);
}

/* Botón "Chat de seguimiento": antes era solo una imagen circular con
   un glow al hover, poco intuitivo como elemento clicable. Ahora es
   una píldora con ícono + texto + flecha, igual de clara que el
   botón "Inicio", y vive en su propia fila (no compite por espacio
   con "Corte al..." / "Inicio"). */
.link-Obra {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
  padding: 8px 18px 8px 8px;
  background: var(--vino);
  border: 1.5px solid var(--oro);
  border-radius: 999px;
  color: #fff;
  text-decoration: none;
  transition: background .15s, color .15s, border-color .15s;
}

.link-Obra:hover {
  background: var(--oro);
  border-color: var(--oro);
  color: var(--vino);
}

.link-Obra img {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  object-fit: cover;
  background: #fff;
  flex: none;
}

.link-Obra p {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .2px;
  text-transform: uppercase;
  white-space: nowrap;
}

.link-Obra p::after {
  content: '›';
  margin-left: 8px;
  font-weight: 700;
}

@media (max-width: 640px) {
  .link-Obra {
    width: 100%;
    justify-content: center;
    padding: 8px 16px 8px 6px;
  }

  .link-Obra img {
    width: 34px;
    height: 34px;
  }

  .link-Obra p {
    font-size: 12px;
  }
}

/* Botón "Chat de seguimiento" dentro de la tarjeta de Inversión total
   del Tablero ejecutivo: pensado para caber en el ancho de la tarjeta,
   con el ícono centrado junto al texto. */
.btn-chat-dash {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  box-sizing: border-box;
  margin-top: 14px;
  padding: 9px 14px;
  background: var(--vino);
  border: 1.5px solid var(--vino);
  border-radius: 50px;
  color: #fff;
  text-decoration: none;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .2px;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s, box-shadow .15s;
}

.btn-chat-dash:hover {
  background: #541630;
  box-shadow: 0 0 10px 2px rgba(105, 27, 60, 0.6);
  color: #dcccd2;
}

.btn-chat-dash img {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  object-fit: cover;
  background: #fff;
  flex: none;
}

.render-itemRec {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.render-item video {
  width: 100%;
  aspect-ratio: 4/3;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #EDE6EA;
  display: block;
  height: auto;
}

/* ===== Dashboard layout KPI top ===== */
.dash-kpi-top {
  display: grid;
  grid-template-columns: 33.3fr 33.3fr 33.3fr;
  grid-template-rows: auto auto;
  gap: 14px;
  margin-bottom: 18px;
}

/* Inversión: ocupa las 2 filas de la col 1 */
.dash-kpi-inv {
  grid-column: 1;
  grid-row: 1 / 3;
  text-align: center;
}

/* Estatus: ocupa las 2 filas de la col 3 */
.dash-kpi-right {
  grid-column: 3;
  grid-row: 1 / 3;
  padding: 14px 16px;
  overflow: hidden;
  width: auto;
}
/* Vacío: col 2, fila 2 */
.dash-kpi-vacio {
  grid-column: 2;
  grid-row: 2;
  border: 1px dashed var(--line);
  border-radius: 14px;
  box-shadow: none;
}

@media (max-width: 768px) {
  .dash-kpi-top {
    grid-template-columns: 1fr !important;
    grid-template-rows: auto !important;
  }

  .dash-kpi-inv,
  .dash-kpi-right,
  .dash-kpi-vacio {
    grid-column: 1 !important;
    grid-row: auto !important;
    width: 100% !important;
  }
}

.dash-etapa-header {
  margin: 24px 0 14px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--vino-2);
}

.dash-etapa-titulo {
  font-family: 'Archivo', sans-serif;
  font-weight: 800;
  font-size: 20px;
  color: var(--vino);
}

.dash-etapa-sub {
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
  line-height: 1.4;
}

.apex-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  padding-top: 10px;
  font-size: 12px;
  color: var(--muted);
}

.apex-leyenda span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.apex-leyenda i {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  display: inline-block;
  flex: none;
}

.dropdown-title {
  background-color: #691B3C;
  color: #fff;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;
  padding: 16px 18px;
  border-radius: 14px;
}

.dropdown-title a {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: inherit;
  text-decoration: none;
}

.dropdown-arrow {
  display: inline-block;
  transition: transform 0.2s ease;
}

.dropdown-panel.active {
  background: rgba(105, 27, 60, 0.06);
  border-color: #691B3C;
}

.dropdown-panel.active .dropdown-title {
  background-color: #fff;
  color: #691B3C;
}

.dropdown-title.active .dropdown-arrow {
  transform: rotate(180deg);
}

.hidden {
  display: none !important;
}

.historyChat {
  background: none;
  border: none;
  color: #E0BFCC;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  margin-bottom: 4px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: color .15s;
}

.historyChat:hover {
  color: #fff;
}

/* La impresión del modal "Permisos Requeridos" (botón "Imprimir") arma
   su propio documento en una ventana aparte -- ver imprimirPermisos() en
   edomex.html -- con sus estilos de impresión inline en esa ventana, así
   que no necesita reglas @media print aquí. */

/* ===== Scrollbars personalizados: delgados y color vino, en todo el
   sitio (tablas con scroll horizontal, modales, tarjetas de PDF, etc.).
   scrollbar-color/-width son heredables, así que basta con ponerlos en
   :root; los pseudo-elementos ::-webkit-scrollbar no heredan, por eso
   van con el selector universal. */
:root {
  scrollbar-width: thin;
  /* "auto" en vez de un color de fondo -- deja el track transparente
     (Firefox no tiene una palabra clave "transparent" para esto, así
     que se omite el segundo valor y usa el fondo real de abajo). */
  scrollbar-color: var(--vino) transparent;
}

*::-webkit-scrollbar {
  width: 8px !important;
  height: 8px !important;
}

*::-webkit-scrollbar-track,
*::-webkit-scrollbar-track-piece,
*::-webkit-scrollbar-corner {
  background: transparent !important;
}

*::-webkit-scrollbar-thumb {
  background: var(--vino) !important;
  border-radius: 8px !important;
  border: none !important;
}

*::-webkit-scrollbar-thumb:hover {
  background: var(--vino-2) !important;
}

/* Sin flechitas en los extremos -- solo la barra. Algunos Chromium
   necesitan el selector genérico (::-webkit-scrollbar-button) Y las
   variantes :start/:end por orientación para de verdad quitarlas -- con
   solo una de las dos formas a veces siguen apareciendo. */
*::-webkit-scrollbar-button {
  display: none !important;
  width: 0 !important;
  height: 0 !important;
}

*::-webkit-scrollbar-button:vertical:start,
*::-webkit-scrollbar-button:vertical:end,
*::-webkit-scrollbar-button:horizontal:start,
*::-webkit-scrollbar-button:horizontal:end,
*::-webkit-scrollbar-button:increment,
*::-webkit-scrollbar-button:decrement {
  display: none !important;
  width: 0 !important;
  height: 0 !important;
}