delight: hero entrance, badge materialise, scroll reveal, parallax, image hover
This commit is contained in:
+88
@@ -224,6 +224,58 @@
|
||||
.project:nth-of-type(even) .project-image { order: initial; }
|
||||
.project-image { position: relative; top: auto; }
|
||||
}
|
||||
|
||||
/* ── Delight ─────────────────────────────────────────────────────── */
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
|
||||
/* Hero: eyebrow, title, and paragraph stagger in on load */
|
||||
@keyframes archiveIn {
|
||||
from { opacity: 0; transform: translateY(22px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.hero-copy .eyebrow { animation: archiveIn 0.7s cubic-bezier(0.22,1,.36,1) 0.08s both; }
|
||||
.hero-copy h1 { animation: archiveIn 1.0s cubic-bezier(0.22,1,.36,1) 0.22s both; }
|
||||
.hero-copy p { animation: archiveIn 0.7s cubic-bezier(0.22,1,.36,1) 0.48s both; }
|
||||
|
||||
/* Masthead badge: letter-spacing collapses as it materialises */
|
||||
@keyframes badgeIn {
|
||||
from { opacity: 0; letter-spacing: .32em; }
|
||||
to { opacity: .72; letter-spacing: .18em; }
|
||||
}
|
||||
.masthead::after { animation: badgeIn 1.5s cubic-bezier(0.22,1,.36,1) 0.65s both; }
|
||||
|
||||
/* Scroll-reveal: sections fade and slide up as they enter the viewport */
|
||||
[data-reveal] {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: opacity 0.7s cubic-bezier(0.22,1,.36,1),
|
||||
transform 0.7s cubic-bezier(0.22,1,.36,1);
|
||||
}
|
||||
[data-reveal].visible { opacity: 1; transform: translateY(0); }
|
||||
|
||||
/* Subtle offset for even-numbered sections to break rhythm */
|
||||
.project:nth-of-type(even)[data-reveal] {
|
||||
transition-delay: 0.06s;
|
||||
}
|
||||
|
||||
/* Project images: contained zoom on hover */
|
||||
.project-image { overflow: hidden; }
|
||||
.project-image img {
|
||||
transition: transform 0.6s cubic-bezier(0.22,1,.36,1);
|
||||
}
|
||||
.project-image:hover img { transform: scale(1.04); }
|
||||
|
||||
/* Divider: fade in with slight width expansion */
|
||||
img.divider[data-reveal] {
|
||||
transform: none;
|
||||
filter: opacity(0) blur(2px);
|
||||
transition: filter 0.6s cubic-bezier(0.22,1,.36,1),
|
||||
transform 0.6s cubic-bezier(0.22,1,.36,1);
|
||||
}
|
||||
img.divider[data-reveal].visible {
|
||||
filter: opacity(0.9) blur(0px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
@@ -340,5 +392,41 @@
|
||||
<p>You are not completing the colony's story.<br />You are creating the place where its next story can begin.</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||
|
||||
if (!reducedMotion) {
|
||||
// Scroll reveal ─ sections and dividers materialise as they enter view
|
||||
const reveal = new IntersectionObserver((entries) => {
|
||||
entries.forEach(e => {
|
||||
if (e.isIntersecting) {
|
||||
e.target.classList.add('visible')
|
||||
reveal.unobserve(e.target)
|
||||
}
|
||||
})
|
||||
}, { threshold: 0.06, rootMargin: '0px 0px -40px 0px' })
|
||||
|
||||
document.querySelectorAll('.intro, .project, .document, img.divider').forEach(el => {
|
||||
el.setAttribute('data-reveal', '')
|
||||
reveal.observe(el)
|
||||
})
|
||||
|
||||
// Masthead parallax ─ background drifts very slowly upward on scroll
|
||||
const masthead = document.querySelector('.masthead')
|
||||
if (masthead) {
|
||||
let ticking = false
|
||||
window.addEventListener('scroll', () => {
|
||||
if (!ticking) {
|
||||
requestAnimationFrame(() => {
|
||||
const y = Math.min(window.scrollY * 0.12, 80)
|
||||
masthead.style.backgroundPositionY = `calc(30% + ${y}px)`
|
||||
ticking = false
|
||||
})
|
||||
ticking = true
|
||||
}
|
||||
}, { passive: true })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user