/*
 * Mara Quinn Coaching — the motion layer.
 *
 * Every keyframe and utility here is carried over from .design/index.html.
 * Two deliberate changes from the reference:
 *
 *  1. Class names are namespaced `mq-`. The reference uses bare `.card`,
 *     `.tab`, `.path`, `.count` and `.book`, which share a page with core
 *     block styles, the chassis and the sfp-blocks plugin here.
 *  2. Scroll reveals keep `animation-timeline: view()` where it is supported
 *     and fall back to an IntersectionObserver class in site.js elsewhere —
 *     the reference simply showed the content, which is fine, but the
 *     fallback is cheap and the design reads better with it.
 */

/* ---------------- keyframes ---------------- */
@keyframes mq-rise { from { opacity: 0; transform: translateY(38px) rotate(1.5deg); } to { opacity: 1; transform: none; } }
@keyframes mq-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes mq-strike { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes mq-spin { to { transform: rotate(360deg); } }
@keyframes mq-spinr { to { transform: rotate(-360deg); } }
@keyframes mq-floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
@keyframes mq-floaty2 { 0%, 100% { transform: translateY(0) rotate(-3deg); } 50% { transform: translateY(12px) rotate(-1deg); } }
@keyframes mq-marquee { to { transform: translateX(-50%); } }
@keyframes mq-draw { to { stroke-dashoffset: 0; } }
@keyframes mq-pulse { 0%, 100% { transform: scale(1); opacity: 0.9; } 50% { transform: scale(1.18); opacity: 1; } }
@keyframes mq-ripple { from { transform: scale(0.6); opacity: 0.7; } to { transform: scale(2.2); opacity: 0; } }
@keyframes mq-blob {
	0%, 100% { border-radius: 58% 42% 47% 53% / 45% 55% 45% 55%; }
	50% { border-radius: 42% 58% 60% 40% / 58% 38% 62% 42%; }
}
@keyframes mq-orbit { to { transform: rotate(360deg); } }
@keyframes mq-quote-in { from { opacity: 0; transform: translateY(18px); filter: blur(6px); } to { opacity: 1; transform: none; filter: none; } }
@keyframes mq-glow { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.7; } }
@keyframes mq-travel { 0% { offset-distance: 0%; } 100% { offset-distance: 100%; } }
@keyframes mq-seat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes mq-kenburns { 0% { transform: scale(1.02) translate(0, 0); } 100% { transform: scale(1.14) translate(-2%, -1.5%); } }
@keyframes mq-unveil { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes mq-unveil-x { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes mq-drift { from { transform: scale(1.12) translateX(-3%); } to { transform: scale(1.12) translateX(3%); } }
@keyframes mq-tilt { 0%, 100% { transform: rotate(-2deg) translateY(0); } 50% { transform: rotate(1deg) translateY(-10px); } }

/* ---------------- ambient ---------------- */
.mq-kb { animation: mq-kenburns 14s ease-in-out infinite alternate; }
.mq-drift { animation: mq-drift 22s ease-in-out infinite alternate; }
.mq-tilt { animation: mq-tilt 8s ease-in-out infinite; }
.mq-float { animation: mq-floaty 6s ease-in-out infinite; }
.mq-float2 { animation: mq-floaty2 7s ease-in-out infinite; }
.mq-blob { animation: mq-blob 12s ease-in-out infinite; }
.mq-imgin { animation: mq-unveil 1.4s 0.3s var(--mq-ease-draw) both, mq-blob 12s ease-in-out infinite; }
.mq-ring { animation: mq-spin 26s linear infinite; transform-origin: 50% 50%; }
.mq-ringr { animation: mq-spinr 40s linear infinite; transform-origin: 50% 50%; }
.mq-orbit { animation: mq-orbit 14s linear infinite; transform-origin: 50% 50%; }
.mq-glow { animation: mq-glow 5s ease-in-out infinite; }
.mq-pulse { animation: mq-pulse 2.4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.mq-ripple { animation: mq-ripple 2.4s ease-out infinite; transform-box: fill-box; transform-origin: center; }
.mq-seat { animation: mq-seat 3s ease-in-out infinite; }
.mq-track { display: flex; width: max-content; animation: mq-marquee 32s linear infinite; }
.mq-traveler {
	offset-path: path("M20 150 C 110 150, 120 40, 210 60 S 300 150, 340 40");
	animation: mq-travel 4.5s ease-in-out infinite alternate;
}

/* ---------------- entrance ---------------- */
.mq-w { display: inline-block; opacity: 0; animation: mq-rise 0.9s var(--mq-ease) forwards; }
.mq-fade { opacity: 0; animation: mq-fade 1s ease forwards; }
/* The reference staggers these with inline animation-delay; as blocks they
   carry a modifier class instead, so the editor cannot strip the timing. */
.mq-fade--late { animation-delay: 1s; }
.mq-fade--later { animation-delay: 1.2s; }

.mq-strike { position: relative; display: inline-block; }
.mq-strike::after {
	content: "";
	position: absolute;
	left: -4px;
	right: -4px;
	top: 54%;
	height: 7px;
	background: var(--mq-acc);
	transform: scaleX(0);
	transform-origin: left;
	animation: mq-strike 0.7s 1.5s var(--mq-ease-draw) forwards;
	border-radius: 4px;
}

.mq-path { stroke-dasharray: 1700; stroke-dashoffset: 1700; animation: mq-draw 3.2s cubic-bezier(0.6, 0, 0.2, 1) forwards; }
.mq-p2 { animation-delay: 0.35s; }
.mq-p3 { animation-delay: 0.7s; }

/* Re-triggered by site.js on tab change; separate from .mq-quote layout. */
.mq-quote--in { animation: mq-quote-in 0.7s var(--mq-ease); }

/* ---------------- hover ---------------- */
.mq-zoomwrap { overflow: hidden; }
.mq-zoomwrap img { transition: transform 1.2s var(--mq-ease); }
.mq-card:hover .mq-zoomwrap img,
.mq-guide:hover .mq-zoomwrap img { transform: scale(1.08); }

.mq-card { transition: transform 0.5s var(--mq-ease), box-shadow 0.5s; }
.mq-card:hover { transform: translateY(-10px) rotate(-0.4deg); box-shadow: var(--mq-shadow-card); }

.mq-guide { transition: transform 0.6s var(--mq-ease), box-shadow 0.6s; }
.mq-guide:hover { transform: translateY(-12px) rotate(-1deg); box-shadow: var(--mq-shadow-book); }

/*
 * The count-up. The reference rendered the number itself as CSS generated
 * content — `counter()` over an @property integer — which means no real text
 * for a screen reader or a crawler, and a literal 0 wherever @property is
 * unsupported. Here the number is real text in the markup, and site.js
 * animates it in place only when motion is allowed, so the figure is always
 * readable and the count is an enhancement that cannot fail closed.
 */

/* ---------------- scroll reveal ---------------- */
@supports (animation-timeline: view()) {
	.mq-reveal {
		animation: mq-rise linear both;
		animation-timeline: view();
		animation-range: entry 0% entry 45%;
	}
	.mq-unveil {
		animation: mq-unveil-x linear both;
		animation-timeline: view();
		animation-range: entry 5% cover 40%;
	}
}

/*
 * IntersectionObserver fallback. site.js sets `mq-js` on <html> and marks
 * each element `mq-seen` as it enters. Scoped to browsers without a view()
 * timeline so the two mechanisms never both drive the same element.
 */
@supports not (animation-timeline: view()) {
	.mq-js .mq-reveal { opacity: 0; }
	.mq-js .mq-reveal.mq-seen { animation: mq-rise 0.9s var(--mq-ease) both; }
	.mq-js .mq-unveil { clip-path: inset(0 100% 0 0); }
	.mq-js .mq-unveil.mq-seen { animation: mq-unveil-x 1.1s var(--mq-ease-draw) both; }
}

/* ---------------- motion off ---------------- */
/*
 * `.mq-still` freezes every animation at its end state. The capture scripts
 * add it before screenshotting: Chrome's one-shot headless screenshot never
 * delivers an IntersectionObserver and does not drive a view() timeline, so
 * without this a below-the-fold capture is a blank band (platform gotcha 33).
 */
.mq-still *,
.mq-still *::before,
.mq-still *::after {
	animation-duration: 0s !important;
	animation-delay: 0s !important;
	animation-iteration-count: 1 !important;
	transition-duration: 0s !important;
}
.mq-still .mq-reveal,
.mq-still .mq-unveil { animation: none !important; opacity: 1 !important; clip-path: none !important; }

/*
 * Full-page capture fallback.
 *
 * A full-page screenshot resizes the viewport to the whole document, and the
 * view() timelines are recalculated against that new scrollport at the moment
 * the shutter opens. Elements that had not yet entered can snapshot at their
 * entry state, which produces a perfectly valid PNG with whole sections
 * missing from it — the portfolio bundle lost the testimonial heading and its
 * tab list exactly this way (platform gotcha 33 territory).
 *
 * No real viewport is 2000px tall, so this only ever applies to a capture.
 * `.mq-still` does the same job for a script that can set a class; this
 * covers the ones that cannot.
 */
@media (min-height: 2000px) {
	.mq-reveal,
	.mq-unveil {
		animation: none !important;
		opacity: 1 !important;
		clip-path: none !important;
	}
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: 0s !important;
		animation-delay: 0s !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0s !important;
	}
	.mq-reveal, .mq-unveil { animation: none !important; opacity: 1 !important; clip-path: none !important; }
	.mq-js .mq-reveal { opacity: 1; }
	.mq-js .mq-unveil { clip-path: none; }
	html { scroll-behavior: auto; }
}
