From dbc3eba0b327ec5085363cbaaf8e5f56df0e2c26 Mon Sep 17 00:00:00 2001 From: man4ish Date: Sun, 4 Oct 2026 01:55:37 -0500 Subject: [PATCH] Refine landing page animations --- index.html | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 902d7ba..dfdbfc6 100644 --- a/index.html +++ b/index.html @@ -96,6 +96,10 @@ .live-stat-sep{opacity:0.5} .site-data-status{margin-top:0.5rem;font-family:'JetBrains Mono',monospace;font-size:0.62rem;color:var(--text-dim)} .site-data-status[data-state="error"]{color:#d99a55} +.reveal-on-scroll{opacity:0;transform:translateY(18px);transition:opacity .65s ease,transform .65s cubic-bezier(.22,1,.36,1)} +.reveal-on-scroll.is-visible{opacity:1;transform:none} +.live-stat-num.updated{animation:metric-update .7s ease-out} +@keyframes metric-update{0%{text-shadow:0 0 0 transparent}45%{text-shadow:0 0 16px rgba(0,212,170,.8)}100%{text-shadow:0 0 0 transparent}} /* ── Tag marquee ── */ .tag-marquee{position:relative;width:100%;max-width:1120px;margin-top:2.75rem;overflow:hidden;-webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)} @@ -104,6 +108,7 @@ .marquee-tag{font-family:'JetBrains Mono',monospace;font-size:0.65rem;color:var(--text-dim);background:rgba(255,255,255,0.03);border:1px solid var(--border);border-radius:2px;padding:0.3rem 0.7rem;letter-spacing:0.04em;white-space:nowrap;flex-shrink:0} @keyframes tag-marquee-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}} @media(prefers-reduced-motion:reduce){.tag-marquee-track{animation:none}} +@media(prefers-reduced-motion:reduce){.reveal-on-scroll{opacity:1;transform:none;transition:none}.live-stat-num.updated{animation:none}} /* ── Sections ── */ section{position:relative;z-index:1;padding:6rem 2rem;max-width:1180px;margin:0 auto} @@ -1522,6 +1527,25 @@

Request Access

/* Keep catalog figures data-driven while retaining the server-rendered values as an offline fallback. The JSON is one versioned source for all mirrored counts on this page. */ +(function(){ + var reduceMotion=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches; + var sections=document.querySelectorAll('section'); + if(reduceMotion||!('IntersectionObserver' in window)){ + Array.prototype.forEach.call(sections,function(section){section.classList.add('is-visible')}); + return; + } + var observer=new IntersectionObserver(function(entries){ + entries.forEach(function(entry){ + if(!entry.isIntersecting)return; + entry.target.classList.add('is-visible'); + observer.unobserve(entry.target); + }); + },{threshold:0.12,rootMargin:'0px 0px -8%'}); + Array.prototype.forEach.call(sections,function(section){ + section.classList.add('reveal-on-scroll'); + observer.observe(section); + }); +})(); (function(){ var status=document.getElementById('site-data-status'); var cacheKey='omnibioai-site-data-v1'; @@ -1689,6 +1713,11 @@

Request Access

}); track.appendChild(frag); track.style.animationDuration=Math.max(24,names.length*0.9)+'s'; + var marquee=track.parentElement; + function pause(){track.style.animationPlayState='paused'} + function resume(){track.style.animationPlayState=''} + marquee.addEventListener('focusin',pause); + marquee.addEventListener('focusout',resume); })(); (function(){ var el=document.getElementById('hero-rotator'); @@ -1704,7 +1733,7 @@

Request Access

el.textContent=phrases[i]; el.classList.remove('fade'); },320); - },2600); + },3600); })(); (function(){ var wrap=document.getElementById('live-ecosystem-stats'); @@ -1714,14 +1743,19 @@

Request Access

if(!wrap||!elLines||!elRepos||!elCoverage)return; var reduceMotion=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches; function animateNumber(el,target,format,duration){ - if(reduceMotion){el.textContent=format(target);return} + function markUpdated(){ + el.classList.remove('updated'); + void el.offsetWidth; + el.classList.add('updated'); + } + if(reduceMotion){el.textContent=format(target);markUpdated();return} var start=null; function step(ts){ if(!start)start=ts; var p=Math.min(1,(ts-start)/duration); var eased=1-Math.pow(1-p,3); el.textContent=format(target*eased); - if(p<1)requestAnimationFrame(step); + if(p<1)requestAnimationFrame(step);else markUpdated(); } requestAnimationFrame(step); }