/*
  Componente: sabor-scroll
  Secuencia de imágenes controlada por scroll (scroll-scrubbing), por sabor.

  Dos motores posibles:
    1. Nativo: animation-timeline: view() — cero JS, solo en navegadores que
       lo soportan (bloque @supports al final de este archivo).
    2. Fallback JS: src/scripts/sabor-scroll.js escribe opacity inline por
       frame en cada tick. Ver docs/ARCHITECTURE.md para el detalle del
       mecanismo y por qué ambos caminos dividen el scroll en 16 dieciseisavos
       iguales, con crossfade entre frames consecutivos.

  Cada sección mide 100vh (el viewport visible) + (frame-count * frame-step)
  de scroll adicional: eso es lo que se "consume" mientras el contenedor
  sticky permanece fijo en pantalla. Con 16 frames y frame-step: 150px, son
  2400px de scroll dedicados exclusivamente a esa sección — el mismo carril
  total que con 8 frames, ahora repartido más fino (150px por frame en vez
  de 300px) para que el avance se perciba más continuo.
*/

.sabor-scroll {
  --frame-count: 16;
  --frame-step: 150px;
  position: relative;
  isolation: isolate;
  min-height: calc(100vh + (var(--frame-count) * var(--frame-step)));
}

.sabor-scroll[data-sabor="chocolate-belga"] {
  background-color: var(--color-bg-alt);
}

.sabor-scroll[data-sabor="nuez-cajeta"] {
  background-color: #f6e6c4;
}

.sabor-scroll[data-sabor="avena-chispas"] {
  background-color: var(--color-bg);
}

.sabor-scroll__sticky {
  position: sticky;
  top: var(--header-height);
  height: calc(100vh - var(--header-height));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding-block: var(--space-8);

  /* Estado por defecto: visible sin animar (progressive enhancement).
     Sin JS ni soporte nativo, el contenido simplemente se queda así. */
  --sabor-opacity: 1;
  --sabor-scale: 1;
  --sabor-translate: 0px;
  opacity: var(--sabor-opacity);
  transform: scale(var(--sabor-scale)) translateY(var(--sabor-translate));
  will-change: opacity, transform;
}

.sabor-scroll__frames {
  position: relative;
  width: min(72vw, 440px);
  aspect-ratio: 1 / 1;
  flex-shrink: 0;

  /* Parallax de mouse (src/scripts/parallax.js, solo mouse/desktop) — un
     desplazamiento leve e independiente de todo lo demás en este
     elemento, así que no compite con nada del scroll-scrubbing. */
  --parallax-frames-x: 0px;
  --parallax-frames-y: 0px;
  transform: translate(var(--parallax-frames-x), var(--parallax-frames-y));
}

.sabor-scroll__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
}

/* Estado inicial servido en el HTML: frame 0 visible antes de que corra
   cualquier motor (no-JS, o el instante antes de que el fallback JS haga su
   primer tick). En cuanto un motor toma el control — animación nativa u
   opacity inline por JS — esta regla queda sobrescrita, así que nunca deja
   un frame viejo "pegado" fuera de su turno. */
.sabor-scroll__frame.is-active {
  opacity: 1;
}

.sabor-scroll__content {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 26rem;
  margin-inline: auto;
  margin-block-start: var(--space-6);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-lg);
  background-color: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: var(--shadow-md);
  text-align: center;

  --sabor-content-translate: 0px;
  /* --parallax-content-x: mismo parallax de mouse que .sabor-scroll__frames,
     pero más leve y en dirección opuesta (el texto se mueve menos que el
     producto: sensación de profundidad, no un efecto 3D pesado). Se
     combina con --sabor-content-translate (el fade de entrada/salida
     ligado al scroll) en el mismo transform: translate(); el motor nativo
     hace lo mismo dentro de @keyframes sabor-content más abajo, para que
     el parallax también funcione ahí sin pisar la animación de scroll. */
  --parallax-content-x: 0px;
  transform: translate(var(--parallax-content-x), var(--sabor-content-translate));
}

.sabor-scroll__eyebrow {
  display: block;
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-dark);
  margin-block-end: var(--space-2);
}

.sabor-scroll__title {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  line-height: var(--lh-tight);
}

.sabor-scroll__description {
  margin-block-start: var(--space-3);
  color: var(--color-text-muted);
}

/* Selector de presentación (Individual / Caja de 6 / ...) — las opciones
   son las presentaciones de ESE sabor, generadas por render-sabores.js a
   partir de catalogo.json. Elegir una actualiza .sabor-scroll__price. */
.sabor-scroll__presentaciones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-block-start: var(--space-4);
}

.sabor-scroll__presentacion-btn {
  padding: var(--space-2) var(--space-4);
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background-color: var(--color-surface);
  color: var(--color-text);
  font-size: var(--fs-small);
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--transition-base), background-color var(--transition-base),
    color var(--transition-base);
}

.sabor-scroll__presentacion-btn:hover {
  border-color: var(--color-accent-dark);
}

.sabor-scroll__presentacion-btn.is-selected {
  background-color: var(--color-brown-900);
  border-color: var(--color-brown-900);
  color: var(--color-cream);
}

.sabor-scroll__price {
  margin-block-start: var(--space-3);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  color: var(--color-brown-700);
}

.sabor-scroll__cta {
  margin-block-start: var(--space-5);
}

/* ------------------------------------------------------------------ */
/* Motor nativo: scroll-driven animations (Chrome/Edge recientes)      */
/* ------------------------------------------------------------------ */

