tune overview anchors + stack-title-bar placement
- SCENE_ANCHOR_OFFSET replaced with getSceneAnchorOffset() so the bifrost scene can compute its offset per-viewport instead of using a fixed px count. bifrost lands at offsetTop + 0.85 * vh so the arc and sub-headline are already drawn in; stack-scene drops from 2100 to 1800 so the anchor lands mid-stack rather than on the 4th card's final beat. - .stack-title-bar top drops from clamp(3.75rem, 7vh, 5.25rem) to clamp(1.25rem, 2.8vh, 1.85rem) so the title floats at the same vertical baseline as the fixed .site-mark wordmark in the top-left, instead of sitting below it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9b2c166b6c
commit
5f466e68a9
2 changed files with 29 additions and 23 deletions
|
|
@ -1232,24 +1232,30 @@
|
||||||
* — see sceneOrder[] inside init().
|
* — see sceneOrder[] inside init().
|
||||||
* Special value "hero" scrolls to top (0).
|
* Special value "hero" scrolls to top (0).
|
||||||
*/
|
*/
|
||||||
// Per-scene scroll offsets in pixels. Added to the scene's offsetTop
|
// Per-scene scroll offsets. Added to the scene's offsetTop when a
|
||||||
// when a dot-nav button anchors to it, so the reader lands AFTER the
|
// dot-nav button anchors to it, so the reader lands AFTER the scene's
|
||||||
// scene's initial reveal rather than at an empty frame where the
|
// initial reveal rather than at an empty pre-scrub frame.
|
||||||
// scrub hasn't advanced yet.
|
|
||||||
//
|
//
|
||||||
// stack-scene — the pin is 5000px long; Phase A (cards falling in)
|
// stack-scene — pin is 5000px long; Phase A (cards falling in) is
|
||||||
// completes at ~0.42 of that (~2100px). Landing at +2100 puts
|
// complete at ~0.42 of that (~2100px). 1800 lands just before the
|
||||||
// the reader on the fully stacked state, just before the grid
|
// 4th card fully settles, so the reveal still has one tick to go.
|
||||||
// rearrange begins in Phase B.
|
|
||||||
//
|
//
|
||||||
// hero, bifrost, bifrost-join — short reveal tweens; offsetTop is
|
// bifrost — section is 200vh with a scrubbed reveal that runs from
|
||||||
// already the correct landing spot so offset is 0.
|
// top-top to bottom-bottom (100vh scroll range). The sub-headline
|
||||||
const SCENE_ANCHOR_OFFSET = {
|
// fades in at ~0.83 of that. Offset is computed per viewport as
|
||||||
'hero': 0,
|
// 85% of vh so the reader arrives on the fully-drawn arc +
|
||||||
'stack-scene': 2100,
|
// wordmark, regardless of display size.
|
||||||
'bifrost': 0,
|
//
|
||||||
'bifrost-join': 0,
|
// hero, bifrost-join — short reveal tweens; offsetTop is already
|
||||||
};
|
// the correct landing spot so offset is 0.
|
||||||
|
function getSceneAnchorOffset(sceneId) {
|
||||||
|
const vh = window.innerHeight;
|
||||||
|
switch (sceneId) {
|
||||||
|
case 'stack-scene': return 1800;
|
||||||
|
case 'bifrost': return Math.round(vh * 0.85);
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function scrollTo(sceneId) {
|
function scrollTo(sceneId) {
|
||||||
if (!scrollerEl) return; // init() hasn't run yet — ignore
|
if (!scrollerEl) return; // init() hasn't run yet — ignore
|
||||||
|
|
@ -1260,7 +1266,7 @@
|
||||||
// the scene element directly works in most cases but produces a tiny
|
// the scene element directly works in most cases but produces a tiny
|
||||||
// non-zero offset (padding / border) — hard-code 0 for hero.
|
// non-zero offset (padding / border) — hard-code 0 for hero.
|
||||||
const base = sceneId === 'hero' ? 0 : target.offsetTop;
|
const base = sceneId === 'hero' ? 0 : target.offsetTop;
|
||||||
const scrollY = base + (SCENE_ANCHOR_OFFSET[sceneId] || 0);
|
const scrollY = base + getSceneAnchorOffset(sceneId);
|
||||||
|
|
||||||
if (lenisInstance && typeof lenisInstance.scrollTo === 'function') {
|
if (lenisInstance && typeof lenisInstance.scrollTo === 'function') {
|
||||||
// Lenis does the smooth animation. `immediate: false` uses the
|
// Lenis does the smooth animation. `immediate: false` uses the
|
||||||
|
|
|
||||||
|
|
@ -1076,13 +1076,13 @@ html {
|
||||||
.sc-current token is updated from bifrost.js's ScrollTrigger onUpdate
|
.sc-current token is updated from bifrost.js's ScrollTrigger onUpdate
|
||||||
— 1/4 → 4/4 — one tick per landing card.
|
— 1/4 → 4/4 — one tick per landing card.
|
||||||
|
|
||||||
Vertical offset clears the fixed .site-mark (top:28px, width:118px)
|
Vertical top is aligned with the fixed .site-mark (top:28px) so
|
||||||
so the title sits below the wordmark instead of crashing into it.
|
the title rides beside the wordmark at the very top of the scene,
|
||||||
Horizontal padding on the left is bumped to push past the wordmark's
|
floating horizontally at the same baseline. Horizontal padding on
|
||||||
right edge; the right side uses the same edge token as the theatre. */
|
the left is sized to clear the wordmark's right edge (~146px). */
|
||||||
.stack-title-bar {
|
.stack-title-bar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: clamp(3.75rem, 7vh, 5.25rem);
|
top: clamp(1.25rem, 2.8vh, 1.85rem);
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
|
|
@ -1090,7 +1090,7 @@ html {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
padding-left: clamp(10.5rem, 12vw, 12.5rem);
|
padding-left: clamp(10rem, 12vw, 12rem);
|
||||||
padding-right: clamp(0.75rem, 2vw, 2.25rem);
|
padding-right: clamp(0.75rem, 2vw, 2.25rem);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue