/* ============================================================
   Vive Más CR — estilos del sitio
   Depende de design-system/tokens/tokens.css (importado antes).
   Regla: acá NO se escribe ningún valor de color, espacio, radio,
   sombra o duración a mano. Todo sale de un token.
   ============================================================ */

/* ---------- Utilidades base ---------- */
.contenedor { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.contenedor--ancho { max-width: var(--container-ancho); }
.contenedor--estrecho { max-width: var(--container-estrecho); }

.seccion { padding-block: var(--section-md); }
.seccion--lg { padding-block: var(--section-lg); }
.seccion--sunken { background: var(--surface-sunken); }
.seccion--brand { background: var(--surface-brand); }
.seccion--noche { background: var(--grad-noche); }
.seccion--profundo { background: var(--grad-profundo); }

.overline { font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--text-subtle); margin: 0 0 var(--sp-3); }
.lead { font-size: var(--fs-lead); line-height: 1.55; color: var(--text-muted); }

.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;
}
.saltar {
  position: absolute; left: var(--sp-4); top: -100px; z-index: var(--z-toast);
  background: var(--primary); color: var(--primary-fg);
  padding: var(--sp-3) var(--sp-5); border-radius: var(--r-sm);
  transition: top var(--d-rapido) var(--ease-estandar);
}
.saltar:focus { top: var(--sp-4); }

/* Enlace que cubre toda la tarjeta sin anidar links */
.enlace-cubre { color: inherit; text-decoration: none; }
.enlace-cubre::after { content: ""; position: absolute; inset: 0; }

/* Enlace que se ve igual que el texto que envuelve: nombre de un ponente con
   web (speakers.json → web). Sin subrayado ni color propio; lo que avisa que se
   puede tocar es el cursor, y con teclado, el anillo de foco global. */
.enlace-discreto { color: inherit; text-decoration: none; }

/* ---------- Encabezado de sección ---------- */
.cab-seccion { max-width: 56ch; margin-bottom: var(--sp-12); }
.cab-seccion h2 { font-size: var(--fs-h2); font-variation-settings: "opsz" 110; text-wrap: balance; margin-bottom: var(--sp-4); }
.cab-seccion .overline { color: var(--accent-text); }
.cab-seccion p { margin: 0; }
.cab-seccion--centrada { margin-inline: auto; text-align: center; }
/* Línea de resumen bajo el <h2>: rango horario + conteo del día. */
.cab-seccion .cab-seccion__meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  margin: 0 0 var(--sp-5); font-size: var(--fs-body-sm);
  color: var(--text-subtle); font-variant-numeric: tabular-nums;
}
.agenda__rango { color: var(--accent-text); font-weight: 600; }
.agenda__rango time { display: inline; }

/* ---------- Botones ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 48px; padding: 0 var(--sp-6);
  font-family: var(--font-body); font-size: var(--fs-body); font-weight: 500; line-height: 1;
  text-decoration: none; white-space: nowrap;
  border: 1px solid transparent; border-radius: var(--r-md); cursor: pointer;
  transition: background-color var(--d-rapido) var(--ease-estandar),
              border-color var(--d-rapido) var(--ease-estandar),
              color var(--d-rapido) var(--ease-estandar),
              box-shadow var(--d-rapido) var(--ease-estandar);
}
.btn--sm { min-height: 40px; padding: 0 var(--sp-4); font-size: var(--fs-body-sm); }
.btn--lg { min-height: 56px; padding: 0 var(--sp-8); font-weight: 600; }
/* Lima es el color de toda acción de conversión: el CTA del hero, el botón del
   header y «Quiero ser patrocinador». Lo que se sostiene no es «un solo lima por
   pantalla» sino que nunca haya DOS acciones distintas en lima a la vez — el del
   header es el mismo botón repetido, no una acción que compita. */
.btn--primario { background: var(--cta); color: var(--cta-fg); }
.btn--primario:hover { background: var(--cta-hover); box-shadow: var(--e2); }
.btn--secundario { background: transparent; color: var(--text); border-color: var(--border-strong); }
.btn--secundario:hover { border-color: var(--text); }
.btn--fantasma { background: transparent; color: var(--accent-text); padding-inline: var(--sp-2); min-height: auto; }
.btn--premium { background: var(--grad-oro); color: hsl(var(--vm-noche-900)); box-shadow: var(--e-oro); }
.btn--premium:hover { box-shadow: var(--e-oro), var(--e3); }
.btn:active { transform: translateY(1px); }
.btn[aria-disabled="true"], .btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; pointer-events: none; }
.fila-btn { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.fila-btn--centrada { justify-content: center; margin-top: var(--sp-6); }
@media (max-width: 480px) { .fila-btn { flex-direction: column; align-items: stretch; } .fila-btn .btn { width: 100%; } }

/* ============================================================
   LOGOTIPO
   Las letras van en currentColor: quien lo contiene decide el color y el
   logo lo sigue (blanco sobre el hero, azul noche sobre el header sólido).
   El lima es la excepción: es color de marca, no de tema, así que usa el
   primitivo --vm-lima-600 y NO cambia dentro de [data-tema="oscuro"].
   ============================================================ */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.logo { height: var(--sp-10); width: auto; display: block; }
.logo__acento { fill: hsl(var(--vm-lima-600)); }
.logo__helice { fill: none; stroke: hsl(var(--vm-lima-600)); }

/* ============================================================
   HEADER
   ============================================================ */
.header {
  position: fixed; inset: 0 0 auto; z-index: var(--z-header);
  height: 72px; display: flex; align-items: center;
  border-bottom: 1px solid transparent;
  transition: background-color var(--d-base) var(--ease-estandar),
              border-color var(--d-base) var(--ease-estandar),
              box-shadow var(--d-base) var(--ease-estandar);
}
.header__interior { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-6); width: 100%; }
.header__marca {
  display: flex; align-items: center; gap: var(--sp-2);
  text-decoration: none; color: hsl(var(--vm-marfil-50));
  transition: color var(--d-base) var(--ease-estandar);
}
/* "CR" es lo único que separa este capítulo del VIVE+ global: va discreto,
   en currentColor, para no meter un tercer color al lado del lima. */
.marca__cr {
  font-family: var(--font-body); font-size: var(--fs-overline); font-weight: 700;
  letter-spacing: .14em; color: currentColor; opacity: .7;
  align-self: flex-start; margin-top: var(--sp-1);
}
.header__nav { display: flex; align-items: center; gap: var(--sp-6); }
.header__nav > a,
.header__mas > summary {
  position: relative; font-size: var(--fs-body-sm); font-weight: 500;
  text-decoration: none; color: hsl(var(--vm-marfil-50) / .82); padding-block: var(--sp-2);
  transition: color var(--d-rapido) var(--ease-estandar);
}
.header__nav > a::after,
.header__mas > summary::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 0;
  background: hsl(var(--vm-cyan-400));
  transition: width var(--d-rapido) var(--ease-salida);
}
.header__nav > a:hover,
.header__mas > summary:hover { color: hsl(var(--vm-marfil-50)); }
.header__nav > a:hover::after,
.header__nav > a[aria-current="page"]::after,
.header__mas > summary:hover::after,
.header__mas[open] > summary::after { width: 100%; }
.header__mas { position: relative; }
.header__mas > summary {
  display: flex; align-items: center; gap: var(--sp-1); cursor: pointer; list-style: none;
}
.header__mas > summary::-webkit-details-marker { display: none; }
.header__mas > summary span { transition: transform var(--d-rapido) var(--ease-estandar); }
.header__mas[open] > summary span { transform: rotate(180deg); }
.header__mas-panel {
  position: absolute; top: calc(100% + var(--sp-2)); right: 0;
  display: grid; width: max-content; padding: var(--sp-2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: var(--e3); opacity: 0; visibility: hidden; pointer-events: none;
  transform: translateY(calc(var(--sp-1) * -1));
  transition: opacity var(--d-rapido) var(--ease-estandar),
              transform var(--d-rapido) var(--ease-estandar),
              visibility var(--d-rapido) var(--ease-estandar);
}
.header__mas[open] .header__mas-panel {
  opacity: 1; visibility: visible; pointer-events: auto; transform: none;
}
.header__mas-panel a {
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm);
  color: var(--text-muted); text-decoration: none; white-space: nowrap;
  transition: color var(--d-rapido) var(--ease-estandar),
              background-color var(--d-rapido) var(--ease-estandar);
}
.header__mas-panel a:hover,
.header__mas-panel a:focus-visible { color: var(--text); background: var(--surface-sunken); }
/* El CTA del header es lima en los dos estados. Sobre la foto del hero necesita
   un halo propio: el lima es claro y sin él se diluye contra un cielo quemado. */
.header__cta { box-shadow: 0 0 0 1px hsl(var(--vm-noche-900) / .18); }
.header.es-solido .header__cta { box-shadow: none; }

/* Estado con scroll: vidrio */
.header.es-solido {
  background: hsl(var(--vm-marfil-50) / .82);
  backdrop-filter: var(--vidrio);
  -webkit-backdrop-filter: var(--vidrio);
  border-bottom-color: var(--border);
  box-shadow: var(--e2);
}
.header.es-solido .header__marca { color: hsl(var(--vm-noche-700)); }
.header.es-solido .header__nav > a,
.header.es-solido .header__mas > summary { color: hsl(var(--vm-tinta-700)); }
.header.es-solido .header__nav > a:hover,
.header.es-solido .header__mas > summary:hover { color: hsl(var(--vm-tinta-900)); }
.header.es-solido .menu-btn span { background: hsl(var(--vm-tinta-900)); }

