/* =========================================================================
   ANIMACIONES — se carga la ÚLTIMA, después de components.css.
   =========================================================================
   Está en un fichero aparte a propósito: si algún día decides que sobran,
   borras el <link> de las 7 páginas y la web sigue funcionando igual. Nada
   de aquí es imprescindible para leer el contenido.

   TRES REGLAS QUE SE CUMPLEN EN TODO EL FICHERO
   ---------------------------------------------
   1. Solo se animan `transform` y `opacity`. Son las dos únicas propiedades
      que el navegador puede animar en la tarjeta gráfica sin recalcular la
      maquetación. Animar `width`, `top`, `margin` o `height` obliga a
      rehacer el diseño en cada fotograma y se nota en móviles.

   2. Duraciones cortas: entre 200 y 700 ms. Por encima de un segundo, una
      animación deja de sentirse elegante y empieza a sentirse lenta.

   3. `prefers-reduced-motion` se respeta al final del fichero. Hay gente a
      la que el movimiento le provoca mareo de verdad, y el sistema
      operativo ya expone esa preferencia.
   ========================================================================= */

/* ---------------------------------------------------------------------
   FOTOGRAMAS
   --------------------------------------------------------------------- */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(1.25rem); }
  to   { opacity: 1; transform: none; }
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes menu-in {
  from { opacity: 0; transform: translateY(-0.5rem); }
  to   { opacity: 1; transform: none; }
}

/* Flotación muy lenta y de solo 8 píxeles. Tan sutil que no se mira, pero
   evita que el hero parezca una captura de pantalla congelada. */
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}

/* ---------------------------------------------------------------------
   ENTRADA DEL HERO
   ---------------------------------------------------------------------
   Va en CSS puro, sin JavaScript: se dispara al cargar la página, así que
   no hay riesgo de que el texto parpadee antes de aparecer.

   Los retrasos escalonados (el "stagger") son lo que hace que se lea como
   una secuencia y no como un bloque que aparece de golpe. 90 ms entre cada
   elemento es suficiente para notarlo sin que llegue a impacientar.

   `both` conserva el estado inicial ANTES de empezar (por eso no se ve el
   texto durante el retraso) y el final al terminar. */
.hero__kicker,
.hero__autor  { animation: rise-in 600ms 0ms both; }
.hero__title  { animation: rise-in 600ms 90ms both; }
.hero__claim  { animation: rise-in 600ms 180ms both; }
.hero .btn    { animation: rise-in 600ms 270ms both; }

/* La ilustración usa DOS animaciones a la vez. Funciona porque cada una
   toca una propiedad distinta: fade-in solo la opacidad, float solo el
   transform. Si las dos animaran transform, la segunda pisaría a la
   primera. */
.hero__media {
  animation:
    fade-in 800ms 350ms both,
    float 7s 1.2s ease-in-out infinite;
}

/* ---------------------------------------------------------------------
   REVELADO AL HACER SCROLL
   ---------------------------------------------------------------------
   Las clases las pone main.js, no el HTML: así el marcado se queda limpio
   y, si el JavaScript falla o está desactivado, no hay nada que ocultar y
   todo se ve con normalidad. Es la diferencia entre una mejora progresiva
   y una web rota.

   main.js además NO anima lo que ya está en pantalla al cargar: solo
   prepara lo que queda por debajo del pliegue. Sin eso, se vería un
   parpadeo feo en la parte alta de la página. */
