fix(recorrido): no se puede quedar entre dos estados

Las tarjetas iban atadas a la posición del scroll, así que cualquier
punto intermedio era un fotograma válido: parando a media rueda, la
tarjeta de creeer se quedaba como una losa gris translúcida y parecía un
fallo de render.

Ahora el scroll solo elige el tiempo —doce: pregunta, respuesta,
pregunta…— y las tarjetas animan hacia ese tiempo por duración. Pares
donde pares, aterrizan. Verificado en 41 paradas repartidas por la
sección: cero opacidades a medias.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
erikghandClaude Opus 5 committed 2026-08-03 11:58:08 -06:00
1 parent 81c36bb657
commit 379d80b915
2 files changed
+70 -65

No files matched your search

+12 -3
View File
@@ -88,10 +88,17 @@ function Escenificado() {
// hilo conductor taught this project what an overdamped spring feels like.
const progreso = useSpring(bruto, { stiffness: 260, damping: 42, restDelta: 0.0005 });
const [activo, setActivo] = useState(0);
// Twelve beats, not a continuum: question, answer, question, answer… Scroll
// picks the beat and nothing else. When the cards were driven straight off
// the scroll value, every position in between was a frame you could stop on,
// and creeer's card sat there as a half-transparent grey slab.
const TIEMPOS = TOTAL * 2;
const [tiempo, setTiempo] = useState(0);
useMotionValueEvent(progreso, 'change', (v) => {
setActivo(Math.min(TOTAL - 1, Math.max(0, Math.floor(v * TOTAL))));
setTiempo(Math.min(TIEMPOS - 1, Math.max(0, Math.floor(v * TIEMPOS))));
});
const activo = Math.floor(tiempo / 2);
const respondida = tiempo % 2 === 1;
const barra = useTransform(progreso, [0, 1], [0, 1]);
const fondoY = useTransform(progreso, [0, 1], [0, -140]);
@@ -104,7 +111,7 @@ function Escenificado() {
{/* One viewport of stage, six viewports of scroll to move through it. */}
<div ref={contenedor} className="relative" style={{ height: `${TOTAL * 100}vh` }}>
<div data-escena={activo} className="sticky top-0 h-screen overflow-hidden">
<div data-escena={activo} data-tiempo={tiempo} className="sticky top-0 h-screen overflow-hidden">
<motion.div style={{ y: fondoY }} className="absolute inset-0">
<FondoPuntos className="-bottom-10 -right-16 w-80 md:w-[34rem] text-azul-profundo/10" distance={32} />
</motion.div>
@@ -140,6 +147,8 @@ function Escenificado() {
i={i}
total={TOTAL}
progreso={progreso}
activa={i === activo}
respondida={i === activo && respondida}
n={String(i + 1).padStart(2, '0')}
{...item}
/>