Unify scroll reveals, hero entrance, nav active-underline, button springs, the scroll-progress bar and backdrop parallax under one Motion system (src/scripts/anim.ts), bundled into a self-hosted /_astro module so CSP script-src 'self' holds. Progress bar + parallax now scroll()-driven and cross-browser (was Chromium-only animation-timeline). Fail-open, reduced-motion aware, content fully visible with JS off.
This commit is contained in:
+17
-27
@@ -128,14 +128,15 @@ svg {
|
||||
border: 1px solid var(--border-strong);
|
||||
color: var(--text);
|
||||
background: var(--surface);
|
||||
transition: border-color 0.2s var(--ease), transform 0.2s var(--ease),
|
||||
/* transform is owned by the Motion layer (spring hover/press) — kept out of
|
||||
this transition so CSS and Motion don't fight over the same property. */
|
||||
transition: border-color 0.2s var(--ease),
|
||||
background 0.2s var(--ease), color 0.2s var(--ease);
|
||||
text-decoration: none;
|
||||
}
|
||||
.btn:hover {
|
||||
text-decoration: none;
|
||||
border-color: var(--accent-line);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.btn--primary {
|
||||
background: linear-gradient(100deg, var(--accent), var(--accent-2));
|
||||
@@ -308,23 +309,21 @@ svg {
|
||||
color: var(--shiki-light);
|
||||
}
|
||||
|
||||
/* ---- Reveal-on-scroll (progressive enhancement) -------------------------- */
|
||||
/* Default = visible (JS-off safe). The .reveal class is only added by JS when
|
||||
IntersectionObserver is supported AND motion is allowed. */
|
||||
.reveal {
|
||||
/* ---- Pre-reveal state (progressive enhancement, Motion-driven) ----------- */
|
||||
/* Default = visible (JS-off safe). Only once site.js sets `html.js` do we hide
|
||||
the pre-reveal elements; the Motion layer (src/scripts/anim.ts) then fades
|
||||
them up. Opacity alone gates the flash — Motion owns the y-transform. Under
|
||||
reduced-motion the Motion layer no-ops, so we keep everything visible here. */
|
||||
html.js [data-reveal],
|
||||
html.js .hero__inner > *,
|
||||
html.js [data-reveal] .chip {
|
||||
opacity: 0;
|
||||
transform: translateY(14px);
|
||||
transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
|
||||
}
|
||||
.reveal.is-visible {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.reveal {
|
||||
html.js [data-reveal],
|
||||
html.js .hero__inner > *,
|
||||
html.js [data-reveal] .chip {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +331,9 @@ svg {
|
||||
Native scroll-driven animations (animation-timeline). Degrades to a gentle
|
||||
continuous drift where unsupported; fully disabled under reduced-motion. */
|
||||
|
||||
/* A thin royal line at the very top that fills as the page scrolls. */
|
||||
/* A thin royal line at the very top that fills as the page scrolls. Its scaleX
|
||||
is scrubbed by scroll progress in the Motion layer (scroll() — cross-browser,
|
||||
unlike the Chromium-only CSS animation-timeline this replaced). */
|
||||
.scroll-progress {
|
||||
position: fixed;
|
||||
inset: 0 0 auto 0;
|
||||
@@ -344,17 +345,6 @@ svg {
|
||||
transform-origin: 0 50%;
|
||||
pointer-events: none;
|
||||
}
|
||||
@supports (animation-timeline: scroll()) {
|
||||
.scroll-progress {
|
||||
animation: progressGrow linear both;
|
||||
animation-timeline: scroll(root block);
|
||||
}
|
||||
}
|
||||
@keyframes progressGrow {
|
||||
to {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Cinematic backing: the Bat-Computer board, panned by scroll -----------
|
||||
A fixed full-screen image (dark/light per theme) that pans S → E → SE → NE as
|
||||
|
||||
Reference in New Issue
Block a user