<header class="hero">
<div class="sun"></div>
<div class="hills far"></div>
<div class="hills near"></div>
<div class="title">
<p class="eyebrow">Trail season 2026</p>
<h1>Walk further than you think you can</h1>
<p>Routes, maps and gear notes from people who spend their weekends above the tree line.</p>
</div>
</header>
<main class="content">
<h2>Scroll to see the layers separate</h2>
<p>The sun and the far hills barely move, the near hills slide faster and the title lifts away. All of it is CSS bound to the scroll position rather than a script watching scroll events.</p>
<p>Once the hero has left the viewport the animations sit at their end state, so nothing keeps running while you read.</p>
<p>Resize the preview or scroll back up and the layers return to where they started, because the animation is a function of scroll position rather than time.</p>
</main>
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
background: #0b1120;
color: #f8fafc;
}
.hero {
position: relative;
height: 100vh;
overflow: hidden;
background: linear-gradient(180deg, #1e1b4b 0%, #4c1d95 45%, #db2777 100%);
}
.sun {
position: absolute;
left: 50%;
top: 8%;
width: 150px;
height: 150px;
margin-left: -75px;
border-radius: 50%;
background: radial-gradient(circle at 50% 40%, #fde68a, #f97316 70%);
box-shadow: 0 0 80px 30px rgba(249, 115, 22, 0.4);
}
.hills {
position: absolute;
left: -10%;
right: -10%;
bottom: -40px;
height: 46%;
}
.hills::before,
.hills::after {
content: "";
position: absolute;
bottom: 0;
border-radius: 50% 50% 0 0;
}
.far {
height: 55%;
}
.far::before {
left: 0;
width: 60%;
height: 100%;
background: #6d28d9;
}
.far::after {
right: 0;
width: 55%;
height: 80%;
background: #5b21b6;
}
.near::before {
left: -5%;
width: 55%;
height: 100%;
background: #1e1b4b;
}
.near::after {
right: -5%;
width: 65%;
height: 90%;
background: #172554;
}
.title {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: min(90%, 620px);
text-align: center;
}
.eyebrow {
font-size: 0.8125rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: #fde68a;
margin: 0 0 12px;
}
.title h1 {
font-size: clamp(2rem, 6vw, 3.5rem);
line-height: 1.05;
letter-spacing: -0.02em;
margin: 0 0 16px;
}
.title p:last-child {
margin: 0;
font-size: 1.0625rem;
line-height: 1.6;
color: rgba(255, 255, 255, 0.85);
}
.content {
position: relative;
background: #0b1120;
padding: 60px 24px 120px;
max-width: 640px;
margin: 0 auto;
}
.content h2 {
font-size: 1.5rem;
margin: 0 0 16px;
}
.content p {
color: #cbd5e1;
line-height: 1.7;
margin: 0 0 18px;
}
@keyframes drift-sun {
to { transform: translateY(50px) scale(0.9); }
}
@keyframes drift-far {
to { transform: translateY(40px); }
}
@keyframes drift-near {
to { transform: translateY(-140px); }
}
@keyframes lift-title {
to { transform: translate(-50%, -140%); opacity: 0; }
}
@supports (animation-timeline: scroll()) {
.sun, .far, .near, .title {
animation-timing-function: linear;
animation-fill-mode: both;
animation-timeline: scroll(root);
animation-range: 0 90vh;
}
.sun { animation-name: drift-sun; }
.far { animation-name: drift-far; }
.near { animation-name: drift-near; }
.title { animation-name: lift-title; }
}