/* Botón y panel móvil */
.menu-btn { display: none; width: 44px; height: 44px; background: none; border: 0; cursor: pointer; padding: 0; place-items: center; }
.menu-btn span { display: block; width: 22px; height: 2px; background: hsl(var(--vm-marfil-50)); border-radius: 2px; transition: transform var(--d-base) var(--ease-estandar), opacity var(--d-rapido) linear; }
.menu-btn span + span { margin-top: 5px; }
.menu-btn[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-btn[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.menu-movil {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  background: var(--grad-noche);
  display: flex; flex-direction: column; justify-content: safe center; overflow-y: auto;
  padding: var(--sp-16) var(--gutter) var(--sp-10);
  transform: translateX(100%);
  transition: transform var(--d-lento) var(--ease-salida);
  visibility: hidden;
}
.menu-movil[data-abierto="true"] { transform: none; visibility: visible; }
/* :not(.btn) es obligatorio: sin eso esta regla le gana en especificidad al color
   propio del botón y le impone el color de enlace. Con el CTA lima eso daba 1.01:1. */
.menu-movil a:not(.btn) { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 600; text-decoration: none; color: var(--text); padding-block: var(--sp-3); }
.menu-movil .btn { margin-top: var(--sp-8); width: 100%; }

@media (max-width: 1024px) {
  .header__nav, .header__cta { display: none; }
  .menu-btn { display: grid; }
}

/* ============================================================
   HERO
   ============================================================ */
.hero {
  position: relative; min-height: min(88vh, 900px);
  /* En escritorio mide una pantalla exacta: ver «El hero entra entero». */
  display: flex; align-items: flex-end;
  /* El respiro de abajo es menor que el de una sección normal a propósito: la
     franja de patrocinios tiene que entrar en pantalla junto con el CTA. */
  padding-block: calc(72px + var(--sp-12)) var(--sp-12);
  overflow: hidden;
}
/* La foto del hero. Es el elemento LCP: entra con un zoom mínimo y las capas de
   arriba (.hero__tinte, .hero__velo) la vuelven marca y le garantizan contraste
   al titular. El encuadre 50% 35% es distinto al de Zona Azul a propósito. */
.hero__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  /* 50% 22%: la foto es vertical y el hero es una banda apaisada, así que el
     encuadre decide qué sobrevive. A esta altura entran la señora de pie y el
     saludo de la derecha; más abajo las caras se iban detrás de las métricas. */
  object-fit: cover; object-position: 50% 22%;
  animation: heroEntra 1200ms var(--ease-suave) both;
}
/* Duotono de noche sobre la foto: los mismos tres radial-gradient del
   placeholder anterior, ahora en multiply sobre un velo de noche translúcido.
   Es lo que hace que cualquier foto se lea como Vive Más y no como stock. */
.hero__tinte {
  position: absolute; inset: 0; mix-blend-mode: multiply; pointer-events: none;
  background:
    radial-gradient(120% 90% at 78% 12%, hsl(var(--vm-cyan-500) / .38) 0%, transparent 55%),
    radial-gradient(90% 70% at 12% 88%, hsl(var(--vm-nicoya-600) / .42) 0%, transparent 60%),
    radial-gradient(70% 60% at 50% 40%, hsl(var(--vm-noche-600) / .5) 0%, transparent 70%),
    hsl(var(--vm-noche-900) / .55);
}
.hero__grano {
  position: absolute; inset: 0; opacity: .16; mix-blend-mode: overlay; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Velo de legibilidad: el degradado vertical de siempre + un scrim lateral
   desde la izquierda, para que el titular tenga contraste garantizado sobre
   cualquier foto que venga después. */
.hero__velo {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(100deg, hsl(var(--vm-noche-900) / .9) 0%, hsl(var(--vm-noche-900) / .35) 55%, transparent 80%),
    var(--grad-velo);
}
@media (max-width: 640px) {
  .hero__velo {
    background: linear-gradient(180deg,
      hsl(var(--vm-noche-900) / .38) 0%,
      hsl(var(--vm-noche-900) / .74) 46%,
      hsl(var(--vm-noche-900) / .95) 100%);
  }
}
@keyframes heroEntra { from { scale: 1.06; } to { scale: 1; } }

/* ------------------------------------------------------------
   ADN DE MARCA EN EL HERO — la línea de vida
   Los tres genes del logotipo VIVE+, en movimiento: la doble hélice
   (la longevidad como ciencia), los puntos (las personas) y el signo
   más (el "Más" de Vive Más). Fuente de los trazados y de las reglas:
   design-system/brand/logo/README.md
   No lleva JavaScript: el dibujo está completo en el HTML y los
   desfases van en CSS, así que se ve igual con el JS caído.
   ------------------------------------------------------------ */

/* La retícula de puntos NO es DOM: es un radial-gradient repetido.
   Cero nodos, cero peso de red, y la separación sale de un token. */
.trama-puntos {
  position: absolute; inset: calc(var(--sp-8) * -1);
  background-image: radial-gradient(circle, hsl(var(--vm-marfil-50) / .42) 1.6px, transparent 1.7px);
  background-size: var(--sp-8) var(--sp-8);
  opacity: .72;
  pointer-events: none;
}

/* Vertical: el trazo cuelga del TITULAR, no de un borde del hero. Va dentro
   de .hero__titular —que solo envuelve al h1— con top:100%, o sea la base de
   la última línea del titular. Así arranca siempre justo debajo de "vivirlos
   bien", envuelva el titular en dos renglones o en tres, y sin depender de
   cuánto midan el párrafo o las métricas.

   El margen inferior del h1 se colapsa fuera del envoltorio, así que la altura
   de .hero__titular es la del titular pelado y top:100% cae exacto en su base.

   Horizontal: sale de la caja del contenedor a sangre completa con
   left:50% + width:100vw. El max-width:none es obligatorio — tokens.css le
   pone max-width:100% a todo svg, y eso lo encerraría en el contenedor. */
.hero__titular { position: relative; margin-bottom: var(--sp-6); }
/* Con sello, el logotipo y el sello van en fila. El aire de abajo vive en el
   envoltorio y no en el h1: en flex el margen del h1 ya no se colapsa afuera y
   correría la línea del ADN, que cuelga de la base del envoltorio. */
.hero__titular:has(.hero__sello) { display: flex; align-items: center; gap: var(--sp-8); }
/* El h1 se ajusta al ancho del logotipo: con su max-width de 14ch se estiraba
   más que la imagen y el sello quedaba lejos. */
.hero__titular:has(.hero__sello) h1 { flex: 0 1 auto; min-width: 0; max-width: 32rem; }
.adn-vida {
  position: absolute; top: 100%; left: 50%; z-index: -1;
  width: 100vw; max-width: none;
  translate: -50% -50%;
  /* Más bajo que en el prototipo a propósito: ahí el trazo iba debajo del velo
     del hero, que lo apagaba. Acá va encima, y a la misma alfa le comía el
     protagonismo al titular. */
  opacity: .5;
  pointer-events: none;
}

.adn-vida__trazo {
  stroke: hsl(var(--vm-lima-600));
  stroke-dasharray: 1300; stroke-dashoffset: 1300;
  animation: vidaDibuja 2200ms var(--ease-suave) forwards;
}
@keyframes vidaDibuja { to { stroke-dashoffset: 0; } }

/* Los travesaños entran con el trazo y después se quedan girando. El
   pinzado es en scaleY porque acá la hélice es horizontal; el desfase de
   cada uno es su fase real sobre la onda, y por eso el pinzado recorre la
   hélice en vez de latir todo junto. */
.adn-vida__travesano {
  stroke: hsl(var(--vm-lima-600)); opacity: 0;
  transform-box: fill-box; transform-origin: center;
  animation: travesanoEntra var(--d-base) var(--ease-salida) forwards,
             vidaGira 5s var(--ease-suave) infinite;
}
@keyframes travesanoEntra { to { opacity: 1; } }
@keyframes vidaGira {
  0%, 100% { transform: scaleY(1); }
  50%      { transform: scaleY(.16); }
}

/* Dos tiempos por travesaño: cuándo entra (cuando el trazo le pasa por
   encima) y en qué fase de la vuelta está. La fase va en NEGATIVO, o sea
   que el giro viene corriendo desde el segundo cero: no se ve, porque
   hasta que no entra cada travesaño está en opacity 0, y así al aparecer
   ya están todos en fase. Arrancarlo después del trazo los hacía sumarse
   de a uno y eso sí se notaba. Se repite cada 6 porque una vuelta
   completa de la hélice son dos medias ondas. */
.adn-vida__travesano:nth-child(1)  { animation-delay: 1120ms,  -630ms; }
.adn-vida__travesano:nth-child(2)  { animation-delay: 1180ms, -1250ms; }
.adn-vida__travesano:nth-child(3)  { animation-delay: 1240ms, -1870ms; }
.adn-vida__travesano:nth-child(4)  { animation-delay: 1370ms, -3130ms; }
.adn-vida__travesano:nth-child(5)  { animation-delay: 1430ms, -3750ms; }
.adn-vida__travesano:nth-child(6)  { animation-delay: 1500ms, -4370ms; }
.adn-vida__travesano:nth-child(7)  { animation-delay: 1620ms,  -630ms; }
.adn-vida__travesano:nth-child(8)  { animation-delay: 1690ms, -1250ms; }
.adn-vida__travesano:nth-child(9)  { animation-delay: 1750ms, -1870ms; }
.adn-vida__travesano:nth-child(10) { animation-delay: 1880ms, -3130ms; }
.adn-vida__travesano:nth-child(11) { animation-delay: 1940ms, -3750ms; }
.adn-vida__travesano:nth-child(12) { animation-delay: 2000ms, -4370ms; }

/* El más va con menos alfa que los trazos: es masa sólida contra línea, y
   a igual opacidad pesa el triple. masCierra termina en scale(1) justo
   cuando masLate arranca, también en scale(1): el relevo no se ve. El
   latido son dos golpes y descanso, no un respiro simétrico — es lo que
   lo hace leer como pulso y no como parpadeo. El pico es 7%; más grande
   deja de ser un signo vivo y pasa a ser una alerta. */
.adn-vida__mas {
  fill: hsl(var(--vm-lima-600) / .85); opacity: 0;
  transform-box: fill-box; transform-origin: center;
  animation: masCierra var(--d-cine) var(--ease-salida) 2100ms forwards,
             masLate 4s var(--ease-suave) 2900ms infinite;
}
@keyframes masCierra {
  from { opacity: 0; transform: scale(.55); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes masLate {
  0%        { transform: scale(1); }
  7%        { transform: scale(1.07); }
  15%       { transform: scale(1.01); }
  23%       { transform: scale(1.05); }
  36%, 100% { transform: scale(1); }
}

.hero__contenido { position: relative; z-index: 1; }
.hero__eyebrow { font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: hsl(var(--vm-cyan-400)); margin: 0 0 var(--sp-6); }
.hero h1 {
  font-size: var(--fs-display-xl); line-height: .94; letter-spacing: -.03em;
  font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 0;
  max-width: 14ch; text-wrap: balance; margin-bottom: 0;
}
/* Variante con logotipo del evento: la imagen ocupa el lugar del titular
   tipográfico y hereda su margen inferior. El ancho va en ch para que escale
   con la tipografía igual que lo hacía el texto. */
.hero__logo { display: block; width: 100%; max-width: min(32rem, 100%); height: auto; }
/* Con el logotipo, la línea de vida no puede cruzar por la base del lockup: ahí
   está el descriptor y el trazo lo tacharía. Se corre hacia abajo para que quede
   como un subrayado con aire, igual que hacía con el titular tipográfico. */
.hero__titular:has(.hero__logo) .adn-vida { margin-top: var(--sp-3); }

/* ---------- La línea de vida en pantalla angosta ----------
   En pantalla ancha la hélice y el signo más caen A LA DERECHA de la columna
   de texto: por eso el viewBox arranca en -520 y el dibujo se corre hacia
   allá. Pero por debajo de ~1024 px el párrafo ocupa todo el ancho y pasa a
   compartir esa franja, así que la hélice le cruza el primer renglón.

   La solución no es apagar la línea: es abrirle un carril. El hueco bajo el
   lockup pasa a medir lo que mide la mitad de abajo del SVG —que es la mitad
   de su alto, o sea 210/1150 del ancho de pantalla ≈ 9.2vw— más el corrimiento
   que ya tenía y un respiro. Como las dos medidas escalan con el ancho, el
   carril calza igual en un teléfono de 360 px que en una tableta de 1024.
   Así la línea queda haciendo lo que hace en grande: subrayar el titular, con
   su hélice y su signo más al final del trazo, sin tocar una sola letra. */
@media (max-width: 1024px) {
  .adn-vida { opacity: .42; }
  .hero:has(.hero__logo) .hero__titular { margin-bottom: calc(9.2vw + var(--sp-3) + var(--sp-2)); }
}
/* En el teléfono la línea baja un poco más —el descriptor del lockup queda muy
   cerca de su base a este tamaño—, así que el carril crece lo mismo. */
@media (max-width: 640px) {
  .hero__titular:has(.hero__logo) .adn-vida { margin-top: var(--sp-6); }
  .hero:has(.hero__logo) .hero__titular { margin-bottom: calc(9.2vw + var(--sp-6) + var(--sp-2)); }
}

/* 54ch en vez de las 48 de un párrafo largo: el lead son tres renglones, y con
   cuatro la franja de patrocinios se caía fuera de pantalla en una laptop. */
.hero__lead { font-size: var(--fs-lead); color: var(--text-muted); max-width: 54ch; margin-bottom: var(--sp-4); }
/* Aviso de que la fecha exacta todavía no está: va pegado al lead, antes de los botones. */
.hero__nota-fecha { font-size: var(--fs-body-sm); color: var(--text-muted); max-width: 48ch; margin: 0 0 var(--sp-8); }
.hero__metricas {
  display: flex; flex-wrap: wrap; gap: var(--sp-12);
  margin-top: var(--sp-6); padding-top: var(--sp-6);
  border-top: 1px solid var(--border);
}
.hero__metricas > div { display: flex; flex-direction: column; gap: var(--sp-1); }
/* Sello de Evento esencial COSTA RICA: a la derecha del logotipo VIVE+,
   centrado en su alto y más bajo que el lockup para no competirle. */
.hero__sello { flex: none; margin: 0; }
.hero__sello img { display: block; width: auto; height: calc(var(--sp-24) + var(--sp-8)); }
@media (max-width: 1024px) {
  .hero__sello img { height: var(--sp-24); }
}
@media (max-width: 640px) {
  .hero__titular:has(.hero__sello) { gap: var(--sp-4); }
  .hero__sello img { height: var(--sp-16); }
}
.hero__metricas b { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.hero__metricas span { font-size: var(--fs-caption); color: var(--text-subtle); }

/* ---------- El hero entra entero en la pantalla ----------
   En escritorio el hero mide una pantalla y la franja de logos es su borde de
   abajo. Antes medía ~1.056 px fijos: en una laptop de 1440×900 el carrusel
   quedaba debajo del pliegue. Ahora los altos grandes —logotipo, sello y los
   respiros entre bloques— escalan con el alto de la ventana y tienen tope en su
   medida de siempre, así que en un monitor alto nada cambia.
   Va primero en vh y después en svh: el navegador que no conoce svh se queda
   con la primera. */
@media (min-width: 1025px) {
  .hero {
    min-height: 100vh; min-height: 100svh;
    padding-block: calc(72px + clamp(var(--sp-4), 3vh, var(--sp-12))) clamp(var(--sp-4), 2.5vh, var(--sp-12));
  }
  .hero__eyebrow { margin-bottom: clamp(var(--sp-3), 2vh, var(--sp-6)); }
  .hero__titular { margin-bottom: clamp(var(--sp-3), 2vh, var(--sp-6)); }
  /* max-height y max-width a la vez: una imagen reemplazada conserva su
     proporción y manda el que llegue primero. */
  .hero__logo { width: auto; max-height: 18vh; }
  .hero__lead { margin-bottom: var(--sp-3); }
  .hero__nota-fecha { max-width: 62ch; margin-bottom: clamp(var(--sp-4), 3vh, var(--sp-8)); }
  .hero__metricas {
    margin-top: clamp(var(--sp-3), 2vh, var(--sp-6));
    padding-top: clamp(var(--sp-3), 2vh, var(--sp-6));
  }
  .hero__sello img { height: clamp(var(--sp-16), 11vh, calc(var(--sp-24) + var(--sp-8))); }
  .hero__patrocinios {
    margin-top: clamp(var(--sp-3), 2vh, var(--sp-6));
    padding-top: clamp(var(--sp-3), 2vh, var(--sp-5));
  }
  .hero__patrocinios-overline { margin-bottom: var(--sp-2); }
}
/* Pantallas bajas (una laptop de 1366×768): la nota de fecha repite lo que ya
   dicen el lead y las métricas —dos días, gratis, cupo limitado—, así que es lo
   que se va para que entre la franja. */
@media (min-width: 1025px) and (max-height: 780px) {
  .hero__nota-fecha { display: none; }
  .hero__lead { margin-bottom: var(--sp-6); }
}

/* Franja de patrocinios al pie del hero. Va después de las métricas y con su
   propio aire: los logos son de otro orden que los datos del evento y no deben
   leerse como una cuarta métrica. */
/* Sangrado completo: la franja rompe el contenedor del hero y toca los dos
   bordes de la pantalla. El truco es el clásico —margen negativo de media
   pantalla menos medio contenedor— y es seguro acá porque .hero recorta
   (overflow: hidden): el ancho que la barra de scroll le roba a 100vw no
   ensancha la página. El rótulo vuelve a su carril con su propio .contenedor,
   que build.mjs escribe adentro del bloque. */
.hero__patrocinios {
  margin-top: var(--sp-6); margin-inline: calc(50% - 50vw);
  padding-top: var(--sp-5); border-top: 1px solid var(--border);
}
.hero__patrocinios-overline {
  font-size: var(--fs-caption); font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-subtle); margin: 0 0 var(--sp-5);
}
/* Marquesina de patrocinios: la cinta desfila sola de derecha a izquierda.
   El movimiento es una sola animación de transform sobre la pista —no hay un
   segundo listener de scroll ni una librería— y es puramente decorativo: la
   cinta accesible es la primera, las otras cinco van aria-hidden.

   Las máscaras de los extremos son lo que hace que los logos entren y salgan
   en vez de aparecer cortados contra el borde. */
.marquesina {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--sp-12), #000 calc(100% - var(--sp-12)), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 var(--sp-12), #000 calc(100% - var(--sp-12)), transparent 100%);
}
/* La duración es una variable de la marquesina y no un número fijo: cada cinta
   tiene un largo distinto —logos sueltos en el hero, tarjetas en aliados— y a
   la misma duración desfilarían a velocidades distintas. Cada variante fija su
   --desfile —el tiempo que tarda UNA cinta en cruzar— para que las dos se
   muevan a la misma velocidad aparente. */
.marquesina__pista {
  display: flex; width: max-content;
  animation: desfila var(--desfile, 16s) linear infinite;
}
/* La cinta NO se detiene al pasar el mouse —pedido de la organización: el desfile
   es continuo—. Sí se detiene si algo adentro toma el foco del teclado: si alguien
   está tabulando por la cinta, moverle el objetivo debajo es pelearle.
   El freno para quien no quiere movimiento sigue siendo prefers-reduced-motion,
   que apaga la animación entera. */
.marquesina:focus-within .marquesina__pista { animation-play-state: paused; }
.marquesina[data-en-pantalla="false"] .marquesina__pista { animation-play-state: paused; }
.marquesina__cinta[hidden] { display: none; }
/* El ciclo avanza EXACTAMENTE una cinta, no media pista. Las cintas son todas
   iguales, así que al volver a 0 la de al lado ya ocupó el lugar de la anterior
   y el salto no se ve. Antes el salto era -50%: con eso el ciclo solo cubría
   la mitad de las copias, y en cuanto la pantalla era más ancha que esa mitad
   —6 cintas de ~674 px en el hero: apenas 2022 px— la cinta se cortaba a la
   derecha y volvía a armarse al reiniciar el ciclo. Moviendo una sola cinta,
   el ancho que hay que cubrir es (copias − 1) cintas: el doble de margen con
   los mismos nodos.
   --copias lo escribe build.mjs en el style de la marquesina: el número de
   copias lo decide él, y tenerlo dos veces era tenerlo mal una de las dos. */
@keyframes desfila { to { transform: translate3d(calc(-100% / var(--copias, 6)), 0, 0); } }

/* El aire entre cintas es padding de la propia cinta y NO un gap de la pista:
   así cada cinta mide exactamente lo mismo (logos + su separación) y el paso del
   ciclo —una cinta— cae justo donde empieza la siguiente. Con gap en la pista el
   paso caía a medio hueco y cada vuelta daba un saltito de 20 px. */
.marquesina__cinta {
  display: flex; flex: 0 0 auto; align-items: center;
  gap: var(--sp-16); list-style: none; margin: 0; padding: 0 var(--sp-16) 0 0;
}
/* Cada logo va en su color original, directo sobre el fondo oscuro: sin
   placa ni halo. El archivo lo elige build.mjs (logo, con logoBlanco de
   respaldo). */
.patrocinio {
  display: flex; align-items: center; justify-content: center;
  height: var(--sp-16);
}
/* Reservar la caja antes de descargar el logo: con ambos tamaños en auto,
   las imágenes lazy empezaban con ancho cero y estiraban la cinta al cargar,
   cambiando también el recorrido de la animación. La proporción viene de las
   medidas del archivo en los datos; los límites siguen usando los tokens.
   El punto medio entre el color pleno (siete marcas peleando entre sí y con
   la foto del hero) y el blanco monocromo de antes (muy apagado, pedido de
   la organización de mostrar el color real): la saturación baja a la mitad,
   fija —WCAG exime a los logotipos del mínimo de contraste—. No se anima
   `filter` en el hover porque el movimiento del sitio va solo en `transform`
   y `opacity`; el pase del mouse sube la opacidad, no el color. */
.patrocinio__logo {
  --alto-logo: var(--sp-12);
  --ancho-logo-max: calc(var(--sp-40) + var(--sp-8));
  width: min(var(--ancho-logo-max), calc(var(--alto-logo) * var(--proporcion-logo, 1)));
  height: auto; aspect-ratio: var(--proporcion-logo, 1); object-fit: contain;
  filter: saturate(.5);
  opacity: .7; transition: opacity var(--d-base) var(--ease-estandar);
}
.patrocinio:hover .patrocinio__logo { opacity: 1; }
/* En la banda blanca no hay foto con la que pelear: color pleno. */
.aliados-banda .patrocinio__logo { filter: none; opacity: 1; }
/* Marca con web (aliados.lista[].web): el logo entero es el enlace y se ve igual
   que sin él. Mantiene el centrado de .patrocinio; el foco es el global. */
.patrocinio__enlace { display: flex; align-items: center; justify-content: center; color: inherit; text-decoration: none; }
/* Sellos y escudos: casi cuadrados, y a la altura de un logotipo apaisado no se
   leen. Se les deja toda la altura de la marca. */
.patrocinio__logo--bloque { --alto-logo: var(--sp-16); }
/* Sin archivo de logo: el nombre en texto es un estado final válido. */
.patrocinio__nombre {
  font-family: var(--font-display); font-size: var(--fs-body-sm); font-weight: 600;
  color: var(--text); white-space: nowrap;
}

@media (max-width: 640px) {
  .hero__patrocinios { margin-top: var(--sp-8); }
  .marquesina__cinta { gap: var(--sp-12); padding-right: var(--sp-12); }
  .patrocinio { height: var(--sp-12); }
  .patrocinio__logo { --alto-logo: var(--sp-8); --ancho-logo-max: calc(var(--sp-32) + var(--sp-4)); }
  .patrocinio__logo--bloque { --alto-logo: var(--sp-12); }
}

/* Subrayado grueso de lima, no resaltador: el trazo va DEBAJO de la palabra.
   Anclado a 100% y no a 88%: con el line-height comprimido del h1 (.94) la caja
   de la línea queda más baja que la em, y a 88% el trazo se montaba sobre las
   letras — que sobre el hero oscuro dejaba "bien" en blanco sobre lima. */
.resalta {
  /* Sin trazo lima: el acento debajo del titular ahora es la línea del ADN,
     que arranca justo bajo "vivirlos bien". Dos subrayados lima peleando en el
     mismo renglón era uno de más.
     background-image: linear-gradient(var(--highlight), var(--highlight)); */
  background-repeat: no-repeat; background-position: 0 100%; background-size: 0% .32em;
  transition: background-size var(--d-cine) var(--ease-salida);
}
.resalta.visible { background-size: 100% .32em; }

/* ============================================================
   QUÉ ES
   Cada párrafo lleva su clase en vez de encadenar `p + p`: con el selector de
   hermano, el .overline caía dentro de la regla de display y salía en tamaño
   de titular, y el titular real quedaba en cuerpo de texto.
   ============================================================ */
.manifiesto { display: grid; gap: var(--sp-16); grid-template-columns: 7fr 5fr; align-items: start; }
@media (max-width: 1024px) { .manifiesto { grid-template-columns: 1fr; gap: var(--sp-12); } }
.que-es__titular {
  font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 400;
  line-height: 1.3; letter-spacing: -.01em;
  font-variation-settings: "opsz" 96, "SOFT" 30, "WONK" 1;
  max-width: 24ch; margin: 0;
}
.que-es__parrafo {
  font-size: var(--fs-body); line-height: 1.65; color: var(--text-muted);
  max-width: var(--container-prosa); margin: var(--sp-8) 0 0;
}
.pilares { display: flex; flex-direction: column; gap: var(--sp-8); }
.pilar { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-4); }
.pilar__icono { width: 40px; height: 40px; border-radius: var(--r-sm); display: grid; place-items: center; background: var(--surface); border: 1px solid var(--border); color: var(--accent-text); }
.pilar h3 { font-size: var(--fs-h3); margin-bottom: var(--sp-1); }
.pilar p { font-size: var(--fs-body-sm); color: var(--text-muted); margin: 0; }

/* ============================================================
   PROGRAMA — la agenda de los dos días
   Nada colapsado: cada bloque muestra hora, tipo, título, detalle, ponentes
   con foto y lugar de una sola pasada. Tres capas de lectura:

     1. La portada del día  — numeral gigante sobre capas que se mueven a
        distinta velocidad con el scroll (site.js escribe --parallax).
     2. El riel pegajoso    — a la izquierda: el día, la hora que estás
        cruzando y el avance (--agenda-progreso, también de site.js).
     3. Los bloques         — tarjeta por espacio, con barra de color por tipo
        y un tinte según el momento del día (data-momento), del amanecer del
        registro a la noche del acto de clausura.

   Todo lo de movimiento es decorativo: sin JS y con prefers-reduced-motion la
   agenda se lee completa e igual de ordenada.
   ============================================================ */
.agenda__aviso {
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-body-sm); color: var(--text-muted);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4);
  margin: 0 0 var(--sp-8); max-width: var(--container-estrecho);
}
.agenda__aviso svg { flex: none; color: var(--accent-text); }

