This commit is contained in:
NotSoToothless
2026-06-07 20:11:16 -07:00
committed by GitHub
parent cd9ed02902
commit d0c3abd79a
+25 -15
View File
@@ -111,13 +111,7 @@
@media (min-width: 1024px) { @media (min-width: 1024px) {
.timeline { .timeline {
margin-top: 1.25rem; margin-top: 1.5rem;
/* Approx height of everything above row 1's bottom (header +
margin + row 1 cards). The row-1→row-2 gap is computed as
100vh minus this, so row 2 always lands just below the fold
on any viewport height. THIS is the one knob to tune: raise
it if there's too much empty void, lower it if row 2 peeks. */
--row1-fold-offset: 700px;
} }
.timeline-grid { .timeline-grid {
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
@@ -161,15 +155,12 @@
.timeline-node:nth-child(4) { grid-area: 2 / 3; } .timeline-node:nth-child(4) { grid-area: 2 / 3; }
.timeline-node:nth-child(5) { grid-area: 2 / 2; } .timeline-node:nth-child(5) { grid-area: 2 / 2; }
.timeline-node:nth-child(6) { grid-area: 2 / 1; } .timeline-node:nth-child(6) { grid-area: 2 / 1; }
/* Push row 2 below the fold so it stays hidden on load; the /* Static fallback gap before row 2; JS (applyFirstGap) overrides
connector line snakes down through this gap. Self-adjusts to this on desktop with a measured value so row 2 lands just below
viewport height: bigger void on 1440, smaller on 1080, with a the fold on any viewport height. */
3rem floor. Subtract 10rem for the grid's own row gap. */
.timeline-node:nth-child(4), .timeline-node:nth-child(4),
.timeline-node:nth-child(5), .timeline-node:nth-child(5),
.timeline-node:nth-child(6) { .timeline-node:nth-child(6) { margin-top: 8rem; }
margin-top: max(3rem, calc(100vh - var(--row1-fold-offset) - 10rem));
}
.timeline-node:nth-child(7) { grid-area: 3 / 1; } .timeline-node:nth-child(7) { grid-area: 3 / 1; }
.timeline-node:nth-child(8) { grid-area: 3 / 2; } .timeline-node:nth-child(8) { grid-area: 3 / 2; }
.timeline-node:nth-child(9) { grid-area: 3 / 3; } .timeline-node:nth-child(9) { grid-area: 3 / 3; }
@@ -299,7 +290,7 @@
<%- include('partials/nav', { activePage: 'timeline' }) %> <%- include('partials/nav', { activePage: 'timeline' }) %>
<!-- Header --> <!-- Header -->
<section class="pt-24 pb-6 lg:pt-28 lg:pb-8"> <section class="pt-28 pb-8 lg:pt-36 lg:pb-10">
<div class="max-w-[1400px] mx-auto px-6 lg:px-8 text-center"> <div class="max-w-[1400px] mx-auto px-6 lg:px-8 text-center">
<p class="text-muted text-sm font-semibold tracking-[0.25em] uppercase mb-4"><%= t('timeline.eyebrow') %></p> <p class="text-muted text-sm font-semibold tracking-[0.25em] uppercase mb-4"><%= t('timeline.eyebrow') %></p>
<h1 class="text-4xl lg:text-6xl font-extrabold mb-5 gradient-text"><%= t('timeline.heading') %></h1> <h1 class="text-4xl lg:text-6xl font-extrabold mb-5 gradient-text"><%= t('timeline.heading') %></h1>
@@ -459,8 +450,27 @@
return { x: x, y: y }; return { x: x, y: y };
} }
// Size the gap before row 2 so it sits just below the fold on load,
// measured from the real row-1 bottom and the real viewport height —
// no per-resolution magic numbers. Desktop (3-col) only.
function applyFirstGap() {
var rowTwo = [nodes[3], nodes[4], nodes[5]].filter(Boolean);
if (!rowTwo.length) return;
if (!window.matchMedia('(min-width: 1024px)').matches) {
rowTwo.forEach(function (n) { n.style.marginTop = ''; });
return;
}
// Measure row 2's natural top with no extra gap (grid row gap only).
rowTwo.forEach(function (n) { n.style.marginTop = '0px'; });
var top = rowTwo[0].getBoundingClientRect().top + window.pageYOffset;
// +32 so the marker (which pokes ~1.8rem above the node) clears too.
var gap = Math.max(48, (window.innerHeight + 32) - top);
rowTwo.forEach(function (n) { n.style.marginTop = gap + 'px'; });
}
function build() { function build() {
_samples = null; _samples = null;
applyFirstGap();
// Use layout dimensions (not getBoundingClientRect) so the SVG // Use layout dimensions (not getBoundingClientRect) so the SVG
// coordinate system matches the transform-independent getMarkerCenter. // coordinate system matches the transform-independent getMarkerCenter.
svg.setAttribute('viewBox', '0 0 ' + timeline.offsetWidth + ' ' + timeline.offsetHeight); svg.setAttribute('viewBox', '0 0 ' + timeline.offsetWidth + ' ' + timeline.offsetHeight);