/* ==========================================================================
   Alvarán — Firme por Antioquia
   Hoja de estilos principal. Sin dependencias externas.

   El sistema visual sigue la presentación de campaña: fondo negro, verde
   oscuro como color de acento, tipografía display en mayúsculas y filetes
   finos. Toda la paleta está en :root; cambiarla aquí actualiza el sitio
   entero.

   Contrastes verificados contra la WCAG AA:
     verde   #14532d sobre blanco ............ 9.11:1
     verde claro #37b264 sobre negro ......... 7.17:1
     negro   sobre verde claro (botones) ..... 7.17:1
     blanco  sobre verde oscuro .............. 9.11:1
     blanco  sobre negro .................... 19.72:1
     gris    #56605a sobre blanco ............ 6.68:1
     gris claro #b6bdb8 sobre negro ......... 10.19:1
   ========================================================================== */

/* Anton, condensada pesada, alojada en el propio sitio. Antes el display
   dependía de "Arial Narrow", que no existe en iOS ni en Android: los
   titulares caían a la sans del sistema y perdían el carácter de la
   presentación de campaña. Licencia SIL OFL en assets/fuentes/anton-OFL.txt. */
@font-face {
  font-family: "Anton";
  src: url("../fuentes/anton-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

@font-face {
  font-family: "Anton";
  src: url("../fuentes/anton-latin-ext.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Space Grotesk para el texto. Es una grotesca de formas propias —la "y" de
   asta recta, la "a" de costado plano, la "g" cerrada— pero sin un solo
   adorno: dice algo en cada letra y aun así es mínima. Contrasta bien con
   Anton, que es condensada y estrecha, sin salirse del mismo género.
   Un archivo por subconjunto, variable de 300 a 700, así que la negrita no
   cuesta otra descarga. Licencia SIL OFL en
   assets/fuentes/space-grotesk-OFL.txt. */
@font-face {
  font-family: "Space Grotesk";
  src: url("../fuentes/space-grotesk-latin.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

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

:root {
  /* Paleta principal */
  --blanco: #ffffff;
  --negro: #0b0d0a;
  --negro-suave: #111610;
  --verde: #14532d;
  --verde-claro: #37b264;
  --verde-profundo: #0f3d22;

  /* Neutros de apoyo */
  --gris: #56605a;
  --gris-sobre-negro: #b6bdb8;
  /* Un punto más claro que el gris de apoyo: la cita es contenido, no
     metadato, y necesita leerse casi como texto principal. */
  --claro-sobre-negro: #d3d9d4;
  --linea: #d9ded9;
  --linea-oscura: #222a23;
  --hueso: #f4f7f4;

  /* Tipografía */
  --fuente-display: "Anton", "Arial Narrow", "Liberation Sans Narrow", system-ui,
    sans-serif;
  --fuente-texto: "Space Grotesk", system-ui, -apple-system, "Segoe UI",
    Helvetica, Arial, sans-serif;
  /* Serif del sistema para la voz citada: emparejada con una grotesca pesada
     da contraste real, y la cursiva sola en sans se veía endeble. Cero bytes:
     Georgia está en Windows, macOS e iOS; Noto Serif en Android. */
  --fuente-cita: Georgia, "Times New Roman", "Noto Serif", serif;

  /* Métricas */
  --ancho-max: 1200px;
  --radio: 4px;
  --transicion: 160ms ease;
  /* Alto real de la barra de cabecera. La portada móvil lo descuenta de la
     pantalla, así que si cambia aquí, cambia allí. */
  --alto-cabecera: 74px;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--fuente-texto);
  font-size: 17px;
  line-height: 1.65;
  color: var(--negro);
  background: var(--blanco);
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: var(--verde);
  text-underline-offset: 3px;
}

a:hover {
  color: var(--verde-profundo);
}

p {
  margin: 0 0 1em;
}

/* Tipografía display ------------------------------------------------------ */

h1,
h2 {
  font-family: var(--fuente-display);
  font-weight: 400;
  /* 1.08 y no 1.02: las tildes de las mayúsculas (ALVARÁN, ANTIOQUEÑO) suben
     por encima de la altura de mayúscula y se solapaban con la línea anterior. */
  line-height: 1.08;
  letter-spacing: 0;
  text-transform: uppercase;
  margin: 0 0 0.4em;
}

/* Los rótulos pequeños no son voz display: con la condensada pesada a 1rem se
   vuelven ilegibles. Van en la tipografía de texto, en versales. */
h3,
h4 {
  font-family: var(--fuente-texto);
  font-weight: 700;
  line-height: 1.25;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 0.4em;
}

/* Escala amplia y con saltos claros, no una progresión plana. */
h1 {
  /* El mínimo baja a 2.1rem porque a 320px una palabra larga como
     "ENCONTRADA." no cabe: la fuente condensada no existe en iOS ni Android,
     así que hay que dimensionar para la sans del sistema, más ancha. */
  font-size: clamp(2.1rem, 7.5vw, 5.5rem);
}

h2 {
  font-size: clamp(1.9rem, 4.5vw, 3.25rem);
}

h3 {
  font-size: 1.05rem;
  letter-spacing: 0.04em;
}

/* El punto verde final de cada titular, como en la presentación. */
.punto {
  color: var(--verde-claro);
}

.seccion--clara .punto,
.seccion--hueso .punto {
  color: var(--verde);
}

/* Utilidades -------------------------------------------------------------- */

.contenedor {
  width: 100%;
  max-width: var(--ancho-max);
  margin: 0 auto;
  padding: 0 1.5rem;
}

.seccion {
  padding: 5rem 0;
}

.seccion--oscura {
  background: var(--negro);
  color: var(--blanco);
}

.seccion--oscura h1,
.seccion--oscura h2,
.seccion--oscura h3 {
  color: var(--blanco);
}

.seccion--clara {
  background: var(--blanco);
}

.seccion--hueso {
  background: var(--hueso);
}

.seccion__intro {
  max-width: 60ch;
  font-size: 1.1rem;
  color: var(--gris);
}

.seccion--oscura .seccion__intro {
  color: var(--gris-sobre-negro);
}

/* Estado vacío: donde todavía no hay contenido se dice, y se remite a donde sí
   lo hay. Tres tarjetas sin texto se leen como una página rota. */
.vacio {
  max-width: 56ch;
  margin: 0 0 2.5rem;
  padding-left: 1.1rem;
  border-left: 3px solid var(--verde);
  font-size: 1.05rem;
  color: var(--gris);
}

.seccion--oscura .vacio {
  border-left-color: var(--verde-claro);
  color: var(--gris-sobre-negro);
}

/* Antetítulo: etiqueta corta en versales sobre el titular. */
.antetitulo {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--verde-claro);
  margin-bottom: 0.9rem;
}

.seccion--clara .antetitulo,
.seccion--hueso .antetitulo {
  color: var(--verde);
}

/* Marca de confirmación de la página «ya estás en el boletín». Se dibuja sola
   al cargar —primero el círculo, luego el trazo, con un rebote corto— porque
   el sitio no lleva JS: es una animación CSS que arranca al pintarse. El trazo
   se dibuja con stroke-dashoffset (la longitud del contorno, de oculto a cero)
   y `forwards` lo deja dibujado al terminar. Va en verde sobre la sección
   oscura, alineada a la izquierda como el antetítulo y el titular. */
.tick {
  display: block;
  width: 64px;
  height: 64px;
  margin-bottom: 1.4rem;
  transform-origin: center;
  animation: tick-rebote 0.5s 0.1s both;
}

.tick__circulo {
  stroke: var(--verde-claro);
  stroke-width: 2.5;
  stroke-dasharray: 145;
  stroke-dashoffset: 145;
  animation: tick-dibujo 0.55s ease-out forwards;
}

.tick__trazo {
  stroke: var(--verde-claro);
  stroke-width: 3.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 33;
  stroke-dashoffset: 33;
  animation: tick-dibujo 0.3s 0.45s ease-out forwards;
}

@keyframes tick-dibujo {
  to { stroke-dashoffset: 0; }
}

@keyframes tick-rebote {
  0% { transform: scale(0.8); }
  55% { transform: scale(1.06); }
  100% { transform: scale(1); }
}

/* Quien pide menos movimiento la ve ya dibujada, sin animación ni rebote. */
@media (prefers-reduced-motion: reduce) {
  .tick {
    animation: none;
  }
  .tick__circulo,
  .tick__trazo {
    animation: none;
    stroke-dashoffset: 0;
  }
}

.solo-lectores {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Contenido todavía por redactar. */
.salto-contenido {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--verde-claro);
  color: var(--negro);
  padding: 0.75rem 1.25rem;
  font-weight: 700;
  z-index: 200;
}

.salto-contenido:focus,
.salto-contenido:hover {
  left: 0;
  color: var(--negro);
}

:focus-visible {
  /* Verde oscuro por defecto (9.11:1 sobre blanco). El claro solo donde el
     fondo es negro: sobre blanco daba 2.72:1 y no alcanzaba el mínimo de 3:1
     que la WCAG exige a los componentes de interfaz. */
  outline: 3px solid var(--verde);
  outline-offset: 2px;
}

.cabecera :focus-visible,
.portada :focus-visible,
.seccion--oscura :focus-visible,
.frases :focus-visible,
.cta :focus-visible,
.pie :focus-visible {
  outline-color: var(--verde-claro);
}

/* Botones ----------------------------------------------------------------- */

.boton {
  display: inline-block;
  padding: 0.85rem 1.8rem;
  font-family: var(--fuente-texto);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: var(--radio);
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion),
    border-color var(--transicion);
}

.boton--principal {
  background: var(--verde-claro);
  color: var(--negro);
}

.boton--principal:hover {
  background: var(--blanco);
  color: var(--negro);
}

.boton--contorno {
  background: transparent;
  color: var(--blanco);
  border-color: rgba(255, 255, 255, 0.45);
}

.boton--contorno:hover {
  background: rgba(255, 255, 255, 0.1);
  color: var(--blanco);
  border-color: var(--blanco);
}

/* El botón de contorno nació para la portada, sobre negro. Puesto sobre una
   sección clara —el panel de revisión— quedaba blanco sobre blanco: se veía el
   hueco pero no el botón. */
.seccion--clara .boton--contorno,
.seccion--hueso .boton--contorno {
  color: var(--negro);
  border-color: var(--gris);
}

.seccion--clara .boton--contorno:hover,
.seccion--hueso .boton--contorno:hover {
  background: var(--negro);
  color: var(--blanco);
  border-color: var(--negro);
}

.boton--oscuro {
  background: var(--negro);
  color: var(--blanco);
}

.boton--oscuro:hover {
  background: var(--verde);
  color: var(--blanco);
}

/* Cabecera y navegación --------------------------------------------------- */

/* Variantes de ancho y separación para las páginas del Worker. Existen porque
   la CSP del sitio no admite estilos en línea —style-src 'self' los bloquea sin
   ruido— y durante un tiempo los formularios se renderizaron al doble de su
   ancho sin que nadie lo viera: el style="max-width: 60ch" estaba en el HTML,
   pero el navegador lo descartaba. La prueba de violaciones de CSP existe por
   esto. */
.contenedor--estrecho { max-width: 46ch; }
.contenedor--medio    { max-width: 60ch; }
.contenedor--lectura  { max-width: 68ch; }

.margen-arriba          { margin-top: 2rem; }
.margen-arriba--grande  { margin-top: 2.5rem; }
.sin-margen-arriba      { margin-top: 0; }
.margen-abajo--grande   { margin-bottom: 2.5rem; }

.color-heredado { color: inherit; }
.margen-arriba--mayor  { margin-top: 3rem; }
.margen-arriba--menor  { margin-top: 1rem; }

.cabecera {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--negro);
  color: var(--blanco);
  border-bottom: 1px solid var(--linea-oscura);
}

.cabecera__barra {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  min-height: var(--alto-cabecera);
}

/* El orden visual no es el del documento: la marca a la izquierda, el menú
   después y el botón de vinculación al final, pero en móvil ese botón debe
   quedar junto a la hamburguesa y nunca dentro del menú colapsado. */
.marca {
  order: 1;
  margin-right: auto;
}

.nav {
  order: 2;
}

.cabecera__cta {
  order: 3;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  min-height: 44px;
  padding: 0.55rem 1.1rem;
  background: var(--verde-claro);
  color: var(--negro);
  border-radius: var(--radio);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}

.cabecera__cta:hover,
.cabecera__cta[aria-current="page"] {
  background: var(--blanco);
  color: var(--negro);
}

.nav__boton {
  order: 4;
}

.marca {
  /* En línea con el logotipo y alineados por abajo, para que el rótulo se
     apoye en la misma base que ANTIOQUIA. */
  display: flex;
  align-items: flex-end;
  color: var(--blanco);
  text-decoration: none;
  line-height: 1;
}

.marca:hover {
  color: var(--verde-claro);
}

/* El rótulo aparece al bajar, a la derecha del logotipo y apoyado en la misma
   base que ANTIOQUIA. Arriba del todo la portada ya dice el apellido a tamaño
   gigante, así que solo hace falta cuando esa portada deja de verse.
   Ocupa sitio siempre, también invisible: si entrara y saliera del flujo, la
   cabecera daría un salto cada vez que se cruza el umbral. */
.marca__alvaran {
  flex: 0 0 auto;
  margin-left: 0.55rem;
  /* Ajuste óptico: ANTIOQUIA no llega justo al borde inferior del SVG, así que
     alinear cajas no alinea las letras. */
  padding-bottom: 2px;
  font-family: var(--fuente-display);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  line-height: 1;
  white-space: nowrap;
  text-transform: uppercase;
  color: var(--verde-claro);
  /* Decorativo: el texto alternativo del logotipo ya nombra al candidato, y
     repetirlo obligaría a oír "Alvarán" dos veces seguidas. */
  pointer-events: none;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity var(--transicion), transform var(--transicion);
}

.cabecera[data-desplazada] .marca__alvaran {
  opacity: 1;
  transform: translateX(0);
}

.marca__logotipo {
  display: block;
  width: auto;
  /* Ahora es la marca completa de la cabecera, así que ocupa la altura que la
     barra permite sin apretar: tres líneas necesitan cuerpo para leerse. */
  height: 44px;
}

.nav__lista {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__enlace {
  display: block;
  padding: 0.5rem 0.75rem;
  color: var(--blanco);
  text-decoration: none;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav__enlace:hover {
  color: var(--verde-claro);
}

.nav__enlace[aria-current="page"] {
  color: var(--verde-claro);
  box-shadow: inset 0 -2px 0 var(--verde-claro);
}

.nav__boton {
  display: none;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--radio);
  color: var(--blanco);
  /* 44x44 es el mínimo cómodo para el pulgar; por debajo se falla el toque. */
  min-width: 44px;
  min-height: 44px;
  padding: 0.45rem 0.6rem;
  cursor: pointer;
}

.nav__boton svg {
  display: block;
}

/* El icono lo conmuta el CSS desde aria-expanded: el atributo hidden no existe
   en SVGElement y asignarlo no hace nada. */
.nav__boton[aria-expanded="true"] [data-icono-menu],
.nav__boton:not([aria-expanded="true"]) [data-icono-cerrar] {
  display: none;
}

/* Portada ----------------------------------------------------------------- */

.portada {
  background: var(--negro);
  color: var(--blanco);
  position: relative;
  overflow: hidden;
}

/* min-width: 0 evita que un hijo ancho (el retrato) imponga su tamaño mínimo
   a la columna y empuje el texto fuera de la pantalla. */
.portada__grid > * {
  min-width: 0;
}

.portada__grid {
  display: grid;
  grid-template-columns: 1fr 0.82fr;
  grid-template-areas:
    "titulo foto"
    "pie    foto";
  gap: 0 2rem;
  align-items: end;
  min-height: 68vh;
  padding-block: 3rem 3.5rem;
}

.portada__titulo {
  grid-area: titulo;
  align-self: end;
}

.portada__pie {
  grid-area: pie;
}

.portada__retrato {
  grid-area: foto;
  align-self: end;
  /* Compensa el relleno inferior de la rejilla para que el retrato se apoye
     en el borde de la sección, como en la presentación, en vez de flotar. */
  margin-bottom: -3.5rem;
}

.portada h1 {
  margin-bottom: 0.15em;
}

.portada h1 {
  font-size: clamp(2.4rem, 9vw, 7rem);
}

.portada__nombre {
  display: block;
  line-height: 0.92;
}



.portada__firme {
  display: block;
  color: var(--verde-claro);
}

.portada__por {
  display: block;
  font-size: 0.34em;
  letter-spacing: 0.3em;
  font-weight: 400;
}

.portada__cargo {
  border-top: 1px solid var(--linea-oscura);
  padding-top: 1.1rem;
  margin-top: 1.5rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gris-sobre-negro);
}

.portada__periodo {
  color: var(--verde-claro);
}

.portada__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 2rem;
}

.portada__retrato {
  /* Recorte sin fondo, apoyado en el borde inferior de la portada, como en la
     presentación de campaña. Sin filtros: la foto oficial va tal cual. */
  align-self: end;
  width: 100%;
  max-width: 520px;
  margin-left: auto;
  /* El retrato se apoya siempre por abajo, así que la animación de cambio de
     tamaño escala desde esa base: desde el centro parecería despegarse del
     borde mientras dura. */
  transform-origin: center bottom;
}

/* Carrusel de frases bajo la portada --------------------------------------
   Dos voces, dos tipografías: la cita ajena va en la tipografía de texto, en
   cursiva y entre comillas, porque es alguien a quien se cita; la del
   candidato en la display de campaña, que es la voz propia del sitio.
   Animación con CSS, sin librerías, escalonada entre las dos. */

.frases {
  background: var(--negro-suave);
  color: var(--blanco);
  border-top: 1px solid var(--linea-oscura);
  border-bottom: 1px solid var(--linea-oscura);
  padding: 3rem 0 3.75rem;
  overflow: hidden;
}

.frases__caja {
  position: relative;
  text-align: center;
}

.frases__lista {
  /* Todas las frases ocupan la misma celda: el bloque mide lo que la más alta
     y la página no da saltos al cambiar, sin fijar una altura a ojo. */
  display: grid;
  list-style: none;
  margin: 0;
  padding: 0;
}

.frases__slide {
  grid-area: 1 / 1;
  /* Todas las diapositivas se estiran a la altura de la más alta. Sin esto el
     par de frases se apoyaba en el borde de arriba y las cortas dejaban todo
     el hueco debajo; centrado, el conjunto queda siempre en el eje de la
     franja. El horizontal lo da el `margin: 0 auto` del par. */
  display: grid;
  align-content: center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.frases__slide[data-activa] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.frases__par {
  max-width: 60ch;
  margin: 0 auto;
}

.frases__cita {
  margin: 0;
  opacity: 0;
}

/* Voz ajena: serif, que es la convención de la cita y aguanta el peso de la
   display que lleva debajo. */
.frases__cita--lider {
  font-family: var(--fuente-cita);
  font-size: clamp(1.15rem, 2.3vw, 1.55rem);
  /* En negrita: sobre fondo oscuro la serif fina se adelgaza y la línea en
     Anton que lleva debajo se la comía. Sin cursiva ni comillas, lo que separa
     las dos voces es la serif frente a la display, el color y el filete. */
  font-weight: 700;
  text-transform: uppercase;
  /* Las versales necesitan aire entre letras: van pensadas para titulares
     cortos y aquí sostienen una frase entera. Un cuerpo algo menor que en caja
     normal, porque las mayúsculas ocupan bastante más ancho. */
  letter-spacing: 0.03em;
  line-height: 1.34;
  color: var(--claro-sobre-negro);
}

/* Voz propia: la display de campaña. Las dos frases van en versales, así que
   lo que distingue las voces es la tipografía y el color, no la caja. */
.frases__cita--candidato {
  font-family: var(--fuente-display);
  font-size: clamp(1.45rem, 3.1vw, 2.3rem);
  line-height: 1.18;
  text-transform: uppercase;
  color: var(--verde-claro);
  margin-top: 1.5rem;
}

.frases__autor {
  margin: 0.4rem 0 0;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #8d9382;
  opacity: 0;
}

/* Filete que separa las dos voces sin cargar la composición. */
.frases__autor:not(.frases__autor--candidato)::after {
  content: "";
  display: block;
  width: 28px;
  height: 1px;
  margin: 1.5rem auto 0;
  background: var(--linea-oscura);
}

.frases__autor--candidato {
  color: var(--verde-claro);
}

/* La entrada: cada elemento aparece con su propio retardo. */
.frases__slide[data-activa] .frases__cita,
.frases__slide[data-activa] .frases__autor {
  animation: entra-frase 520ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.frases__slide[data-activa] .frases__cita--lider {
  animation-delay: 0ms;
}

.frases__slide[data-activa] .frases__autor:not(.frases__autor--candidato) {
  animation-delay: 120ms;
}

.frases__slide[data-activa] .frases__cita--candidato {
  animation-delay: 220ms;
}

.frases__slide[data-activa] .frases__autor--candidato {
  animation-delay: 320ms;
}

@keyframes entra-frase {
  from {
    opacity: 0;
    transform: translateY(0.6rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Los puntos van fuera del flujo: si participaran, seis círculos medirían más
   que la frase y serían ellos los que fijaran el alto de la franja. */
.frases__controles {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
}

.frases__puntos {
  display: flex;
  gap: 0.35rem;
}

.frases__punto {
  width: 24px;
  height: 24px;
  padding: 0;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  cursor: pointer;
}

.frases__punto::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #767f73;
  transition: background var(--transicion), transform var(--transicion);
}

.frases__punto:hover::before {
  background: var(--gris-sobre-negro);
}

.frases__punto[aria-current="true"]::before {
  background: var(--verde-claro);
  transform: scale(1.5);
}

@media (max-width: 620px) {
  .frases {
    padding: 2.25rem 0 3rem;
  }

  .frases__controles {
    bottom: -2rem;
  }
}

/* Sin movimiento para quien lo ha desactivado: las frases cambian sin
   desplazamiento ni desvanecido. */
@media (prefers-reduced-motion: reduce) {
  .frases__slide[data-activa] .frases__cita,
  .frases__slide[data-activa] .frases__autor {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* Rejillas y tarjetas ------------------------------------------------------ */

.rejilla {
  display: grid;
  gap: 2rem 2.5rem;
  margin-top: 2.5rem;
}

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

.rejilla--3 {
  grid-template-columns: repeat(3, 1fr);
}

.rejilla--4 {
  grid-template-columns: repeat(4, 1fr);
}

/* Punto de contenido: icono, título y texto. Sin caja ni borde lateral: la
   jerarquía la dan el icono y el filete superior. */
.punto-clave {
  border-top: 1px solid var(--linea);
  padding-top: 1.2rem;
}

.seccion--oscura .punto-clave {
  border-top-color: var(--linea-oscura);
}

.punto-clave__icono {
  width: 30px;
  height: 30px;
  color: var(--verde);
  margin-bottom: 0.9rem;
}

.seccion--oscura .punto-clave__icono {
  color: var(--verde-claro);
}

.punto-clave h3 {
  margin-bottom: 0.4rem;
}

.punto-clave p {
  margin: 0;
  font-size: 0.95rem;
  color: var(--gris);
}

.seccion--oscura .punto-clave p {
  color: var(--gris-sobre-negro);
}

/* Cita destacada */
.cita {
  margin: 2.5rem 0 0;
  padding-left: 2.5rem;
  position: relative;
  font-size: 1.15rem;
  line-height: 1.5;
  font-style: italic;
}

.cita::before {
  content: "“";
  position: absolute;
  left: 0;
  top: -0.35em;
  font-family: var(--fuente-display);
  font-size: 3.5rem;
  color: var(--verde-claro);
  line-height: 1;
}

.seccion--clara .cita::before,
.seccion--hueso .cita::before {
  color: var(--verde);
}

.cita cite {
  display: block;
  margin-top: 0.8rem;
  font-size: 0.8rem;
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--verde);
}

.seccion--oscura .cita cite,
.cta .cita cite {
  color: var(--verde-claro);
}

/* Listas con marca de verificación */
.lista-marcada {
  list-style: none;
  padding: 0;
  margin: 0;
}

.lista-marcada li {
  position: relative;
  padding-left: 1.6rem;
  margin-bottom: 0.7rem;
  color: var(--gris);
}

.seccion--oscura .lista-marcada li {
  color: var(--gris-sobre-negro);
}

.lista-marcada li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px;
  height: 8px;
  background: var(--verde);
}

.seccion--oscura .lista-marcada li::before {
  background: var(--verde-claro);
}

/* Índice de anclas */
.indice {
  list-style: none;
  padding: 0;
  margin: 2rem 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.indice a {
  display: inline-block;
  padding: 0.45rem 1rem;
  border: 1px solid var(--linea);
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--negro);
}

.indice a:hover {
  background: var(--verde);
  border-color: var(--verde);
  color: var(--blanco);
}

/* Un elemento del índice sin enlace es una sección que todavía no existe. El
   filete discontinuo lo dice sin depender del color, para no ofrecer algo que
   al pulsarlo no lleva a ninguna parte. */
.indice span {
  display: inline-block;
  padding: 0.45rem 1rem;
  border: 1px dashed #a9b1a9;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gris);
}

/* Sobre fondo negro el índice iba en negro sobre negro: los enlaces se veían
   como cinco cápsulas vacías y no había forma de leer el programa. El filete
   tampoco vale el gris de las secciones claras; necesita llegar a 3:1 contra
   el fondo para que la cápsula se distinga (WCAG 1.4.11). */
.seccion--oscura .indice a {
  border-color: #6a736c;
  color: var(--blanco);
}

.seccion--oscura .indice a:hover {
  background: var(--verde-claro);
  border-color: var(--verde-claro);
  color: var(--negro);
}

/* Lo que aún no está publicado. Separado por un filete grueso, como las
   regiones que sí lo están, para que se lea como el final de la serie y no
   como una región más. ---------------------------------------------------- */

.por-venir {
  border-top: 2px solid var(--negro);
  padding-top: 2.5rem;
}

.por-venir p {
  max-width: 52ch;
  color: var(--gris);
}

.por-venir .indice {
  margin-top: 1.75rem;
}

/* Eje programático --------------------------------------------------------- */

.eje {
  padding-top: 2rem;
  border-top: 2px solid var(--negro);
  margin-bottom: 3.5rem;
  scroll-margin-top: 110px;
}

.eje__cabecera {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 1rem;
}

.eje__numero {
  font-family: var(--fuente-display);
  font-size: 2.2rem;
  font-weight: 400;
  line-height: 0.9;
  color: var(--verde);
}

.eje h2 {
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  margin: 0;
}

.eje__cuerpo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.5rem;
}

/* Regiones ----------------------------------------------------------------- */

.region {
  scroll-margin-top: 110px;
  margin-bottom: 4.5rem;
}

.region__portada {
  position: relative;
  background: var(--negro);
  color: var(--blanco);
  padding: 3rem;
  margin-bottom: 2.5rem;
}

.region__portada h2 {
  margin-bottom: 0.3em;
}

.region__subtitulo {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--verde-claro);
  margin: 0;
}

/* Fotografías de las subregiones: vienen de Wikimedia Commons con licencia
   Creative Commons, y la atribución del pie de foto es una condición de la
   licencia, no un adorno — no se quita. Cuando haya fotos propias del
   recorrido, se sustituyen archivo a archivo (ver CONTENIDO.md). */
.region__imagen {
  margin: 2.5rem 0 0;
}

.region__imagen img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radio);
}

/* Créditos de las fotografías, agrupados al final de la página en vez de bajo
   cada imagen: la licencia Creative Commons BY exige acreditar autor y
   licencia, pero admite cualquier forma razonable de hacerlo, y nueve pies de
   foto rompían la lectura de las fichas. */
.creditos {
  font-size: 0.85rem;
  color: var(--gris);
}

.creditos summary {
  cursor: pointer;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--negro);
}

