/* ==========================================================================
   La ruta, en movimiento
   ==========================================================================

   Un paquete recorre la línea y, a su paso, cada parada se enciende y sale
   su aviso. Es un bucle de 14 segundos.

   Tres reglas, las mismas que en los mockups del panel:

   1. Cada efecto ocurre DESPUÉS de que el paquete llegue, nunca antes. Si el
      aviso aparece primero, la escena deja de contar una secuencia.
   2. Al reiniciar, la escena vuelve a cero: los avisos se van y las paradas
      se apagan. Si no, la segunda vuelta empieza con todo ya encendido y no
      se entiende nada.
   3. No arranca hasta que la sección está en pantalla.

   NADA de `animation-delay` aquí. Con `both` y un retraso positivo el
   navegador congela el estado FINAL durante el retraso de cada repetición:
   los avisos nunca desaparecerían al empezar la vuelta siguiente. Por eso
   cada elemento lleva su propio keyframe con los tiempos ya dentro.

   Los porcentajes están calculados sobre las cuatro paradas, que caen en el
   12,5%, 37,5%, 62,5% y 87,5% del ancho (el centro de cada columna de un
   grid de cuatro).

   Calendario del ciclo:
      2%   el paquete sale de la 1.ª parada
     18%   llega a la 2.ª    -> 20% enciende, 22% hilo, 26% aviso
     30%   arranca hacia la 3.ª
     46%   llega a la 3.ª    -> 48% enciende, 50% hilo, 54% aviso
     58%   arranca hacia la 4.ª
     74%   llega al destino  -> 76% enciende, 78% hilo, 82% aviso
     88%   la reseña, que llega días después
     98%   todo se desvanece para volver a empezar

   El arranque es lo que más se nota: si el paquete tarda en salir, quien
   mira ve un diagrama quieto y da por hecho que no hay animación. Por eso
   sale casi de inmediato y las esperas se reparten entre las paradas, donde
   sí cuentan algo (el aviso que está saliendo).
   ========================================================================== */

.rt-ruta { --rt-ciclo: 11s; }

/* --------------------------------------------------------------------------
   El paquete

   NO es una caja como los nodos. Se probó así —mismo tamaño, misma forma— y
   competía con las paradas: parecía un checkpoint más, suelto en mitad de la
   línea, en vez de algo que se mueve.

   Ahora es un disco pequeño en violeta sólido, la mitad que un nodo, con un
   halo del color del fondo que lo despega de la línea. Se lee como un objeto
   en tránsito, que es lo que es.

   Se desvanece justo ANTES de entrar en cada parada y reaparece al salir, así
   nunca pisa un icono.
   -------------------------------------------------------------------------- */

.rt-ruta .ruta__viajero {
  position: absolute;
  top: 25px;
  left: 12.5%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  border-radius: 50%;
  background: var(--violeta-hondo);
  color: #fff;
  box-shadow:
    0 0 0 4px var(--papel),
    0 5px 14px -3px rgba(50, 45, 161, .6);
  opacity: 0;
  animation: rt-viaja var(--rt-ciclo) linear infinite;
}
.rt-ruta .ruta__viajero svg {
  width: 17px;
  height: 17px;
  stroke-width: 2.2;
}

@keyframes rt-viaja {
  /* Sale enseguida: es lo que avisa de que esto se mueve */
  0%       { left: 12.5%; opacity: 0; }
  2%       { left: 14%;   opacity: 1; }

  /* Llega a la segunda y se mete dentro */
  15%      { left: 34%;   opacity: 1; }
  18%      { left: 37.5%; opacity: 0; }
  30%      { left: 37.5%; opacity: 0; }

  /* A la tercera */
  32%      { left: 40%;   opacity: 1; }
  43%      { left: 59%;   opacity: 1; }
  46%      { left: 62.5%; opacity: 0; }
  58%      { left: 62.5%; opacity: 0; }

  /* Y al destino */
  60%      { left: 65%;   opacity: 1; }
  71%      { left: 84%;   opacity: 1; }
  74%      { left: 87.5%; opacity: 0; }

  100%     { left: 87.5%; opacity: 0; }
}

/* --------------------------------------------------------------------------
   La línea se va tiñendo a su paso
   Un degradado que avanza: por detrás queda el trazo recorrido, por delante
   el que falta, más apagado.
   -------------------------------------------------------------------------- */

