/* =====================================================================
   PROCESO — el mapa
   ---------------------------------------------------------------------
   Cinco paradas unidas por un camino que serpentea de lado a lado de la
   página. El camino se dibuja mientras se scrollea, un marcador lo
   recorre, y cada parada reacciona cuando el marcador la alcanza.

   POR QUÉ ES UN CAMINO Y NO UNA LISTA
   La pregunta que contesta la sección es "si te llamo, ¿qué pasa?".
   Un recorrido dibujado responde eso antes de leer una palabra: se ve
   dónde empieza, cuántas paradas hay y dónde termina. La forma ES la
   respuesta, no una decoración encima de la respuesta.

   EL CAMINO NO ESTÁ ESCRITO A MANO
   Un path con coordenadas fijas se rompe en cuanto cambia el ancho, el
   tamaño de letra o se abre un panel. Acá js/v2.js lee la posición real
   de cada nodo en el DOM y arma la curva pasando por esos puntos
   (Catmull-Rom → Bézier). Cambia el viewport, se abre una parada, entra
   una fuente distinta: el camino se rearma solo y siempre pasa por
   donde están los nodos de verdad.

   APPLE-DESIGN, APLICADO
   §1  El dibujo del camino y el marcador siguen al scroll 1:1, sin
       resorte. Lo que se arrastra responde en el cuadro; un resorte acá
       sería lag disfrazado de suavidad.
   §3  --p es posición normalizada. Volver para atrás deshace el camino
       exactamente por donde vino, sin estado que rebobinar.
   §4  Dos movimientos, dos físicas distintas, a propósito:
       · el recorrido, crítico y sin rebote (lo maneja el scroll);
       · el golpe del nodo al ser alcanzado, CON rebote — ahí sí hay
         impulso: algo llegó y lo tocó.
   §7  Cada tarjeta entra desde el lado donde está su nodo. Sale por el
       mismo lado. Nada aparece desde un costado arbitrario.
   §8  El marcador se orienta a la tangente del camino: apunta a dónde
       sigue, no a dónde está.
   §11 Sólo transform y opacity en el camino del scroll. El trazo usa
       stroke-dashoffset sobre pathLength=1, que es una sola propiedad
       sobre un solo path.
   §14 Con movimiento reducido el mapa se muestra dibujado y quieto: la
       información (el recorrido completo) queda, lo que se cae es el
       viaje. Sin JS los paneles quedan abiertos y todo se lee.
   §16 Nada es un redondeo cómodo. La línea de lectura está en el 58%
       del alto de ventana porque es donde cae la vista.
   ===================================================================== */

/* =====================================================================
   CABECERA
   ===================================================================== */
/* La cabecera es .sec__head (css/v2.css). Acá sólo el aire extra que
   pide el mapa: el camino necesita respirar antes de arrancar. */
.mapa .sec__head{margin-bottom:clamp(56px, 7vw, 104px)}

/* La nota va centrada como todo lo demás, y la hairline que la separaba
   del bloque de arriba ahora es un filo corto y centrado: un borde de
   ancho completo sobre texto centrado lee como corte de sección. */
.mapa__note{
  display:flex;align-items:flex-start;gap:var(--space-3);
  margin:0;padding-top:var(--space-5);
  justify-content:center;max-width:52ch;text-align:center;
  font-size:var(--text-xs);line-height:var(--lh-body);
  color:var(--paper-dim);text-wrap:pretty;
}
.mapa__note .ico{--ico-size:17px;color:var(--cyan-400);margin-top:2px;flex:none}

/* =====================================================================
   EL ESCENARIO — camino, marcador y paradas comparten sistema de
   coordenadas. Todo lo absoluto de acá abajo se mide contra esta caja,
   que es además la que js/v2.js mide para calcular --p.
   ===================================================================== */
.mapa__stage{
  position:relative;
  --nodo:72px;                       /* diámetro de una parada */
  /* Aire entre el nodo y su tarjeta. NO es sólo respiro visual: es el
     corredor por el que baja el camino al salir del nodo, antes de
     poder cruzar. Angostarlo hace que la curva roce la tarjeta de su
     propia parada — medido a 1000px con 26px de carril. */
  --carril:clamp(36px, 5vw, 72px);
  --caja:clamp(260px, 46%, 560px);   /* ancho de la tarjeta */
}

.mapa__svg{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;
  overflow:visible;pointer-events:none;
}
.mapa__road{
  fill:none;stroke-linecap:round;stroke-linejoin:round;
  stroke:rgba(255,255,255,.11);
  stroke-width:2;
}
/* El trazo recorrido. pathLength=1 en el marcado normaliza el largo,
   así que el avance es literalmente --p y no hace falta que el JS
   escriba un dashoffset en píxeles cuadro a cuadro. */