.creditos p {
  margin: 0.75rem 0 0.5rem;
}

.creditos__lista {
  margin: 0;
  padding-left: 1.1rem;
}

.creditos__lista li {
  margin-bottom: 0.2rem;
}

.creditos a {
  color: inherit;
}

.region__datos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem;
}

.region__bloque h3 {
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--linea);
  margin-bottom: 1rem;
}

/* Cifras destacadas */
.cifras {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  list-style: none;
  padding: 0;
  margin: 3rem 0 0;
}

.cifra__valor {
  display: block;
  font-family: var(--fuente-display);
  font-size: clamp(2.5rem, 5vw, 3.8rem);
  font-weight: 700;
  line-height: 1;
  color: var(--verde-claro);
}

.seccion--clara .cifra__valor,
.seccion--hueso .cifra__valor {
  color: var(--verde);
}

.cifra__texto {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gris);
}

.seccion--oscura .cifra__texto {
  color: var(--gris-sobre-negro);
}

/* Retrato de la biografía */
.bio__foto {
  width: 100%;
  max-width: 380px;
  margin-bottom: 1.5rem;
}

/* Canales oficiales -------------------------------------------------------- */

.canal {
  display: flex;
  align-items: center;
  /* Envuelve en pantallas estrechas: con el rótulo empujado a la derecha, la
     caja se salía 29px a 320px de ancho. */
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  padding: 1.25rem 1.4rem;
  border: 1px solid var(--linea);
  color: var(--negro);
  text-decoration: none;
  transition: border-color var(--transicion), background var(--transicion);
}