/* ---------- Selector de días ----------
   La barra de pestañas la revela site.js; sin JS queda oculta (hidden en el
   HTML) y los dos días se leen apilados, cada uno con su portada.
   El :not([hidden]) no es adorno: sin él la clase le gana en especificidad a
   la regla [hidden] del navegador y la barra se vería igual sin JS. */
.agenda-dias:not([hidden]) {
  display: flex; width: max-content; gap: var(--sp-1); margin: 0 0 var(--sp-4);
  padding: var(--sp-1); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-pill);
}
.agenda-dia__tab {
  appearance: none; border: 0; cursor: pointer;
  font-family: var(--font-body); font-size: var(--fs-body-sm); font-weight: 600;
  color: var(--text-muted); background: transparent;
  padding: var(--sp-2) var(--sp-6); border-radius: var(--r-pill);
  transition: background-color var(--d-rapido) var(--ease-estandar),
              color var(--d-rapido) var(--ease-estandar);
}
.agenda-dia__tab:hover:not([aria-selected="true"]) { color: var(--text); }
.agenda-dia__tab[aria-selected="true"] { background: var(--primary); color: var(--primary-fg); }

/* ---------- Filtros por tipo ----------
   Solo filtran con JS, así que el HTML los trae con hidden. Nunca esconden
   información que no se pueda recuperar con un clic en "Todo". */
/* Debajo de las pestañas, en su propio renglón: primero se elige el día y
   después se filtra dentro de él. */
.agenda-filtros:not([hidden]) {
  display: flex; flex-wrap: wrap; gap: var(--sp-2);
  margin: 0 0 var(--sp-10);
}
.agenda-filtro {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-body); font-size: var(--fs-caption); font-weight: 600;
  color: var(--text-muted); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-pill);
  padding: var(--sp-2) var(--sp-4);
  transition: border-color var(--d-rapido) var(--ease-estandar),
              color var(--d-rapido) var(--ease-estandar),
              background-color var(--d-rapido) var(--ease-estandar);
}
.agenda-filtro:hover { color: var(--text); border-color: var(--border-strong); }
.agenda-filtro[aria-pressed="true"] {
  background: var(--surface-brand); color: var(--accent-text);
  border-color: var(--accent);
}
.agenda-filtro__n {
  font-variant-numeric: tabular-nums; font-weight: 500;
  color: var(--text-subtle); font-size: var(--fs-overline);
}
.agenda-filtro[aria-pressed="true"] .agenda-filtro__n { color: var(--accent-text); }

.agenda-dia:not([hidden]) + .agenda-dia { margin-top: var(--sp-24); }
.agenda-dia:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: var(--sp-3); border-radius: var(--r-md); }

/* ---------- Portada del día ----------
   Tres capas con velocidades distintas + velo de contraste. Va con
   data-tema="oscuro" para que el texto use los semánticos del tema oscuro en
   vez de primitivos sueltos. Sin dia.imagen quedan el degradado y la trama:
   la foto es un plus, no un requisito. */
.dia-portada {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; flex-direction: column; justify-content: flex-end;
  min-height: clamp(12rem, 24vw, 19rem);
  padding: var(--sp-8);
  margin-bottom: var(--sp-10);
  border-radius: var(--r-xl);
  background: var(--grad-noche);
  box-shadow: var(--e3);
}
.dia-portada__capa {
  position: absolute; inset: -14%; z-index: -2;
  background-size: cover; background-position: center;
  will-change: transform;
}
/* El fondo se mueve poco y la trama el doble: eso es la profundidad. */
.dia-portada__capa--fondo { transform: translate3d(0, calc(var(--parallax, 0) * 3rem), 0) scale(1.08); }
.dia-portada__capa--trama {
  background-image: repeating-linear-gradient(112deg,
    hsl(var(--vm-marfil-50) / .08) 0 1px, transparent 1px 15px);
  transform: translate3d(0, calc(var(--parallax, 0) * 6rem), 0);
}
.dia-portada__velo { position: absolute; inset: 0; z-index: -1; background: var(--grad-velo); }

/* La portada de cada momento del día tiñe su degradado de fondo. */
.dia-portada[data-momento="amanecer"] .dia-portada__capa--fondo { background-image: var(--grad-amanecer); }
.dia-portada[data-momento="manana"]   .dia-portada__capa--fondo { background-image: var(--grad-amanecer); }
.dia-portada[data-momento="mediodia"] .dia-portada__capa--fondo { background-image: var(--grad-oro); }
.dia-portada[data-momento="tarde"]    .dia-portada__capa--fondo { background-image: var(--grad-oro); }
.dia-portada[data-momento="noche"]    .dia-portada__capa--fondo { background-image: var(--grad-profundo); }

.dia-portada__texto {
  display: flex; align-items: baseline; gap: var(--sp-5);
  margin: 0; font-weight: 600;
  transform: translate3d(0, calc(var(--parallax, 0) * -1rem), 0);
}
.dia-portada__numero {
  font-family: var(--font-display); font-size: var(--fs-display-xl);
  line-height: .82; font-variant-numeric: tabular-nums;
  letter-spacing: -.03em; color: var(--text);
}
.dia-portada__nombre { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.dia-portada__semana {
  font-family: var(--font-display); font-size: var(--fs-h2);
  line-height: 1; color: var(--text);
}
.dia-portada__mes {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: hsl(var(--vm-cyan-400));
}
.dia-portada__resumen {
  margin: var(--sp-5) 0 0; font-size: var(--fs-body-sm);
  color: var(--text-muted); font-variant-numeric: tabular-nums;
}

/* ---------- Cuerpo del día: riel pegajoso + bloques ---------- */
.agenda-cuerpo {
  position: relative;
  display: grid; justify-content: center;
  grid-template-columns: minmax(0, 10rem) minmax(0, var(--container));
  gap: var(--sp-10);
}
/* Deriva de tono: un lavado vertical que va del cian del amanecer al arena de
   la tarde y al azul noche del cierre. Degradado ilustrativo, por eso usa
   primitivos; la opacidad es tan baja que no toca el contraste del texto. */
.agenda-cuerpo::before {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  inset: calc(var(--sp-8) * -1) calc(var(--sp-6) * -1);
  border-radius: var(--r-2xl);
  background: linear-gradient(180deg,
    hsl(var(--vm-cyan-200) / .28) 0%,
    hsl(var(--vm-marfil-50) / 0) 24%,
    hsl(var(--vm-arena-300) / .26) 70%,
    hsl(var(--vm-noche-700) / .10) 100%);
  /* El lavado deriva un poco contra el scroll: el fondo se despega del texto
     y la sección deja de sentirse una lámina. El .5 por defecto vale 0, así
     que sin JS y con movimiento reducido queda exactamente donde está. */
  transform: translate3d(0, calc((var(--agenda-progreso, .5) - .5) * var(--sp-10)), 0);
  will-change: transform;
}
/* La portada y el contenido van por encima del lavado: el ::before de
   .agenda-cuerpo nace 32px más arriba y además deriva, así que sin esto se
   monta sobre la portada del día —viene después en el DOM y gana el pintado. */
.dia-portada { z-index: 1; }
.agenda-riel, .agenda { position: relative; z-index: 1; }

.agenda-riel {
  position: sticky; top: var(--sp-20); align-self: start;
  display: flex; flex-direction: column; gap: var(--sp-1);
  padding-block: var(--sp-2);
}
.agenda-riel__numero {
  font-family: var(--font-display); font-size: var(--fs-display-lg);
  font-weight: 600; line-height: .85; letter-spacing: -.03em;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.agenda-riel__semana {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-subtle);
}
/* La hora que estás cruzando. La escribe site.js; el parpadeo la hace notar
   sin que uno tenga que buscarla. */
.agenda-riel__hora {
  display: flex; align-items: baseline; gap: var(--sp-1);
  margin: var(--sp-8) 0 var(--sp-3);
  font-family: var(--font-display); font-size: var(--fs-h1); font-weight: 600;
  line-height: 1; letter-spacing: -.02em;
  color: var(--accent-text); font-variant-numeric: tabular-nums;
}
.agenda-riel__meridiano { font-size: var(--fs-body-sm); font-weight: 500; color: var(--text-subtle); }
.agenda-riel__hora.es-nueva { animation: hora-entra var(--d-lento) var(--ease-salida); }
@keyframes hora-entra {
  from { opacity: 0; transform: translateY(var(--sp-2)); }
  to   { opacity: 1; transform: none; }
}
.agenda-riel__barra {
  display: block; height: var(--sp-1); border-radius: var(--r-pill);
  background: var(--border); overflow: hidden;
}
.agenda-riel__barra::after {
  content: ""; display: block; height: 100%; border-radius: inherit;
  background: linear-gradient(90deg, hsl(var(--vm-lima-600)), hsl(var(--vm-cyan-500)));
  transform: scaleX(var(--agenda-progreso, 0)); transform-origin: left;
  transition: transform var(--d-base) var(--ease-salida);
}
.agenda-riel__pie {
  margin: var(--sp-3) 0 0; font-size: var(--fs-caption); color: var(--text-subtle);
}

/* ---------- La lista de bloques ----------
   El riel vertical (::before del <ol>) y su relleno (::after) corren por el
   canal de la izquierda; cada bloque pone su punto, coloreado por tipo. */
.agenda {
  --riel-x: var(--sp-3);
  --bloque-hora: 7rem;
  --bloque-gente: 19rem;
  list-style: none; padding: 0; margin: 0;
}
.agenda::before, .agenda::after {
  content: ""; position: absolute; top: var(--sp-5); bottom: var(--sp-5);
  left: var(--riel-x); width: 2px; margin-left: -1px;
}
.agenda::before { background: var(--border); }
.agenda::after {
  background: linear-gradient(hsl(var(--vm-lima-600)), hsl(var(--vm-cyan-500)));
  transform: scaleY(var(--agenda-progreso, 0)); transform-origin: top;
  transition: transform var(--d-base) var(--ease-salida);
}

.agenda__bloque { position: relative; padding-left: var(--sp-10); }
.agenda__bloque + .agenda__bloque { margin-top: var(--sp-4); }
/* Halo del hito activo. Nace invisible y solo late mientras el bloque es el
   que se está cruzando: es la única pieza que se mueve sola en la sección, y
   marca dónde va uno sin tener que buscar la barra del riel. */
.agenda__bloque::before {
  content: ""; position: absolute; top: var(--sp-6);
  left: var(--riel-x); width: 12px; height: 12px; margin-left: -6px;
  border-radius: 50%; border: 2px solid var(--agenda-color);
  opacity: 0; pointer-events: none;
}
.agenda__bloque.es-activo::before { animation: hito-late var(--d-pulso) var(--ease-salida) infinite; }
@keyframes hito-late {
  from { opacity: .5; transform: scale(1); }
  to   { opacity: 0;  transform: scale(2.8); }
}
.agenda__bloque::after {                       /* punto — toma el color del tipo */
  content: ""; position: absolute; top: var(--sp-6);
  left: var(--riel-x); width: 12px; height: 12px; margin-left: -6px;
  border-radius: 50%; background: var(--surface);
  box-shadow: 0 0 0 2px var(--agenda-color);
  transition: transform var(--d-base) var(--ease-salida),
              box-shadow var(--d-base) var(--ease-salida);
}
.agenda__bloque.es-activo::after {
  transform: scale(1.35);
  box-shadow: 0 0 0 3px var(--agenda-color), var(--e-cyan);
}

/* ---------- La tarjeta de cada bloque ---------- */
.bloque {
  position: relative;
  display: grid; grid-template-columns: var(--bloque-hora) 1fr; gap: var(--sp-6);
  padding: var(--sp-5) var(--sp-6) var(--sp-5) var(--sp-8);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: linear-gradient(135deg, var(--momento-tinte, transparent), transparent 60%), var(--surface);
  box-shadow: var(--e1);
  transition: box-shadow var(--d-base) var(--ease-salida),
              border-color var(--d-base) var(--ease-salida),
              transform var(--d-base) var(--ease-salida);
}
.bloque::before {                              /* barra de color por tipo */
  content: ""; position: absolute; left: var(--sp-4); top: var(--sp-5); bottom: var(--sp-5);
  width: 3px; border-radius: var(--r-pill); background: var(--agenda-color); opacity: .55;
  transform-origin: left;
  transition: opacity var(--d-base) var(--ease-salida),
              transform var(--d-base) var(--ease-salida);
}
/* Con ancho de sobra la tarjeta se abre en tres columnas —hora · contenido ·
   ponentes— en vez de estirar el renglón: una medida de 90 caracteres no se
   lee mejor por ser más ancha, solo cansa. Donde no haya :has(), la tarjeta
   se queda en dos columnas y los ponentes caen debajo, que es el orden del
   HTML: no se pierde nada. */
@media (min-width: 1100px) {
  .bloque:has(.bloque__gente) {
    grid-template-columns: var(--bloque-hora) minmax(0, 1fr) minmax(0, var(--bloque-gente));
  }
}
.bloque:hover {
  border-color: var(--border-strong); box-shadow: var(--e2);
  transform: translateY(-2px);
}
.agenda__bloque.es-activo .bloque {
  box-shadow: var(--e3), var(--e-cyan); border-color: var(--accent);
  transform: translateY(-4px);
}
/* La barra de tipo engorda al activarse: es la misma pieza, no una nueva. */
.agenda__bloque.es-activo .bloque::before { opacity: 1; transform: scaleX(2); }

/* Las pausas son el respiro visual del día: mismo contenido, menos peso. */
.agenda__bloque[data-tipo="pausa"] .bloque {
  background: none; box-shadow: none; border-style: dashed;
}

/* La hora en dos pesos: el reloj grande manda y el a.m./p.m. acompaña. En una
   sola línea no cabía y "a.m." caía solo al renglón de abajo. */
.bloque__hora { margin: 0; display: flex; flex-direction: column; gap: var(--sp-1); }
.bloque__hora time {
  display: flex; align-items: baseline; gap: var(--sp-1);
  font-family: var(--font-display); font-weight: 600;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.bloque__reloj { font-size: var(--fs-h3); line-height: 1.05; }
.bloque__meridiano { font-size: var(--fs-caption); color: var(--text-subtle); font-weight: 500; }
.bloque__fin { font-size: var(--fs-caption); color: var(--text-subtle); font-variant-numeric: tabular-nums; }

.bloque__cuerpo { min-width: 0; }
.bloque__tipo {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--agenda-color); margin: 0 0 var(--sp-2);
}
.bloque__cuenta {
  padding: var(--sp-1) var(--sp-2); border-radius: var(--r-pill);
  background: var(--surface-brand); color: var(--text-muted);
  font-size: var(--fs-caption); letter-spacing: normal; text-transform: none;
}
.bloque__titulo {
  font-family: var(--font-display); font-size: var(--fs-lead); font-weight: 600;
  line-height: 1.25; text-wrap: balance; margin: 0;
}
.bloque__detalle {
  font-size: var(--fs-body-sm); color: var(--text-muted);
  margin: var(--sp-2) 0 0; max-width: var(--container-prosa);
}

/* ---------- Ponentes dentro del bloque ----------
   Foto redonda + nombre + rol. Sin foto, las iniciales sobre el degradado de
   amanecer: se ve intencional, no como un hueco esperando una imagen. */
/* El panel vive en la tercera columna cuando hay ancho, y debajo del cuerpo
   cuando no. El 2 / -1 lo alinea con el texto y no con la hora: en el salto a
   una sola columna, un panel arrancando bajo el reloj se lee como otro bloque. */
.bloque__gente { grid-column: 2 / -1; min-width: 0; align-self: start; margin-top: var(--sp-5); }
.bloque__gente-rotulo {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text-subtle); margin: 0 0 var(--sp-3);
}
@media (min-width: 1100px) {
  .bloque:has(.bloque__gente) .bloque__gente {
    grid-column: 3; margin-top: 0;
    padding-left: var(--sp-6); border-left: 1px solid var(--border);
  }
}
.bloque__ponentes {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: var(--sp-3);
}
/* En el rango de en medio —ya no cabe la tercera columna, pero sobra ancho
   debajo del texto— las personas van de a dos. */