.mapa__road--done{
  stroke:var(--cyan-400);
  stroke-width:2.5;
  stroke-dasharray:1;
  stroke-dashoffset:calc(1 - var(--p, 0));
}
/* Halo del trazo recorrido: separa el camino del suelo sin encender la
   sección entera. Es la misma geometría, más gruesa y casi apagada. */
.mapa__road--glow{
  stroke:rgba(12,192,223,.20);
  stroke-width:9;
  stroke-dasharray:1;
  stroke-dashoffset:calc(1 - var(--p, 0));
  filter:blur(5px);
}

/* --- El marcador que recorre el camino --- */
/* js/v2.js le escribe --mx/--my (punto sobre la curva) y --ang (tangente).
   La rotación va en una capa aparte para poder estirar el cuerpo a lo
   largo del avance sin deformar el halo. */
.mapa__marker{
  position:absolute;left:0;top:0;z-index:2;
  width:18px;height:18px;margin:-9px 0 0 -9px;
  pointer-events:none;
  transform:translate3d(var(--mx, 0px), var(--my, 0px), 0);
  opacity:calc(var(--p, 0) * 14);
  will-change:transform;
}
.mapa__marker::before,
.mapa__marker::after{content:"";position:absolute;inset:0;border-radius:var(--radius-pill)}
/* Halo */
.mapa__marker::before{
  inset:-9px;
  background:radial-gradient(circle, rgba(12,192,223,.55) 0%, rgba(12,192,223,0) 70%);
}
/* Cuerpo: se estira sobre la tangente. Un punto muy rápido leído como
   círculo perfecto estroboscopia; estirado sobre su propia dirección
   se lee como velocidad (§11). --vel lo escribe el motor. */
.mapa__marker::after{
  inset:4px;
  background:var(--cyan-200);
  box-shadow:0 0 12px rgba(79,214,236,.9);
  transform:rotate(var(--ang, 0deg)) scaleX(calc(1 + var(--vel, 0) * 1.6));
}

/* =====================================================================
   LAS PARADAS
   Zigzag: impar a la izquierda, par a la derecha. El nodo va siempre
   del lado de adentro, así el camino cruza de un costado al otro y la
   página entera participa del recorrido.
   ===================================================================== */
/* El aire vertical NO es decorativo: es lo que le da lugar al camino
   para cruzar de un borde al otro sin pasar por encima de las tarjetas.
   Con poco gap la diagonal entre dos nodos opuestos corta la caja de la
   parada anterior. Medido: hace falta que la distancia vertical entre
   nodos supere el alto de una tarjeta, y por eso el gap es grande. */
.mapa__list{
  position:relative;z-index:1;
  list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;
  gap:clamp(88px, 11vw, 184px);
}

/* EL NODO VA AL BORDE DE AFUERA, la tarjeta hacia adentro. Es lo que
   hace que esto sea un mapa y no una ondulación: con el nodo del lado
   interno, las paradas alternadas empujan los nodos al centro y el
   camino apenas se mueve. Primera versión medida: 144px de vaivén
   sobre 1085 de ancho. Con el nodo afuera, el camino cruza la página
   entera. */
.parada{
  display:grid;
  grid-template-columns:var(--nodo) minmax(0, var(--caja));
  gap:var(--carril);
  align-items:center;
  justify-content:start;
}
/* Las pares se espejan. Se reordena con grid-column y no con
   row-reverse ni direction para no romper el orden de lectura: en el
   DOM el nodo va siempre antes que su tarjeta. */
.parada:nth-child(even){
  grid-template-columns:minmax(0, var(--caja)) var(--nodo);
  justify-content:end;
}
.parada:nth-child(odd)  .parada__nodo{grid-column:1;grid-row:1}
.parada:nth-child(odd)  .parada__caja{grid-column:2;grid-row:1}
.parada:nth-child(even) .parada__nodo{grid-column:2;grid-row:1}
.parada:nth-child(even) .parada__caja{grid-column:1;grid-row:1}

/* Cada tarjeta entra desde el lado donde está su nodo (§7): las impares
   desde la izquierda, las pares desde la derecha. */
.parada:nth-child(odd)  .parada__caja{--travel-x:-28px}
.parada:nth-child(even) .parada__caja{--travel-x:28px}