.canal:hover {
  border-color: var(--verde);
  background: var(--hueso);
  color: var(--negro);
}

.canal svg {
  flex: 0 0 auto;
  color: var(--verde);
}

.canal__nombre {
  font-family: var(--fuente-display);
  font-size: clamp(1.1rem, 4vw, 1.35rem);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

/* Siempre en su propia línea. Empujado a la derecha cabía con tres tarjetas,
   pero con cuatro unas lo partían y otras no, y la fila quedaba desigual. */
.canal__red {
  flex-basis: 100%;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gris);
}

/* Ruta del recorrido: línea horizontal de hitos, uno por subregión ----------
   Las recorridas llevan un tick dentro de un círculo lleno; las pendientes, el
   círculo vacío. La marca es una forma, no solo un color: quien no distinga el
   verde ve igualmente qué está hecho y qué no. */

.ruta__cuenta {
  margin: 2.5rem 0 0;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gris);
}

.ruta__cuenta strong {
  font-family: var(--fuente-display);
  font-size: 1.6rem;
  letter-spacing: 0;
  vertical-align: -0.15em;
  color: var(--verde);
}

.ruta {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  list-style: none;
  margin: 1.75rem 0 0;
  padding: 0;
}

.ruta__hito {
  position: relative;
  min-width: 0;
  padding-top: 3.1rem;
  text-align: center;
}

/* El tramo de línea sale del centro de cada hito y llega al centro del
   siguiente; el último no pinta ninguno. */
.ruta__hito::before {
  content: "";
  position: absolute;
  top: 1.05rem;
  left: 50%;
  right: -50%;
  height: 2px;
  background: var(--linea);
}

.ruta__hito:last-child::before {
  display: none;
}

/* Verde solo cuando los dos extremos del tramo están recorridos: si no, la
   línea diría que está hecho un trecho que no lo está. */
.ruta__hito[data-estado="recorrida"]:has(+ .ruta__hito[data-estado="recorrida"])::before {
  background: var(--verde);
}