@supports (animation-timeline: view()) {
  .sabor-scroll {
    view-timeline-name: --sabor-view;
    view-timeline-axis: block;
  }

  .sabor-scroll__sticky {
    animation-name: sabor-weight;
    animation-timeline: --sabor-view;
    animation-fill-mode: both;
    animation-duration: 1ms; /* ignorado: la duración real la da el timeline */
  }

  .sabor-scroll__content {
    animation-name: sabor-content;
    animation-timeline: --sabor-view;
    animation-fill-mode: both;
    animation-duration: 1ms;
  }

  .sabor-scroll__frame {
    animation-name: sabor-frame;
    animation-timeline: --sabor-view;
    animation-fill-mode: both;
    animation-duration: 1ms;
  }

  /* 16 dieciseisavos del scroll total de la sección (frame N va de
     N*6.25% a (N+1)*6.25%), pero el animation-range de cada frame arranca
     un poco ANTES de su dieciseisavo — extendido hacia atrás un 15% del
     ancho de un frame (0.9375 puntos porcentuales) — para que ese tramo
     extra se solape exactamente con la cola del frame anterior. El frame 0
     no tiene de dónde tomar ese margen (no hay frame -1), así que su rango
     arranca en 0% sin extender. Ver frameAlpha() en sabor-scroll.js para el
     razonamiento completo de por qué el traslape tiene que ser una ventana
     COMPARTIDA entre dos frames, no dos rampas en ventanas contiguas. */
  .sabor-scroll__frame[data-frame="0"] { animation-range: 0% 6.25%; }
  .sabor-scroll__frame[data-frame="1"] { animation-range: 5.3125% 12.5%; }
  .sabor-scroll__frame[data-frame="2"] { animation-range: 11.5625% 18.75%; }
  .sabor-scroll__frame[data-frame="3"] { animation-range: 17.8125% 25%; }
  .sabor-scroll__frame[data-frame="4"] { animation-range: 24.0625% 31.25%; }
  .sabor-scroll__frame[data-frame="5"] { animation-range: 30.3125% 37.5%; }
  .sabor-scroll__frame[data-frame="6"] { animation-range: 36.5625% 43.75%; }
  .sabor-scroll__frame[data-frame="7"] { animation-range: 42.8125% 50%; }
  .sabor-scroll__frame[data-frame="8"] { animation-range: 49.0625% 56.25%; }
  .sabor-scroll__frame[data-frame="9"] { animation-range: 55.3125% 62.5%; }
  .sabor-scroll__frame[data-frame="10"] { animation-range: 61.5625% 68.75%; }
  .sabor-scroll__frame[data-frame="11"] { animation-range: 67.8125% 75%; }
  .sabor-scroll__frame[data-frame="12"] { animation-range: 74.0625% 81.25%; }
  .sabor-scroll__frame[data-frame="13"] { animation-range: 80.3125% 87.5%; }
  .sabor-scroll__frame[data-frame="14"] { animation-range: 86.5625% 93.75%; }
  .sabor-scroll__frame[data-frame="15"] { animation-range: 92.8125% 100%; }

  /* Crossfade entre frames consecutivos: dentro del animation-range ya
     extendido de cada frame (ver arriba), el frame rampa 0→1 en el primer
     13.04% (ese es el tramo prestado de la cola del frame anterior), se
     sostiene en opacity: 1 el resto, y rampa 1→0 en el último 13.04% (el
     tramo que le presta a la entrada del siguiente). Como el rango de cada
     frame ya está corrido hacia atrás, la rampa de salida del frame N y la
     rampa de entrada del frame N+1 ocurren sobre el MISMO tramo de scroll
     — ahí es donde de verdad se traslapan (uno desvaneciéndose mientras el
     otro aparece), no dos rampas en tramos contiguos que solo se tocan en
     un punto. fill-mode: both mantiene ese opacity: 0 de los extremos
     fuera del rango también, para que un frame no se quede visible después
     de su turno. */
  @keyframes sabor-frame {
    0% {
      opacity: 0;
    }
    13.04% {
      opacity: 1;
    }
    86.96% {
      opacity: 1;
    }
    100% {
      opacity: 0;
    }
  }

  /* Peso de la transición entre secciones: la sección entra/sale con un
     leve fundido + escala, en vez de cortar seco. Ocupa el 15% inicial y
     el 15% final del scroll de la sección; el 70% de en medio (donde
     avanzan los frames) se mantiene a opacidad/escala completa. */
  @keyframes sabor-weight {
    0% {
      opacity: 0;
      transform: scale(0.94) translateY(40px);
    }
    15% {
      opacity: 1;
      transform: scale(1) translateY(0);
    }
    85% {
      opacity: 1;
      transform: scale(1) translateY(0);
    }
    100% {
      opacity: 0;
      transform: scale(0.94) translateY(-40px);
    }
  }

  /* La X de cada keyframe lee var(--parallax-content-x) en vez de un valor
     fijo — las custom properties se resuelven en cada recálculo de estilo,
     así que esto sigue reaccionando en vivo a lo que escribe parallax.js
     aunque la animación (la Y) la siga manejando por completo el scroll. */
  @keyframes sabor-content {
    0% {
      opacity: 0;
      transform: translate(var(--parallax-content-x, 0px), 20px);
    }
    15% {
      opacity: 1;
      transform: translate(var(--parallax-content-x, 0px), 0px);
    }
    85% {
      opacity: 1;
      transform: translate(var(--parallax-content-x, 0px), 0px);
    }
    100% {
      opacity: 0;
      transform: translate(var(--parallax-content-x, 0px), -20px);
    }
  }
}