/* --- El nodo --- */
.parada__nodo{
  position:relative;isolation:isolate;
  display:grid;place-items:center;
  width:var(--nodo);height:var(--nodo);
  border-radius:var(--radius-pill);
  /* OPACO SIEMPRE. El camino pasa por detrás del nodo: cualquier fondo
     translúcido acá deja ver el trazo cruzando la cifra. El tinte del
     estado alcanzado vive en ::before, debajo del número. */
  background:var(--ground-base);
  border:1px solid rgba(255,255,255,.16);
  font-family:var(--font-subhead);
  font-size:var(--text-sm);font-weight:var(--fw-semibold);
  letter-spacing:var(--ls-ui);
  color:var(--paper-mute);
  transition:
    color var(--dur-base) var(--ease-out-soft),
    border-color var(--dur-base) var(--ease-out-soft),
    box-shadow var(--dur-base) var(--ease-out-soft);
}
.parada__nodo::before{
  content:"";position:absolute;inset:0;z-index:-1;
  border-radius:inherit;
  background:rgba(12,192,223,.16);
  opacity:0;transition:opacity var(--dur-base) var(--ease-out-soft);
}
/* Anillo que sale despedido cuando el marcador pasa. Un solo pulso, no
   un latido: late lo que está esperando algo, y esto ya pasó. */
.parada__nodo::after{
  content:"";position:absolute;inset:-1px;z-index:-1;
  border-radius:inherit;
  border:1px solid var(--cyan-400);
  opacity:0;
}
.parada.is-on .parada__nodo{
  border-color:rgba(12,192,223,.6);
  color:var(--cyan-200);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16);
}
.parada.is-on .parada__nodo::before{opacity:1}
/* El golpe y la onda: rebote, porque acá SÍ hay impulso — algo llegó y
   lo tocó. Es lo único de la página con overshoot, y se justifica solo.
   Va con keyframes y no con resorte porque es una reacción de una sola
   vez: nadie la está agarrando, así que no hay nada que interrumpir. */
.parada.is-on .parada__nodo{animation:mapa-golpe 520ms var(--ease-out-soft) 1}
.parada.is-on .parada__nodo::after{animation:mapa-onda 620ms var(--ease-out-soft) 1}
@keyframes mapa-golpe{
  0%  {transform:scale(1)}
  38% {transform:scale(1.14)}
  100%{transform:scale(1)}
}
@keyframes mapa-onda{
  from{opacity:.8;transform:scale(1)}
  to  {opacity:0;transform:scale(1.55)}
}

/* --- La tarjeta: se aprieta y se agranda --- */
/* OPACA, NO TRANSLÚCIDA. El camino pasa POR DETRÁS de las tarjetas, que
   es como se dibuja una ruta detrás de un rótulo en un mapa de verdad.
   Con fondo translúcido se vería el trazo cian atravesando el texto.

   Esto reemplaza a la evasión puramente geométrica, que funcionaba a la
   mayoría de los anchos pero no a todos: con las tarjetas más anchas en
   proporción (~1000px) o con las cinco paradas abiertas, al camino no le
   quedaba corredor por donde bajar. La curva igual esquiva —por eso los
   puntos de control salen de la banda libre medida— pero ya no depende
   de esquivar para verse bien. Dos defensas, no una.

   El color es --ground-base aclarado a mano, no una capa blanca al 4%:
   una superficie que tapa algo tiene que ser opaca de verdad. */
.parada__caja{
  border-radius:var(--radius-lg);
  background:#08193B;
  border:1px solid rgba(255,255,255,.09);
  overflow:hidden;
  transition:
    background-color var(--dur-base) var(--ease-standard),
    border-color var(--dur-base) var(--ease-standard),
    box-shadow var(--dur-base) var(--ease-standard);
}
/* La parada alcanzada se levanta del suelo: sombra y borde, no brillo. */
.parada.is-on .parada__caja{
  background:#0A1E44;
  border-color:rgba(255,255,255,.15);
  box-shadow:0 18px 44px rgba(0,6,20,.5);
}

.parada__head{
  width:100%;display:block;
  padding:clamp(18px, 2vw, 26px);
  border:0;background:transparent;
  font:inherit;color:inherit;text-align:left;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  /* El aprieto se siente en el pointer-down (§1): lo aplica el navegador
     en el mismo cuadro del evento, no una clase que llegue después. */
  transition:transform var(--dur-instant) var(--ease-out-soft);
}
.parada__head:active{transform:scale(.985)}
.parada__head:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-3px}

.parada__fila{display:flex;align-items:center;gap:var(--space-4)}
.parada__title{
  flex:1;min-width:0;margin:0;
  font-family:var(--font-subhead);
  font-size:var(--type-h4-size);font-weight:var(--fw-semibold);
  letter-spacing:var(--ls-h3);line-height:var(--lh-heading);
  color:var(--text-strong);
}
/* Gira con el mismo resorte que abre el panel: es un solo movimiento
   contado dos veces, no dos animaciones que se parecen. */