.ruta__marca {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 2.1rem;
  height: 2.1rem;
  display: grid;
  place-items: center;
  border: 2px solid var(--linea);
  border-radius: 50%;
  background: var(--blanco);
  color: var(--blanco);
}

.ruta__marca svg {
  opacity: 0;
}

.ruta__hito[data-estado="recorrida"] .ruta__marca {
  border-color: var(--verde);
  background: var(--verde);
}

.ruta__hito[data-estado="recorrida"] .ruta__marca svg {
  opacity: 1;
}

.ruta__nombre {
  display: inline-block;
  font-family: var(--fuente-display);
  font-size: 0.92rem;
  line-height: 1.15;
  text-transform: uppercase;
  color: var(--gris);
  text-decoration: none;
}

.ruta__hito[data-estado="recorrida"] .ruta__nombre {
  color: var(--negro);
}

/* Las subregiones con página propia van subrayadas ya en reposo: sin eso son
   un enlace que no parece enlace, porque el color lo fija el estado del hito
   y no la condición de enlace. */
a.ruta__nombre {
  text-decoration: underline;
  text-decoration-color: var(--verde-claro);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

a.ruta__nombre:hover {
  text-decoration-color: var(--verde);
}

/* En un teléfono nueve nombres no caben: la ruta se arrastra de lado, con
   anclaje, igual que la tira de fotografías. La cuenta de arriba dice el
   avance sin necesidad de desplazarse. */
@media (max-width: 980px) {
  .ruta {
    grid-auto-columns: 7.5rem;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    margin-inline: -1.5rem;
    padding-inline: 1.5rem;
    scrollbar-width: none;
  }

  .ruta::-webkit-scrollbar {
    display: none;
  }

  .ruta__hito {
    scroll-snap-align: center;
  }
}

/* Tira de fotografías del recorrido ---------------------------------------
   En pantallas anchas es una fila completa; en móvil se desplaza de lado, así
   seis fotos no añaden seis pantallas de scroll. */

.tira-recorrido {
  display: grid;
  /* Cuadrícula que baja de línea, no una fila que encoge. Con una sola fila,
     cada foto que se añade estrecha a TODAS: con nueve salían a 117 px en vez
     de 190 y las caras dejaban de leerse. Así las de arriba se quedan como
     están y las nuevas se ponen debajo. En móvil sigue siendo una tira que se
     arrastra, que ahí sí funciona. */
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0.75rem;
  list-style: none;
  margin: 3rem 0 0;
  padding: 0;
}

.tira-recorrido img {
  width: 100%;
  height: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  background: var(--linea);
}

@media (max-width: 980px) {
  .tira-recorrido {
    /* Vuelve a ser una fila: sin anular las columnas, el flujo por columnas no
       manda y la tira no se desplazaría. */
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 62%;
    /* Desplazamiento lateral con anclaje: el pulgar arrastra y cada foto se
       detiene en su sitio. */
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin-inline: -1.5rem;
    padding-inline: 1.5rem;
    scrollbar-width: none;
  }

  .tira-recorrido::-webkit-scrollbar {
    display: none;
  }

  .tira-recorrido li {
    scroll-snap-align: start;
  }
}

/* La caja de frases quedaba algo alta tras centrarla. */
.frases {
  padding-block: 2.5rem 3.25rem;
}

/* Noticias y agenda -------------------------------------------------------- */

.noticia {
  display: flex;
  flex-direction: column;
}

.noticia__imagen {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--hueso);
  margin-bottom: 1rem;
}

.noticia__fecha {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--verde);
  margin-bottom: 0.4rem;
}

.noticia h2,
.noticia h3 {
  font-size: 1.25rem;
  margin-bottom: 0.5rem;
}

.noticia p {
  color: var(--gris);
  font-size: 0.95rem;
}

.enlace-flecha {
  /* Blanco de toque de 24px como mínimo (WCAG 2.2, 2.5.8). */
  display: inline-block;
  padding: 0.3rem 0;
  min-height: 24px;
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  align-self: flex-start;
}

.enlace-flecha::after {
  content: " →";
}

.agenda {
  list-style: none;
  margin: 2.5rem 0 0;
  padding: 0;
}

.agenda__evento {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 1.5rem;
  align-items: center;
  padding: 1.3rem 0;
  border-bottom: 1px solid var(--linea);
}

.agenda__fecha {
  background: var(--negro);
  color: var(--blanco);
  text-align: center;
  padding: 0.7rem 0.3rem;
  line-height: 1.05;
}

.agenda__dia {
  display: block;
  font-family: var(--fuente-display);
  font-size: 1.9rem;
  font-weight: 700;
}

.agenda__mes {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--verde-claro);
}

.agenda__detalle {
  margin: 0;
  font-size: 0.95rem;
  color: var(--gris);
}

/* Formularios -------------------------------------------------------------- */

.formulario {
  border: 1px solid var(--linea);
  padding: 2rem;
}

.campo {
  margin-bottom: 1.2rem;
}

.campo label {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 0.4rem;
}

.campo .obligatorio {
  color: #b3261e;
}

.campo input,
.campo select,
.campo textarea {
  width: 100%;
  padding: 0.75rem 0.85rem;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  font: inherit;
  font-size: 0.98rem;
  background: var(--blanco);
  color: var(--negro);
}

/* El chevron nativo del <select> se dibuja pegado al borde derecho; con el
   padding compartido (0.85rem) el texto le quedaba justo debajo y en iOS se
   cortaba a media palabra («Prefiero no d…»). Se le reserva sitio a la derecha
   y, si aun así no cupiera, que termine en puntos suspensivos y no a hachazo. */
.campo select {
  padding-right: 2.25rem;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

.campo input:focus,
.campo select:focus,
.campo textarea:focus {
  border-color: var(--verde);
}

.campo textarea {
  min-height: 130px;
  resize: vertical;
}

.campo--casilla {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
}

.campo--casilla input {
  /* 24x24 mínimo: la casilla del navegador mide 13x13 y quedaba por debajo del
     objetivo táctil que exige la WCAG 2.5.8. */
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  /* margin en las cuatro caras, no solo arriba: el navegador deja 3-4 px a los
     lados de una casilla, y eso la separaba del borde izquierdo de los demás
     campos —quedaba descolada— e inflaba el hueco hasta el texto. Con el lado
     izquierdo a cero, la casilla se alinea con nombre, correo y subregión, y el
     enlace de la política (con su sangría fija) vuelve a caer bajo la etiqueta. */
  margin: 0.1rem 0 0 0;
  accent-color: var(--verde);
}

.campo--casilla label {
  font-size: 0.88rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--gris);
}

/* La etiqueta y el enlace de la política van juntos en una columna al lado
   de la casilla. Antes el enlace iba fuera del bloque con una sangría fija
   (2,1 rem) calculada para una casilla de 24 px: en Safari de iOS la casilla
   se pinta más ancha y con sus propios márgenes, y el enlace dejaba de caer
   bajo la etiqueta; y como la nota no tenía margen inferior, el botón de
   enviar quedaba pegado al enlace. En columna, el enlace cae bajo la etiqueta
   mida lo que mida la casilla, y el margen del .campo separa el botón. */
.campo--casilla__texto {
  flex: 1 1 auto;
  min-width: 0;
}

.campo--casilla .campo__nota {
  margin-left: 0;
}

/* El enlace a la política sale de la etiqueta: dentro, tocar para autorizar
   navegaba fuera en buena parte del área. */
.campo__nota {
  margin: 0.5rem 0 0 2.1rem;
  font-size: 0.88rem;
}

/* El botón de envío es el último hijo del formulario y venía pegado a lo que
   tuviera encima: en el alta al boletín, al enlace de la política (sin margen
   inferior), y sin este aire parecía recortado en el móvil. */
.formulario button[type="submit"] {
  margin-top: 1rem;
}

.campo__error {
  display: block;
  color: #b3261e;
  font-size: 0.85rem;
  margin-top: 0.3rem;
  min-height: 1.2em;
}

.campo input[aria-invalid="true"],
.campo select[aria-invalid="true"],
.campo textarea[aria-invalid="true"] {
  border-color: #b3261e;
}

.aviso {
  padding: 1rem 1.2rem;
  margin-bottom: 1.2rem;
  font-size: 0.94rem;
  border: 1px solid var(--linea);
  border-top: 3px solid var(--verde);
}

.aviso--exito {
  border-top-color: #2e7d43;
  background: #f1f8f2;
}

.aviso--error {
  border-top-color: #b3261e;
  background: #fdf1f0;
}

.resumen-errores__titulo {
  margin: 0 0 0.5rem;
  font-weight: 700;
}

.resumen-errores__lista {
  margin: 0;
  padding-left: 1.2rem;
  font-size: 0.92rem;
}

.resumen-errores__lista li {
  margin-bottom: 0.25rem;
}

.aviso--alerta {
  border-top-color: #b58900;
  background: #fdf8e8;
}

.aviso[hidden] {
  display: none;
}

/* Contacto */
.redes {
  display: flex;
  gap: 0.6rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

.redes a {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--linea);
  color: var(--negro);
  text-decoration: none;
}

.redes a:hover {
  background: var(--verde);
  border-color: var(--verde);
  color: var(--blanco);
}

.pie .redes a {
  border-color: var(--linea-oscura);
  color: var(--blanco);
}

.pie .redes a:hover {
  background: var(--verde-claro);
  border-color: var(--verde-claro);
  color: var(--negro);
}

/* Llamado a la acción ------------------------------------------------------ */

/* Menos aire abajo que arriba: sin la nota que iba bajo el botón, el hueco
   sobrante hacía que la sección pareciera cortada a media página. */
.cta {
  background: var(--negro);
  color: var(--blanco);
  padding: 4.5rem 0 3rem;
  text-align: center;
}

.cta h2 {
  color: var(--blanco);
}

.cta p {
  max-width: 55ch;
  margin: 0 auto 2rem;
  color: var(--gris-sobre-negro);
  font-size: 1.1rem;
}

/* En móvil los dos botones de la portada se apilan a ancho completo, con
   "Ver propuestas" primero y "Súmate a la campaña" debajo. ----------------- */

@media (max-width: 980px) {
  .portada__acciones {
    flex-direction: column;
  }

  .portada__acciones .boton {
    width: 100%;
    text-align: center;
  }

  .portada__acciones .boton--contorno {
    order: 1;
  }

  .portada__acciones .boton--principal {
    order: 2;
  }
}

/* Pie ---------------------------------------------------------------------- */

