/* =========================================================
   Animations — reveals, clip masks, marquee, splash, moon pulse
   ========================================================= */

/* Scroll reveal — translateY fade-up */
.reveal {
	opacity: 0;
	transform: translateY(24px);
	transition: opacity .55s var(--ease), transform .55s var(--ease);
}
.reveal.is-in {
	opacity: 1;
	transform: translateY(0);
}
.reveal[data-delay="1"] { transition-delay: .08s; }
.reveal[data-delay="2"] { transition-delay: .16s; }
.reveal[data-delay="3"] { transition-delay: .24s; }
.reveal[data-delay="4"] { transition-delay: .32s; }
.reveal[data-delay="5"] { transition-delay: .40s; }
.reveal[data-delay="6"] { transition-delay: .48s; }

/* LCP fix for above-the-fold hero content: run the fade-up as a CSS
 * keyframe animation that fires on render — NO JS dependency.
 * Previously the .reveal { opacity: 0 } base hid the hero until JS
 * IntersectionObserver added .is-in, which on slow mobile happened
 * 5-10s after first paint, killing LCP. Now the hero content fades
 * itself in immediately as the browser renders the page. */
@keyframes mona-hero-fade-up {
	from { opacity: 0; transform: translateY(24px); }
	to   { opacity: 1; transform: translateY(0); }
}
.home-hero .reveal {
	/* Override base — fallback visible state if animation unsupported */
	opacity: 1;
	transform: none;
	transition: none;
	animation: mona-hero-fade-up .55s var(--ease) both;
}
.home-hero .reveal[data-delay="1"] { animation-delay: .08s; }
.home-hero .reveal[data-delay="2"] { animation-delay: .16s; }
.home-hero .reveal[data-delay="3"] { animation-delay: .24s; }
.home-hero .reveal[data-delay="4"] { animation-delay: .32s; }
.home-hero .reveal[data-delay="5"] { animation-delay: .40s; }
.home-hero .reveal[data-delay="6"] { animation-delay: .48s; }

/* Hero clip-reveal — words slide up from behind a mask.
 * padding-bottom + negative margin extends the mask downward so letter
 * descenders (g, y, p, j) don't get clipped under tight line-heights.
 * Net layout impact is zero. */
.clip-reveal {
	display: inline-block;
	overflow: hidden;
	vertical-align: bottom;
	padding-bottom: 0.22em;
	margin-bottom: -0.22em;
}
.clip-reveal > span {
	display: inline-block;
	transform: translateY(110%);
	transition: transform .7s var(--ease);
}
.clip-reveal.is-in > span {
	transform: translateY(0);
}

/* Word-by-word reveal (alternative API — used when [data-word-split] is applied) */
.word-reveal {
	display: inline-block;
	overflow: hidden;
	vertical-align: bottom;
}
.word-reveal > span {
	display: inline-block;
	transform: translateY(110%);
	transition: transform .7s var(--ease);
}
.word-reveal.is-in > span {
	transform: translateY(0);
}

/* Moon pulse — subtle breathing on moon icon */
.moon-pulse {
	animation: moonPulse 4s ease-in-out infinite;
}
@keyframes moonPulse {
	0%, 100% { opacity: .75; }
	50%      { opacity: 1; }
}

/* Live dot (hero top indicator) */
@keyframes livePulse {
	0%, 100% { opacity: 1; }
	50%      { opacity: .3; }
}

/* Marquee */
@keyframes marqScroll {
	to { transform: translateX(-50%); }
}

/* Splash screen — loads only on front page (and only on first session visit;
 * dismissal is wired to real document load progress in main.js). */
.splash {
	position: fixed; inset: 0;
	background: #0C0D0D;
	z-index: 9999;
	display: grid;
	place-items: center;
	overflow: hidden;
	/* clip-path lift — the splash retracts UPWARD from the bottom edge as
	 * a clean wipe, revealing the page already-painted beneath. */
	transition: opacity .55s var(--ease), transform .85s cubic-bezier(.65, 0, .35, 1), clip-path .85s cubic-bezier(.65, 0, .35, 1);
}
.splash.out {
	opacity: 0;
	pointer-events: none;
	transform: translateY(-3%) scale(1.015);
	clip-path: inset(0 0 100% 0);
}
.splash-inner {
	text-align: center;
	color: #F5F5F4;
	position: relative;
}
.splash-brand {
	font-family: var(--font-display);
	font-weight: 500;
	font-size: clamp(1.4rem, 2.4vw, 2rem);
	letter-spacing: -0.03em;
	text-transform: lowercase;
	color: #F5F5F4;
	opacity: 0;
	transform: translateY(.4em);
	animation: splashBrandIn .85s cubic-bezier(.16, 1, .3, 1) .15s forwards;
}
.splash-bar {
	width: clamp(180px, 24vw, 280px);
	height: 1px;
	background: rgba(245, 245, 244, .14);
	margin: 1.8rem auto 1.4rem;
	position: relative;
	overflow: hidden;
	/* Bar slot fades in slightly later so the wordmark lands first. */
	opacity: 0;
	animation: splashFadeIn .55s var(--ease) .35s forwards;
}
.splash-bar::before {
	content: "";
	position: absolute; inset: 0;
	background: var(--accent);
	transform-origin: left;
	transform: scaleX(0);
	/* Bar fills from 0 → ~80% over 1.4s, then sits there. main.js dismisses
	 * on real `window.load`, completing the visual at that point. */
	animation: splashBarFill 1.6s cubic-bezier(.16, 1, .3, 1) .4s forwards;
}
/* When dismissing: bar snaps to 100% during the fade-out for closure. */
.splash.out .splash-bar::before {
	animation: splashBarComplete .5s cubic-bezier(.16, 1, .3, 1) forwards;
}
.splash-lbl {
	font-family: var(--font-mono);
	font-size: .68rem;
	color: rgba(245, 245, 244, .45);
	text-transform: lowercase;
	letter-spacing: .12em;
	opacity: 0;
	animation: splashFadeIn .55s var(--ease) .55s forwards;
}
@keyframes splashFadeIn {
	to { opacity: 1; }
}
@keyframes splashBrandIn {
	to {
		opacity: 1;
		transform: translateY(0);
	}
}
@keyframes splashBarFill {
	0%  { transform: scaleX(0); }
	100% { transform: scaleX(.82); } /* parks at 82% — completion happens on dismiss */
}
@keyframes splashBarComplete {
	to { transform: scaleX(1); }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .01ms !important;
		transition-duration: .01ms !important;
	}
	.splash { display: none; }
}