@media (min-width: 700px) and (max-width: 1099.98px) {
  .bloque__ponentes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.bloque-ponente {
  min-width: 0; display: grid; grid-template-columns: auto 1fr;
  align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); border: 1px solid var(--border);
  border-radius: var(--r-md); background: var(--surface-sunken);
  transition: border-color var(--d-base) var(--ease-salida),
              transform var(--d-base) var(--ease-salida);
}
.bloque-ponente:hover { border-color: var(--accent); transform: translateY(-2px); }
.bloque-ponente__foto {
  width: var(--sp-10); aspect-ratio: 1; flex: none;
  border-radius: 50%; overflow: hidden; display: grid; place-items: center;
  background: var(--grad-amanecer);
  box-shadow: 0 0 0 2px var(--surface), var(--e1);
  transition: box-shadow var(--d-base) var(--ease-salida);
}
.bloque-ponente__foto img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.bloque-ponente__foto span {
  font-family: var(--font-display); font-size: var(--fs-body-sm); font-weight: 600;
  color: hsl(var(--vm-marfil-50) / .95);
}
.agenda__bloque.es-activo .bloque-ponente__foto { box-shadow: 0 0 0 2px var(--accent), var(--e2); }
.bloque-ponente__texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.bloque-ponente__texto b { font-size: var(--fs-body-sm); color: var(--text); }
.bloque-ponente__texto span { font-size: var(--fs-caption); color: var(--text-muted); }
/* Ponente de honor en la agenda: la tarjeta del bloque no cambia; su ficha
   lleva el rótulo, borde de acento y un avatar un escalón más grande. */
.bloque-ponente--honor { border-color: var(--accent); }
.bloque-ponente--honor .bloque-ponente__foto { width: var(--sp-12); box-shadow: 0 0 0 2px var(--accent), var(--e1); }
.bloque-ponente__texto .bloque-ponente__honor {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent-text);
}
.bloque__ponentes-texto { font-size: var(--fs-body-sm); font-weight: 600; color: var(--text); margin: var(--sp-4) 0 0; }

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

.bloque__lugar {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-caption); color: var(--text-subtle); margin: var(--sp-3) 0 0;
}
.bloque__lugar svg { flex: none; }

/* Sede única del programa: va una vez en la cabecera y no repetida en cada
   tarjeta. */
.agenda__sede {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-body-sm); font-weight: 600; color: var(--text); margin: var(--sp-4) 0 0;
}
.agenda__sede svg { flex: none; color: var(--accent-text); }

/* ---------- Bloque con ponente destacado ----------
   No es keynote —eso es de la sección de speakers—: es un conferencista que la
   organización quiere que se vea primero al recorrer la agenda. La tarjeta tiene
   el mismo fondo que las demás; lo que cambia es que la persona destacada deja la
   columna de ponentes y ocupa el centro, con foto grande, más el filo de amanecer
   arriba y el borde de acento. */
.bloque--destacado {
  overflow: hidden;
  border-color: var(--accent); box-shadow: var(--e2), var(--e-cyan);
}
.bloque--destacado::after {
  content: ""; position: absolute; inset-inline: 0; top: 0; height: var(--sp-1);
  background: var(--grad-amanecer);
}
.bloque--destacado .bloque__titulo { font-size: var(--fs-h3); }

.bloque__protagonista {
  grid-column: 1 / -1; justify-self: center; max-width: 100%;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--sp-5) var(--sp-8);
  padding: var(--sp-5) var(--sp-8);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface-sunken);
}
.protagonista__foto,
.protagonista__mini {
  flex: none; aspect-ratio: 1; border-radius: 50%; overflow: hidden;
  display: grid; place-items: center; background: var(--grad-amanecer);
}
.protagonista__foto { width: var(--sp-24); box-shadow: 0 0 0 3px var(--premium), var(--e3); }
.protagonista__mini { width: var(--sp-8); box-shadow: 0 0 0 1px var(--border-strong); }
.protagonista__foto img,
.protagonista__mini img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.protagonista__foto span,
.protagonista__mini span {
  font-family: var(--font-display); font-weight: 600; color: hsl(var(--vm-marfil-50) / .95);
}
.protagonista__foto span { font-size: var(--fs-h3); }
.protagonista__mini span { font-size: var(--fs-caption); }
.protagonista__texto {
  display: flex; flex-direction: column; gap: var(--sp-1); margin: 0;
  max-width: calc(var(--sp-40) + var(--sp-32));
}
.protagonista__resto-rotulo {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
}
.protagonista__texto b {
  font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 600;
  line-height: 1.1; color: var(--text);
}
.protagonista__texto > span:last-child { font-size: var(--fs-body-sm); color: var(--text-muted); }
.protagonista__resto { padding-left: var(--sp-8); border-left: 1px solid var(--border); }
.protagonista__resto-rotulo { color: var(--text-subtle); margin: 0 0 var(--sp-3); }
.protagonista__resto ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.protagonista__resto li { display: flex; align-items: center; gap: var(--sp-3); }
.protagonista__resto li > span:last-child { display: flex; flex-direction: column; min-width: 0; }
.protagonista__resto b { font-size: var(--fs-body-sm); color: var(--text); }
.protagonista__resto li > span:last-child > span { font-size: var(--fs-caption); color: var(--text-muted); }

@media (max-width: 700px) {
  .bloque__protagonista { justify-content: flex-start; padding: var(--sp-5); }
  .protagonista__foto { width: var(--sp-20); }
  .protagonista__texto b { font-size: var(--fs-h3); }
  .protagonista__resto {
    flex: 1 1 100%; padding: var(--sp-4) 0 0; border-left: 0; border-top: 1px solid var(--border);
  }
}

.agenda-vacio {
  margin: var(--sp-8) 0 0; font-size: var(--fs-body-sm);
  color: var(--text-muted); text-align: center;
}

/* Color y tinte por tipo y por momento del día. Son categorías de contenido,
   no estados de tema. Tres colores salen de semánticos; "experiencia" usa el
   primitivo nicoya-600 porque no hay semántico equivalente — seguro porque
   esta sección nunca es oscura. Los cuatro están verificados en el checker. */
.agenda__bloque                          { --agenda-color: var(--text-subtle); }
.agenda__bloque[data-tipo="charla"]      { --agenda-color: var(--accent-text); }
.agenda__bloque[data-tipo="experiencia"] { --agenda-color: hsl(var(--vm-nicoya-600)); }
.agenda__bloque[data-tipo="comunidad"]   { --agenda-color: var(--premium-text); }
.agenda__bloque[data-tipo="pausa"]       { --agenda-color: var(--text-subtle); }

.agenda__bloque[data-momento="amanecer"] { --momento-tinte: hsl(var(--vm-cyan-200) / .26); }
.agenda__bloque[data-momento="manana"]   { --momento-tinte: hsl(var(--vm-lima-200) / .20); }
.agenda__bloque[data-momento="mediodia"] { --momento-tinte: hsl(var(--vm-arena-300) / .22); }
.agenda__bloque[data-momento="tarde"]    { --momento-tinte: hsl(var(--vm-arena-500) / .18); }
.agenda__bloque[data-momento="noche"]    { --momento-tinte: hsl(var(--vm-noche-700) / .12); }

.agenda__pie { margin-top: var(--sp-16); }

/* El riel de la izquierda no cabe: pasa a barra pegajosa horizontal arriba de
   los bloques, con el mismo contenido (día, hora viva y avance). */
@media (max-width: 900px) {
  .agenda-cuerpo { grid-template-columns: 1fr; gap: var(--sp-6); }
  .agenda-cuerpo::before { inset: calc(var(--sp-6) * -1) calc(var(--sp-4) * -1); }
  .agenda-riel {
    top: var(--sp-16); z-index: 2;
    display: grid; grid-template-columns: auto auto 1fr; align-items: center;
    gap: var(--sp-1) var(--sp-3);
    padding: var(--sp-2) var(--sp-4); border-radius: var(--r-pill);
    background: var(--surface); border: 1px solid var(--border);
    box-shadow: var(--e2); backdrop-filter: var(--vidrio);
  }
  .agenda-riel__numero { font-size: var(--fs-h2); grid-row: 1 / span 2; }
  .agenda-riel__semana { grid-column: 2; grid-row: 1; }
  .agenda-riel__hora { margin: 0; grid-column: 2; grid-row: 2; font-size: var(--fs-h3); }
  .agenda-riel__barra { grid-column: 3; grid-row: 1 / span 2; margin-left: var(--sp-2); }
  .agenda-riel__pie { display: none; }
}

@media (max-width: 600px) {
  .dia-portada { padding: var(--sp-6); }
  .dia-portada__texto { gap: var(--sp-4); }
  .agenda__bloque { padding-left: var(--sp-6); }
  .agenda { --riel-x: var(--sp-1); }
  .bloque {
    grid-template-columns: 1fr; gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-6);
  }
  .bloque::before { left: var(--sp-2); top: var(--sp-4); bottom: var(--sp-4); }
  .bloque__hora { flex-direction: row; align-items: baseline; gap: var(--sp-2); }
  .bloque__hora time { font-size: var(--fs-body); }
  .bloque__ponentes { gap: var(--sp-3); }
  /* Acá la tarjeta es de una sola columna: sin esto, el 2 / -1 del panel le
     inventa una segunda columna a la grilla y la tarjeta se sale de pantalla. */
  .bloque__gente { grid-column: 1; margin-top: var(--sp-4); }
}

/* Con movimiento reducido queda todo quieto: sin parallax, sin desplazamiento
   del riel y sin la entrada de la hora. La información no cambia. */
@media (prefers-reduced-motion: reduce) {
  .dia-portada__capa, .dia-portada__texto { transform: none; }
  .agenda-riel__hora.es-nueva { animation: none; }
  .agenda__bloque.es-activo .bloque { transform: none; }
  .agenda-cuerpo::before { transform: none; }
  /* El halo es lo único que se repite solo: se apaga entero, no se ralentiza. */
  .agenda__bloque.es-activo::before { animation: none; }
}

/* ============================================================
   UBICACIÓN
   ============================================================ */
.ubicacion { display: grid; grid-template-columns: 6fr 6fr; gap: var(--sp-16); align-items: stretch; }
@media (max-width: 900px) { .ubicacion { grid-template-columns: 1fr; gap: var(--sp-10); } }

/* La foto de Nicoya, con el mismo lenguaje visual que .zona-azul__media: el
   degradado de ::before queda detrás mientras carga. Imagen estática y nunca
   un iframe de mapas: carga scripts de terceros y castiga el LCP. El rótulo
   «Nicoya» va abajo a la izquierda para no tapar la fachada. */
.ubicacion__media {
  position: relative; min-height: 26rem; border-radius: var(--r-2xl); overflow: hidden;
  isolation: isolate;
}
.ubicacion__imagen { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; }
.ubicacion__pin {
  position: absolute; left: var(--sp-5); bottom: var(--sp-5); margin: 0; transform-origin: left bottom;
  display: flex; align-items: center; gap: var(--sp-3);
  font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600;
  color: hsl(var(--vm-marfil-50));
  background: hsl(var(--vm-noche-900) / .72);
  backdrop-filter: var(--vidrio); -webkit-backdrop-filter: var(--vidrio);
  padding: var(--sp-3) var(--sp-5); border-radius: var(--r-pill);
}
.ubicacion__pin span { width: 10px; height: 10px; border-radius: 50%; background: hsl(var(--vm-lima-500)); }

.ubicacion__texto h2 { font-size: var(--fs-h1); font-variation-settings: "opsz" 120; text-wrap: balance; margin-bottom: var(--sp-5); }
.ubicacion__texto .lead { margin-bottom: var(--sp-8); }

.ubicacion__sede {
  display: grid; gap: var(--sp-1); margin: 0 0 var(--sp-10);
  padding: var(--sp-4) var(--sp-5);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
}
.ubicacion__sede b { color: var(--text); }
.ubicacion__sede span { font-size: var(--fs-body-sm); color: var(--text-muted); }

/* El cuadro del ícono: el mismo lenguaje de .pilar__icono, un paso más grande.
   Lo usan la sede, las formas de llegar y el hospedaje. */
.ubicacion__sede .ubicacion__icono, .ubicacion__icono, .llegar__icono {
  width: var(--sp-12); height: var(--sp-12); flex: none;
  display: grid; place-items: center; border-radius: var(--r-md);
  background: var(--surface-sunken); border: 1px solid var(--border); color: var(--accent-text);
  transition: background-color var(--d-base) var(--ease-salida), color var(--d-base) var(--ease-salida), border-color var(--d-base) var(--ease-salida);
}

/* La sede en la landing: pin a la izquierda y, debajo del texto, los botones
   que abren la ruta en el mapa del teléfono. Son enlaces, no un mapa
   incrustado: no cargan nada de terceros. */
.ubicacion__sede--con-icono {
  grid-template-columns: auto 1fr; gap: var(--sp-4); align-items: start;
  padding: var(--sp-5); border-radius: var(--r-lg); box-shadow: var(--e1);
}
.ubicacion__sede--con-icono > p { display: grid; gap: var(--sp-1); margin: 0; }
.ubicacion__sede--con-icono .ubicacion__icono { background: var(--accent); color: var(--accent-fg); border-color: transparent; }
.ubicacion__mapas { grid-column: 2; display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-1); }
.ubicacion__mapas svg { width: var(--sp-5); height: var(--sp-5); }
@media (max-width: 600px) {
  .ubicacion__mapas { grid-column: 1 / -1; }
  .ubicacion__mapas .btn { flex: 1 1 auto; }
}