.pie {
  background: var(--negro);
  color: var(--gris-sobre-negro);
  padding: 3.5rem 0 1.5rem;
  font-size: 0.92rem;
  border-top: 1px solid var(--linea-oscura);
}

/* Sin la barra fija, el aviso legal ya no necesita reserva de alto: solo el
   respiro del área segura del gesto de inicio. */
@media (max-width: 980px) {
  .pie {
    padding-bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px));
  }
}

.pie a {
  color: var(--gris-sobre-negro);
  text-decoration: none;
}

.pie a:hover {
  color: var(--verde-claro);
}

/* Antes eran tres columnas con sus rótulos: "Navegación" y "Contacto" no
   decían nada que no dijeran los propios enlaces, las redes salían dos veces
   (como icono y como texto) y "Únete" tres. Queda la marca, una fila de
   enlaces y el aviso legal. */

.pie__cabeza {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 1.5rem;
}

.pie__nombre {
  margin: 0;
  color: var(--blanco);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.pie__lema {
  font-family: var(--fuente-display);
  font-size: 1.1rem;
  text-transform: uppercase;
  color: var(--verde-claro);
  margin: 0;
}

.pie__cabeza .redes {
  margin: 0;
  /* Empujadas al extremo: la marca y el lema forman una unidad y los perfiles
     son otra cosa. */
  margin-left: auto;
}

.pie__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.5rem;
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--linea-oscura);
}

.pie__nav a {
  /* 24px de alto mínimo: por debajo el enlace falla al tocarlo con el dedo. */
  display: inline-block;
  padding: 0.4rem 0;
  min-height: 24px;
}

/* El canal de denuncias, en el pie de todas las páginas. En rojo, como el botón
   de la portada: quien quiere reportar algo busca ese color, y así no depende de
   haber llegado a la portada para encontrarlo. Rojo claro y no el #b3261e del
   botón: el rojo oscuro sobre el pie negro no llega al mínimo de contraste.

   El selector lleva `.pie__nav` delante porque `.pie__nav a` gana por
   especificidad a un `.pie__denuncia` a secas, y el enlace salía del mismo gris
   que los demás. Es el mismo tropiezo que con `.opcion`: aquí la especificidad
   se comprueba midiendo el color que sale, no leyendo el archivo. */
.pie__nav a.pie__denuncia {
  color: #ff8a80;
}

/* Lema de cierre: lo último que se lee del sitio, así que va a escala display
   y en verde, no como una línea más de pie de página. El nombre en blanco:
   parte la frase en sus dos mitades y es el nombre el que destaca. */
.pie__cierre {
  margin: 2rem 0 0;
  font-family: var(--fuente-display);
  font-size: clamp(1.5rem, 4vw, 2.4rem);
  line-height: 1.1;
  text-transform: uppercase;
  color: var(--verde-claro);
}

.pie__cierre-nombre {
  color: var(--blanco);
}

.pie__legal {
  margin-top: 1.5rem;
  font-size: 0.8rem;
  color: #8d9382;
}

/* Panel y noticias ---------------------------------------------------------
   Todo lo que genera el Worker: cola de revisión, envíos, invitaciones y
   cuentas. Sin primitivas nuevas: los mismos filetes, la misma paleta y la
   misma tipografía que el resto del sitio. */

/* Cabecera del panel, compacta. El titular enorme es el lenguaje de las
   páginas públicas; en una herramienta que se usa veinte veces al día,
   cabecera y menú ocupaban más de una pantalla en un teléfono antes del primer
   dato (medido: unos 900 px a 390 px de ancho). El título sigue en Anton para
   no perder la identidad, pero a tamaño de sección. */
.panel__cabecera {
  padding: 1.75rem 0 0;
}

.panel__cabecera .antetitulo {
  font-size: 0.66rem;
  letter-spacing: 0.18em;
}

.panel__cabecera h1 {
  margin: 0.15rem 0 0;
  font-size: clamp(1.5rem, 3vw, 2rem);
}

.panel__cabecera .seccion__intro {
  margin: 0.35rem 0 0;
  max-width: 70ch;
  font-size: 0.9rem;
}

/* Confirmación antes de enviar correos: un <dialog> nativo —foco atrapado,
   Escape cierra, fondo velado— que solo se abre con JavaScript. Sin él, los
   envíos masivos siguen pidiendo confirmación en el servidor. */
.modal {
  width: min(32rem, calc(100% - 2rem));
  border: 0;
  border-radius: var(--radio);
  padding: 0;
  color: var(--negro);
  background: var(--blanco);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35);
}

.modal::backdrop {
  background: rgba(10, 12, 10, 0.72);
}

.modal__caja {
  margin: 0;
  padding: 1.5rem;
}

.modal__titulo {
  margin: 0 0 0.75rem;
  font-size: 1.6rem;
}

.modal__texto {
  margin: 0 0 0.75rem;
  line-height: 1.5;
}

/* La afectación —lo que ya no tiene vuelta atrás— va entera en negrita y con
   un filete que la separa de la frase. Vacía no ocupa: hay envíos que no
   necesitan avisar de nada. */
.modal__aviso {
  margin: 0 0 1.25rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--linea);
  line-height: 1.5;
  font-weight: 700;
}

.modal__aviso:empty {
  display: none;
}

/* El diálogo es blanco y vive fuera de las secciones: el botón de contorno,
   que nació para la portada oscura, saldría blanco sobre blanco (otra vez). */
.modal .boton--contorno {
  color: var(--negro);
  border-color: var(--gris);
}

.modal .boton--contorno:hover {
  background: var(--negro);
  color: var(--blanco);
  border-color: var(--negro);
}

/* El botón que pliega el menú en móvil. Solo existe con JavaScript (el HTML
   lo trae con hidden) y solo en pantallas estrechas; en escritorio el menú
   siempre está a la vista. */
.panel__plegar {
  display: none;
  width: 100%;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1rem;
  padding: 0.85rem 0;
  border: 0;
  border-top: 1px solid var(--linea-oscura);
  background: none;
  color: var(--blanco);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}

.panel__plegar-donde {
  flex: 1 1 auto;
}

.panel__plegar[aria-expanded="true"] .panel__plegar-flecha {
  transform: rotate(180deg);
}

/* Menú del panel, por grupos. Eran quince enlaces seguidos en una fila: en
   un teléfono ocupaban tres líneas sin orden y había que leerlos todos para
   dar con «Denuncias». Cada grupo lleva un rótulo pequeño en verde y sus
   enlaces debajo; en pantallas anchas los grupos van en fila y en estrechas
   se apilan. La insignia con la cifra va en negro sobre verde claro (7,2:1):
   el gris de los enlaces sobre negro no la distinguiría. */
.panel__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 1rem 2.5rem;
  margin-top: 2rem;
  border-top: 1px solid var(--linea-oscura);
  padding-top: 1.25rem;
}

.panel__grupo {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 0;
}

.panel__grupo-titulo {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--verde-claro);
}

.panel__grupo-enlaces {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.25rem;
}

.panel__nav a,
.panel__salir {
  display: inline-block;
  padding: 0.55rem 0;
  min-height: 24px;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gris-sobre-negro);
  text-decoration: none;
}

.panel__nav a:hover,
.panel__salir:hover {
  color: var(--verde-claro);
}

.panel__nav a[aria-current="page"] {
  color: var(--blanco);
  box-shadow: inset 0 -2px 0 var(--verde-claro);
}

.panel__cuenta {
  display: inline-block;
  min-width: 1.6em;
  margin-left: 0.3em;
  padding: 0.1em 0.45em;
  border-radius: 999px;
  background: var(--verde-claro);
  color: var(--negro);
  font-size: 0.72rem;
  letter-spacing: 0;
  text-align: center;
  vertical-align: 0.1em;
}

/* El botón de salir es un formulario, no un enlace: cerrar sesión cambia algo
   en el servidor y eso no se hace con un GET. Se compone igual que el resto. */
.panel__grupo--salir {
  margin-left: auto;
  align-self: flex-end;
}

.panel__salir {
  background: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
}

@media (max-width: 720px) {
  .panel__plegar:not([hidden]) {
    display: flex;
  }

  /* Más específico que .panel__nav a secas: si no, display: flex le gana al
     atributo hidden y el menú «plegado» sigue a la vista. */
  .panel__nav[hidden] {
    display: none;
  }

  .panel__nav {
    flex-direction: column;
    gap: 0.75rem;
    margin-top: 0;
    border-top: 0;
    padding: 0.25rem 0 0.75rem;
  }

  .panel__grupo--salir {
    margin-left: 0;
    align-self: flex-start;
  }
}

/* Marca de subregión recorrida: sale solo cuando administración la fija con
   fecha. En la ficha va sobre negro (verde claro, 7,2:1); en la tarjeta del
   índice, sobre blanco (verde, 9,1:1). */
.region__recorrida {
  margin: 0.75rem 0 1.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--verde-claro);
}

.region-tarjeta__recorrida {
  margin: 0.4rem 0 0;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--verde);
}

/* Agenda pública: el día en grande, como un calendario de pared, y el resto
   del acto al lado. Los que ya pasaron se apagan (gris de apoyo, 6,7:1) pero
   se quedan: la página cuenta también el recorrido hecho. */
.agenda {
  display: grid;
  gap: 0;
}

.evento {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  gap: 1.25rem;
  padding: 1.5rem 0;
  border-top: 1px solid var(--linea);
}

.evento__cuando {
  text-align: center;
  line-height: 1;
}

.evento__dia {
  display: block;
  font-family: var(--fuente-display);
  font-size: 2.6rem;
  color: var(--verde);
}

.evento__mes {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gris);
}

.evento__titulo {
  margin: 0 0 0.35rem;
  font-size: clamp(1.25rem, 2.6vw, 1.7rem);
}

.evento__donde {
  margin: 0;
  font-size: 0.9rem;
  color: var(--gris);
}

.evento__texto {
  max-width: 68ch;
  margin-top: 0.75rem;
}

.evento--pasado .evento__dia,
.evento--pasado .evento__titulo {
  color: var(--gris);
}

@media (max-width: 480px) {
  .evento {
    grid-template-columns: 4rem 1fr;
    gap: 0.9rem;
  }

  .evento__dia {
    font-size: 2rem;
  }
}

/* Avance del envío de un boletín. <progress> nativo: no hace falta un ancho
   en línea, que la CSP tiraría. */
.progreso {
  display: block;
  width: 100%;
  max-width: 40rem;
  height: 0.9rem;
  margin: 0.5rem 0 1.5rem;
  accent-color: var(--verde);
}

