Keep the hero logo on screen while it scales down on scroll.

The sticky stage was scrolling away, so the title clipped under the header and left an empty gap above the next section.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Artemii Peretiachenko 2026-09-24 19:26:37 +02:00
parent 8dac694a3c
commit f6d611aec1
10 changed files with 81 additions and 19 deletions

View file

@ -87,6 +87,23 @@ function initHeroScroll(config){
const siteHeader = document.querySelector('.site-header'); const siteHeader = document.querySelector('.site-header');
const mainNav = document.querySelector('.main-nav'); const mainNav = document.querySelector('.main-nav');
let heroPin = null;
if (section && !section.parentElement?.classList.contains('hero-scroll')){
const heroScroll = document.createElement('div');
heroScroll.className = 'hero-scroll';
section.parentElement.insertBefore(heroScroll, section);
heroScroll.appendChild(section);
}
if (section?.parentElement?.classList.contains('hero-scroll')){
heroPin = section.parentElement.querySelector(':scope > .hero-pin');
if (!heroPin){
heroPin = document.createElement('div');
heroPin.className = 'hero-pin';
heroPin.setAttribute('aria-hidden', 'true');
section.parentElement.appendChild(heroPin);
}
}
let cachedBaseHeight = 0; let cachedBaseHeight = 0;
let cachedBrandGap = 32; let cachedBrandGap = 32;
let cachedMaxScale = 1.9; let cachedMaxScale = 1.9;
@ -113,6 +130,7 @@ function initHeroScroll(config){
heroRoot.style.removeProperty('--hero-nav-shift-max'); heroRoot.style.removeProperty('--hero-nav-shift-max');
heroRoot.style.removeProperty('--hero-scroll-start'); heroRoot.style.removeProperty('--hero-scroll-start');
heroRoot.style.removeProperty('--hero-scroll-end'); heroRoot.style.removeProperty('--hero-scroll-end');
heroRoot.style.removeProperty('--hero-pin-space');
if (brandInner){ if (brandInner){
brandInner.style.removeProperty('animation-range'); brandInner.style.removeProperty('animation-range');
brandInner.style.removeProperty('animation-timeline'); brandInner.style.removeProperty('animation-timeline');
@ -304,6 +322,19 @@ function initHeroScroll(config){
updateHeroBrand(); updateHeroBrand();
updateHeroContentLift(); updateHeroContentLift();
syncHeroPinSpace();
}
function syncHeroPinSpace(){
if (!section || heroIsMobile || prefersReducedMotion || heroRunway <= 0){
heroRoot.style.removeProperty('--hero-pin-space');
return;
}
const runway = getHeroEffectiveRunway();
const progress = runway > 0 ? Math.min(getHeroScrollProgress() / runway, 1) : 1;
const multiplier = getHeroScrollRunwayMultiplier();
const spacer = heroRunway * Math.max(multiplier - 1, 0) * (1 - progress);
heroRoot.style.setProperty('--hero-pin-space', `${spacer}px`);
} }
function updateHeroBrand(){ function updateHeroBrand(){
@ -335,6 +366,7 @@ function initHeroScroll(config){
heroRoot.style.setProperty('--hero-scale', scale.toFixed(4)); heroRoot.style.setProperty('--hero-scale', scale.toFixed(4));
heroRoot.style.setProperty('--hero-brand-height', `${brandHeight}px`); heroRoot.style.setProperty('--hero-brand-height', `${brandHeight}px`);
heroRoot.style.setProperty('--hero-stage-height', `${brandHeight + cachedNavHeight}px`); heroRoot.style.setProperty('--hero-stage-height', `${brandHeight + cachedNavHeight}px`);
syncHeroPinSpace();
} }
let heroScrollRaf = 0; let heroScrollRaf = 0;

View file

@ -88,7 +88,7 @@
} }
})(); })();
</script> </script>
<link rel="stylesheet" href="/styles.css?v=20260923k"> <link rel="stylesheet" href="/styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -446,7 +446,7 @@
</div> </div>
<link rel="stylesheet" href="/fonts/inter.css"> <link rel="stylesheet" href="/fonts/inter.css">
<script src="/common.js?v=20260923d"></script> <script src="/common.js?v=20260924d"></script>
<script src="/app.js"></script> <script src="/app.js"></script>
</body> </body>

View file

@ -88,7 +88,7 @@
} }
})(); })();
</script> </script>
<link rel="stylesheet" href="/styles.css?v=20260923k"> <link rel="stylesheet" href="/styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -296,7 +296,7 @@
</div> </div>
<link rel="stylesheet" href="/fonts/inter.css"> <link rel="stylesheet" href="/fonts/inter.css">
<script src="/common.js?v=20260923d"></script> <script src="/common.js?v=20260924d"></script>
<script src="/terminal.js"></script> <script src="/terminal.js"></script>
</body> </body>

View file

@ -88,7 +88,7 @@
} }
})(); })();
</script> </script>
<link rel="stylesheet" href="/styles.css?v=20260923k"> <link rel="stylesheet" href="/styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -446,7 +446,7 @@
</div> </div>
<link rel="stylesheet" href="/fonts/inter.css"> <link rel="stylesheet" href="/fonts/inter.css">
<script src="/common.js?v=20260923d"></script> <script src="/common.js?v=20260924d"></script>
<script src="/app.js"></script> <script src="/app.js"></script>
</body> </body>

View file

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
{{HEAD_META}} {{HEAD_META}}
{{LANG_REDIRECT_SCRIPT}} {{LANG_REDIRECT_SCRIPT}}
<link rel="stylesheet" href="{{ASSET_PREFIX}}styles.css?v=20260923k"> <link rel="stylesheet" href="{{ASSET_PREFIX}}styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -359,7 +359,7 @@
</div> </div>
<link rel="stylesheet" href="{{ASSET_PREFIX}}fonts/inter.css"> <link rel="stylesheet" href="{{ASSET_PREFIX}}fonts/inter.css">
<script src="{{ASSET_PREFIX}}common.js?v=20260923d"></script> <script src="{{ASSET_PREFIX}}common.js?v=20260924d"></script>
<script src="{{ASSET_PREFIX}}app.js"></script> <script src="{{ASSET_PREFIX}}app.js"></script>
</body> </body>

View file

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
{{HEAD_META}} {{HEAD_META}}
{{LANG_REDIRECT_SCRIPT}} {{LANG_REDIRECT_SCRIPT}}
<link rel="stylesheet" href="{{ASSET_PREFIX}}styles.css?v=20260923k"> <link rel="stylesheet" href="{{ASSET_PREFIX}}styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -209,7 +209,7 @@
</div> </div>
<link rel="stylesheet" href="{{ASSET_PREFIX}}fonts/inter.css"> <link rel="stylesheet" href="{{ASSET_PREFIX}}fonts/inter.css">
<script src="{{ASSET_PREFIX}}common.js?v=20260923d"></script> <script src="{{ASSET_PREFIX}}common.js?v=20260924d"></script>
<script src="{{ASSET_PREFIX}}terminal.js"></script> <script src="{{ASSET_PREFIX}}terminal.js"></script>
</body> </body>

View file

@ -45,7 +45,7 @@ body{
-webkit-font-smoothing:antialiased; -webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale; -moz-osx-font-smoothing:grayscale;
transition: background var(--transition), color var(--transition); transition: background var(--transition), color var(--transition);
overflow-x:hidden; overflow-x:clip;
} }
.ambient{ .ambient{
@ -182,10 +182,37 @@ main, .site-footer{
--hero-max-scale:1.95; --hero-max-scale:1.95;
--hero-active-scale:var(--hero-max-scale); --hero-active-scale:var(--hero-max-scale);
--hero-logo-size:clamp(60px, 11vw, 128px); --hero-logo-size:clamp(60px, 11vw, 128px);
position:relative; position:sticky;
top:var(--site-header-height);
z-index:2;
padding-top:var(--hero-stage-offset); padding-top:var(--hero-stage-offset);
padding-bottom:var(--hero-bottom-gap); padding-bottom:var(--hero-bottom-gap);
text-align:left; text-align:left;
background:var(--bg);
}
.hero-scroll{
position:relative;
z-index:2;
}
.hero-pin{
height:var(--hero-pin-space, 0px);
}
.hero-scroll + .post-hero-lift{
position:relative;
z-index:1;
margin-top:calc(var(--hero-pin-space, 0px) * -1);
}
.hero::before,
.terminal-hero::before{
content:'';
position:absolute;
z-index:-1;
left:50%;
top:0;
bottom:0;
width:100vw;
transform:translateX(-50%);
background:var(--bg);
} }
.hero-stage{ .hero-stage{
position:sticky; position:sticky;
@ -697,11 +724,14 @@ main, .site-footer{
--hero-logo-size:clamp(72px, 13.5vw, 158px); --hero-logo-size:clamp(72px, 13.5vw, 158px);
--hero-terminal-overflow:1.14; --hero-terminal-overflow:1.14;
--hero-brand-gap:var(--hero-bottom-gap); --hero-brand-gap:var(--hero-bottom-gap);
position:relative; position:sticky;
top:var(--site-header-height);
z-index:2;
padding-top:var(--hero-stage-offset); padding-top:var(--hero-stage-offset);
padding-bottom:var(--hero-bottom-gap); padding-bottom:var(--hero-bottom-gap);
text-align:center; text-align:center;
overflow:visible; overflow:visible;
background:var(--bg);
} }
.terminal-stage{ .terminal-stage{
position:sticky; position:sticky;

View file

@ -88,7 +88,7 @@
} }
})(); })();
</script> </script>
<link rel="stylesheet" href="/styles.css?v=20260923k"> <link rel="stylesheet" href="/styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -296,7 +296,7 @@
</div> </div>
<link rel="stylesheet" href="/fonts/inter.css"> <link rel="stylesheet" href="/fonts/inter.css">
<script src="/common.js?v=20260923d"></script> <script src="/common.js?v=20260924d"></script>
<script src="/terminal.js"></script> <script src="/terminal.js"></script>
</body> </body>

View file

@ -88,7 +88,7 @@
} }
})(); })();
</script> </script>
<link rel="stylesheet" href="/styles.css?v=20260923k"> <link rel="stylesheet" href="/styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -446,7 +446,7 @@
</div> </div>
<link rel="stylesheet" href="/fonts/inter.css"> <link rel="stylesheet" href="/fonts/inter.css">
<script src="/common.js?v=20260923d"></script> <script src="/common.js?v=20260924d"></script>
<script src="/app.js"></script> <script src="/app.js"></script>
</body> </body>

View file

@ -88,7 +88,7 @@
} }
})(); })();
</script> </script>
<link rel="stylesheet" href="/styles.css?v=20260923k"> <link rel="stylesheet" href="/styles.css?v=20260924d">
</head> </head>
<body> <body>
<div class="ambient" aria-hidden="true"> <div class="ambient" aria-hidden="true">
@ -296,7 +296,7 @@
</div> </div>
<link rel="stylesheet" href="/fonts/inter.css"> <link rel="stylesheet" href="/fonts/inter.css">
<script src="/common.js?v=20260923d"></script> <script src="/common.js?v=20260924d"></script>
<script src="/terminal.js"></script> <script src="/terminal.js"></script>
</body> </body>