.ubicacion__subtitulo {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-subtle); margin: 0 0 var(--sp-5);
}

/* Las tres formas de llegar son alternativas, no pasos: por eso <ul>. */
.llegar { list-style: none; padding: 0; margin: 0 0 var(--sp-8); display: grid; gap: var(--sp-5); }
.llegar li {
  display: grid; grid-template-columns: 1fr auto; gap: var(--sp-1) var(--sp-4);
  padding-bottom: var(--sp-5); border-bottom: 1px solid var(--border);
}
.llegar li:last-child { padding-bottom: 0; border-bottom: 0; }
.llegar__desde { font-weight: 600; color: var(--text); margin: 0; }
.llegar__tiempo { font-size: var(--fs-body-sm); color: var(--accent-text); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; margin: 0; }
.llegar__detalle { grid-column: 1 / -1; font-size: var(--fs-body-sm); color: var(--text-muted); margin: 0; }
/* Con ícono: el cuadro a la izquierda ocupa las dos filas. */
.llegar .llegar__ruta { grid-template-columns: auto 1fr auto; align-items: start; }
.llegar__ruta .llegar__icono { grid-row: 1 / span 2; }
.llegar__ruta .llegar__detalle { grid-column: 2 / -1; }
/* Pie opcional de una ruta (hoy, el transporte privado): el enlace a la
   izquierda y el logo de quien da el servicio a la derecha, chico, para que
   no compita con la tarjeta. */
.llegar__pie {
  grid-column: 2 / -1; margin-top: var(--sp-1);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3);
}
.llegar__enlace svg { width: var(--sp-5); height: var(--sp-5); }
.llegar__logo { display: block; width: auto; height: var(--sp-10); }

/* En la landing cada forma de llegar es una tarjeta que se levanta al pasar
   el mouse o tocarla, y su ícono se enciende en cian. */
.llegar--tarjetas { gap: var(--sp-3); }
.llegar--tarjetas .llegar__ruta,
.llegar--tarjetas .llegar__ruta:last-child {
  padding: var(--sp-4) var(--sp-5); border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--e1);
  transition: transform var(--d-base) var(--ease-salida), box-shadow var(--d-base) var(--ease-salida), border-color var(--d-base) var(--ease-salida);
}
.llegar--tarjetas .llegar__ruta:hover,
.llegar--tarjetas .llegar__ruta:active { transform: translateY(calc(var(--sp-1) * -1)); box-shadow: var(--e3); border-color: var(--accent); }
.llegar__ruta:hover .llegar__icono,
.llegar__ruta:active .llegar__icono { background: var(--accent); color: var(--accent-fg); border-color: transparent; }
/* En el teléfono la hora baja bajo el título y el detalle toma todo el ancho:
   en tres columnas el título se partía en tres renglones. */
@media (max-width: 600px) {
  .llegar .llegar__ruta { grid-template-columns: auto 1fr; }
  .llegar__ruta .llegar__tiempo { grid-column: 2; grid-row: 2; text-align: left; }
  .llegar__ruta .llegar__detalle, .llegar__pie { grid-column: 1 / -1; }
  .llegar.llegar--tarjetas .llegar__ruta { padding: var(--sp-4); }
}

.ubicacion__hospedaje { font-size: var(--fs-body-sm); color: var(--text-muted); margin: 0 0 var(--sp-8); display: flex; align-items: center; gap: var(--sp-4); }
/* ============================================================
   ZONA AZUL
   ============================================================ */
.zona-azul { display: grid; grid-template-columns: 6fr 6fr; align-items: center; gap: 0; }
@media (max-width: 900px) { .zona-azul { grid-template-columns: 1fr; } }
.zona-azul__media {
  position: relative; min-height: 30rem; border-radius: var(--r-2xl); overflow: hidden;
  background:
    radial-gradient(100% 80% at 20% 20%, hsl(var(--vm-nicoya-500) / .55) 0%, transparent 60%),
    radial-gradient(80% 70% at 85% 80%, hsl(var(--vm-arena-500) / .35) 0%, transparent 60%),
    hsl(var(--vm-nicoya-700));
}
/* La foto cubre el bloque. El degradado de .zona-azul__media queda detrás como
   color de espera mientras la imagen carga. El velo la oscurece lo justo para
   que el dato en vidrio siga legible encima. */
.zona-azul__imagen { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.zona-azul__media::after { content: ""; position: absolute; inset: 0; background: var(--grad-velo); }
.zona-azul__dato {
  position: absolute; z-index: 1; left: var(--sp-6); bottom: var(--sp-6);
  background: hsl(var(--vm-noche-900) / .78); backdrop-filter: var(--vidrio);
  border-radius: var(--r-md); padding: var(--sp-4) var(--sp-5); max-width: 15rem;
}
.zona-azul__dato b { display: block; font-family: var(--font-display); font-size: var(--fs-h2); line-height: 1; color: hsl(var(--vm-lima-400)); font-variant-numeric: tabular-nums; margin-bottom: var(--sp-1); }
.zona-azul__dato span { font-size: var(--fs-caption); color: hsl(var(--vm-marfil-200)); }
.zona-azul__texto { padding: var(--sp-12) 0 var(--sp-12) var(--sp-16); }
@media (max-width: 900px) { .zona-azul__texto { padding: var(--sp-10) 0 0; } .zona-azul__media { min-height: 20rem; } }
.zona-azul__texto h2 { font-size: var(--fs-h1); font-variation-settings: "opsz" 120; text-wrap: balance; margin-bottom: var(--sp-5); }
.zona-azul__texto .lead { margin-bottom: var(--sp-6); }
.zona-azul__lista { list-style: none; padding: 0; margin: 0 0 var(--sp-8); display: grid; gap: var(--sp-4); }
.zona-azul__lista li { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-3); font-size: var(--fs-body-sm); color: var(--text-muted); }
.zona-azul__lista b { color: var(--text); font-weight: 600; }
.zona-azul__lista i { width: 6px; height: 6px; border-radius: 50%; background: var(--premium); margin-top: .55em; }

/* ============================================================
   SPEAKERS
   Sección oscura. Dos grupos: keynotes con foto redonda grande + texto al lado,
   y el resto en filas compactas de avatar + texto en dos columnas. Escala a 15+
   sin volverse un muro. Los avatares NO usan --grad-profundo (es el mismo
   degradado de la sección y el círculo desaparecería): van sobre marfil al 8%.
   ============================================================ */
.speakers__keynotes {
  display: grid; gap: var(--grid-gap);
  /* min() y no 24rem pelado: en un teléfono de 390px la columna mínima de
     24rem (384px) es más ancha que la pantalla menos los márgenes, y la
     página entera terminaba con scroll horizontal. */
  grid-template-columns: repeat(auto-fit, minmax(min(24rem, 100%), 1fr));
  margin-bottom: var(--sp-16);
}
.keynote { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: var(--sp-6); }
.keynote__foto {
  width: var(--sp-32); aspect-ratio: 1; flex: none;
  border-radius: 50%; overflow: hidden; display: grid; place-items: center;
  background: hsl(var(--vm-marfil-50) / .08);
  box-shadow: 0 0 0 2px hsl(var(--vm-arena-500)), var(--e-oro);
}
.keynote__foto img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.keynote__foto span { font-family: var(--font-display); font-size: var(--fs-h2); color: hsl(var(--vm-marfil-50) / .45); }
.keynote__texto { min-width: 0; }
.keynote__etiqueta { font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--premium-text); margin: 0 0 var(--sp-1); }
.keynote__texto h3 { font-size: var(--fs-h3); margin: 0 0 2px; }
.keynote__rol { font-size: var(--fs-body-sm); color: var(--text-muted); margin: 0 0 2px; }
.keynote__pais { font-size: var(--fs-caption); color: var(--text-subtle); margin: 0; }
.keynote__bio { font-size: var(--fs-body-sm); color: var(--text-muted); margin: var(--sp-3) 0 0; }
@media (max-width: 480px) {
  .keynote { grid-template-columns: 1fr; justify-items: start; gap: var(--sp-4); }
}

/* ---------- Ficha de honor ----------
   Entre el keynote y la lista. Foto de --sp-24 contra --sp-32 del keynote y
   --sp-16 de las filas; aro de acento (el oro es del keynote) y bio visible. */
.speakers__honores { display: grid; gap: var(--grid-gap); margin-bottom: var(--sp-12); }
.honor {
  display: grid; grid-template-columns: auto 1fr; align-items: center; gap: var(--sp-6);
  padding-top: var(--sp-8); border-top: 1px solid var(--border);
}
.honor__foto {
  width: var(--sp-24); aspect-ratio: 1; flex: none;
  border-radius: 50%; overflow: hidden; display: grid; place-items: center;
  background: hsl(var(--vm-marfil-50) / .08);
  box-shadow: 0 0 0 2px var(--accent-text), var(--e-cyan);
}
.honor__foto img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.honor__foto span { font-family: var(--font-display); font-size: var(--fs-h3); color: hsl(var(--vm-marfil-50) / .45); }
.honor__texto { min-width: 0; max-width: var(--container-prosa); }
.honor__etiqueta { font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--accent-text); margin: 0 0 var(--sp-1); }
.honor__texto h3 { font-size: var(--fs-lead); margin: 0 0 2px; }
.honor__rol { font-size: var(--fs-body-sm); color: var(--text-muted); margin: 0 0 2px; }
.honor__pais { font-size: var(--fs-caption); color: var(--text-subtle); margin: 0; }
.honor__bio { font-size: var(--fs-body-sm); color: var(--text-muted); margin: var(--sp-3) 0 0; }
@media (max-width: 480px) {
  .honor { grid-template-columns: 1fr; justify-items: start; gap: var(--sp-4); }
}

.speakers__lista {
  list-style: none; padding: 0; margin: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6) var(--sp-10);
}
@media (max-width: 900px) { .speakers__lista { grid-template-columns: 1fr; } }
.speaker-fila {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  gap: var(--sp-4); padding-top: var(--sp-6); border-top: 1px solid var(--border);
}
.speaker-fila__foto {
  width: var(--sp-16); aspect-ratio: 1; flex: none;
  border-radius: 50%; overflow: hidden; display: grid; place-items: center;
  background: hsl(var(--vm-marfil-50) / .08); border: 1px solid var(--border);
  transition: box-shadow var(--d-base) var(--ease-salida);
}
.speaker-fila__foto img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.speaker-fila__foto span { font-family: var(--font-body); font-weight: 600; font-size: var(--fs-body); color: hsl(var(--vm-marfil-50) / .45); }
.speaker-fila:hover .speaker-fila__foto { box-shadow: 0 0 0 2px var(--accent-text); }
.speaker-fila h3 { font-size: var(--fs-body); margin: 0 0 2px; }
.speaker-fila__rol { font-size: var(--fs-body-sm); color: var(--text-muted); margin: 0; }
.speaker-fila__pais { font-size: var(--fs-caption); color: var(--text-subtle); margin: 2px 0 0; }

/* ============================================================
   ALIADOS — la banda que desfila
   La sección dejó de ser una grilla de tarjetas quietas: la cabecera se queda
   en el contenedor y los aliados desfilan de derecha a izquierda, de un borde
   al otro de la pantalla, con el mismo motor de la franja del hero
   (.marquesina). El movimiento es decoración pura: con prefers-reduced-motion
   la cinta se detiene y los logos caen a una fila que envuelve, así que la
   sección se lee entera igual.
   ============================================================ */
/* Blanca desde el 24 de setiembre de 2026 (pedido de la organización): sobre
   blanco los logos se ven en su color, sin versiones aclaradas ni desaturado.
   Es la única sección en --surface pura, entre el marfil hundido de Ubicación
   y el marfil de Contacto. */
.aliados-banda { position: relative; overflow: hidden; background: var(--surface); }
.aliados-banda > .contenedor { position: relative; z-index: 1; }
/* La marquesina va sobre las capas decorativas, pero sin z-index propio: le
   alcanza con ser posterior en el DOM y crear contexto al animarse. */
.aliados-banda .marquesina { position: relative; }

/* Halo de marca detrás del desfile: el mismo aire de amanecer que el hero, en
   degradado —ilustración, que es donde los primitivos están permitidos—. Respira
   con el scroll usando el --avance de la escena, y el valor por defecto de var()
   es el estado quieto y visible: sin JS el halo se queda en su punto medio. */
.aliados-banda__aurora {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(64% 62% at 14% 12%, hsl(var(--vm-cyan-500) / .08) 0%, transparent 64%),
    radial-gradient(58% 60% at 86% 88%, hsl(var(--vm-nicoya-500) / .07) 0%, transparent 66%);
  transform: translate3d(0, calc((var(--avance, .5) - .5) * var(--sp-16) * -1), 0);
}

/* El llamado a patrocinar cierra la banda, debajo del desfile y centrado: en la
   cabecera quedaba flotando a la derecha, y acá le da un final a la sección en
   vez de dejar un hueco debajo de las tarjetas. */
.aliados__pie { margin-top: var(--sp-12); }

/* ---------- Patrocinadores por paquete ----------
   Quietos y arriba de la cinta: los que pagan no desfilan, se quedan. El paquete
   no se rotula, se nota: baja el tamaño de la tarjeta de un nivel al siguiente y
   cambia el metal del filo —oro cálido, platino frío, plata tenue, bronce cobrizo—, con un brillo
   propio alrededor y los rombos de la esquina (tres, dos, uno). La tarjeta es
   blanca sobre la banda blanca, separada por el filo y la sombra, y el logo va
   a su color original, sin placa.
   Los metales son ilustración —degradados—, por eso van en primitivos. */
.patrocinadores { margin-top: var(--sp-12); }
.aliados__subtitulo {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-subtle); text-align: center; margin: 0 0 var(--sp-8);
}
.nivel + .nivel { margin-top: var(--sp-8); }
/* Cada paquete llena el ancho del contenedor ancho: --columnas tarjetas por fila
   (Gold 2, Platinum 3, Silver 3, Bronce 4). Si hay más patrocinadores que columnas, bajan a
   otra fila; si hay menos, se centran con el mismo ancho. En alto también se
   centran: una medalla es más alta que una tarjeta de su paquete y, pegadas
   arriba, los logos quedaban desalineados. */
.nivel__lista {
  --hueco: var(--sp-6);
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--hueco);
}
/* Silver es el valor por defecto. Creció (setiembre 2026, pedido de la
   organización): tres por fila y casi el alto de Platinum, que conserva la
   diferencia por alto y por metal. Todos los paquetes crecieron otra vez el
   2 de octubre de 2026: no se esperan más de diez patrocinadores en total, así
   que hay lugar para que cada logo se lea grande. */
.nivel {
  --columnas: 3; --placa-alto: calc(var(--sp-40) + var(--sp-8));
  --placa-relleno: var(--sp-4) var(--sp-8); --mas: var(--sp-10);
  --metal: linear-gradient(135deg, hsl(var(--vm-tinta-300) / .75) 0%, hsl(var(--vm-tinta-300) / .25) 50%, hsl(var(--vm-tinta-300) / .6) 100%);
  --metal-brillo: transparent;
  --metal-tinte: hsl(var(--vm-tinta-300) / .1);
}
.nivel--gold {
  --columnas: 2; --placa-alto: calc(var(--sp-40) + var(--sp-24));
  --placa-relleno: var(--sp-8) var(--sp-16); --mas: var(--sp-16);
  --metal: linear-gradient(135deg, hsl(var(--vm-arena-300)) 0%, hsl(var(--vm-arena-600)) 38%, hsl(var(--vm-arena-100)) 62%, hsl(var(--vm-arena-800)) 100%);
  --metal-brillo: hsl(var(--vm-arena-500) / .3);
  --metal-tinte: hsl(var(--vm-arena-500) / .14);
}
.nivel--platinum {
  --columnas: 3; --placa-alto: calc(var(--sp-40) + var(--sp-12));
  --placa-relleno: var(--sp-6) var(--sp-12); --mas: var(--sp-12);
  --metal: linear-gradient(135deg, hsl(var(--vm-tinta-300)) 0%, hsl(var(--vm-tinta-500)) 40%, hsl(var(--vm-marfil-200)) 65%, hsl(var(--vm-tinta-500)) 100%);
  --metal-brillo: hsl(var(--vm-cyan-400) / .16);
  --metal-tinte: hsl(var(--vm-tinta-300) / .12);
}
/* Bronce, el último paquete (28-09-2026): cuatro por fila y la tarjeta más baja.
   Su metal es cobrizo —propio, no un oro oscurecido— para que no se lea como Gold. */