/* Resumen de inicio de administración: cifras grandes en tarjetas enlazadas
   a la página donde se atiende cada cosa. La cifra va en la tipografía
   display, como los titulares, y la etiqueta en el gris de apoyo (6,7:1
   sobre blanco). La tarjeta con algo esperando lleva el verde pálido de las
   marcas de estado, para que se vea de un vistazo y no solo por el número. */
.resumen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1rem;
  margin-bottom: 2.75rem;
}

.resumen__tarjeta {
  display: block;
  padding: 1.25rem 1.25rem 1.1rem;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  color: var(--negro);
  text-decoration: none;
}

.resumen__tarjeta:hover {
  border-color: var(--verde);
}

.resumen__tarjeta--atencion {
  background: #eaf5ec;
  border-color: var(--verde);
}

.resumen__cifra {
  display: block;
  font-family: var(--fuente-display);
  font-size: 2.6rem;
  line-height: 1;
  color: var(--verde);
}

.resumen__etiqueta {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gris);
}

.resumen__nota {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.82rem;
  color: var(--gris);
}

.resumen__bloques {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 2rem 3rem;
  margin-bottom: 2.75rem;
}

/* Pestañas de estado de la cola de revisión. */
.pestanas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 2.5rem;
}

.pestanas a {
  padding: 0.45rem 1rem;
  border: 1px solid var(--linea);
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--negro);
}

.pestanas a[aria-current="page"] {
  background: var(--verde);
  border-color: var(--verde);
  color: var(--blanco);
}

/* Sobre fondo oscuro el texto negro por defecto queda negro sobre negro. Ya
   pasó con el índice del programa: cinco pastillas vacías y nadie las vio. */
.seccion--oscura .pestanas a {
  border-color: rgba(255, 255, 255, 0.35);
  color: var(--blanco);
}

.seccion--oscura .pestanas a[aria-current="page"] {
  background: var(--verde);
  border-color: var(--verde);
  color: var(--blanco);
}

/* Ficha de revisión. */
.revision {
  border-top: 2px solid var(--negro);
  padding: 1.75rem 0 2.25rem;
}

.revision h2 {
  font-size: clamp(1.4rem, 3vw, 2rem);
  margin-bottom: 0.3rem;
}

.revision__firma {
  margin: 0 0 1rem;
  font-size: 0.82rem;
  color: var(--gris);
}

.revision__resumen {
  max-width: 68ch;
  font-size: 1.05rem;
}

.revision__texto summary {
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--verde);
  padding: 0.5rem 0;
}

.revision__texto > div {
  max-width: 68ch;
  padding: 0.5rem 0 0 1.1rem;
  border-left: 3px solid var(--linea);
  color: var(--gris);
}

.revision__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.revision__acciones input {
  flex: 1 1 18ch;
  min-width: 0;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  font: inherit;
  font-size: 0.95rem;
}

/* Los códigos de invitación son 32 caracteres en monoespaciada y sin ningún
   punto de corte natural. En la columna estrecha de un teléfono no cabían y
   empujaban la tabla —y con ella la página entera— 12 px fuera de la pantalla,
   que se desplazaba de lado. Que puedan partirse por cualquier punto. */
code {
  overflow-wrap: anywhere;
}

/* Tablas de envíos, invitaciones y cuentas. */
.tabla {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}

.tabla th,
.tabla td {
  padding: 0.9rem 1rem 0.9rem 0;
  border-bottom: 1px solid var(--linea);
  vertical-align: top;
  font-weight: 400;
}

.tabla thead th {
  border-bottom: 2px solid var(--negro);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--verde);
}

.tabla tbody th {
  font-weight: 700;
}

/* Botón de acción dentro de una tabla. No puede heredar el de la barra del
   panel, que es gris claro por ir sobre negro: en la tabla blanca daba 1,9:1. */
/* Las acciones de una fila, agrupadas. Van en su propio contenedor y no
   sueltas en la celda porque en el teléfono la tabla se convierte en fichas
   apiladas y entonces «Ficha» y «Escribir» quedaban pegadas al teléfono de la
   persona, sin nada que dijera dónde acaba el dato y empieza lo que se puede
   pulsar. El filete de arriba solo aparece ahí, en la vista apilada: en la
   tabla de escritorio las acciones ya tienen su propia columna y una línea
   sobre una sola celda se vería como un trazo suelto. */
.tabla__acciones {
  display: flex;
  /* Envuelven si no caben. No se pone nowrap aunque el objetivo sea una sola
     fila: en la tabla de cuentas hay cinco acciones y en un teléfono estrecho
     no caben de ninguna manera; con nowrap se saldrían de pantalla en vez de
     bajar de línea. */
  flex-wrap: wrap;
  gap: 0.3rem;
  align-items: center;
}

/* Botones y no enlaces subrayados: dos acciones seguidas en línea se leían
   como una sola frase («FICHA ESCRIBIR»), y con 24 px de alto quedaban muy por
   debajo de lo que se acierta con el pulgar. Con borde propio cada una se ve
   dónde empieza y dónde acaba, y no hace falta separarlas con un símbolo. */
.tabla__accion {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 30px;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--linea);
  border-radius: 999px;
  background: var(--blanco);
  font: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--verde);
  text-decoration: none;
  cursor: pointer;
}

.tabla__accion:hover {
  border-color: var(--verde);
  background: var(--hueso);
  color: var(--verde-profundo);
}

.tabla__nota {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.82rem;
  font-weight: 400;
  color: var(--gris);
}

/* Estado de un envío. El color va acompañado de la palabra, para que no dependa
   de distinguir verde de rojo. */
.marca-estado {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.marca-estado--espera {
  background: #fdf8e8;
  color: #6b5200;
}

.marca-estado--exito {
  background: #eaf5ec;
  color: #14532d;
}

.marca-estado--error {
  background: #fdf1f0;
  color: #8f1d16;
}

.formulario--linea {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
  margin-bottom: 3rem;
}

.formulario--linea .campo {
  flex: 1 1 24ch;
  min-width: 0;
  margin-bottom: 0;
}

.campo__ayuda {
  margin: 0.35rem 0 0;
  font-size: 0.82rem;
  color: var(--gris);
}

/* Paginación del listado de noticias. */
.paginacion {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 3rem;
  border-top: 1px solid var(--linea);
  padding-top: 1.5rem;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.noticia h2 a {
  color: inherit;
  text-decoration: none;
}

.noticia h2 a:hover {
  color: var(--verde);
}

@media (max-width: 620px) {
  /* En un teléfono la tabla se lee mal en columnas: cada fila pasa a bloque. */
  .tabla,
  .tabla tbody,
  .tabla tr,
  .tabla th,
  .tabla td {
    display: block;
    width: auto;
  }

  .tabla thead {
    display: none;
  }

  .tabla tr {
    border-bottom: 1px solid var(--linea);
    padding: 1rem 0;
  }

  .tabla th,
  .tabla td {
    border: 0;
    padding: 0.15rem 0;
  }

  /* La separación que pide la vista apilada: una línea entre los datos de la
     persona y lo que se puede pulsar. */
  .tabla__acciones {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--linea);
  }

  /* En el teléfono se gana algo de alto para el pulgar, pero sin pasarse: con
     42 px las tres acciones del boletín no cabían en una línea y cada ficha
     crecía dos renglones. 34 px es el punto en el que entran en fila y siguen
     siendo cómodas de pulsar. */
  .tabla__accion {
    min-height: 34px;
  }

  /* Con la cabecera escondida, una celda suelta como «2026-03-01» no dice de
     qué es. La etiqueta viaja en data-etiqueta y se pinta delante. */
  .tabla td[data-etiqueta]::before {
    content: attr(data-etiqueta) ": ";
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--verde);
  }
}

/* Casillas de participación ------------------------------------------------
   Una persona puede ser votante y además acompañante electoral, así que son
   casillas y no un desplegable. */

.campo--grupo {
  border: 0;
  padding: 0;
  margin: 0 0 1.5rem;
}

.campo--grupo legend {
  padding: 0;
  margin-bottom: 0.35rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--verde);
}

.opciones {
  display: grid;
  gap: 0.15rem;
  margin-top: 0.9rem;
}

/* El selector lleva .campo delante a propósito. Estas casillas son <label>
   dentro de un .campo, y `.campo label` —que pone display:block, mayúsculas y
   negrita a las etiquetas normales del formulario— gana por especificidad a un
   `.opcion` a secas por muy abajo que esté en el archivo. Sin esto la casilla
   se va encima del texto y la frase entera sale en mayúsculas. */
.campo label.opcion {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  align-items: start;
  /* Alto cómodo para el pulgar: la etiqueta entera es zona de toque. */
  padding: 0.7rem 0;
  margin-bottom: 0;
  border-bottom: 1px solid var(--linea);
  cursor: pointer;
  font-size: 1rem;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}

.campo label.opcion:last-child {
  border-bottom: 0;
}

.campo label.opcion input {
  width: 20px;
  height: 20px;
  margin: 0.15rem 0 0;
  accent-color: var(--verde);
}

.campo label.opcion span {
  font-size: 0.95rem;
  color: var(--gris);
}

.campo label.opcion strong {
  display: block;
  color: var(--negro);
  font-weight: 700;
}

/* Botón de denuncia. Rojo, que es lo que la gente busca cuando quiere reportar
   algo, y el único elemento rojo del sitio para que no compita con nada. */
.boton--alerta {
  background: #b3261e;
  color: var(--blanco);
  border-color: #b3261e;
}

.boton--alerta:hover {
  background: #8f1d16;
  border-color: #8f1d16;
  color: var(--blanco);
}

/* Página 404 --------------------------------------------------------------- */

.error404 {
  text-align: center;
  padding: 7rem 0;
}

/* Perfil: la declaración a la izquierda con un filete verde que la sostiene,
   y a la derecha la ficha del cargo. Antes era un bloque suelto de texto que
   se leía como un párrafo más; ahora la sección tiene dos pesos y un ancla
   de color. -------------------------------------------------------------- */

/* Rejilla por áreas y no por orden del documento: en escritorio la ficha va al
   lado de la declaración, y en móvil detrás de las fotografías. Con `order`
   no bastaba, porque la ficha y la tira de fotos no eran hermanas. */
.perfil {
  display: grid;
  grid-template-columns: 1.25fr 0.75fr;
  grid-template-areas:
    "titular   titular"
    "principal ficha"
    "fotos     fotos";
  column-gap: 3.5rem;
  align-items: start;
}

/* Ningún hijo puede imponer su ancho mínimo a la columna: la tira de fotos lo
   haría y sacaría el texto de la pantalla. */
