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 @@
-
+
+
<%- 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);
}