.nivel--bronce {
  --columnas: 4; --placa-alto: var(--sp-40);
  --placa-relleno: var(--sp-4) var(--sp-6); --mas: var(--sp-8);
  --metal: linear-gradient(135deg, hsl(var(--vm-bronce-300)) 0%, hsl(var(--vm-bronce-500)) 40%, hsl(var(--vm-bronce-300)) 62%, hsl(var(--vm-bronce-700)) 100%);
  --metal-brillo: hsl(var(--vm-bronce-500) / .18);
  --metal-tinte: hsl(var(--vm-bronce-500) / .1);
}
/* El nombre del paquete, entre dos filos de su metal: dice en palabras lo que
   la tarjeta ya dice con el acabado. */
.nivel__rotulo {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-4);
  margin: 0 0 var(--sp-5);
  font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--text);
}
.nivel__rotulo::before,
.nivel__rotulo::after {
  content: ""; width: var(--sp-16); height: 1px; background: var(--metal);
}
/* El filo metálico es el borde: un borde transparente deja ver el degradado de
   border-box, y el vidrio va en padding-box encima. Flex y no grid: con grid la
   fila no tiene alto definido y el height:100% del logo se sale de la tarjeta. */
.patrocinador {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  flex: 0 1 calc((100% - (var(--columnas) - 1) * var(--hueco)) / var(--columnas));
  height: var(--placa-alto); min-width: 0;
  padding: var(--placa-relleno);
  border: 1px solid transparent; border-radius: var(--r-lg);
  background:
    linear-gradient(180deg, var(--metal-tinte) 0%, transparent 70%) padding-box,
    linear-gradient(var(--surface), var(--surface)) padding-box,
    var(--metal) border-box;
  box-shadow: var(--e2), 0 0 var(--sp-12) var(--metal-brillo);
  transition: transform var(--d-base) var(--ease-salida),
              box-shadow var(--d-base) var(--ease-salida);
}
/* Reflejo diagonal: un barrido de luz quieto sobre el vidrio, lo que hace que la
   tarjeta se lea como una pieza y no como un rectángulo. */
.patrocinador::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 30%, hsl(var(--vm-marfil-50) / .07) 48%, transparent 62%);
}
/* Gold lleva además una línea de oro arriba, el acabado que no tienen los otros. */
.nivel--gold .patrocinador::after {
  content: ""; position: absolute; inset-inline: var(--sp-8); top: 0; height: 2px;
  background: var(--metal); pointer-events: none;
}
.patrocinador:hover,
.patrocinador:focus-within {
  transform: translateY(calc(var(--sp-1) * -1));
  box-shadow: var(--e3), 0 0 var(--sp-16) var(--metal-brillo);
}
.patrocinador img { position: relative; flex: 1 1 auto; min-width: 0; min-height: 0; width: 100%; height: 100%; object-fit: contain; }
.patrocinador__nombre {
  position: relative;
  font-family: var(--font-display); font-size: var(--fs-lead); font-weight: 600;
  text-align: center; color: var(--text);
}
.nivel--silver .patrocinador__nombre,
.nivel--bronce .patrocinador__nombre { font-size: var(--fs-body); }

/* Los rombos del paquete, en el mismo metal del filo. */
.patrocinador__rango {
  position: absolute; top: var(--sp-4); right: var(--sp-5);
  display: flex; gap: var(--sp-2); pointer-events: none;
}
.patrocinador__rango i {
  display: block; width: var(--sp-3); aspect-ratio: 1;
  rotate: 45deg; background: var(--metal);
}

/* Medalla: para logos redondos. El círculo es la tarjeta y el filo de metal es
   el aro; entre el aro y el logo queda un anillo de aire, y ahí arriba, al
   centro, va el rombo del paquete: adentro y entero, como en las otras tarjetas.
   El logo queda de un tamaño que se lee (~165 px). */
.patrocinador--redondo {
  --medalla: calc(var(--sp-40) + var(--sp-12));
  flex: 0 0 auto;
  width: var(--medalla); height: var(--medalla);
  padding: var(--sp-5); border-width: 2px; border-radius: 50%;
}
.patrocinador--redondo img { border-radius: 50%; }
.patrocinador--redondo .patrocinador__rango {
  top: var(--sp-1); right: 0; left: 0; justify-content: center;
}

.patrocinador--libre { padding: 0; }
.patrocinador--libre a {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-2);
  width: 100%; height: 100%; padding: var(--sp-3);
  font-size: var(--fs-body-sm); font-weight: 600; text-align: center; text-decoration: none;
  color: var(--text-muted);
  transition: color var(--d-base) var(--ease-estandar);
}
.patrocinador--libre a:hover,
.patrocinador--libre a:focus-visible { color: var(--text); }
.patrocinador__mas {
  display: grid; place-items: center; width: var(--mas); aspect-ratio: 1; border-radius: 50%;
  background: var(--metal); color: hsl(var(--vm-noche-900));
  font-family: var(--font-display); font-size: var(--fs-h3); line-height: 1;
}
.nivel--gold .patrocinador__mas { font-size: var(--fs-h2); }
.nivel--gold .patrocinador--libre a { font-size: var(--fs-lead); gap: var(--sp-3); }
.nivel--platinum .patrocinador--libre a { font-size: var(--fs-body); }
/* Con patrocinadores arriba, la cinta de aliados abre con su propio rótulo. */
.patrocinadores + .aliados__cinta { margin-top: var(--sp-16); }

@media (max-width: 900px) {
  .nivel--gold { --placa-relleno: var(--sp-8); }
  .nivel--platinum { --placa-relleno: var(--sp-5) var(--sp-8); }
  .nivel--platinum, .nivel--silver, .nivel--bronce { --columnas: 2; }
}
@media (max-width: 640px) {
  .nivel--gold     { --columnas: 1; --placa-alto: calc(var(--sp-40) + var(--sp-8)); --placa-relleno: var(--sp-6) var(--sp-8); }
  .nivel--platinum { --columnas: 1; --placa-alto: var(--sp-40); --placa-relleno: var(--sp-5) var(--sp-8); }
  .nivel--silver   { --columnas: 1; --placa-alto: calc(var(--sp-32) + var(--sp-4)); --placa-relleno: var(--sp-3) var(--sp-4); --mas: var(--sp-8); }
  .nivel--bronce   { --columnas: 1; --placa-alto: var(--sp-32); --placa-relleno: var(--sp-3) var(--sp-4); }
  /* En teléfono la medalla vuelve a su tamaño anterior: así dos caben lado a lado. */
  .patrocinador--redondo { --medalla: calc(var(--sp-40) + var(--sp-2)); }
  .nivel__lista { --hueco: var(--sp-4); }
}
@media (hover: none) {
  .patrocinador:hover { transform: none; }
}

/* ============================================================
   INSCRIPCIÓN
   ============================================================ */
.inscripcion { display: grid; grid-template-columns: 5fr 7fr; gap: var(--sp-16); align-items: start; }
@media (max-width: 1024px) { .inscripcion { grid-template-columns: 1fr; gap: var(--sp-10); } }
.inscripcion h2 { font-size: var(--fs-h1); font-variation-settings: "opsz" 120; text-wrap: balance; margin-bottom: var(--sp-5); }
.inscripcion__nota { font-size: var(--fs-caption); color: var(--text-subtle); margin-top: var(--sp-4); }

.formulario { display: grid; gap: var(--sp-5); }
.campo { display: flex; flex-direction: column; gap: var(--sp-2); }
.campo label { font-size: var(--fs-body-sm); font-weight: 500; }
.campo input:not([type="checkbox"]), .campo select {
  height: 48px; padding: 0 var(--sp-4); width: 100%;
  font-family: var(--font-body); font-size: var(--fs-body); color: var(--text);
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--r-sm);
  transition: border-color var(--d-rapido) var(--ease-estandar);
}
.campo input::placeholder { color: var(--text-subtle); }
.campo input:focus, .campo select:focus { border-color: var(--focus-ring); }
.campo small { font-size: var(--fs-caption); color: var(--text-subtle); }
.campo[data-error="true"] input, .campo[data-error="true"] select { border-color: hsl(var(--vm-error)); }
.campo[data-error="true"] small { color: hsl(var(--vm-error)); }
.consentimiento { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-3); align-items: start; font-size: var(--fs-body-sm); color: var(--text-muted); }
.consentimiento input { width: 20px; height: 20px; margin-top: 2px; accent-color: hsl(var(--vm-noche-700)); }

/* ---------- El asistente de postulación ----------
   Regla que manda en toda esta sección: ninguna declaración de display cae
   sobre .paso, .pasos o .formulario a secas, siempre sobre :not([hidden]). Sin
   JavaScript los tres pasos llegan apilados y visibles —que es el estado
   legible— y el atributo hidden tiene que poder ganarle al CSS sin recurrir
   a !important. */
/* El riel: tres hitos con número y rótulo, más una línea fina de avance.
   Los hitos son botones —una vez recorrido un paso se vuelve a él de un
   clic— y nacen deshabilitados: site.js los abre a medida que se avanza. */
.pasos:not([hidden]) { display: grid; gap: var(--sp-4); margin-bottom: var(--sp-8); }
.pasos__hitos {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: var(--sp-2); list-style: none; margin: 0; padding: 0;
}
.pasos__ir {
  position: relative; display: flex; align-items: center; gap: var(--sp-3); width: 100%;
  padding: var(--sp-2); background: transparent; border: 0; border-radius: var(--r-sm);
  font-family: var(--font-body); font-size: var(--fs-body-sm); text-align: left;
  color: var(--text-subtle); cursor: default;
  transition: color var(--d-rapido) var(--ease-estandar);
}
.pasos__ir:enabled { cursor: pointer; }
.pasos__ir:enabled:hover { color: var(--text); }
.pasos__num {
  display: grid; place-items: center; flex: 0 0 auto;
  width: var(--sp-8); height: var(--sp-8);
  border: 1px solid var(--border-strong); border-radius: var(--r-pill);
  font-size: var(--fs-caption); font-weight: 600; font-variant-numeric: tabular-nums;
  transition: background-color var(--d-rapido) var(--ease-estandar),
              border-color var(--d-rapido) var(--ease-estandar),
              color var(--d-rapido) var(--ease-estandar);
}
.pasos__rotulo { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pasos__hito[data-estado="actual"] .pasos__ir { color: var(--text); font-weight: 600; }
.pasos__hito[data-estado="actual"] .pasos__num {
  background: var(--primary); border-color: var(--primary); color: var(--primary-fg);
}
.pasos__hito[data-estado="hecho"] .pasos__ir { color: var(--text-muted); }
.pasos__hito[data-estado="hecho"] .pasos__num {
  background: var(--accent); border-color: var(--accent); color: var(--accent-fg);
  font-size: 0;
}
/* El número cumplido se cambia por una marca: el dígito ya no informa nada.
   El <span> es aria-hidden, así que esto no le quita nada a nadie. */
.pasos__hito[data-estado="hecho"] .pasos__num::after { content: "✓"; font-size: var(--fs-caption); }
/* En pantalla angosta quedan los números; el rótulo del paso en curso se
   mantiene y los otros se esconden sin salir del árbol de accesibilidad. */
@media (max-width: 640px) {
  .pasos__hitos { grid-auto-columns: auto; justify-content: start; }
  .pasos__hito:not([data-estado="actual"]) .pasos__rotulo {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
}
.pasos__riel { height: var(--sp-1); background: var(--border); border-radius: var(--r-pill); overflow: hidden; }
.pasos__avance {
  display: block; height: 100%;
  background: var(--accent); border-radius: var(--r-pill);
  transform-origin: left center;
  transform: scaleX(var(--avance-pasos, 1));
  transition: transform var(--d-base) var(--ease-salida);
}
/* Los hitos ya dicen en qué paso va la persona, así que este texto no se
   dibuja — pero se queda en el árbol de accesibilidad: es el role="status"
   que anuncia el cambio de paso a un lector de pantalla. */
.pasos__cuenta { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

.paso:not([hidden]) { display: grid; gap: var(--sp-2); }
.paso__titulo { font-size: var(--fs-h2); font-variation-settings: "opsz" 110; text-wrap: balance; }
/* El foco de cada paso se mueve a su título para que un lector de pantalla
   anuncie dónde quedó. Es foco programático, no de teclado: no se dibuja. */
.paso__titulo:focus:not(:focus-visible) { outline: none; }
.paso__lead { color: var(--text-muted); font-size: var(--fs-body); max-width: 52ch; }
.paso__campos { display: grid; gap: var(--sp-6); grid-template-columns: repeat(2, 1fr); margin-top: var(--sp-8); }
.campo { grid-column: 1 / -1; }
.campo--medio { grid-column: span 1; }
@media (max-width: 600px) { .campo--medio { grid-column: 1 / -1; } }
.campo--consiento { gap: var(--sp-2); }

.paso-acciones {
  display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center;
  margin-top: var(--sp-4); padding-top: var(--sp-6); border-top: 1px solid var(--border);
}
@media (max-width: 600px) {
  .paso-acciones { flex-direction: column-reverse; align-items: stretch; }
  .paso-acciones .btn--primario { margin-left: 0; }
}
.paso-acciones .btn--primario { margin-left: auto; }
.btn[hidden] { display: none; }
/* Estado de envío: el botón no cambia de texto —eso viviría en el JS— sino
   que suma un disco girando junto a la etiqueta. */
.btn[data-cargando="true"] { pointer-events: none; }
.btn[data-cargando="true"]::after {
  content: ""; width: var(--sp-4); height: var(--sp-4);
  border: 2px solid currentColor; border-top-color: transparent; border-radius: var(--r-pill);
  animation: girar var(--d-cine) linear infinite;
}
@keyframes girar { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) { .btn[data-cargando="true"]::after { animation: none; } }

.formulario[hidden] { display: none; }

.form-error:not([hidden]) {
  display: block;
  padding: var(--sp-3) var(--sp-4);
  border-left: 2px solid hsl(var(--vm-error)); border-radius: var(--r-sm);
  background: var(--surface-sunken); color: hsl(var(--vm-error));
  font-size: var(--fs-body-sm);
}

/* Campo trampa: para una persona no existe; un bot lo llena y se delata.
   Se colapsa a tamaño cero en vez de display:none, que muchos bots detectan. */
.trampa { position: absolute; width: 0; height: 0; overflow: hidden; }

@media (prefers-reduced-motion: no-preference) {
  .paso:not([hidden]) { animation: paso-entra var(--d-base) var(--ease-salida) both; }
}
@keyframes paso-entra { from { opacity: 0; transform: translateY(var(--sp-2)); } }

/* ---------- Campos nuevos del asistente ----------
   Opción única, opción múltiple y escala. Los tres son inputs nativos: el
   radio y la casilla siguen ahí, con su semántica y su navegación por teclado.
   Lo único que hace el CSS es vestirlos de tarjeta. */
.campo textarea {
  padding: var(--sp-3) var(--sp-4); width: 100%; resize: vertical;
  font-family: var(--font-body); font-size: var(--fs-body); color: var(--text);
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--r-sm);
  transition: border-color var(--d-rapido) var(--ease-estandar);
}
.campo textarea::placeholder { color: var(--text-subtle); }
.campo textarea:focus { border-color: var(--focus-ring); }
.campo__opcional { color: var(--text-subtle); font-weight: 400; }

/* min-width:0 para que un fieldset dentro de una grilla no se niegue a encoger. */
.grupo { min-width: 0; margin: 0; padding: 0; border: 0; }
.grupo__titulo { padding: 0; margin-bottom: var(--sp-2); font-size: var(--fs-body-sm); font-weight: 500; }
.grupo__ayuda { margin-bottom: var(--sp-3); font-size: var(--fs-caption); color: var(--text-subtle); }

.opciones { display: grid; gap: var(--sp-2); }
.opciones[data-columnas="2"] { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 600px) { .opciones[data-columnas="2"] { grid-template-columns: 1fr; } }

.opcion {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-3); align-items: center;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-body-sm);
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--d-rapido) var(--ease-estandar),
              background-color var(--d-rapido) var(--ease-estandar);
}
.opcion:hover { border-color: var(--border-strong); }
.opcion input { width: 20px; height: 20px; margin: 0; accent-color: var(--primary); }
/* Sin :has() la opción marcada se reconoce igual por el propio radio: la
   tarjeta resaltada es una mejora, no la única señal. */