.perfil > * {
  min-width: 0;
}

.perfil__titular {
  grid-area: titular;
}

/* El filete verde hace de comillas: marca dónde empieza la voz del candidato
   sin recurrir a una tarjeta con sombra. */
.perfil__principal {
  grid-area: principal;
  margin-top: 2.75rem;
  border-left: 4px solid var(--verde);
  padding-left: clamp(1.25rem, 3vw, 2.25rem);
}

.perfil__fotos {
  grid-area: fotos;
}

.perfil__declaracion {
  font-family: var(--fuente-display);
  font-size: clamp(1.7rem, 3.4vw, 2.6rem);
  line-height: 1.14;
  /* En caja normal, no en versales: son tres líneas seguidas y las mayúsculas
     sostenidas cuestan de leer al eliminar la silueta de las palabras. La
     tipografía display ya la distingue del texto corrido. */
  margin: 0 0 1.4rem;
  max-width: 26ch;
}

.perfil__texto {
  margin: 0 0 1.6rem;
  max-width: 52ch;
  font-size: 1.05rem;
  color: var(--gris);
}

/* Ficha del cargo: los mismos datos que ya declara la portada, ordenados
   como una tabla de referencia. Cada fila tiene su filete, que es lo que las
   agrupa sin necesidad de caja. */
.perfil__ficha {
  grid-area: ficha;
  margin: 2.75rem 0 0;
  border-top: 2px solid var(--negro);
}

.perfil__ficha > div {
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--linea);
}

.perfil__ficha dt {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--verde);
}

.perfil__ficha dd {
  margin: 0.4rem 0 0;
  font-family: var(--fuente-display);
  font-size: 1.15rem;
  line-height: 1.25;
  color: var(--negro);
}

/* Ejes del programa como lista editorial numerada, no como rejilla de
   tarjetas iguales: la numeración aquí sí informa (son cinco prioridades
   ordenadas). ------------------------------------------------------------- */

.ejes {
  list-style: none;
  margin: 3rem 0 0;
  padding: 0;
  counter-reset: eje;
}

.ejes li {
  counter-increment: eje;
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  gap: 1.5rem;
  align-items: baseline;
  padding: 1.6rem 0;
  border-top: 1px solid var(--linea-oscura);
}

.ejes li::before {
  content: counter(eje, decimal-leading-zero);
  font-family: var(--fuente-display);
  font-size: 2.4rem;
  line-height: 0.9;
  color: var(--verde-claro);
}

.ejes h3 {
  font-family: var(--fuente-display);
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  font-weight: 400;
  letter-spacing: 0;
  margin-bottom: 0.25rem;
}

.ejes p {
  margin: 0;
  color: var(--gris-sobre-negro);
  max-width: 60ch;
}

/* Los nombres de los municipios, grandes: son el dato del recorrido, no un pie
   de foto. Se usan en la página de regiones. ------------------------------- */

.municipios-destacados {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 1.4rem;
  font-family: var(--fuente-display);
  font-size: clamp(1.35rem, 2.6vw, 1.9rem);
  line-height: 1.25;
  text-transform: uppercase;
}

.municipios-destacados li::after {
  content: " ·";
  color: var(--verde);
}

.municipios-destacados li:last-child::after {
  content: "";
}

/* Tranquilidad antes de pedir datos ---------------------------------------- */

@media (max-width: 980px) {
  /* En una sola columna la ficha se va al final, detrás de las fotografías:
     el recorrido interesa antes que los datos de referencia del cargo. */
  .perfil {
    grid-template-columns: 1fr;
    grid-template-areas:
      "titular"
      "principal"
      "fotos"
      "ficha";
  }

  .ejes li {
    grid-template-columns: 3rem 1fr;
    gap: 1rem;
  }

  .ejes li::before {
    font-size: 1.8rem;
  }
}

/* Adaptación --------------------------------------------------------------- */

@media (max-width: 980px) {
  .portada__grid,
  .rejilla--2,
  .rejilla--3,
  .rejilla--4,
  .eje__cuerpo,
  .region__datos {
    grid-template-columns: 1fr;
  }

  /* En una columna el lema debajo del nombre, y los perfiles sin el empujón
     que en escritorio los manda al extremo derecho. */
  .pie__cabeza {
    gap: 0.35rem;
  }

  .pie__cabeza .redes {
    margin-left: 0;
    margin-top: 0.6rem;
    flex-basis: 100%;
  }

  .cifras {
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
  }

  /* La portada móvil se compone como una sola pantalla: el nombre arriba y
     el retrato apoyado en la esquina inferior derecha, sangrado por el borde
     como en la presentación de campaña. Antes la foto quedaba centrada y
     flotando, cortada por el borde inferior sin que pareciera intencionado. */
  /* Una pantalla exacta: el texto ocupa lo que necesita y el retrato el resto,
     así su base coincide siempre con el borde inferior de la pantalla en vez
     de quedar cortado por el pliegue. svh evita el salto de la barra del
     navegador al hacer scroll; vh queda de reserva para navegadores viejos. */
  /* En móvil manda el orden que pidió el cliente: nombre, retrato y después
     la petición. La foto queda entre el titular y los botones.

     La portada mide exactamente una pantalla descontando la cabecera fija, y
     la fila del retrato es la única elástica: absorbe todo el hueco libre, de
     modo que la foto es tan grande como el teléfono permita y "Súmate a la
     campaña" queda justo a ras del pliegue. Hay que desplazarse para ver lo
     que sigue, que es lo que se buscaba.
     svh en lugar de vh: con vh la barra del navegador entra en la cuenta y el
     botón se iría por debajo del borde. La línea con vh queda de reserva para
     navegadores que no entiendan svh. */
  .portada__grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "titulo"
      "foto"
      "pie";
    gap: 0;
    min-height: 0;
    padding-block: 1.25rem 0.9rem;
    padding-bottom: max(0.9rem, env(safe-area-inset-bottom, 0px));
  }

  .portada h1 {
    font-size: clamp(2.8rem, 17vw, 5rem);
  }

  .portada__retrato {
    width: auto;
    max-width: 100%;
    max-height: 40vh;
    margin: 0.75rem auto 0;
    align-self: center;
  }

  /* El retrato se apoya en el filete, sin holgura: con object-fit: contain la
     base de la caja es la base de la foto, así que basta con quitar el margen
     que había encima del filete. */
  .portada__cargo {
    margin-top: 0;
  }

  .portada__acciones {
    margin-top: 1.15rem;
    gap: 0.55rem;
  }

  /* Botones del mismo ancho: apilados con anchos distintos se leían como un
     descuido. */
  .portada__acciones .boton {
    flex: 1 1 100%;
    text-align: center;
  }

  .nav__boton {
    display: block;
  }

  /* El menú ocupa la pantalla entera, no una lengüeta bajo la cabecera. Va
     fijo al viewport y con su propio fondo; la barra de cabecera queda por
     encima para que el botón de cerrar y la marca sigan a mano. */
  .nav {
    position: fixed;
    inset: 0;
    z-index: 1;
    display: grid;
    align-content: center;
    /* "safe" evita que, si los enlaces no caben, el centrado los saque por
       arriba dejándolos fuera de alcance. Los navegadores que no lo entiendan
       se quedan con la línea anterior. */
    align-content: safe center;
    background: var(--negro);
    padding: calc(var(--alto-cabecera) + 1rem) 1.5rem 2rem;
    padding-bottom: max(2rem, env(safe-area-inset-bottom, 0px));
    /* Con pocos enlaces sobra sitio, pero si algún día son muchos o el
       teléfono está apaisado, el panel se desplaza en vez de recortarlos. */
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .nav[hidden] {
    display: none;
  }

  /* La marca, el botón de vinculación y la hamburguesa se quedan por encima
     del panel: en el DOM van antes que el menú, así que sin esto quedarían
     debajo y no habría forma de cerrarlo. */
  .marca,
  .cabecera__cta,
  .nav__boton {
    position: relative;
    z-index: 2;
  }

  .nav__lista {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
  }

  /* A escala de titular: con la pantalla entera disponible, el cuerpo de
     texto de una lengüeta se veía perdido. */
  .nav__enlace {
    font-family: var(--fuente-display);
    /* Atado también a la altura: con 9vw a secas, un teléfono apaisado daba
       48 px por enlace y la lista se salía de la pantalla. */
    font-size: clamp(1.5rem, min(9vw, 7.5vh), 3rem);
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1.1;
    padding: 0.45em 0;
    border-bottom: 1px solid var(--linea-oscura);
  }

  .nav__enlace[aria-current="page"] {
    box-shadow: none;
  }

  /* La página actual se marca con el punto verde de la casa, no con un
     subrayado que a este cuerpo se confundiría con el filete de separación. */
  .nav__enlace[aria-current="page"]::after {
    content: ".";
    color: var(--verde-claro);
  }

  /* Mientras el panel está abierto, la página de debajo no se desplaza. */
  .menu-abierto,
  .menu-abierto body {
    overflow: hidden;
  }

  /* Y la cabecera pasa a fija, que no es un capricho de estilo: `position:
     sticky` deja de anclarse en cuanto un ancestro tiene `overflow: hidden`,
     justo lo que acaba de hacer la regla de arriba. Con la página desplazada,
     la cabecera volvía a su sitio natural del documento —cientos de píxeles por
     encima del pliegue— y se llevaba consigo el botón de cerrar. Como el scroll
     también estaba bloqueado, no había forma de alcanzarlo: el menú se quedaba
     abierto y la única salida era el botón atrás del navegador. Medido: con
     600 px de desplazamiento el botón caía en y=-585.

     Fija es equivalente a pegada arriba, porque con el panel abierto la página
     no se mueve de todos modos. */
  .menu-abierto .cabecera {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
  }

  }

/* Una sola pantalla, pero solo donde hay altura para ella --------------------
   La portada mide exactamente lo que la pantalla deja bajo la cabecera, y la
   fila del retrato es la única elástica: absorbe todo el hueco libre, de modo
   que la foto es tan grande como el teléfono permita y "Súmate a la campaña"
   queda a ras del pliegue.

   La altura va definida, no en min-height: con altura automática una fila 1fr
   se comporta como max-content, el retrato imponía su tamaño natural y el
   botón caía hasta 172 px por debajo del pliegue.

   Y solo a partir de 480 px de alto: con el teléfono apaisado el titular y los
   botones ya no caben, la fila del retrato se quedaba en cero y el botón
   principal se perdía hasta 151 px por debajo del overflow: hidden de la
   portada, sin forma de alcanzarlo. Por debajo de ese umbral la portada crece
   con su contenido, como cualquier otra sección.

   svh en lugar de vh: con vh la barra del navegador entra en la cuenta y el
   botón se iría por debajo del borde. La línea con vh queda de reserva para
   navegadores que no entiendan svh. */