.reveal {
  opacity: 0;
  transform: translateY(1.5rem);
  /* 500 ms: con 600 se hacía lenta y con 350 apenas se notaba. */
  transition: opacity 500ms ease-out, transform 500ms ease-out;
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* Escalonado dentro de una misma rejilla: las tres tarjetas no entran a la
   vez, entran una detrás de otra. El retraso se aplica a la transición, no
   a una animación, porque aquí el disparo lo decide el observador. */
.grid > .reveal:nth-child(2)  { transition-delay: 70ms; }
.grid > .reveal:nth-child(3)  { transition-delay: 140ms; }
.grid > .reveal:nth-child(4)  { transition-delay: 210ms; }
.grid > .reveal:nth-child(5)  { transition-delay: 280ms; }

/* En la línea de tiempo el escalonado se nota mucho: los hitos aparecen en
   el mismo orden en que se leen. */
.timeline__item:nth-child(2) { transition-delay: 70ms; }
.timeline__item:nth-child(3) { transition-delay: 140ms; }
.timeline__item:nth-child(4) { transition-delay: 210ms; }
.timeline__item:nth-child(5) { transition-delay: 280ms; }

/* ---------------------------------------------------------------------
   NAVEGACIÓN — subrayado que crece desde la izquierda
   ---------------------------------------------------------------------
   Sustituye al box-shadow que marcaba la página activa en layout.css, y
   añade el mismo subrayado en hover y en foco de teclado.

   Se anula aquel box-shadow porque si no se verían los dos a la vez. Y si
   algún día borras este fichero, el de layout.css vuelve a aparecer solo:
   la página activa nunca se queda sin marcar.

   El selector con [aria-current] hace falta: el de layout.css tiene clase +
   atributo, y un .nav__link solo (una clase) pesa menos y no lo anularía. */
.nav__link {
  position: relative;
}

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

.nav__link::after {
  content: "";
  position: absolute;
  right: var(--space-3);
  bottom: 0.3rem;
  left: var(--space-3);
  height: 2px;
  background-color: currentColor;
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 220ms ease;
}

.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link[aria-current="page"]::after {
  transform: scaleX(1);
}

/* ---------------------------------------------------------------------
   MENÚ MÓVIL
   ---------------------------------------------------------------------
   `display` no se puede animar, así que en vez de una transición se lanza
   una animación en el momento en que el menú pasa a mostrarse. Al cerrar
   desaparece de golpe: es lo que espera el usuario y no merece más código. */
.nav__toggle[aria-expanded="true"] + .nav__list {
  animation: menu-in 220ms ease both;
}

/* El icono gira un poco al cambiar de hamburguesa a aspa. */
.nav__toggle .icon {
  transition: transform 220ms ease;
}

.nav__toggle[aria-expanded="true"] .icon {
  transform: rotate(90deg);
}

/* ---------------------------------------------------------------------
   TARJETAS
   --------------------------------------------------------------------- */
.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

/* La foto se acerca ligeramente dentro de su marco. El recorte lo hace el
   overflow:hidden que ya tiene .card__media en components.css. */
.card__media img,
.card__media .placeholder {
  transition: transform 400ms ease;
}

.card:hover .card__media img,
.card:hover .card__media .placeholder {
  transform: scale(1.04);
}

/* ---------------------------------------------------------------------
   NIVELES DE PRECIO
   --------------------------------------------------------------------- */
.tier {
  transition: transform var(--transition), border-color var(--transition),
              box-shadow var(--transition);
}

.tier:hover {
  transform: translateY(-3px);
  border-color: var(--color-accent-ink);
  box-shadow: var(--shadow);
}

/* ---------------------------------------------------------------------
   PUNTOS DE LA LÍNEA DE TIEMPO
   ---------------------------------------------------------------------
   El punto crece cuando el hito entra en pantalla. Usa el mismo estado
   .is-visible que pone el observador, así va sincronizado con el texto. */
.timeline__item::after {
  transform: scale(0.4);
  opacity: 0;
  transition: transform 400ms 150ms ease, opacity 400ms 150ms ease;
}

.timeline__item.is-visible::after,
html:not(.js) .timeline__item::after {
  transform: scale(1);
  opacity: 1;
}

/* ---------------------------------------------------------------------
   BOTONES Y ENLACES
   --------------------------------------------------------------------- */
.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

/* :active gana a :hover porque va después y tiene la misma especificidad.
   El botón se "hunde" al pulsarlo, que es la confirmación táctil. */
.btn:active {
  transform: translateY(1px);
  box-shadow: none;
}

.social a {
  transition: color var(--transition), border-color var(--transition),
              transform var(--transition);
}

.social a:hover {
  transform: translateY(-2px);
}

/* =========================================================================
   ACCESIBILIDAD — esto no es opcional
   =========================================================================
   Con "reducir movimiento" activado en el sistema, se anula TODO: las
   entradas, el revelado, la flotación y los desplazamientos del hover.

   Lo importante es que el contenido queda VISIBLE, no escondido. Un
   revelado que nunca se dispara dejaría media web en blanco, que es un
   fallo mucho peor que una animación de más.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .hero__kicker,
  .hero__title,
  .hero__claim,
  .hero .btn,
  .hero__media,
  .nav__toggle[aria-expanded="true"] + .nav__list {
    animation: none !important;
  }

  .reveal,
  .reveal.is-visible {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .timeline__item::after {
    opacity: 1 !important;
    transform: scale(1) !important;
  }

  .card:hover,
  .tier:hover,
  .btn--primary:hover,
  .social a:hover,
  .btn:active {
    transform: none !important;
  }

  .card:hover .card__media img,
  .card:hover .card__media .placeholder,
  .nav__toggle[aria-expanded="true"] .icon {
    transform: none !important;
  }
}
