diff --git a/new front/css/style.css b/new front/css/style.css index d6b8c9f..5759b6e 100644 --- a/new front/css/style.css +++ b/new front/css/style.css @@ -4118,3 +4118,42 @@ or: var(--c-teal); .acc__q[aria-expanded="false"] + .acc__a p { padding-top: 0; } + +/* ========================================================= + Scroll reveal + each top-level section fades and rises into place the first + time it crosses into view; its cards cascade in right after + ========================================================= */ +@media (prefers-reduced-motion: no-preference) { + .reveal { + opacity: 0; + transform: translateY(2.5rem); + transition: + opacity 0.7s var(--ease), + transform 0.7s var(--ease); + } + + .reveal.is-visible { + opacity: 1; + transform: none; + } + + .reveal-item { + opacity: 0; + } + + .reveal-item.is-visible { + animation: card-rise 0.6s var(--ease) both; + } + + @keyframes card-rise { + from { + opacity: 0; + transform: translateY(1.5rem); + } + to { + opacity: 1; + transform: none; + } + } +} diff --git a/new front/js/main.js b/new front/js/main.js index fcd86ac..f909923 100644 --- a/new front/js/main.js +++ b/new front/js/main.js @@ -539,4 +539,36 @@ ticketForm.reset(); }); } + + /* ---------- scroll reveal: sections fade/rise in, cards cascade after ---------- */ + var reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; + if (!reduceMotion && 'IntersectionObserver' in window) { + var revealSections = Array.prototype.slice.call(document.querySelectorAll('#main > section')); + var cardSelector = '.dcard, .acard, .titem, .rcard, .quote, .statcard'; + var groupCounts = new Map(); + + revealSections.forEach(function (section) { + section.classList.add('reveal'); + Array.prototype.forEach.call(section.querySelectorAll(cardSelector), function (card) { + var group = card.parentElement; + var i = groupCounts.get(group) || 0; + groupCounts.set(group, i + 1); + card.classList.add('reveal-item'); + card.style.animationDelay = (Math.min(i, 7) * 0.07) + 's'; + }); + }); + + var revealObserver = new IntersectionObserver(function (entries, obs) { + entries.forEach(function (entry) { + if (!entry.isIntersecting) return; + entry.target.classList.add('is-visible'); + Array.prototype.forEach.call(entry.target.querySelectorAll('.reveal-item'), function (item) { + item.classList.add('is-visible'); + }); + obs.unobserve(entry.target); + }); + }, { threshold: 0.15, rootMargin: '0px 0px -8% 0px' }); + + revealSections.forEach(function (section) { revealObserver.observe(section); }); + } })();