.opcion:has(input:checked) { border-color: var(--primary); background: var(--surface); }
.opcion:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* La escala reparte sus pasos solo: no sabe si son cinco o siete. */
.escala { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--sp-2); }
.escala__paso {
  position: relative; display: grid; place-items: center; min-height: 48px;
  font-size: var(--fs-body); font-weight: 500;
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--d-rapido) var(--ease-estandar),
              background-color var(--d-rapido) var(--ease-estandar),
              color var(--d-rapido) var(--ease-estandar);
}
/* El radio se vuelve invisible pero sigue existiendo: enfocable, anunciable y
   navegable con flechas. Nada de reemplazarlo por un div. */
.escala__paso input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.escala__paso:hover { border-color: var(--border-strong); }
.escala__paso:has(input:checked) { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.escala__paso:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.escala__anclas {
  display: flex; justify-content: space-between; gap: var(--sp-4);
  margin-top: var(--sp-2); font-size: var(--fs-caption); color: var(--text-subtle);
}

/* ============================================================
   LA PÁGINA DE POSTULACIÓN
   ============================================================ */
.header--simple .header__interior { justify-content: space-between; }
/* El header flota sobre el escenario oscuro hasta que hay scroll: ahí su botón
   necesita el color de la noche, no el del tema claro en el que vive la página.
   Es el mismo caso que el header sobre la foto del hero en la landing. */
.header--simple:not(.es-solido) .btn--secundario {
  color: hsl(var(--vm-marfil-50)); border-color: hsl(var(--vm-marfil-50) / .38);
}
.header--simple:not(.es-solido) .btn--secundario:hover { border-color: hsl(var(--vm-marfil-50)); }

/* ---------- El escenario ----------
   Una sola pantalla con dos columnas: a la izquierda de qué se trata, a la
   derecha el asistente. No hay portada previa a propósito — el formulario es
   lo primero que se ve.
   El fondo oscuro es una capa decorativa y NO data-tema en la sección: así la
   tarjeta del asistente se queda en el tema claro (fondo blanco, texto tinta)
   y solo la columna de la izquierda, que sí lleva data-tema, sale en marfil. */
.escena {
  position: relative; isolation: isolate; z-index: 0;
  padding-block: calc(72px + var(--sp-12)) var(--section-md);
}
/* El recorte va acá y no en .escena: un overflow en la sección convertiría a
   la columna izquierda en un sticky que no pega. */
.escena__fondo {
  position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  background:
    radial-gradient(75% 60% at 12% 8%, hsl(var(--vm-nicoya-600) / .45) 0%, transparent 60%),
    radial-gradient(65% 55% at 92% 28%, hsl(var(--vm-cyan-500) / .3) 0%, transparent 60%),
    var(--grad-noche);
}
.escena__fondo .trama-puntos { opacity: .14; }
/* El borde de abajo no corta: se disuelve en el fondo de la sección siguiente. */
.escena__fondo::after {
  content: ""; position: absolute; inset: auto 0 0; height: var(--sp-24);
  background: linear-gradient(180deg, transparent 0%, var(--surface-sunken) 100%);
}

.escena__grid {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 5fr 7fr; gap: var(--sp-12); align-items: start;
}
/* En una sola columna el asistente sube: primero el titular, enseguida el
   formulario, y los datos del encuentro y los ponentes debajo. La columna
   izquierda se disuelve con display:contents para poder reordenar sus piezas
   sin duplicar una sola línea de HTML; el data-tema sigue heredándose. */
@media (max-width: 1024px) {
  .escena__grid { grid-template-columns: 1fr; gap: var(--sp-8); }
  .escena__intro { display: contents; }
  .escena__hero { order: 1; }
  .postulacion__caja { order: 2; }
  .escena__datos { order: 3; margin-top: 0; }
  .escena__prueba { order: 4; margin-top: 0; }
}
@media (max-width: 600px) {
  .escena__datos { grid-template-columns: 1fr; gap: var(--sp-4); }
}

/* La columna izquierda acompaña todo el recorrido del asistente: en el paso 3
   la fecha y la sede siguen a la vista. Se despega en una sola columna. */
@media (min-width: 1025px) { .escena__intro { position: sticky; top: calc(72px + var(--sp-8)); } }
.escena__intro .overline { color: hsl(var(--vm-lima-400)); }
.escena__intro h1 {
  font-size: var(--fs-h1); font-variation-settings: "opsz" 120;
  text-wrap: balance; margin-bottom: var(--sp-5);
}
.escena__intro .lead { color: var(--text-muted); margin-bottom: var(--sp-4); }
.escena__nota { font-size: var(--fs-body-sm); color: var(--text-subtle); }

.escena__datos {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5);
  margin: var(--sp-8) 0 0; padding-top: var(--sp-8); border-top: 1px solid var(--border);
}
.escena__datos dt {
  font-size: var(--fs-overline); font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text-subtle); margin-bottom: var(--sp-1);
}
.escena__datos dd { margin: 0; font-size: var(--fs-body-sm); font-weight: 500; }

.escena__prueba {
  display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap;
  margin-top: var(--sp-8); font-size: var(--fs-body-sm); color: var(--text-muted);
}
.escena__prueba-texto { display: grid; gap: var(--sp-1); }
.escena__prueba a { color: hsl(var(--vm-cyan-400)); }
/* Las caras se solapan como una pila de fichas: ocupan poco y dicen mucho. */
.avatares { display: flex; }
.avatares__foto {
  display: grid; place-items: center; overflow: hidden; flex: 0 0 auto;
  width: 40px; height: 40px; margin-left: calc(var(--sp-3) * -1);
  background: var(--surface-brand); border: 2px solid var(--bg); border-radius: var(--r-pill);
  font-size: var(--fs-caption); font-weight: 600; color: var(--text-muted);
}
.avatares__foto:first-child { margin-left: 0; }
.avatares__foto img { width: 100%; height: 100%; object-fit: cover; }

/* La tarjeta del asistente: lo más claro y lo más elevado de la pantalla.
   Es el único objeto de la página que puede permitirse la sombra grande. */
.postulacion__caja {
  padding: var(--sp-10);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-2xl); box-shadow: var(--e4);
}
@media (max-width: 600px) {
  .postulacion__caja { padding: var(--sp-6) var(--sp-5); border-radius: var(--r-xl); }
}

/* ---------- Qué vas a vivir: cuatro claves ---------- */
.claves {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--sp-5); list-style: none; padding: 0; margin: 0;
}
.clave {
  padding: var(--sp-6);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
}
.clave__titulo {
  font-family: var(--font-display); font-size: var(--fs-h3);
  margin: 0 0 var(--sp-2); text-wrap: balance;
}
.clave__texto { margin: 0; font-size: var(--fs-body-sm); color: var(--text-muted); }

.tira-speakers {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--sp-8) var(--sp-6); list-style: none; padding: 0;
}
.tira-speakers__foto {
  display: grid; place-items: center; overflow: hidden;
  width: 72px; height: 72px; margin-bottom: var(--sp-3);
  background: var(--surface-brand); border-radius: var(--r-pill);
  font-weight: 600; color: var(--text-muted);
}
.tira-speakers__foto img { width: 100%; height: 100%; object-fit: cover; }
.tira-speakers__nombre { font-size: var(--fs-body-sm); font-weight: 600; }
.tira-speakers__rol { font-size: var(--fs-caption); color: var(--text-muted); }

/* ---------- Lo que conviene saber: preguntas + sede ----------
   Todo lo que va debajo del asistente es material de apoyo, y se lee como
   tal: dos columnas en vez de dos pantallas de scroll. */
.detalles { display: grid; grid-template-columns: 7fr 5fr; gap: var(--sp-12); align-items: start; }
@media (max-width: 900px) { .detalles { grid-template-columns: 1fr; gap: var(--sp-10); } }

.sede-tarjeta {
  padding: var(--sp-8);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-xl);
}
@media (min-width: 901px) { .sede-tarjeta { position: sticky; top: calc(72px + var(--sp-6)); } }
.sede-tarjeta .overline { color: var(--accent-text); }
.sede-tarjeta__titulo { font-size: var(--fs-h3); margin: var(--sp-2) 0 var(--sp-5); }
/* Dentro de la tarjeta el bloque de la sede ya no puede ser blanco sobre blanco. */
.sede-tarjeta .ubicacion__sede { background: var(--surface-sunken); margin-bottom: var(--sp-6); }
.sede-tarjeta .llegar { margin-bottom: 0; }

/* Las preguntas se abren con <details>: cero JavaScript, y el buscador del
   navegador las abre solo cuando encuentra texto adentro. */
.faq { display: grid; gap: var(--sp-2); }
.faq__item { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); }
.faq__item summary {
  display: flex; justify-content: space-between; align-items: center; gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5); font-weight: 500; cursor: pointer; list-style: none;
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after { content: "+"; color: var(--accent-text); font-size: var(--fs-h3); line-height: 1; }
.faq__item[open] summary::after { content: "–"; }
.faq__item p { padding: 0 var(--sp-5) var(--sp-5); max-width: 66ch; color: var(--text-muted); }

.exito {
  display: none; text-align: center; padding: var(--sp-12) var(--sp-6);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--e2);
}
.exito[data-visible="true"] { display: block; }
.exito__check { width: 56px; height: 56px; border-radius: 50%; background: hsl(var(--vm-nicoya-600)); color: var(--text-on-brand); display: grid; place-items: center; margin: 0 auto var(--sp-5); }
.exito h3 { font-family: var(--font-display); font-size: var(--fs-h2); margin-bottom: var(--sp-3); }
.exito p { color: var(--text-muted); max-width: 40ch; margin-inline: auto; }

/* ============================================================
   CIERRE + FOOTER
   ============================================================ */
.cierre { text-align: center; }
.cierre h2 { font-size: var(--fs-h1); font-variation-settings: "opsz" 130; text-wrap: balance; max-width: 20ch; margin: 0 auto var(--sp-8); }
.cierre__nota { font-size: var(--fs-caption); color: var(--text-subtle); margin-top: var(--sp-5); }

.footer { background: hsl(var(--vm-noche-900)); padding-block: var(--section-md) var(--sp-8); }
.footer__grid { display: grid; gap: var(--sp-10); grid-template-columns: 2fr 1fr 1.4fr 1.2fr; }
/* En tableta y teléfono la marca sube sola y centrada, y las tres columnas
   quedan debajo en columnas de verdad: en una sola fila el pie se volvía una
   lista larguísima. En el teléfono Contacto va bajo El evento, que es corta,
   para que Navegación —la más larga— no deje un hueco al lado. */
@media (max-width: 900px) {
  .footer__grid {
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas: "identidad identidad identidad" "navegacion encuentro contacto";
  }
  .footer__identidad {
    grid-area: identidad; display: grid; justify-items: center; text-align: center;
    padding-bottom: var(--sp-8); border-bottom: 1px solid var(--border);
  }
  .footer__navegacion { grid-area: navegacion; }
  .footer__encuentro { grid-area: encuentro; }
  .footer__contacto { grid-area: contacto; }
}
@media (max-width: 600px) {
  .footer__grid {
    gap: var(--sp-8) var(--sp-6);
    grid-template-columns: 1fr 1fr;
    grid-template-areas: "identidad identidad" "navegacion encuentro" "navegacion contacto";
  }
  .footer__contacto a { overflow-wrap: anywhere; }
}
.footer h4 { font-size: var(--fs-overline); font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--text-subtle); margin: 0 0 var(--sp-4); }
.footer ul { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-3); }
.footer a { color: var(--text-muted); text-decoration: none; font-size: var(--fs-body-sm); transition: color var(--d-rapido) var(--ease-estandar); }
.footer a:hover { color: var(--text); }
.footer li time { display: block; font-size: var(--fs-caption); color: var(--text-subtle); font-variant-numeric: tabular-nums; }
/* Columna "El evento" del pie: etiqueta chica + dato. */
.footer__evento li { display: grid; gap: var(--sp-1); }
.footer__evento li > span:first-child { font-size: var(--fs-caption); letter-spacing: .1em; text-transform: uppercase; color: var(--text-subtle); }
.footer__dato { font-size: var(--fs-body-sm); color: var(--text-muted); }
.footer__marca { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.logo--pie { height: var(--sp-10); }
.footer__frase { font-size: var(--fs-body-sm); color: var(--text-muted); max-width: 26ch; }
.footer__barra {
  margin-top: var(--section-sm); padding-top: var(--sp-6); border-top: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: var(--sp-6); justify-content: space-between;
  font-size: var(--fs-caption); color: var(--text-subtle);
}
.footer__credito { margin-top: var(--sp-3); font-size: var(--fs-caption); color: var(--text-subtle); }
.footer__credito a { font-size: inherit; color: inherit; }
@media (max-width: 600px) { .footer__barra { justify-content: center; text-align: center; gap: var(--sp-3); }
  .footer__credito { text-align: center; } }

/* ============================================================
   ENTRADA AL VIEWPORT
   ============================================================ */
/* ============================================================
   MOVIMIENTO DE SCROLL
   Las reglas de acá leen dos números que escribe site.js y nada más:

     --avance   por escena (0→1). Lo pone el elemento con data-escena.
     --leido    en :root (0→1): cuánto de la página se recorrió.

   Cada regla trae su propio valor por defecto en var(), y ese valor por
   defecto es SIEMPRE el estado legible. Por eso sin JavaScript y con
   prefers-reduced-motion —donde no se registra ninguna escena— la página se
   ve entera y quieta, sin una sola regla extra que la rescate.

   Todo va en transform y opacity. Nada de filter, top, height ni
   background-position animados: son las propiedades que sacan el trabajo del
   compositor y vuelven barato un efecto caro.
   ============================================================ */

/* ---------- Aurora: la capa que cose la página ----------
   Fija detrás de todo y más lenta que el contenido. Solo se asoma por las
   secciones que no traen fondo propio (#que-es, #inscripcion) y por los
   bordes; las hundidas y las oscuras la tapan. Ese asomarse y desaparecer es
   justo lo que hace que la página se lea como una sola pieza. */
.aurora {
  position: fixed; inset: -25% 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(45% 30% at 15% 10%, hsl(var(--vm-cyan-500) / .14) 0%, transparent 70%),
    radial-gradient(42% 26% at 88% 34%, hsl(var(--vm-lima-500) / .11) 0%, transparent 70%),
    radial-gradient(50% 32% at 28% 66%, hsl(var(--vm-arena-500) / .16) 0%, transparent 70%),
    radial-gradient(40% 26% at 80% 90%, hsl(var(--vm-nicoya-500) / .12) 0%, transparent 70%);
  transform: translate3d(0, calc(var(--leido, 0) * -16vh), 0);
}

/* ---------- Barra de avance de lectura ----------
   Aparece recién cuando el header se vuelve sólido: sobre el hero sería una
   línea suelta sin explicación. */
.header::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: linear-gradient(90deg, hsl(var(--vm-lima-600)), hsl(var(--vm-cyan-500)));
  transform: scaleX(var(--leido, 0)); transform-origin: left;
  opacity: 0; transition: opacity var(--d-base) var(--ease-estandar);
}
.header.es-solido::after { opacity: 1; }

/* ---------- Hero: cuatro capas a cuatro velocidades ----------
   El opener: la foto escala y baja, la trama de puntos sube al doble, el
   titular sube más rápido todavía y se desvanece, y un velo de noche cierra
   la escena justo cuando entra el programa.

   La entrada de la foto se mudó de transform a la propiedad `scale` a
   propósito: una animación con fill:both se queda dueña de la propiedad para
   siempre, así que si el zoom de entrada siguiera en transform, el parallax
   no podría tocarlo nunca. Separadas, las dos cosas conviven. */
.hero__img { transform: translate3d(0, calc(var(--avance, 0) * 7%), 0) scale(calc(1 + var(--avance, 0) * .12)); }
.hero .trama-puntos { transform: translate3d(0, calc(var(--avance, 0) * -5rem), 0); }
.hero__grano { transform: translate3d(0, calc(var(--avance, 0) * -2rem), 0); }
.hero__contenido {
  transform: translate3d(0, calc(var(--avance, 0) * -7rem), 0);
  opacity: clamp(0, calc(1.5 - var(--avance, 0) * 1.6), 1);
}
.hero::after {                       /* el hero se hunde en la noche */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: hsl(var(--vm-noche-900));
  opacity: calc(var(--avance, 0) * .8);
}

/* ---------- «Qué es»: el párrafo se revela renglón por renglón ----------
   Sin partir el texto en <span>: un degradado vertical recortado al glifo
   avanza con el scroll, así que el revelado sigue el orden de lectura y no
   cuesta un solo nodo ni una clase por palabra. El texto sin revelar queda en
   --text-muted, que ya pasa AA: si alguien se detiene a media pantalla, lo
   que falta se lee igual. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .que-es__parrafo {
    background-image: linear-gradient(180deg,
      var(--text) 0%,
      var(--text) calc(var(--avance, 1) * 250% - 60%),
      var(--text-muted) calc(var(--avance, 1) * 250% - 42%));
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
  }
  /* En papel no hay scroll que revele nada. */
  @media print {
    .que-es__parrafo { background-image: none; color: var(--text-muted); }
  }
}