.rt-ruta::before {
  background:
    linear-gradient(90deg,
      var(--violeta) 0%,
      var(--violeta) 58%,
      #0bbd8c 100%) !important;
  /* El trazo se revela de izquierda a derecha */
  mask-image: linear-gradient(90deg, #000 0 var(--rt-avance, 0%), rgba(0, 0, 0, .22) var(--rt-avance, 0%) 100%);
  animation: rt-tinta var(--rt-ciclo) cubic-bezier(.65, 0, .35, 1) infinite;
}

@keyframes rt-tinta {
  0%      { --rt-avance: 0%; }
  18%     { --rt-avance: 34%; }
  30%     { --rt-avance: 34%; }
  46%     { --rt-avance: 67%; }
  58%     { --rt-avance: 67%; }
  74%     { --rt-avance: 100%; }
  /* Se apaga con el resto para que la vuelta empiece limpia */
  94%     { --rt-avance: 100%; }
  98%     { --rt-avance: 0%; }
  100%    { --rt-avance: 0%; }
}

/* `--rt-avance` tiene que declararse como propiedad animable o el navegador la
   interpola a saltos en vez de suavemente. */
@property --rt-avance {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}

/* --------------------------------------------------------------------------
   Las paradas se encienden al llegar el paquete

   Antes de su turno están apagadas, pero OPACAS: con transparencia se veía
   la línea del trayecto por debajo del icono y quedaba sucio. Gris claro
   sólido y el icono en gris medio.

   Se interpolan el fondo y el color del icono, nunca la opacidad, así que la
   línea no se transparenta en ningún fotograma.
   -------------------------------------------------------------------------- */

.rt-ruta .ruta__parada:nth-child(3) .ruta__nodo { animation: rt-enciende-2 var(--rt-ciclo) both infinite; }
.rt-ruta .ruta__parada:nth-child(4) .ruta__nodo { animation: rt-enciende-3 var(--rt-ciclo) both infinite; }
.rt-ruta .ruta__parada:nth-child(5) .ruta__nodo { animation: rt-enciende-4 var(--rt-ciclo) both infinite; }

/* Y la sombra fuera mientras está apagado: un nodo gris con halo violeta
   canta. */
.rt-ruta .ruta__parada:nth-child(3) .ruta__nodo,
.rt-ruta .ruta__parada:nth-child(4) .ruta__nodo,
.rt-ruta .ruta__parada:nth-child(5) .ruta__nodo {
  box-shadow: 0 0 0 5px var(--papel);
}

@keyframes rt-enciende-2 {
  0%, 18%   { background: #e2e0ee; color: #a5a1bd; }
  21%       { background: var(--violeta-hondo); color: #fff; }
  94%       { background: var(--violeta-hondo); color: #fff; }
  98%, 100% { background: #e2e0ee; color: #a5a1bd; }
}
@keyframes rt-enciende-3 {
  0%, 46%   { background: #e2e0ee; color: #a5a1bd; }
  49%       { background: var(--violeta-hondo); color: #fff; }
  94%       { background: var(--violeta-hondo); color: #fff; }
  98%, 100% { background: #e2e0ee; color: #a5a1bd; }
}
/* El destino es verde y además da un pequeño latido al recibir el paquete */
@keyframes rt-enciende-4 {
  0%, 74%   { background: #e2e0ee; color: #a5a1bd; transform: scale(1); }
  77%       { background: #04a878; color: #fff; transform: scale(1.12); }
  81%       { background: #04a878; color: #fff; transform: scale(1); }
  94%       { background: #04a878; color: #fff; transform: scale(1); }
  98%, 100% { background: #e2e0ee; color: #a5a1bd; transform: scale(1); }
}

/* --------------------------------------------------------------------------
   Los avisos, cada uno tras su parada
   El hilo baja primero y la burbuja aparece después: el aviso «sale» de la
   parada, no está ahí desde el principio.

   Cada uno con su keyframe propio y SIN delay, para que al reiniciar el ciclo
   desaparezcan todos (ver la nota de arriba sobre `both` + `animation-delay`).
   -------------------------------------------------------------------------- */

.rt-ruta .ruta__hilo { transform-origin: top; }

.rt-ruta .ruta__parada:nth-child(3) .ruta__hilo { animation: rt-hilo-2 var(--rt-ciclo) ease both infinite; }
.rt-ruta .ruta__parada:nth-child(4) .ruta__hilo { animation: rt-hilo-3 var(--rt-ciclo) ease both infinite; }
.rt-ruta .ruta__parada:nth-child(5) .ruta__hilo { animation: rt-hilo-4 var(--rt-ciclo) ease both infinite; }

@keyframes rt-hilo-2 {
  0%, 20%   { transform: scaleY(0); opacity: 0; }
  23%       { transform: scaleY(1); opacity: 1; }
  94%       { transform: scaleY(1); opacity: 1; }
  98%, 100% { transform: scaleY(0); opacity: 0; }
}
@keyframes rt-hilo-3 {
  0%, 48%   { transform: scaleY(0); opacity: 0; }
  51%       { transform: scaleY(1); opacity: 1; }
  94%       { transform: scaleY(1); opacity: 1; }
  98%, 100% { transform: scaleY(0); opacity: 0; }
}
@keyframes rt-hilo-4 {
  0%, 76%   { transform: scaleY(0); opacity: 0; }
  79%       { transform: scaleY(1); opacity: 1; }
  94%       { transform: scaleY(1); opacity: 1; }
  98%, 100% { transform: scaleY(0); opacity: 0; }
}

.rt-ruta .ruta__parada:nth-child(3) .ruta__aviso { animation: rt-aviso-2 var(--rt-ciclo) cubic-bezier(.2, .8, .25, 1) both infinite; }
.rt-ruta .ruta__parada:nth-child(4) .ruta__aviso { animation: rt-aviso-3 var(--rt-ciclo) cubic-bezier(.2, .8, .25, 1) both infinite; }
.rt-ruta .ruta__parada:nth-child(5) .ruta__aviso { animation: rt-aviso-4 var(--rt-ciclo) cubic-bezier(.2, .8, .25, 1) both infinite; }
/* La reseña llega más tarde que el «entregado»: son dos momentos distintos */
.rt-ruta .ruta__parada:nth-child(5) .ruta__aviso--resena { animation-name: rt-aviso-resena; }

@keyframes rt-aviso-2 {
  0%, 23%   { opacity: 0; transform: translateY(-6px); }
  27%       { opacity: 1; transform: none; }
  94%       { opacity: 1; transform: none; }
  98%, 100% { opacity: 0; transform: translateY(-6px); }
}
@keyframes rt-aviso-3 {
  0%, 51%   { opacity: 0; transform: translateY(-6px); }
  55%       { opacity: 1; transform: none; }
  94%       { opacity: 1; transform: none; }
  98%, 100% { opacity: 0; transform: translateY(-6px); }
}
@keyframes rt-aviso-4 {
  0%, 79%   { opacity: 0; transform: translateY(-6px); }
  83%       { opacity: 1; transform: none; }
  94%       { opacity: 1; transform: none; }
  98%, 100% { opacity: 0; transform: translateY(-6px); }
}
@keyframes rt-aviso-resena {
  0%, 86%   { opacity: 0; transform: translateY(-6px); }
  90%       { opacity: 1; transform: none; }
  94%       { opacity: 1; transform: none; }
  98%, 100% { opacity: 0; transform: translateY(-6px); }
}

/* --------------------------------------------------------------------------
   Quieta hasta que se ve
   `arranque.js` quita esta clase cuando la sección entra en pantalla.
   -------------------------------------------------------------------------- */

.rt-ruta.rt-espera *,
.rt-ruta.rt-espera::before {
  animation-play-state: paused !important;
}

/* --------------------------------------------------------------------------
   En móvil el recorrido va en vertical

   El paquete baja en lugar de avanzar. Sin él lo primero que se movía era el
   segundo nodo, ya bien entrado el ciclo, y parecía que no pasaba nada.

   Las alturas no se pueden escribir a mano como los porcentajes horizontales:
   cada parada mide distinto según lleve aviso colgando o no. Las mide
   `arranque.js` y las deja en `--rt-y1`..`--rt-y4`.
   -------------------------------------------------------------------------- */

@media (max-width: 760px) {
  .rt-ruta .ruta__viajero {
    /* Sobre la línea, que en vertical va a 26px del borde izquierdo */
    top: var(--rt-y1, 26px);
    left: 26px;
    animation-name: rt-viaja-vertical;
  }

  /* El teñido se queda fuera: la máscara recorre una horizontal que aquí no
     existe. La línea vertical va entera desde el principio. */
  .rt-ruta::before { mask-image: none; animation: none; }
}

/* Mismo calendario que en horizontal, cambiando `left` por `top` */
@keyframes rt-viaja-vertical {
  0%       { top: var(--rt-y1, 26px); opacity: 0; }
  2%       { top: calc(var(--rt-y1, 26px) + 8px); opacity: 1; }

  15%      { top: calc(var(--rt-y2, 120px) - 8px); opacity: 1; }
  18%      { top: var(--rt-y2, 120px); opacity: 0; }
  30%      { top: var(--rt-y2, 120px); opacity: 0; }

  32%      { top: calc(var(--rt-y2, 120px) + 8px); opacity: 1; }
  43%      { top: calc(var(--rt-y3, 240px) - 8px); opacity: 1; }
  46%      { top: var(--rt-y3, 240px); opacity: 0; }
  58%      { top: var(--rt-y3, 240px); opacity: 0; }

  60%      { top: calc(var(--rt-y3, 240px) + 8px); opacity: 1; }
  71%      { top: calc(var(--rt-y4, 360px) - 8px); opacity: 1; }
  74%      { top: var(--rt-y4, 360px); opacity: 0; }

  100%     { top: var(--rt-y4, 360px); opacity: 0; }
}

/* --------------------------------------------------------------------------
   Sin movimiento: el estado final, que es lo que importa
   Todo encendido y todos los avisos a la vista, como antes de animar nada.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .rt-ruta .ruta__viajero { display: none; }
  .rt-ruta::before { mask-image: none; animation: none; }
  .rt-ruta .ruta__nodo,
  .rt-ruta .ruta__hilo,
  .rt-ruta .ruta__aviso {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  /* Y los nodos en su color de siempre: el apagado solo existe mientras hay
     recorrido que contar */
  .rt-ruta .ruta__parada .ruta__nodo {
    background: var(--violeta-hondo);
    color: #fff;
    box-shadow: 0 0 0 5px var(--papel), 0 10px 24px -10px rgba(50, 45, 161, .7);
  }
  .rt-ruta .ruta__parada .ruta__nodo--fin {
    background: linear-gradient(140deg, #0bbd8c, #04a878);
    box-shadow: 0 0 0 5px var(--papel), 0 12px 28px -10px rgba(4, 168, 120, .75);
  }
}
