/*
 * Motion: a few calm entrances, so the page feels alive without performing.
 *
 * Everything here sits under html.motion. header.php sets that class before first paint, on every page,
 * but never with prefers-reduced-motion. Without the class, or without JS, every element is simply there.
 *
 * - The hero and the page heads play once on load, in CSS only: the band grows down from the top
 *   edge, the heading and intro rise, the photo opens up.
 * - Further down, elements with data-reveal come in once as they scroll into view (motion.js adds
 *   .is-in):
 *     rise     the element rises and fades in
 *     stagger  its children do, each as it comes into view; children arriving together follow
 *              each other (--i, set by motion.js)
 *     frame    a photo opens from a slightly smaller rounded clip
 *     draw     the loop's helix draws itself, bottom turn first (--k, set by loop.js)
 *     band     the band of a container grows down from the top edge
 * - Reveals use keyframes with only a "from" and fill-mode backwards: once done, the element's own
 *   styles apply again, so hover transforms (case cards) keep working. After its entrance an element
 *   gets .is-done, so being shown again (the case filter) does not replay it.
 */
:root {
	--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
	--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

@keyframes motion-rise {
	from { opacity: 0; transform: translateY(22px); }
}
@keyframes motion-band {
	from { clip-path: inset(0 0 100% 0); }
	to { clip-path: inset(0 0 0 0); }
}
@keyframes motion-frame {
	from { opacity: 0; clip-path: inset(7% 5% 0 5% round var(--radius)); }
	to { opacity: 1; clip-path: inset(0 0 0 0 round var(--radius)); }
}
/* Like frame, without the fade: the hero photo must paint from the first frame. */
@keyframes motion-open {
	from { clip-path: inset(6% 4% 0 4% round var(--radius)); }
	to { clip-path: inset(0 0 0 0 round var(--radius)); }
}
@keyframes motion-settle {
	from { transform: scale(1.06); }
}
@keyframes motion-draw {
	from { stroke-dashoffset: 1.05; }
}

/* Hero, on load
   -------------------------------------------------------------------------- */
.motion .hero-top > .band { animation: motion-band 1300ms var(--ease-in-out) both; }
.motion .hero h1 { animation: motion-rise 1000ms var(--ease-out) 120ms backwards; }
.motion .hero-intro { animation: motion-rise 1000ms var(--ease-out) 260ms backwards; }
.motion .hero-actions { animation: motion-rise 1000ms var(--ease-out) 340ms backwards; }
/* The photo is visible from the first frame (it is the LCP), it just opens up and settles. */
.motion .hero-media {
	overflow: hidden;
	border-radius: var(--radius);
	animation: motion-open 1400ms var(--ease-out) 200ms backwards;
}
.motion .hero-media img { animation: motion-settle 1800ms var(--ease-out) 200ms backwards; }

/* Page heads (template pages, blog, cases), on load: same idea, a step smaller.
   -------------------------------------------------------------------------- */
.motion :is(.page-head, .case-hero) > .band { animation: motion-band 1300ms var(--ease-in-out) both; }
.motion :is(.page-head .split, .case-hero-inner) > * { animation: motion-rise 1000ms var(--ease-out) 120ms backwards; }
.motion :is(.page-head .split, .case-hero-inner) > * + * { animation-delay: 260ms; }
.motion .page-media img { animation: motion-open 1400ms var(--ease-out) 200ms backwards; }

/* On scroll
   -------------------------------------------------------------------------- */
.motion [data-reveal="rise"]:not(.is-in),
.motion [data-reveal="stagger"] > :not(.is-in),
.motion [data-reveal="frame"]:not(.is-in) { opacity: 0; }

.motion [data-reveal="rise"].is-in:not(.is-done),
.motion [data-reveal="stagger"] > .is-in:not(.is-done) {
	animation: motion-rise 900ms var(--ease-out) backwards;
	animation-delay: calc(var(--i, 0) * 80ms);
}

.motion [data-reveal="frame"].is-in:not(.is-done) { animation: motion-frame 1200ms var(--ease-out) backwards; }
/* No zoom on the photo here: in a coloured frame (services, toned text-media) it would grow into the frame. */

.motion [data-reveal="band"]:not(.is-in) > .band { clip-path: inset(0 0 100% 0); }
.motion [data-reveal="band"].is-in > .band { animation: motion-band 1300ms var(--ease-in-out) both; }

/* The helix: each half turn draws in after the one below it. */
.motion [data-reveal="draw"] .loop-spiral path { stroke-dasharray: 1 1.1; }
.motion [data-reveal="draw"]:not(.is-in) .loop-spiral path { stroke-dashoffset: 1.05; }
.motion [data-reveal="draw"].is-in .loop-spiral path {
	animation: motion-draw 520ms var(--ease-out) backwards;
	animation-delay: calc(150ms + var(--k, 0) * 95ms);
}

/* Small touches
   -------------------------------------------------------------------------- */
/* Buttons answer a press. */
.motion .btn { transition: background .2s, color .2s, transform 160ms var(--ease-out); }
.motion .btn:active { transform: scale(0.97); }

/* A case card's photo leans in a little on hover. */
.motion .case .case-img { transition: transform 700ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
	.motion a.case:hover .case-img { transform: scale(1.03); }
}
