/* ==========================================================================
   Motion pre-states.
   Everything here is scoped to html.js-motion, which the head bootstrap adds
   only when prefers-reduced-motion is "no-preference" (and removes after 3s
   if motion.js never runs). Without JS, with reduced motion, or on script
   failure, all content is fully visible. motion.js adds .anim-ready to each
   element as soon as it has taken over its initial state.
   ========================================================================== */

html.js-motion :is(
	.anim-fade-up:not(.anim-children),
	.anim-mask-up,
	.is-style-anim-mask-up,
	.anim-mask-wipe,
	.anim-sunrise,
	.rv-accent.anim-draw-path,
	.anim-counter,
	.anim-scrub-words,
	[data-anim]:not([data-anim~="parallax"]):not([data-anim~="magnetic"])
):not(.anim-ready) {
	opacity: 0;
}

html.js-motion :is(.anim-children, .is-style-anim-fade-up):not(.anim-ready) > * {
	opacity: 0;
}

/* Hero: the image is visible from first paint; it only settles. */
html.js-motion .rv-hero__image img {
	animation: rv-settle 1.6s cubic-bezier(0.16, 1, 0.3, 1) both;
}
html.js-motion .rv-hero__media::before {
	animation: rv-rise 1.1s cubic-bezier(0.76, 0, 0.24, 1) .05s both;
}
@keyframes rv-settle {
	from { transform: scale(1.06); }
	to { transform: scale(1); }
}
@keyframes rv-rise {
	from { clip-path: inset(100% 0 0 0 round 8px); }
	to { clip-path: inset(0 0 0 0 round 8px); }
}
.rv-hero__image { overflow: clip; border-radius: var(--radius-md); }


/* SVG line drawing: stroke dash set by JS; until then hidden via opacity. */
.rv-accent svg path,
.rv-icon path { stroke-dasharray: none; }

/* 404 benchmark marker */
@media (prefers-reduced-motion: no-preference) {
	html.js-motion .rv-404__marker { animation: rv-drop .6s cubic-bezier(0.16, 1, 0.3, 1) 1.6s both; }
	html.js-motion .rv-404__ring { animation: rv-ripple 1.4s cubic-bezier(0.16, 1, 0.3, 1) 2.1s both; }
}
@keyframes rv-drop {
	from { opacity: 0; transform: translateY(-12px); }
	to { opacity: 1; transform: none; }
}
@keyframes rv-ripple {
	0% { opacity: .9; transform: scale(1); }
	100% { opacity: 0; transform: scale(4); }
}

/* Mobile menu */
@media (prefers-reduced-motion: no-preference) {
	.rv-menu {
		transition: clip-path .8s cubic-bezier(0.76, 0, 0.24, 1), visibility 0s linear .8s;
	}
	.rv-menu.is-open {
		transition: clip-path .8s cubic-bezier(0.76, 0, 0.24, 1), visibility 0s;
	}
	.rv-menu.is-closing {
		transition: clip-path .48s cubic-bezier(0.76, 0, 0.24, 1), visibility 0s linear .48s;
	}
	.rv-menu__list > li > a {
		transform: translateY(110%);
		transition: transform .7s cubic-bezier(0.16, 1, 0.3, 1);
	}
	.rv-menu.is-open .rv-menu__list > li > a {
		transform: none;
		transition-delay: calc(.25s + var(--i, 0) * .06s);
	}
	.rv-menu.is-closing .rv-menu__list > li > a { transition-duration: .3s; transition-delay: 0s; }
	.rv-menu__contact,
	.rv-menu__cta,
	.rv-menu__title,
	.rv-menu__sub {
		opacity: 0;
		transform: translateY(12px);
		transition: opacity .5s ease, transform .7s cubic-bezier(0.16, 1, 0.3, 1);
	}
	.rv-menu.is-open :is(.rv-menu__contact, .rv-menu__cta, .rv-menu__title, .rv-menu__sub) {
		opacity: 1;
		transform: none;
		transition-delay: .55s;
	}
}
@media (prefers-reduced-motion: reduce) {
	.rv-menu {
		clip-path: none !important;
		opacity: 0;
		transition: opacity .15s linear, visibility 0s linear .15s;
	}
	.rv-menu.is-open {
		opacity: 1;
		transition: opacity .15s linear, visibility 0s;
	}
	.rv-header-part,
	.rv-header,
	.rv-header .wp-block-site-logo img { transition-duration: 0s !important; }
	.rv-nav .rv-nav-services > .wp-block-navigation__submenu-container { clip-path: none !important; transition: opacity .15s linear !important; }
}

/* Stacked plates dim layer + testimonial/form helpers */
.rv-plate,
.rv-plate__dim { will-change: auto; }
.rv-testimonials__viewport { transition: none; }

/* Checkbox tick draw */
.rv-check__box path { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset .25s ease; }
.rv-check input:checked + .rv-check__box path { stroke-dashoffset: 0; }
@media (prefers-reduced-motion: reduce) {
	.rv-check__box path { transition: none; }
}

/* Headline text (.anim-reveal-lines and the home hero title) is deliberately NOT
   hidden here: it is visible from first paint, and SplitText's line masks hide
   and then reveal it the moment motion.js takes over. */

/* Components choreographed by motion.js (hidden until it takes over). */
html.js-motion .rv-hero:not(.anim-ready) :is(.rv-hero__eyebrow, .rv-hero__lead, .rv-hero__buttons, .rv-strip, .rv-hero__note),
html.js-motion :is(.rv-service-card, .rv-team-card):not(.anim-ready) {
	opacity: 0;
}

/* Parallax frames (desktop + fine pointer, set by motion.js). */
.rv-parallax-frame { position: relative; overflow: clip; }
.rv-parallax-frame img {
	position: absolute;
	left: 0;
	top: -7%;
	width: 100% !important;
	height: 114% !important;
	max-width: none !important;
	aspect-ratio: auto !important;
	object-fit: cover;
}

/* SplitText line masks (overflow: clip) — extend each mask below the line so
   descenders (g, p, y, j) are never cut off at tight line-heights. The
   negative margin keeps line spacing unchanged; the masks persist after the
   reveal, so this also covers the finished state. */
.rv-line-mask {
	padding-bottom: .18em;
	margin-bottom: -.18em;
}
