From a3776ec03818bbce225b27af9543b144be951e44 Mon Sep 17 00:00:00 2001 From: NotSoToothless <67082114+FURRO404@users.noreply.github.com> Date: Sun, 7 Jun 2026 20:53:30 -0700 Subject: [PATCH] please (#1321) --- web/views/timeline.ejs | 69 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/web/views/timeline.ejs b/web/views/timeline.ejs index 775de6a..caaf88b 100644 --- a/web/views/timeline.ejs +++ b/web/views/timeline.ejs @@ -45,7 +45,7 @@ } @media (min-width: 1024px) { .timeline-hero { - padding-top: 8.5rem; /* clearance below the fixed nav */ + padding-top: 9.75rem; /* clearance below the fixed nav (~20px lower on tall screens) */ padding-bottom: 1.75rem; /* JS centering adds the rest of the hero→row1 gap */ } } @@ -295,6 +295,38 @@ 100% { top: 100%; } } + /* Full hint (text + animated line) only on tall desktop, where there's + a roomy void below the comet for it to sit in. */ + @media (min-width: 1024px) and (min-height: 1081px) { + #scroll-hint { display: flex; } + } + + /* Small bouncing arrow for shorter screens (and mobile), tucked just + under the comet's resting area. */ + #scroll-arrow { + display: flex; + position: fixed; + bottom: 1.4rem; + left: 50%; + transform: translateX(-50%); + z-index: 50; + color: rgba(144, 238, 144, 0.55); + font-size: 1.05rem; + pointer-events: none; + transition: opacity 0.5s ease; + animation: arrowBounce 1.6s ease-in-out infinite; + } + @media (min-width: 1024px) and (min-height: 1081px) { + #scroll-arrow { display: none; } + } + @keyframes arrowBounce { + 0%, 100% { transform: translateX(-50%) translateY(0); } + 50% { transform: translateX(-50%) translateY(6px); } + } + @media (prefers-reduced-motion: reduce) { + #scroll-arrow { animation: none; } + } + .timeline-node { position: relative; z-index: 2; @@ -389,11 +421,13 @@ - +
<%= t('timeline.scroll') %>
+ <%- include('partials/footer') %> @@ -591,7 +625,15 @@ var REVEAL_FRACTION = 0.85; function frontierProgress() { if (!pathLength || !_samples) return state.progress; - var revealY = window.innerHeight * REVEAL_FRACTION - timeline.getBoundingClientRect().top; + var tlTop = timeline.getBoundingClientRect().top; + var revealY = window.innerHeight * REVEAL_FRACTION - tlTop; + // The line/comet render behind the opaque cards, so never let the + // comet rest within column 3's card — keep it at least COMET_BAND + // below card 3's bottom (node index 2, the column the line descends). + if (nodes[2]) { + var card3Bottom = nodes[2].getBoundingClientRect().bottom - tlTop; + revealY = Math.max(revealY, card3Bottom + COMET_BAND); + } var frontierL = 0; for (var i = 0; i < _samples.length; i++) { if (_samples[i].y <= revealY) frontierL = _samples[i].l; @@ -704,8 +746,19 @@ }); } + // Fade both scroll hints out for good on the first scroll (CSS media + // queries decide which one is actually visible per screen size). + function setupScrollHints() { + var hints = [document.getElementById('scroll-hint'), + document.getElementById('scroll-arrow')]; + function hide() { hints.forEach(function (h) { if (h) h.style.opacity = '0'; }); } + if (window.scrollY > 8) { hide(); return; } + window.addEventListener('scroll', hide, { once: true, passive: true }); + } + function init() { build(); + setupScrollHints(); if (reduceMotion) { drawProgress = 1; state.progress = 1; @@ -717,16 +770,6 @@ createScrollTriggers(); ScrollTrigger.refresh(); updateFromScroll(); - - var hint = document.getElementById('scroll-hint'); - function hideScrollHint() { - if (!hint) return; - hint.style.opacity = '0'; - hint = null; - } - - if (window.scrollY > 8) hideScrollHint(); - window.addEventListener('scroll', hideScrollHint, { once: true, passive: true }); } else { advanceTo(1, 0); }