/*
 * Capa de movimiento de la portada (fase 2, spec §7). Todo va dentro de la consulta de movimiento no
 * reducido y cuelga de una clase que pone movimiento.js: sin script o con movimiento reducido no se
 * oculta ni se anima nada. Solo transform, opacity y las propiedades independientes translate/scale
 * (que el compositor trata igual que transform). Las animaciones de entrada son cortas y se
 * ejecutan una vez, asi que no se pausan: lo que se para es el recorrido (movimiento.js), y
 * congelarlas a medias dejaria la ficha medio transparente.
 *
 * --- PARALLAX POR SECCIONES (2026-09-17, decision del titular) --------------------------------
 *
 * El 2026-09-06 se retiro una mecanica atada al scroll. Lo que se retiro fueron ESCENAS ANCLADAS
 * (position: sticky) que se quedaban la pantalla y alargaban la portada un 43%: scrolleabas y la
 * pagina no bajaba, se reproducia una escena. Esto es otra cosa, y por eso vuelve a haber
 * animaciones guiadas por el scroll: la pagina baja exactamente igual que antes -- misma longitud,
 * nada anclado, nada capturado --, y lo que cambia es que las capas de dentro de cada seccion
 * viajan a velocidades distintas. La prohibicion de anclar secciones y la de tocar el scroll siguen
 * en pie, y las pruebas las siguen vigilando.
 *
 * Tres reglas de oficio, que son las que hacen que esto se pueda leer:
 *
 *   1. Lo que lleva texto TERMINA su viaje antes de llegar al centro de la pantalla. El movimiento
 *      ocurre al entrar y al salir, nunca en la zona de lectura: nadie deberia leer un parrafo que
 *      se esta moviendo. De ahi los rangos "entry" (entrada, se posa) frente a "cover" (decorado,
 *      viaja sin parar).
 *   2. El heroe usa "exit", no "cover": con "cover" la portada cargaria con el h1 ya desplazado,
 *      porque al abrir la pagina el heroe lleva media pantalla recorrida. Con "exit" esta quieto
 *      hasta que empiezas a irte de el.
 *   3. translate/scale y no transform: la foto de la capsula derecha y la marca de agua de las
 *      secciones pares YA llevan un transform: scaleX(-1) (su espejo). Animar transform aqui lo
 *      borraria y saldrian del reves. Las propiedades independientes se componen con el.
 *
 * El @supports deja fuera al navegador que no lleve animaciones guiadas por scroll: alli la portada
 * se ve exactamente como antes del parallax, no como una portada rota. Y dentro del @supports el
 * revelado por IntersectionObserver se apaga, porque la entrada la conduce ya el scroll y dejar los
 * dos puestos sumaba dos desplazamientos sobre la misma pieza.
 */
