diff --git a/src/pages/index.astro b/src/pages/index.astro
index 03994dc..c373d75 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -125,12 +125,26 @@ const canonical = new URL('/', Astro.site);
+
+
+ 03 / Machine fabric
+ Hydrangea ↗
+
+ Not kept anywhere — alive everywhere, whole wherever you meet it.
+
+
+
01
/
- 02
+ 03
@@ -138,6 +152,7 @@ const canonical = new URL('/', Astro.site);
+
@@ -510,9 +525,12 @@ const canonical = new URL('/', Astro.site);
row-gap: clamp(2.75rem, 7vh, 6rem);
}
+ /* Scroll length is per story beat, not a fixed page height: a card added to the
+ stack has to lengthen this or every beat gets shorter. Sized so three beats each
+ hold the stage for about as long as the two-card stack gave one. */
.hero-lead.has-scroll-stack {
position: relative;
- min-height: clamp(54rem, 145svh, 84rem);
+ min-height: clamp(66rem, 178svh, 103rem);
align-items: stretch;
}
@@ -548,7 +566,8 @@ const canonical = new URL('/', Astro.site);
.is-stacked-stack .technology-stack {
width: min(100%, 28rem);
min-width: 0;
- min-height: 100svh;
+ /* Same per-beat rule as the two-column stack above, at this fallback's own pace. */
+ min-height: 130svh;
margin-top: clamp(3.25rem, 9vh, 6rem);
margin-left: auto;
}
@@ -812,12 +831,26 @@ const canonical = new URL('/', Astro.site);
position: absolute;
inset: 0;
display: none;
- grid-template-rows: repeat(2, minmax(0, 1fr));
pointer-events: none;
}
+ /* Deliberately not equal shares. A step box is read against a band across the
+ middle of the viewport, and the stack's own top edge starts well below it, so
+ the opening box has to be the longest simply to reach that band — split evenly,
+ the first product would flick past in a third of the scroll the middle one gets.
+ Measured against the rendered page: these hold each product for within ~10% of
+ the same distance from 700px to 1100px tall. */
.is-scroll-stack .technology-steps {
display: grid;
+ grid-template-rows: 44% 19% 37%;
+ }
+
+ /* The wrapped fallback pins its card near the top of the viewport rather than at
+ the middle of a column, so the opening box reaches the band far sooner and needs
+ the smallest share here, not the largest. Declared after the rule above because
+ the two selectors weigh the same. */
+ .is-stacked-stack .technology-steps {
+ grid-template-rows: 20% 32% 48%;
}
.footer {
@@ -982,9 +1015,11 @@ const canonical = new URL('/', Astro.site);
}
/* Scroll length for the story, and nothing else — the card no longer spends any
- of it travelling, so a full viewport of it would read as a dead stretch. */
+ of it travelling, so a full viewport of it would read as a dead stretch. Holds
+ the phone's pace from the two-card stack across three beats rather than making
+ the story a third longer again. */
.has-scroll-stack .technology-stack {
- min-height: 70svh;
+ min-height: 90svh;
}
/* The script pins this at the card's own resting offset. The clamp is the fallback
@@ -998,12 +1033,12 @@ const canonical = new URL('/', Astro.site);
min-height: 11.9rem;
}
- /* Keep Nucleic alone for roughly the first half of the scroll, then move directly
- into the next product without the old empty stretch between story beats. The
- split is below half because the step boxes are read against a band at the middle
- of the viewport, which the stack's own top edge starts well below. */
+ /* The same unequal split as the desktop stack, retuned: a phone's step boxes are
+ read against the same centre band, but the stack starts much further down its
+ own scroll, so the opening share is larger again. Measured across 640–932px
+ tall, these keep the three products within ~25% of one another. */
.is-scroll-stack .technology-steps {
- grid-template-rows: 23% 77%;
+ grid-template-rows: 29% 19% 52%;
}
/* One line each: side by side these two need ~360px of tracking-heavy mono, which
@@ -1235,10 +1270,14 @@ const canonical = new URL('/', Astro.site);
}
};
+ /* A card waits below the active one and leaves above it, so which side of the
+ composition a given card sits on depends on where the story currently is — the
+ markup class is only the resting state of the stack before any of this runs. */
const activateTechnology = (index: number) => {
cards.forEach((card, cardIndex) => {
const isActive = cardIndex === index;
card.classList.toggle('is-active', isActive);
+ card.classList.toggle('product-card-next', cardIndex > index);
card.toggleAttribute('inert', !isActive);
card.setAttribute('aria-hidden', String(!isActive));
});