.parada__chev{
  flex:0 0 auto;display:grid;place-items:center;
  width:32px;height:32px;border-radius:var(--radius-pill);
  background:rgba(255,255,255,.06);
  color:var(--paper-dim);
  transform:rotate(calc(var(--open, 0) * 180deg));
}
.parada__chev .ico{--ico-size:18px}
.parada.is-on .parada__chev{color:var(--cyan-300)}

.parada__body{
  margin:var(--space-3) 0 0;
  font-size:var(--text-sm);line-height:var(--lh-body);
  color:var(--text-muted);text-wrap:pretty;
  transition:color var(--dur-base) var(--ease-out-soft);
}
.parada.is-on .parada__body{color:var(--text-body)}

/* Panel. Por defecto ABIERTO: si el script no corre, se lee todo. Es
   js/v2.js el que marca .is-js y lo cierra. */
.parada__panel{overflow:hidden}
.parada.is-js .parada__panel{height:0}
.parada__panel-in{padding:0 clamp(18px, 2vw, 26px) clamp(18px, 2vw, 26px)}
.parada__meta{
  display:inline-flex;align-items:center;gap:var(--space-2);
  margin:0 0 var(--space-3);
  padding:5px var(--space-4);border-radius:var(--radius-pill);
  background:rgba(12,192,223,.12);
  border:1px solid rgba(12,192,223,.28);
  font-size:var(--text-2xs);font-weight:var(--fw-semibold);
  letter-spacing:var(--ls-eyebrow);text-transform:uppercase;
  color:var(--cyan-200);
}
.parada__meta .ico{--ico-size:14px}
.parada__more{
  margin:0;
  font-size:var(--text-sm);line-height:var(--lh-body);
  color:var(--text-muted);text-wrap:pretty;
}

/* =====================================================================
   RESPONSIVE
   El zigzag necesita ancho. Por debajo de 860px las paradas se apilan
   en una sola columna con el nodo a la izquierda: el camino deja de
   cruzar y se convierte en una línea con ondulación suave, que es lo
   que el mismo motor dibuja sin ningún caso especial — los puntos que
   mide son otros, la curva sale sola.
   ===================================================================== */
@media (max-width:1080px){
  .mapa__stage{--nodo:60px;--caja:clamp(240px, 52%, 480px)}
  .parada__title{font-size:var(--text-md)}
  .mapa__list{gap:clamp(56px, 8vw, 112px)}
}
@media (max-width:860px){
  /* Una columna: el camino deja de cruzar y baja ondulando. El motor no
     tiene un caso especial para esto — mide otros puntos y la curva sale
     sola. */
  .mapa__stage{--nodo:48px;--carril:var(--space-4);--caja:1fr}
  .mapa__list{gap:var(--space-8)}
  .parada,
  .parada:nth-child(even){
    grid-template-columns:var(--nodo) minmax(0,1fr);
    justify-content:stretch;
    align-items:start;
  }
  .parada:nth-child(odd) .parada__nodo,
  .parada:nth-child(even) .parada__nodo{grid-column:1}
  .parada:nth-child(odd) .parada__caja,
  .parada:nth-child(even) .parada__caja{grid-column:2}
  .parada:nth-child(odd) .parada__caja,
  .parada:nth-child(even) .parada__caja{--travel-x:-18px}
}
@media (max-width:640px){
  .mapa__stage{--nodo:42px}
  .parada__nodo{font-size:var(--text-2xs)}
  .parada__head{padding:var(--space-4)}
  .parada__panel-in{padding:0 var(--space-4) var(--space-4)}
}

/* =====================================================================
   ACCESIBILIDAD
   ===================================================================== */
@media (prefers-reduced-motion: reduce){
  /* El motor no escribe --p. El mapa se muestra entero y quieto: el
     recorrido completo es la información, el viaje era el adorno. */
  .mapa__road--done,.mapa__road--glow{stroke-dashoffset:0}
  .mapa__road--glow{opacity:.6}
  .mapa__marker{display:none}
  .parada.is-on .parada__nodo,
  .parada.is-on .parada__nodo::after{animation:none}
  .parada__nodo{transform:none;transition:none}
  .parada__nodo::before,.parada__body,.parada__caja{transition:none}
  .parada__head{transition:none}
}
@media (prefers-contrast: more){
  .mapa__road{stroke:rgba(255,255,255,.34)}
  .parada__caja,.parada.is-on .parada__caja{border-color:rgba(255,255,255,.4)}
  .parada__nodo{border-color:rgba(255,255,255,.5);color:var(--paper-dim)}
  .parada__body,.parada__more{color:var(--paper-dim)}
}