@media screen and (prefers-reduced-motion: no-preference) {

  /* Aparicion de las secciones al entrar en pantalla */
  .movimiento-revela .aparece,
  .movimiento-revela .aparece-cifra {
    opacity: 0;
    transform: translate3d(0, 26px, 0);
    transition: opacity .55s cubic-bezier(.22, .9, .28, 1), transform .6s cubic-bezier(.22, .9, .28, 1);
  }

  .movimiento-revela .aparece-cifra {
    transform: translate3d(0, 10px, 0) scale(.82);
  }

  .movimiento-revela .aparece.visible,
  .movimiento-revela .aparece-cifra.visible {
    opacity: 1;
    transform: none;
  }

  /* Lo que el foco alcanza nunca se queda invisible */
  .aparece:focus-within,
  .aparece-cifra:focus-within {
    opacity: 1 !important;
    transform: none !important;
    animation-name: none !important;
    transition: none !important;
  }

  /* Recorrido del diagrama: el trazo sale del centro hacia el area activa */
  .movimiento-js .orbita-radio--activo .orbita-viaje {
    animation-name: orbita-viaje;
    animation-duration: 1.05s;
    animation-timing-function: cubic-bezier(.3, .6, .3, 1);
    animation-fill-mode: both;
  }

  /* ...y cuando llega, se subraya la pastilla */
  .movimiento-js .orbita-area--activa::after {
    animation-name: orbita-subrayado;
    animation-duration: .45s;
    animation-delay: .75s;
    animation-fill-mode: both;
  }

  .movimiento-js .orbita-lista:not([hidden]) {
    animation-name: orbita-ficha;
    animation-duration: .35s;
    animation-fill-mode: both;
  }

  .movimiento-js .orbita-area {
    transition: transform .3s ease;
  }

  @keyframes orbita-viaje {
    from { transform: translateX(-100%); }
    to { transform: none; }
  }

  @keyframes orbita-subrayado {
    from { transform: scaleX(.15); }
    to { transform: none; }
  }

  @keyframes orbita-ficha {
    from { opacity: .25; }
    to { opacity: 1; }
  }

  /*
   * ==============================================================================================
   * Parallax por secciones
   * ==============================================================================================
   */
  /*
   * =================== Desfile de clientes de la franja (2026-09-18) ===================
   * El titular lo pidio con estas palabras: "scroll infinito hacia la izquierda, pero que siempre
   * se vean las empresas". Las dos mitades importan, y la segunda es la que tiene truco.
   *
   * "Que siempre se vean": la pista lleva VARIAS copias de la lista (las clona movimiento.js,
   * tantas como haga falta para cubrir la pantalla) y el bucle desplaza exactamente UNA copia. Al
   * terminar, la pista vuelve a 0 y lo que hay en pantalla es identico pixel a pixel, asi que no
   * hay ni salto ni hueco: nunca se ve un trozo de cinta vacio.
   *
   * De ahi que el paso NO este escrito aqui: es -100/copias por ciento, y depende de cuantas
   * copias haya puesto el script, asi que lo calcula el y lo pasa en `--desfile-paso`. La ficha
   * vive en tokens.css con el valor de tres copias, el minimo que monta el script, y el style de
   * la pista lo pisa -- el mismo reparto que `--angulo` con los radios del diagrama.
   *
   * Se para de tres maneras, y hacen falta las tres: con movimiento reducido ni llega a existir
   * (este @media y el return del script), con el raton o el foco encima (nadie puede leer un
   * nombre que se le escapa) y con el boton que crea el script. Lo ultimo no es adorno: WCAG 2.2.2
   * pide un control de verdad para lo que se mueve solo y no para nunca, y el sitio ya tiene ese
   * mismo boton para el recorrido del diagrama.
   */
  .movimiento-js .franja-clientes-cinta {
    overflow: hidden;
    /* Los nombres se desvanecen en los bordes en vez de cortarse en seco contra el aire. */
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  }

  .movimiento-js .franja-clientes-pista {
    display: flex;
    width: max-content;
    animation-name: franja-desfile;
    animation-duration: 32s;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
  }

  /* Dentro de la pista los nombres van en una sola linea: envolver aqui romperia el bucle. */
  .movimiento-js .franja-clientes-pista .franja-clientes-lista {
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 0 44px;
    padding-right: 44px;
  }

  .movimiento-js .franja-clientes-cinta:hover .franja-clientes-pista,
  .movimiento-js .franja-clientes-cinta:focus-within .franja-clientes-pista,
  .movimiento-js .franja-clientes-cinta.franja-quieta .franja-clientes-pista {
    animation-play-state: paused;
  }

  /*
   * El boton de pausa. Vivia en la linea del pie de la franja ("Ver que hace cada una -> - Pausar")
   * hasta que el titular pidio quitar esa linea; el enlace a /casos/ se fue con ella (el menu y la
   * seccion de casos de mas abajo siguen llevando alli), pero EL BOTON NO PUEDE IRSE: el desfile se
   * repite sin fin y WCAG 2.2.2 exige un control real, que ademas es lo que la prueba del infinito
   * de test/movimiento.test.js comprueba una por una (raton, foco Y boton).
   *
   * Asi que se queda, discreto, anclado a la esquina de abajo a la derecha de la banda. No estorba
   * a nada -- el contenido esta centrado -- y sigue siendo alcanzable con el tabulador.
   *
   * EL `bottom` SE MIDE DESDE EL SESGO, MAS LA DERIVA DEL PARALLAX. Dos sumandos, y cada uno
   * corrige un fallo que se vio midiendo:
   *
   *  - El sesgo, porque el recorte en diagonal vive en el ::before y NO en la banda: un boton
   *    pegado al borde de abajo no se recorta, se queda flotando en el blanco de la seccion
   *    siguiente, blanco sobre blanco. Con `bottom: 22px` caia 23 px por debajo del rojo. A simple
   *    vista solo se veia que el boton "no estaba".
   *  - Los 22 px de deriva, porque el boton viaja con la cinta (regla de arriba) y el recorte no
   *    viaja con nadie: sin ese margen, en el extremo del recorrido volvia a asomar 1 px fuera.
   *
   * El resto son 20 px de holgura. Y el relleno inferior de la banda subio a 118 px (portada.css)
   * para que quepa todo esto sin que el boton se le eche encima a los nombres.
   */
  .movimiento-js .franja-clientes-pausa {
    position: absolute;
    right: 28px;
    bottom: calc(var(--franja-sesgo) + 42px);
    border: 0;
    padding: 4px 2px;
    background: none;
    font: inherit;
    font-size: .82rem;
    color: var(--sobre-rojo);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
  }

  .movimiento-js .franja-clientes-pausa:hover,
  .movimiento-js .franja-clientes-pausa:focus-visible {
    color: var(--oro-sobre-rojo);
  }

  /*
   * En pantalla estrecha la esquina no vale: la cinta de nombres ocupa TODO el ancho, y con el
   * vaiven del parallax (hasta 22 px) se le echa encima -- medido, quedaban 3 px de hueco en
   * reposo, o sea 19 de solape en el peor momento. Ahi el boton baja al flujo, centrado bajo los
   * nombres. Es una linea de mas, pero es el unico sitio donde no pisa nada.
   */
  @media (max-width: 600px) {
    .movimiento-js .franja-clientes-pausa {
      position: static;
      display: block;
      /* 34 y no 18: `translate` no reserva sitio, asi que la cinta se le echa encima 22 px sin que
         la maquetacion se entere. Con 18 quedaban -4 en el peor momento; con 34 sobran 12. */
      margin: 34px auto 0;
    }
  }

  @keyframes franja-desfile {
    from { translate: 0 0; }
    to { translate: var(--desfile-paso) 0; }
  }

  @supports (animation-timeline: view()) {

    /* El revelado por observador cede el sitio: aqui la entrada la conduce el scroll. */
    .movimiento-revela .aparece,
    .movimiento-revela .aparece-cifra {
      opacity: 1;
      transform: none;
      transition: none;
    }

    /* ---------- Capa de fondo: la marca de agua va mas lenta que su seccion ---------- */
    /* El scale sobra por los cuatro lados para que el viaje no destape nunca un borde; lo que
       desborda lo recortan el clip-path de la seccion y el overflow del pie (base.css). */
    .movimiento-js .seccion-hero::before,
    .movimiento-js main > .seccion::before,
    .movimiento-js .pie::before {
      scale: 1.36;
      animation-name: parallax-marca;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      animation-timing-function: linear;
      animation-fill-mode: both;
    }

    /*
     * El parallax del heroe SOLO donde va en dos columnas (el mismo corte que usa portada.css).
     * Por debajo de 861 px el heroe se apila y su columna de texto pasa a medir mas que la
     * pantalla; cuando la pieza es mas alta que la ventana el rango "exit" se degenera a longitud
     * cero y el navegador deja de interpolar: en vez de un viaje sale un salto seco al estado
     * final (comprobado en Chrome a 390 px: neutro hasta y=1400 y de golpe a opacidad .35). Se
     * probo "exit-crossing", que si esta definido para piezas mas altas que la ventana, y es peor:
     * pinta el estado final tambien arriba del todo, con el h1 desvanecido nada mas cargar.
     * Abajo de ese corte el heroe se queda quieto, que en un movil es ademas lo que se lee mejor.
     */
    @media (min-width: 861px) {
      /* ---------- Heroe: el texto y el diagrama se separan al salir ---------- */
      .movimiento-js .heroe-discurso {
        animation-name: parallax-heroe-texto;
        animation-timeline: view();
        animation-range: exit 0% exit 100%;
        animation-timing-function: linear;
        animation-fill-mode: both;
      }

      .movimiento-js .orbita-circulo {
        animation-name: parallax-heroe-circulo;
        animation-timeline: view();
        animation-range: exit 0% exit 100%;
        animation-timing-function: linear;
        animation-fill-mode: both;
      }

      .movimiento-js .orbita-ficha {
        animation-name: parallax-heroe-ficha;
        animation-timeline: view();
        animation-range: exit 0% exit 100%;
        animation-timing-function: linear;
        animation-fill-mode: both;
      }

      /* El foco no puede acabar en una pieza a media transparencia: el diagrama lleva pastillas y
         enlaces, y se puede tabular hasta el mientras el heroe se esta yendo. */
      .movimiento-js .heroe-discurso:focus-within,
      .movimiento-js .orbita-circulo:focus-within,
      .movimiento-js .orbita-ficha:focus-within {
        opacity: 1 !important;
        animation-name: none !important;
        translate: none !important;
        scale: none !important;
      }
    }

    /* ---------- Precio: la foto viaja dentro de su capsula ---------- */
    .movimiento-js .precio-foto img {
      scale: 1.44;
      animation-name: parallax-foto;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      animation-timing-function: linear;
      animation-fill-mode: both;
    }

    .movimiento-js .precio-texto {
      animation-name: parallax-sube-texto;
      animation-timeline: view();
      animation-range: cover 0px cover 420px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    /* La calculadora va ENCIMA de la foto de la capsula: esta es la unica tarjeta que no se
       transparenta al entrar. Una tarjeta a medio opacar sobre una foto no se lee como un efecto,
       se lee como un fallo de pintado -- y ademas deja ver la foto a traves del texto. Entra solo
       desplazandose. */
    .movimiento-js .precio-datos {
      animation-name: parallax-sube-solida;
      animation-timeline: view();
      animation-range: cover 0px cover 480px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    .movimiento-js .precio-sello {
      animation-name: parallax-sube-suave;
      animation-timeline: view();
      animation-range: cover 0px cover 460px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    .movimiento-js .precio-datos:focus-within {
      opacity: 1 !important;
      animation-name: none !important;
      translate: none !important;
      scale: none !important;
    }

    /* ---------- Ahorro: la tarjeta entra de lado y las barras crecen ---------- */
    .movimiento-js .ahorro-texto {
      animation-name: parallax-sube-texto;
      animation-timeline: view();
      animation-range: cover 0px cover 420px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    .movimiento-js .ahorro-cifra {
      animation-name: parallax-entra-lado;
      animation-timeline: view();
      animation-range: cover 0px cover 480px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    .movimiento-js .ahorro-numero {
      animation-name: parallax-cifra;
      animation-timeline: view();
      animation-range: cover 0px cover 340px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    /* scaleX y no width: el ancho de cada barra lo escribe la plantilla con el dato real, y
       animarlo recalcularia maquetacion en cada fotograma. */
    .movimiento-js .ahorro-barra-relleno {
      transform-origin: left center;
      animation-name: parallax-barra;
      animation-timeline: view();
      animation-range: cover 60px cover 420px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    .movimiento-js .ahorro-barra--nuestra .ahorro-barra-relleno {
      animation-range: cover 120px cover 500px;
    }

    .movimiento-js .ahorro-cifra:focus-within {
      opacity: 1 !important;
      animation-name: none !important;
      translate: none !important;
      scale: none !important;
    }

    /* ---------- Casos: las tres fichas llegan escalonadas ---------- */
    .movimiento-js .casos-cabecera {
      animation-name: parallax-sube-texto;
      animation-timeline: view();
      animation-range: cover 0px cover 420px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    .movimiento-js .tarjeta-caso {
      animation-name: parallax-sube-tarjeta;
      animation-timeline: view();
      animation-range: cover 0px cover 480px;
      animation-timing-function: cubic-bezier(.22, .9, .28, 1);
      animation-fill-mode: both;
    }

    .movimiento-js .tarjeta-caso:nth-child(2) {
      animation-range: cover 60px cover 560px;
    }

    .movimiento-js .tarjeta-caso:nth-child(3) {
      animation-range: cover 120px cover 640px;
    }

    .movimiento-js .casos-cabecera:focus-within,
    .movimiento-js .tarjeta-caso:focus-within {
      opacity: 1 !important;
      animation-name: none !important;
      translate: none !important;
      scale: none !important;
    }

    /* ---------- Franja de clientes: dos planos a distinta velocidad ---------- */
    /*
     * La banda roja NO se mueve: es el plano de referencia, y es lo que hace que lo de dentro se
     * lea como que flota por delante. Lo que viaja es el contenido, en dos capas de amplitud
     * decreciente -- titular con su entradilla, y cinta de nombres --, de abajo arriba conforme la
     * banda cruza la pantalla. Eran tres: la tercera era la linea del pie, retirada con ella.
     *
     * La cinta puede llevar su propio `translate` sin pelearse con el desfile: el bucle infinito
     * vive en `.franja-clientes-pista`, que es el HIJO. Dos elementos, dos animaciones, ningun
     * conflicto -- si las dos cayeran en el mismo elemento, la ultima declarada ganaria y el
     * desfile se pararia en seco.
     *
     * Amplitudes cortas a proposito (44 / 22 / 12 px). El relleno de la banda es de 92 px y el
     * sesgo llega a 64: con un viaje mas largo, el titular se acercaria al borde en diagonal en
     * pantallas anchas. Aqui le quedan 48 px de holgura en el peor momento del recorrido.
     */
    .movimiento-js .franja-clientes-titulo,
    .movimiento-js .franja-clientes-sub {
      animation-name: parallax-franja-titulo;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      animation-timing-function: linear;
      animation-fill-mode: both;
    }

    /*
     * El boton de pausa viaja EN EL MISMO PLANO que la cinta, no quieto ni en uno propio. Es lo que
     * mantiene constante el hueco entre los nombres y el boton: `translate` no reserva sitio, asi
     * que con la cinta moviendose sola se le echaba encima 12 px en el extremo del recorrido
     * (medido, congelando la animacion para leer la posicion de reposo). Moviendose los dos igual,
     * el hueco es el mismo a cualquier altura del scroll.
     */
    .movimiento-js .franja-clientes-cinta,
    .movimiento-js .franja-clientes-pausa {
      animation-name: parallax-franja-cinta;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      animation-timing-function: linear;
      animation-fill-mode: both;
    }

    @keyframes parallax-franja-titulo {
      from { translate: 0 44px; }
      to { translate: 0 -44px; }
    }

    @keyframes parallax-franja-cinta {
      from { translate: 0 22px; }
      to { translate: 0 -22px; }
    }

    @keyframes parallax-marca {
      from { translate: 0 -13%; }
      to { translate: 0 13%; }
    }

    @keyframes parallax-foto {
      from { translate: 0 -15%; }
      to { translate: 0 15%; }
    }

    @keyframes parallax-heroe-texto {
      from { translate: none; opacity: 1; }
      to { translate: 0 -190px; opacity: .45; }
    }

    @keyframes parallax-heroe-circulo {
      from { translate: none; scale: 1; opacity: 1; }
      to { translate: 0 130px; scale: .78; opacity: .5; }
    }

    @keyframes parallax-heroe-ficha {
      from { translate: none; opacity: 1; }
      to { translate: 0 190px; opacity: .65; }
    }

    @keyframes parallax-sube-texto {
      from { translate: 0 130px; opacity: .15; }
      to { translate: none; opacity: 1; }
    }

    @keyframes parallax-sube-suave {
      from { translate: 0 100px; opacity: .12; }
      to { translate: none; opacity: 1; }
    }

    @keyframes parallax-sube-solida {
      from { translate: 0 210px; }
      to { translate: none; }
    }

    @keyframes parallax-sube-tarjeta {
      from { translate: 0 210px; scale: .88; opacity: 0; }
      to { translate: none; scale: 1; opacity: 1; }
    }

    @keyframes parallax-entra-lado {
      from { translate: 130px 170px; scale: .82; opacity: 0; }
      to { translate: none; scale: 1; opacity: 1; }
    }

    @keyframes parallax-cifra {
      from { scale: .35; opacity: 0; }
      to { scale: 1; opacity: 1; }
    }

    @keyframes parallax-barra {
      from { transform: scaleX(0); }
      to { transform: none; }
    }
  }
}