/* ---------- Zona Azul: sección anclada ----------
   #zona-azul mide una pantalla más que su contenido y .zona-pin__marco se
   queda pegado adentro. Mientras dura el anclado, el dato entra, la foto se
   acerca y las cuatro claves aparecen una por una.

   El recorrido va en padding-bottom y no en height: así el marco puede crecer
   con su contenido sin que nada quede cortado. Y va en svh, no en vh, porque
   en el teléfono vh mide con la barra de direcciones retraída y la sección
   daría un salto cada vez que aparece. */
/* El recorrido del anclado va en min-height y NO en padding-bottom: el
   rectángulo dentro del que un sticky puede viajar es el CONTENT BOX del padre,
   y el padding queda afuera. Con padding-bottom el marco se quedaba sin un solo
   píxel por donde desplazarse y la sección no se anclaba nunca.
   svh y no vh: en el teléfono vh mide con la barra de direcciones retraída y la
   sección daría un salto cada vez que aparece. */
.zona-pin { padding-block: 0; min-height: 210svh; }
.zona-pin__marco {
  position: sticky; top: 0; min-height: 100svh;
  display: flex; align-items: center;
  /* Aire justo: el marco no puede pasarse de una pantalla o lo de abajo
     queda inalcanzable mientras dura el anclado. */
  padding-block: var(--sp-10);
}
.zona-pin .zona-azul__imagen {
  transform: scale(calc(1.04 + var(--avance, 0) * .1));
}
.zona-pin .zona-azul__dato {
  --vis: clamp(0, calc((var(--avance, 1) - .08) * 8), 1);
  opacity: var(--vis);
  transform: translateY(calc((1 - var(--vis)) * var(--sp-6))) scale(calc(.94 + var(--vis) * .06));
}
/* Las cuatro claves de longevidad, una por una. El umbral de cada una es
   dónde en el anclado le toca aparecer. */
.zona-pin .zona-azul__lista li {
  --vis: clamp(0, calc((var(--avance, 1) - var(--umbral, 0)) * 7), 1);
  opacity: var(--vis);
  transform: translateY(calc((1 - var(--vis)) * var(--sp-5)));
}
.zona-pin .zona-azul__lista li:nth-child(1) { --umbral: .16; }
.zona-pin .zona-azul__lista li:nth-child(2) { --umbral: .28; }
.zona-pin .zona-azul__lista li:nth-child(3) { --umbral: .40; }
.zona-pin .zona-azul__lista li:nth-child(4) { --umbral: .52; }

/* En el teléfono el contenido tiene que entrar entero en una pantalla: si el
   marco anclado fuera más alto que la ventana, lo de abajo quedaría
   inalcanzable mientras dura el anclado. Por eso acá la foto es una banda y
   el aire se aprieta. El recorrido también se acorta: en una pantalla chica,
   una pantalla y media de anclado ya se siente largo. */
@media (max-width: 900px) {
  .zona-pin { min-height: 175svh; }
  .zona-pin__marco { padding-block: var(--sp-8); }
  .zona-pin .zona-azul { gap: var(--sp-5); }
  .zona-pin .zona-azul__media { min-height: 11rem; }
  .zona-pin .zona-azul__texto { padding: 0; }
  .zona-pin .zona-azul__texto h2 { margin-bottom: var(--sp-3); }
  .zona-pin .zona-azul__texto .lead { margin-bottom: var(--sp-4); }
  .zona-pin .zona-azul__lista { gap: var(--sp-3); margin-bottom: var(--sp-5); }
  .zona-pin .zona-azul__dato { left: var(--sp-4); bottom: var(--sp-4); padding: var(--sp-3) var(--sp-4); max-width: 13rem; }
}

/* Red de seguridad. El anclado solo es aceptable si el contenido entra
   completo en la ventana: si no, el botón de inscripción quedaría inalcanzable
   mientras dura. Dos casos donde no entra y por eso no se ancla:
     · portátiles bajos (1280×720, 1366×768) — la columna de texto se angosta,
       envuelve más y crece de alto;
     · cualquier ventana muy baja, típicamente un teléfono chico.
   En los dos la sección se lee de corrido y todo aparece revelado. */
@media (min-width: 901px) and (max-height: 800px), (max-height: 680px) {
  .zona-pin { min-height: 0; padding-block: var(--section-md); }
  .zona-pin__marco { position: static; min-height: 0; padding-block: 0; }
  .zona-pin .zona-azul__lista li,
  .zona-pin .zona-azul__dato { opacity: 1; transform: none; }
}

/* ---------- Speakers: profundidad dentro del marco ----------
   La foto se mueve más lento que su círculo. Con iniciales el efecto es
   mínimo —se mueven las letras— y con foto real es el que da la sensación de
   ventana. Está escrito para las dos y no hay que tocarlo cuando lleguen. */
#speakers .keynote__foto img,
#speakers .honor__foto img,
#speakers .speaker-fila__foto img,
#speakers .keynote__foto span,
#speakers .honor__foto span,
#speakers .speaker-fila__foto span {
  transform: translateY(calc((var(--avance, .5) - .5) * -1.5rem));
}
#speakers .keynote__foto img,
#speakers .honor__foto img,
#speakers .speaker-fila__foto img { scale: 1.14; }

/* Retratos con poco aire sobre la cabeza: ampliar desde arriba baja la foto
   dentro del círculo. El encuadre queda quieto para que el scroll no vuelva
   a recortar la frente; el tamaño y el borde del avatar se conservan. */
#speakers .speaker-fila__foto img[data-encuadre="superior"] {
  transform-origin: center top;
  transform: none;
}

/* ---------- Ubicación: el mapa se acerca ----------
   Los degradados se mudaron a ::before para poder moverlos con transform en
   vez de animar background-position, que repinta en cada cuadro. */
.ubicacion__media { background: hsl(var(--vm-noche-800)); }
.ubicacion__media::before {
  content: ""; position: absolute; inset: -10%; pointer-events: none;
  background:
    radial-gradient(90% 70% at 30% 25%, hsl(var(--vm-nicoya-500) / .5) 0%, transparent 60%),
    radial-gradient(80% 70% at 75% 85%, hsl(var(--vm-cyan-500) / .32) 0%, transparent 60%);
  transform: translate3d(0, calc((var(--avance, .5) - .5) * -3rem), 0) scale(calc(1 + var(--avance, 0) * .08));
}
.ubicacion__imagen { transform: scale(calc(1.04 + var(--avance, 0) * .08)); }
.ubicacion__pin {
  --vis: clamp(0, calc((var(--avance, 1) - .3) * 6), 1);
  opacity: var(--vis);
  transform: scale(calc(.82 + var(--vis) * .18));
}

/* ---------- Cierre: la sección se abre desde el centro ---------- */
.cierre { position: relative; overflow: hidden; }
.cierre::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(58% 55% at 50% 45%, hsl(var(--vm-cyan-500) / .3) 0%, transparent 70%);
  opacity: clamp(0, calc(var(--avance, 1) * 2.4 - .35), 1);
  transform: scale(calc(.5 + clamp(0, calc(var(--avance, 1) * 2.4 - .35), 1) * .5));
}
.cierre .contenedor { position: relative; z-index: 1; }

/* ---------- Cifras que cuentan ---------- */
.cifra { font-weight: 600; color: var(--accent-text); font-variant-numeric: tabular-nums; }

/* Con movimiento reducido no se registra ninguna escena, así que todo lo de
   arriba cae a su estado legible solo. Lo único que hay que apagar a mano es
   lo que solo existe para el movimiento. */
@media (prefers-reduced-motion: reduce) {
  .header::after { display: none; }
  /* La cinta se detiene y cae a una fila que envuelve: los aliados se ven de
     una sola vez, sin que haya que esperar a que pasen. */
  /* Las dos marquesinas sangran a los bordes de la pantalla y se apoyan en la
     máscara para no cortar nada contra el filo. Sin máscara y sin movimiento,
     el aire lo tiene que poner el padding. */
  /* Sin movimiento la cinta se lee como una grilla, y una grilla que arranca en
     el filo de la pantalla no se alinea con el titular que tiene encima. El
     padding la devuelve al carril de su contenedor —75rem en aliados, 88rem en
     el hero— y nunca baja del margen mínimo de pantalla. */
  .marquesina {
    overflow: visible;
    padding-inline: max(var(--gutter), calc(50% - var(--carril, var(--container)) / 2 + var(--gutter)));
    -webkit-mask-image: none; mask-image: none;
  }
  .hero__patrocinios .marquesina { --carril: var(--container-ancho); }
  .marquesina__pista { animation: none; width: 100%; flex-wrap: wrap; }
  .marquesina__cinta[aria-hidden="true"] { display: none; }
  /* flex: 1 1 100% es lo que hace que la cinta ocupe el ancho de la pista y sus
     hijos envuelvan de verdad: con el flex: 0 0 auto del desfile la cinta se
     quedaba en su ancho máximo y las últimas tarjetas se iban de pantalla. */
  .marquesina__cinta { flex: 1 1 100%; flex-wrap: wrap; justify-content: center; gap: var(--sp-8) var(--sp-16); }
  .aurora { transform: none; }
  /* El anclado también es movimiento: sin él la sección se lee de corrido. */
  .zona-pin { min-height: 0; padding-block: var(--section-md); }
  .zona-pin__marco { position: static; min-height: 0; padding-block: 0; }
}

/* Las entradas al viewport solo se esconden si hay JS que las pueda revelar:
   la bandera data-js la pone un script inline del <head>. Sin JS el contenido
   se ve tal cual, que es el contrato del sitio. */
[data-js="si"] .entra { opacity: 0; transform: translateY(24px); transition: opacity var(--d-lento) var(--ease-salida), transform var(--d-lento) var(--ease-salida); }
.entra.visible { opacity: 1; transform: none; }
/* Los bloques de la agenda entran con una inclinación mínima además del
   desplazamiento: la tarjeta llega desde atrás en vez de resbalar, que es la
   diferencia entre una lista y una sección que uno mira. */
[data-js="si"] .agenda__bloque.entra { transform: perspective(60rem) rotateX(6deg) translateY(28px); }
[data-js="si"] .agenda__bloque.entra.visible { transform: none; }
@media (prefers-reduced-motion: reduce) { [data-js="si"] .entra { opacity: 1; transform: none; } }

/* ---------- Móvil: limitar superficies y trabajo gráfico ----------
   La agenda puede medir miles de píxeles: mover su fondo como una textura
   completa, junto a las cintas y desenfoques, presiona la memoria de Safari.
   En pantallas pequeñas o táctiles se conserva la lectura y la navegación,
   sin parallax ni anclados decorativos. Coincide con mobileMotion en site.js. */
@media (max-width: 1024px), (pointer: coarse) {
  .aurora, .hero__grano, .hero::after, .agenda-cuerpo::before { display: none; }
  .hero__img { animation: none; transform: none; }
  .adn-vida__trazo { animation: none; stroke-dashoffset: 0; }
  .adn-vida__travesano, .adn-vida__mas { animation: none; transform: none; opacity: 1; }
  .hero .trama-puntos, .hero__contenido { transform: none; }
  .hero__contenido { opacity: 1; }
  .dia-portada__capa, .dia-portada__texto { transform: none; will-change: auto; }
  .agenda-cuerpo::before { transform: none; will-change: auto; }
  .agenda-riel__hora.es-nueva, .agenda__bloque.es-activo::before { animation: none; }
  .agenda__bloque.es-activo .bloque { transform: none; }
  .header.es-solido, .agenda-riel, .ubicacion__pin, .zona-azul__dato {
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .header.es-solido { background: var(--bg); }
  .marquesina { mask-image: none; -webkit-mask-image: none; }
  .aliados-banda__aurora, .ubicacion__media::before, .ubicacion__imagen, .cierre::before { transform: none; }
  .que-es__parrafo { background-image: none; color: var(--text); }
  .zona-pin { min-height: calc(var(--sp-1) * 0); padding-block: var(--section-md); }
  .zona-pin__marco { position: static; min-height: calc(var(--sp-1) * 0); padding-block: calc(var(--sp-1) * 0); }
  .zona-pin .zona-azul__imagen, .zona-pin .zona-azul__dato,
  .zona-pin .zona-azul__lista li { transform: none; opacity: 1; }
  #speakers .keynote__foto img, #speakers .honor__foto img, #speakers .speaker-fila__foto img,
  #speakers .keynote__foto span, #speakers .honor__foto span, #speakers .speaker-fila__foto span { transform: none; }
  [data-js="si"] .agenda__bloque.entra { transform: none; }
}

/* ---------- Ubicación: las formas de llegar entran una por una ----------
   La lista entera es un .entra; al volverse .visible cada tarjeta llega con su
   retraso. La entrada va en `translate` y la elevación del hover en
   `transform`: así el hover no hereda el retraso de la entrada. Sin JS o con
   movimiento reducido las tarjetas están quietas y a la vista. */
@media (prefers-reduced-motion: no-preference) {
  [data-js="si"] .llegar--tarjetas .llegar__ruta {
    opacity: 0; translate: 0 var(--sp-6);
    transition: opacity var(--d-cine) var(--ease-salida) var(--retraso, calc(var(--d-instant) * 0)),
                translate var(--d-cine) var(--ease-salida) var(--retraso, calc(var(--d-instant) * 0)),
                transform var(--d-base) var(--ease-salida), box-shadow var(--d-base) var(--ease-salida), border-color var(--d-base) var(--ease-salida);
  }
  [data-js="si"] .llegar--tarjetas .llegar__ruta:nth-child(2) { --retraso: var(--d-rapido); }
  [data-js="si"] .llegar--tarjetas .llegar__ruta:nth-child(3) { --retraso: calc(var(--d-rapido) * 2); }
  [data-js="si"] .llegar--tarjetas .llegar__ruta:nth-child(4) { --retraso: calc(var(--d-rapido) * 3); }
  [data-js="si"] .llegar--tarjetas.visible .llegar__ruta { opacity: 1; translate: none; }
}
@media (prefers-reduced-motion: reduce) {
  .llegar--tarjetas .llegar__ruta:hover, .llegar--tarjetas .llegar__ruta:active { transform: none; }
}

/* ---------- Móvil: Zona Azul sin anclado, pero no quieta ----------
   En el teléfono no hay anclado ni --avance (ver el bloque de arriba), así que
   la escena se cuenta de otra forma: cuando la sección entra en pantalla, la
   foto se acerca, aparece el dato y las cuatro claves llegan una por una. Lo
   dispara la misma clase .visible de las entradas —nada nuevo escuchando el
   scroll— y pasa una sola vez. Es una capa chica, sin sticky ni parallax.
   Sin JS o con movimiento reducido no aplica y todo se ve de una. */
@media (max-width: 1024px) and (prefers-reduced-motion: no-preference),
       (pointer: coarse) and (prefers-reduced-motion: no-preference) {
  [data-js="si"] .zona-pin .zona-azul__imagen {
    transform: scale(1.14);
    transition: transform calc(var(--d-cine) * 3) var(--ease-salida);
  }
  [data-js="si"] .zona-pin .zona-azul__dato,
  [data-js="si"] .zona-pin .zona-azul__lista li {
    opacity: 0; transform: translateY(var(--sp-5));
    transition: opacity var(--d-cine) var(--ease-salida), transform var(--d-cine) var(--ease-salida);
  }
  [data-js="si"] .zona-pin .zona-azul__dato { transition-delay: var(--d-cine); }
  [data-js="si"] .zona-pin .zona-azul__lista li:nth-child(1) { transition-delay: var(--d-lento); }
  [data-js="si"] .zona-pin .zona-azul__lista li:nth-child(2) { transition-delay: calc(var(--d-lento) * 2); }
  [data-js="si"] .zona-pin .zona-azul__lista li:nth-child(3) { transition-delay: calc(var(--d-lento) * 3); }
  [data-js="si"] .zona-pin .zona-azul__lista li:nth-child(4) { transition-delay: calc(var(--d-lento) * 4); }
  [data-js="si"] .zona-pin .zona-azul__media.visible .zona-azul__imagen { transform: scale(1.04); }
  [data-js="si"] .zona-pin .zona-azul__media.visible .zona-azul__dato,
  [data-js="si"] .zona-pin .zona-azul__texto.visible .zona-azul__lista li { opacity: 1; transform: none; }
}