@media (max-width: 980px) and (min-height: 480px) {
  .portada__grid {
    grid-template-rows: auto minmax(0, 1fr) auto;
    height: calc(100vh - var(--alto-cabecera));
    height: calc(100svh - var(--alto-cabecera));
  }

  .portada__retrato {
    /* Ocupa toda la fila elástica. object-fit: contain conserva la proporción
       dentro de la caja que le toque, sin recortar la cara ni deformarla. */
    height: 100%;
    width: 100%;
    max-width: 100%;
    max-height: none;
    /* Sin margen: el margen no entra en el height: 100%, así que un margen
       superior empujaba la foto 8 px por debajo de su fila y la hacía montarse
       sobre el filete en vez de apoyarse en él. La separación con el titular la
       da el margen inferior del propio h1. */
    margin: 0;
    object-fit: contain;
    object-position: center bottom;
    align-self: stretch;
  }
}

/* Teléfonos de pantalla corta: el retrato ya se encoge solo, porque su fila es
   elástica, pero el titular y los filetes no. Se aprietan para que le quede
   sitio a la foto. */
@media (max-width: 980px) and (max-height: 700px) {
  .portada__grid {
    padding-block: 0.9rem 0.75rem;
  }

  .portada h1 {
    font-size: clamp(2.4rem, 14vw, 5rem);
  }

  .portada__cargo {
    padding-top: 0.75rem;
  }

  .portada__acciones {
    margin-top: 0.9rem;
  }
}

@media (max-width: 620px) {
  body {
    font-size: 16px;
  }

  /* Tres cifras en fila no caben en un teléfono: se apilan. */
  .cifras {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    text-align: left;
  }

  .portada__cargo {
    padding-top: 0.9rem;
  }
}

/* Movimiento reducido. Esta regla estaba anidada dentro del bloque de 620px y
   sin cerrar, así que en escritorio no se aplicaba nunca: quien había pedido
   menos movimiento seguía viendo todas las transiciones. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  * {
    transition: none !important;
  }
}

/* --- Prensa: noticias y columnas como periódico digital -------------------
   La voz del sitio no cambia —Anton para titulares, Space Grotesk de apoyo—
   pero el cuerpo del artículo pasa a la serifa del sistema (la misma de las
   citas): es la convención de lectura larga de la prensa y no cuesta un byte.
   Los filetes finos y el kicker en mayúsculas hacen el resto. */

.prensa__kicker {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--verde);
}

.prensa__apertura {
  padding-bottom: 2rem;
  border-bottom: 3px solid var(--negro);
}

.prensa__titular {
  margin: 0 0 0.6rem;
  font-family: var(--fuente-display);
  letter-spacing: 0.01em;
  line-height: 1.08;
  text-transform: uppercase;
}

.prensa__titular a {
  color: var(--negro);
  text-decoration: none;
}

.prensa__titular a:hover,
.prensa__titular a:focus-visible {
  color: var(--verde);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.prensa__titular--grande {
  max-width: 22ch;
  font-size: clamp(2rem, 5.5vw, 3.5rem);
}

.prensa__entradilla {
  max-width: 60ch;
  margin: 0 0 0.75rem;
  font-family: var(--fuente-cita);
  font-style: italic;
  font-size: 1.2rem;
  line-height: 1.5;
  color: var(--gris);
}

.prensa__entradilla--clara {
  color: var(--claro-sobre-negro);
}

.prensa__firma {
  margin: 0;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gris);
}

.prensa__firma--cabecera {
  margin-top: 1rem;
  color: var(--gris-sobre-negro);
}

.prensa__autor {
  font-weight: 700;
  color: inherit;
}

.prensa__rejilla {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 2.5rem;
  margin-top: 2rem;
}

.prensa__tarjeta {
  padding: 1.5rem 0;
  border-top: 1px solid var(--linea);
}

.prensa__tarjeta .prensa__titular {
  font-size: 1.35rem;
}

.prensa__resumen {
  margin: 0 0 0.75rem;
  font-size: 0.95rem;
  line-height: 1.55;
}

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

/* Cuerpo del artículo: serifa, capitular en el primer párrafo y remate al
   final. Solo toca lo que sale de parrafos(). */
.texto-prensa {
  font-family: var(--fuente-cita);
  font-size: 1.1rem;
  line-height: 1.75;
}

.texto-prensa > p:first-child::first-letter {
  float: left;
  padding: 0.05em 0.08em 0 0;
  font-family: var(--fuente-display);
  font-size: 3.4em;
  line-height: 0.8;
  color: var(--verde);
}

.texto-prensa > p:last-of-type::after {
  content: " ■";
  color: var(--verde);
  font-family: var(--fuente-texto);
  font-size: 0.8em;
}

.texto-prensa h2,
.texto-prensa h3 {
  font-family: var(--fuente-display);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.texto-prensa blockquote {
  margin: 2rem 0;
  padding-left: 1.25rem;
  border-left: 3px solid var(--verde);
  font-style: italic;
  color: var(--gris);
}

.texto-prensa img {
  display: block;
  width: 100%;
  height: auto;
  margin: 2rem 0;
  border-radius: var(--radio);
}

.prensa__descargo {
  margin-top: 2.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--linea);
  font-size: 0.85rem;
  color: var(--gris);
}

.prensa__mas {
  margin-top: 2.5rem;
  padding: 1.5rem;
  background: var(--hueso);
  border-radius: var(--radio);
}

.prensa__mas ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.prensa__mas li {
  padding: 0.6rem 0;
  border-top: 1px solid var(--linea);
}

.prensa__mas li:first-child {
  border-top: 0;
}

.prensa__mas a {
  font-weight: 700;
  color: var(--negro);
  text-decoration: none;
}

.prensa__mas a:hover,
.prensa__mas a:focus-visible {
  color: var(--verde);
  text-decoration: underline;
}

.prensa__mas .prensa__firma {
  display: block;
  margin-top: 0.15rem;
  text-transform: none;
  letter-spacing: 0;
}

/* --- Barra de formato del editor ----------------------------------------- */

.editor__barra {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-bottom: 0.5rem;
}

.editor__boton {
  /* 36x36 mínimo y sin depender solo del color: cada botón lleva su título. */
  min-width: 36px;
  min-height: 36px;
  padding: 0.35rem 0.6rem;
  background: var(--blanco);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  color: var(--negro);
  font-family: inherit;
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
}

.editor__boton:hover,
.editor__boton:focus-visible {
  background: var(--negro);
  border-color: var(--negro);
  color: var(--blanco);
}

.editor__separador {
  width: 1px;
  align-self: stretch;
  background: var(--linea);
}

.editor__cuenta {
  margin-left: auto;
  align-self: center;
  font-size: 0.8rem;
  color: var(--gris);
}

/* La vista previa enseña el HTML que devuelve el servidor: mismo conversor
   que la página publicada, misma pinta que un artículo. */
.editor__vista {
  margin: 1.25rem 0;
  padding: 1.25rem 1.5rem;
  background: var(--hueso);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
}

.editor__vista-titulo {
  margin: 0 0 1rem;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gris);
}

/* Las imágenes del panel de imágenes, contenidas para poder comparar de un
   vistazo sin desplazarse un kilómetro. */
.imagen-panel img {
  max-width: 480px;
}

.imagen-panel--retrato img {
  max-width: 160px;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

/* --- Equipo de la campaña ------------------------------------------------- */

.equipo__rejilla {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem;
}

.equipo__ficha {
  border-top: 3px solid var(--negro);
  padding-top: 1.25rem;
}

.equipo__foto {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  margin-bottom: 1rem;
  border-radius: var(--radio);
  background: var(--hueso);
}

.equipo__nombre {
  margin: 0 0 0.6rem;
  font-family: var(--fuente-display);
  font-size: 1.5rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.equipo__descripcion {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--gris);
}

.equipo__descripcion p {
  margin: 0 0 0.75rem;
}

@media (max-width: 980px) {
  .equipo__rejilla {
    grid-template-columns: repeat(2, 1fr);
  }
}

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

/* --- Marcado dentro de una noticia publicada ------------------------------
   Solo estas etiquetas salen del formateador, así que solo estas se estilan.
   Van acotadas a .contenedor para no tocar el resto del sitio. */

.seccion--clara .contenedor h2,
.seccion--clara .contenedor h3 {
  margin: 2.25rem 0 0.75rem;
}

.seccion--clara .contenedor ul,
.seccion--clara .contenedor ol {
  margin: 0 0 1.25rem;
  padding-left: 1.25rem;
}

.seccion--clara .contenedor li {
  margin-bottom: 0.4rem;
}

.seccion--clara .contenedor blockquote {
  margin: 1.75rem 0;
  padding-left: 1.1rem;
  border-left: 3px solid var(--verde);
  color: var(--gris);
}

.seccion--clara .contenedor blockquote p {
  margin: 0;
}

/* Las imágenes de una noticia nunca desbordan, aunque vengan grandes. */
.seccion--clara .contenedor img {
  max-width: 100%;
  height: auto;
  margin: 1.5rem 0;
  border-radius: var(--radio);
}

/* --- Índice de regiones: una tarjeta por subregión -------------------------
   Cada subregión tiene ya su propia página, así que el índice es un escaparate
   de nueve entradas y no una lista de anclas. */
.region-tarjetas {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
}

.region-tarjeta__foto {
  display: block;
  margin-bottom: 0.9rem;
}

.region-tarjeta__foto img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--radio);
}

.region-tarjeta__nombre {
  margin: 0 0 0.35rem;
  font-family: var(--fuente-display);
  font-size: 1.5rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.region-tarjeta__nombre a {
  color: var(--negro);
  text-decoration: none;
}

.region-tarjeta__nombre a:hover,
.region-tarjeta__nombre a:focus-visible {
  color: var(--verde);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.region-tarjeta__pie {
  margin: 0;
  font-size: 0.95rem;
  color: var(--gris);
}

/* --- Galería del recorrido ------------------------------------------------ */
.galeria {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  margin-top: 2rem;
}

.galeria__foto {
  margin: 0;
}

.galeria__foto img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radio);
  background: var(--linea);
}

.galeria__foto figcaption {
  margin-top: 0.5rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--gris);
}

@media (max-width: 980px) {
  .region-tarjetas,
  .galeria {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .region-tarjetas,
  .galeria {
    grid-template-columns: 1fr;
  }
}
