/* Page load + scroll animations — pure CSS keyframes.
   Used by homepage hero, posts list, post pages, and static pages. */

/* ——— Keyframes ——— */
@keyframes slideUp {
	from { opacity: 0; transform: translateY(40px); }
	to { opacity: 1; transform: translateY(0); }
}

@keyframes fadeSlideLeft {
	from { opacity: 0; transform: translateX(-25px); }
	to { opacity: 1; transform: translateX(0); }
}

@keyframes charReveal {
	from { opacity: 0; transform: translateY(100%) rotate(8deg); }
	to { opacity: 1; transform: translateY(0) rotate(0); }
}

@keyframes scaleIn {
	from { opacity: 0; transform: scaleX(0); }
	to { opacity: 1; transform: scaleX(1); }
}

@keyframes wordReveal {
	from { opacity: 0; transform: translateY(30px); }
	to { opacity: 1; transform: translateY(0); }
}

@keyframes scrollReveal {
	from { opacity: 0; transform: translateY(30px); }
	to { opacity: 1; transform: translateY(0); }
}

/* ——— Char-split titles (hero + static-page h1) ——— */
.hero-title,
.page-h1 { visibility: hidden; }

.hero-title.anim-ready,
.page-h1.anim-ready {
	visibility: visible;
	display: flex;
	flex-wrap: wrap;
}

.anim-char {
	display: inline-block;
	opacity: 0;
	animation: charReveal 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* ——— Tagline (homepage) ——— */
.hero-tagline {
	opacity: 0;
	animation: slideUp 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.45s forwards;
}

/* ——— Section label (recent posts, all posts) ——— */
.section-label {
	opacity: 0;
	transform-origin: left center;
	animation: scaleIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.55s forwards;
}

/* ——— Post list items (homepage + posts page) ——— */
.post-list-item {
	opacity: 0;
	animation: fadeSlideLeft 0.55s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* ——— Post page header (article view) ——— */
.post-header .post-meta {
	opacity: 0;
	animation: fadeSlideLeft 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.1s forwards;
}

.post-header h1 { visibility: hidden; }
.post-header h1.anim-ready { visibility: visible; }

.anim-word {
	display: inline-block;
	opacity: 0;
	animation: wordReveal 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.post-header .tags .tag {
	opacity: 0;
	animation: slideUp 0.4s cubic-bezier(0.22, 1, 0.36, 1) 0.5s forwards;
}

/* ——— Static pages: eyebrow / cascade / stagger / closing fade ——— */
.page-eyebrow {
	opacity: 0;
	animation: fadeSlideLeft 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.1s forwards;
}

.anim-stagger > * {
	opacity: 0;
	animation: fadeSlideLeft 0.55s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* When a .prose block is marked anim-cascade, suppress its block-level fade
   so the per-child cascade is what the eye reads. */
.prose.anim-cascade {
	opacity: 1;
	animation: none;
}

.anim-cascade-item {
	opacity: 0;
	animation: slideUp 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* Inside a cascade, h2 enters from the left — a section-break beat
   distinct from paragraphs sliding up from below. */
.anim-cascade > h2.anim-cascade-item,
.anim-cascade > h3.anim-cascade-item {
	animation: fadeSlideLeft 0.55s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.anim-fade-up {
	opacity: 0;
	animation: slideUp 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.6s forwards;
}

/* Default block-level fade for any .prose that isn't a cascade (post pages). */
.prose:not(.anim-cascade) {
	opacity: 0;
	animation: slideUp 0.65s cubic-bezier(0.22, 1, 0.36, 1) 0.6s forwards;
}

/* ——— Scroll-driven reveals for long post pages ——— */
@supports (animation-timeline: view()) {
	.prose h2,
	.prose h3,
	.prose blockquote,
	.prose .post-figure {
		animation: scrollReveal linear both;
		animation-timeline: view();
		animation-range: entry 0% cover 25%;
	}
}

/* ——— Reduced motion ——— */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		animation-delay: 0s !important;
		transition-duration: 0.01ms !important;
	}
	.hero-title, .post-header h1, .page-h1 { visibility: visible; }
}
