// ── Pepsi gallery: shuffled on load, swipe cycles through on click ─ (function () { const COUNT = 20; const img = document.querySelector('.pepsi-placeholder img'); if (!img) return; const box = img.parentElement; const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); const src = (n) => `Pepsi/Pepsi-${n}.jpg`; // Fisher–Yates shuffle of [1..COUNT]; clicks cycle through this order const order = Array.from({ length: COUNT }, (_, i) => i + 1); for (let i = order.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [order[i], order[j]] = [order[j], order[i]]; } let pos = 0; img.src = src(order[pos]); const seen = (n) => { if (window.achv) window.achv.pepsi(n, COUNT); }; seen(order[pos]); let busy = false; box.addEventListener('click', () => { if (busy) return; if (window.achv) window.achv.mark('pepsi'); pos = (pos + 1) % order.length; const next = order[pos]; if (reduceMotion.matches) { img.src = src(next); seen(next); return; } busy = true; const incoming = new Image(); incoming.src = src(next); incoming.alt = img.alt; incoming.draggable = false; incoming.className = 'pepsi-incoming'; // Decode before animating so the swipe never reveals a half-loaded frame incoming.decode().then(() => { box.appendChild(incoming); seen(next); const opts = { duration: 300, easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' }; img.animate( [{ transform: 'translateX(0)' }, { transform: 'translateX(-100%)' }], opts ); incoming.animate( [{ transform: 'translateX(100%)' }, { transform: 'translateX(0)' }], opts ).finished.then(() => { img.src = incoming.src; // already decoded, swaps instantly incoming.remove(); busy = false; }); }).catch(() => { busy = false; }); }); })();