/* ==========================================================
   Entrance animations (CSS only)

   Usage: add ONE class to an element.
   "anim-fade-in-up"       animates as it scrolls into view
   "anim-fade-in-up-load"  animates on page load (hero / above the fold)

   Optional per element: --anim-duration, --anim-delay, --anim-ease
   (load classes only; scroll follows the scrollbar).
   --anim-distance sets how far the -sm fades move (default 2rem).
   --anim-end sets where scroll animations finish (default 25%;
   lower = finishes sooner, closer to the bottom of the screen).

   Stagger: add "anim-stagger" (or "anim-stagger-slow") to a parent
   so its animated children play one after another.

   Inside a wrapper with overflow (horizontal scroller, slider)?
   Add "anim-scope" to that wrapper or scroll animations won't run.

   Browsers without support simply show the content.
   To add an animation: keyframes + an effect class pair.
   ========================================================== */

/* Setup: stops off-screen start positions causing sideways scroll */
body {
	overflow-x: clip;
}

/* Setup: no blur on phones (smoother on low-end devices) */
@media (max-width: 767px) {
	:root {
		--anim-blur: none;
	}
}

/* Keyframes: fade */
@keyframes anim-fade-in {
	from { opacity: 0; }
}
@keyframes anim-fade-in-down {
	from { opacity: 0; translate: 0 -100%; }
}
@keyframes anim-fade-in-down-big {
	from { opacity: 0; translate: 0 -2000px; }
}
@keyframes anim-fade-in-left {
	from { opacity: 0; translate: -100% 0; }
}
@keyframes anim-fade-in-left-big {
	from { opacity: 0; translate: -2000px 0; }
}
@keyframes anim-fade-in-right {
	from { opacity: 0; translate: 100% 0; }
}
@keyframes anim-fade-in-right-big {
	from { opacity: 0; translate: 2000px 0; }
}
@keyframes anim-fade-in-up {
	from { opacity: 0; translate: 0 100%; }
}
@keyframes anim-fade-in-up-big {
	from { opacity: 0; translate: 0 2000px; }
}
@keyframes anim-fade-in-top-left {
	from { opacity: 0; translate: -100% -100%; }
}
@keyframes anim-fade-in-top-right {
	from { opacity: 0; translate: 100% -100%; }
}
@keyframes anim-fade-in-bottom-left {
	from { opacity: 0; translate: -100% 100%; }
}
@keyframes anim-fade-in-bottom-right {
	from { opacity: 0; translate: 100% 100%; }
}

/* Keyframes: bounce */
@keyframes anim-bounce-in {
	0%, 20%, 40%, 60%, 80%, to {
		animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
	}
	0%  { opacity: 0; scale: 0.3; }
	20% { scale: 1.1; }
	40% { scale: 0.9; }
	60% { opacity: 1; scale: 1.03; }
	80% { scale: 0.97; }
	to  { opacity: 1; scale: 1; }
}

/* Keyframes: slide */
@keyframes anim-slide-in-down {
	from { translate: 0 -100%; }
}
@keyframes anim-slide-in-left {
	from { translate: -100% 0; }
}
@keyframes anim-slide-in-right {
	from { translate: 100% 0; }
}
@keyframes anim-slide-in-up {
	from { translate: 0 100%; }
}

/* Keyframes: depth (from Animista) */
@keyframes anim-slide-in-fwd {
	from { opacity: 0; scale: 0.4; }
}
@keyframes anim-slide-in-back {
	from { opacity: 0; scale: 2.5; }
}
@keyframes anim-puff-in {
	from { opacity: 0; scale: 2; filter: var(--anim-blur, blur(4px)); }
}

/* Keyframes: blurred slide (from Animista) */
@keyframes anim-slide-in-blurred-top {
	from { opacity: 0; translate: 0 -1000px; scale: 0.2 2.5; transform-origin: 50% 0%; filter: var(--anim-blur, blur(40px)); }
}
@keyframes anim-slide-in-blurred-bottom {
	from { opacity: 0; translate: 0 1000px; scale: 0.2 2.5; transform-origin: 50% 100%; filter: var(--anim-blur, blur(40px)); }
}
@keyframes anim-slide-in-blurred-left {
	from { opacity: 0; translate: -1000px 0; scale: 2.5 0.2; transform-origin: 100% 50%; filter: var(--anim-blur, blur(40px)); }
}
@keyframes anim-slide-in-blurred-right {
	from { opacity: 0; translate: 1000px 0; scale: 2.5 0.2; transform-origin: 0% 50%; filter: var(--anim-blur, blur(40px)); }
}

/* Keyframes: subtle fade (short move, tweak with --anim-distance) */
@keyframes anim-fade-in-up-sm {
	from { opacity: 0; translate: 0 var(--anim-distance, 2rem); }
}
@keyframes anim-fade-in-down-sm {
	from { opacity: 0; translate: 0 calc(var(--anim-distance, 2rem) * -1); }
}
@keyframes anim-fade-in-left-sm {
	from { opacity: 0; translate: calc(var(--anim-distance, 2rem) * -1) 0; }
}
@keyframes anim-fade-in-right-sm {
	from { opacity: 0; translate: var(--anim-distance, 2rem) 0; }
}

/* Keyframes: zoom */
@keyframes anim-zoom-in {
	from { opacity: 0; scale: 0.9; }
}

/* Keyframes: clip reveal (wipes in, element doesn't move) */
@keyframes anim-reveal-left {
	from { clip-path: inset(0 100% 0 0); }
	to   { clip-path: inset(0 0 0 0); }
}
@keyframes anim-reveal-right {
	from { clip-path: inset(0 0 0 100%); }
	to   { clip-path: inset(0 0 0 0); }
}
@keyframes anim-reveal-up {
	from { clip-path: inset(100% 0 0 0); }
	to   { clip-path: inset(0 0 0 0); }
}
@keyframes anim-reveal-down {
	from { clip-path: inset(0 0 100% 0); }
	to   { clip-path: inset(0 0 0 0); }
}

/* Keyframes: text focus (from Animista) */
@keyframes anim-text-focus-in {
	from { opacity: 0; filter: var(--anim-blur, blur(12px)); }
}

/* Keyframes: scale horizontal (from Animista) */
@keyframes anim-scale-in-hor {
	from { scale: 0 1; }
}

/* Effect classes: scroll + load version, each picks its keyframes */
.anim-fade-in,
.anim-fade-in-load { --anim-name: anim-fade-in; }
.anim-fade-in-down,
.anim-fade-in-down-load { --anim-name: anim-fade-in-down; }
.anim-fade-in-down-big,
.anim-fade-in-down-big-load { --anim-name: anim-fade-in-down-big; }
.anim-fade-in-left,
.anim-fade-in-left-load { --anim-name: anim-fade-in-left; }
.anim-fade-in-left-big,
.anim-fade-in-left-big-load { --anim-name: anim-fade-in-left-big; }
.anim-fade-in-right,
.anim-fade-in-right-load { --anim-name: anim-fade-in-right; }
.anim-fade-in-right-big,
.anim-fade-in-right-big-load { --anim-name: anim-fade-in-right-big; }
.anim-fade-in-up,
.anim-fade-in-up-load { --anim-name: anim-fade-in-up; }
.anim-fade-in-up-big,
.anim-fade-in-up-big-load { --anim-name: anim-fade-in-up-big; }
.anim-fade-in-top-left,
.anim-fade-in-top-left-load { --anim-name: anim-fade-in-top-left; }
.anim-fade-in-top-right,
.anim-fade-in-top-right-load { --anim-name: anim-fade-in-top-right; }
.anim-fade-in-bottom-left,
.anim-fade-in-bottom-left-load { --anim-name: anim-fade-in-bottom-left; }
.anim-fade-in-bottom-right,
.anim-fade-in-bottom-right-load { --anim-name: anim-fade-in-bottom-right; }
.anim-bounce-in,
.anim-bounce-in-load { --anim-name: anim-bounce-in; --anim-duration: 0.75s; }
.anim-slide-in-down,
.anim-slide-in-down-load { --anim-name: anim-slide-in-down; }
.anim-slide-in-left,
.anim-slide-in-left-load { --anim-name: anim-slide-in-left; }
.anim-slide-in-right,
.anim-slide-in-right-load { --anim-name: anim-slide-in-right; }
.anim-slide-in-up,
.anim-slide-in-up-load { --anim-name: anim-slide-in-up; }
.anim-slide-in-fwd,
.anim-slide-in-fwd-load { --anim-name: anim-slide-in-fwd; --anim-duration: 0.4s; --anim-ease: cubic-bezier(0.25, 0.46, 0.45, 0.94); }
.anim-slide-in-back,
.anim-slide-in-back-load { --anim-name: anim-slide-in-back; --anim-duration: 0.6s; --anim-ease: cubic-bezier(0.25, 0.46, 0.45, 0.94); }
.anim-puff-in,
.anim-puff-in-load { --anim-name: anim-puff-in; --anim-duration: 0.7s; --anim-ease: cubic-bezier(0.47, 0, 0.745, 0.715); }
.anim-slide-in-blurred-top,
.anim-slide-in-blurred-top-load { --anim-name: anim-slide-in-blurred-top; --anim-ease: cubic-bezier(0.23, 1, 0.32, 1); }
.anim-slide-in-blurred-bottom,
.anim-slide-in-blurred-bottom-load { --anim-name: anim-slide-in-blurred-bottom; --anim-ease: cubic-bezier(0.23, 1, 0.32, 1); }
.anim-slide-in-blurred-left,
.anim-slide-in-blurred-left-load { --anim-name: anim-slide-in-blurred-left; --anim-ease: cubic-bezier(0.23, 1, 0.32, 1); }
.anim-slide-in-blurred-right,
.anim-slide-in-blurred-right-load { --anim-name: anim-slide-in-blurred-right; --anim-ease: cubic-bezier(0.23, 1, 0.32, 1); }
.anim-fade-in-up-sm,
.anim-fade-in-up-sm-load { --anim-name: anim-fade-in-up-sm; }
.anim-fade-in-down-sm,
.anim-fade-in-down-sm-load { --anim-name: anim-fade-in-down-sm; }
.anim-fade-in-left-sm,
.anim-fade-in-left-sm-load { --anim-name: anim-fade-in-left-sm; }
.anim-fade-in-right-sm,
.anim-fade-in-right-sm-load { --anim-name: anim-fade-in-right-sm; }
.anim-zoom-in,
.anim-zoom-in-load { --anim-name: anim-zoom-in; }
.anim-reveal-left,
.anim-reveal-left-load { --anim-name: anim-reveal-left; --anim-duration: 0.8s; --anim-ease: cubic-bezier(0.77, 0, 0.175, 1); }
.anim-reveal-right,
.anim-reveal-right-load { --anim-name: anim-reveal-right; --anim-duration: 0.8s; --anim-ease: cubic-bezier(0.77, 0, 0.175, 1); }
.anim-reveal-up,
.anim-reveal-up-load { --anim-name: anim-reveal-up; --anim-duration: 0.8s; --anim-ease: cubic-bezier(0.77, 0, 0.175, 1); }
.anim-reveal-down,
.anim-reveal-down-load { --anim-name: anim-reveal-down; --anim-duration: 0.8s; --anim-ease: cubic-bezier(0.77, 0, 0.175, 1); }
.anim-text-focus-in,
.anim-text-focus-in-load { --anim-name: anim-text-focus-in; --anim-duration: 1s; --anim-ease: cubic-bezier(0.55, 0.085, 0.68, 0.53); }
.anim-scale-in-hor,
.anim-scale-in-hor-load { --anim-name: anim-scale-in-hor; --anim-duration: 0.5s; --anim-ease: cubic-bezier(0.25, 0.46, 0.45, 0.94); }

/* Stagger helper: put on a parent, children animate one after another.
   Children still need their own anim-* class (scroll or -load).
   Load:   "anim-stagger" = 0.1s gap, "anim-stagger-slow" = 0.2s gap.
   Scroll: each child starts a little further down the scroll
           (5% / 10% of the scroll range).
   Custom gaps per parent: --anim-stagger, --anim-stagger-scroll.
   Wait before the first child (load only): --anim-delay-start. */
.anim-stagger-slow {
	--anim-stagger: 0.2s;
	--anim-stagger-scroll: 10%;
}
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(2) { --anim-step: 1; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(3) { --anim-step: 2; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(4) { --anim-step: 3; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(5) { --anim-step: 4; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(6) { --anim-step: 5; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(7) { --anim-step: 6; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(8) { --anim-step: 7; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(9) { --anim-step: 8; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(10) { --anim-step: 9; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(11) { --anim-step: 10; }
:is(.anim-stagger, .anim-stagger-slow) > :nth-child(n+12) { --anim-step: 11; }

/* Stagger off on phones: grids stack to one column, so no waiting */
@media (max-width: 767px) {
	.anim-stagger,
	.anim-stagger-slow {
		--anim-stagger: 0s;
		--anim-stagger-scroll: 0%;
	}
}

@media (prefers-reduced-motion: no-preference) {

	/* On scroll: Chrome, Edge, Safari 26+ */
	@supports (animation-timeline: view()) {
		[class^="anim-"],
		[class*=" anim-"] {
			animation: var(--anim-name) linear backwards;
			animation-timeline: view();
			/* Staggered items start later, but their end only moves half
			   as far, so the last item doesn't finish high up the screen. */
			--anim-range-start: calc(var(--anim-step, 0) * var(--anim-stagger-scroll, 5%));
			animation-range:
				cover var(--anim-range-start)
				cover max(
					calc(var(--anim-range-start) + 10%),
					calc(var(--anim-end, 25%) + var(--anim-range-start) / 2)
				);
		}

		/* Scroll scope: put "anim-scope" on a wrapper with overflow
		   (sliders, horizontal scrollers). Children then track the
		   wrapper's position on the page instead of the wrapper itself. */
		.anim-scope {
			view-timeline: --anim-scope block;
		}
		.anim-scope [class^="anim-"],
		.anim-scope [class*=" anim-"] {
			animation-timeline: --anim-scope;
		}
	}

	/* Page load: any class ending in -load */
	[class^="anim-"][class*="-load"],
	[class*=" anim-"][class*="-load"] {
		animation: var(--anim-name) var(--anim-duration, 0.6s) var(--anim-ease, ease-out) var(--anim-delay, calc(var(--anim-delay-start, 0s) + var(--anim-step, 0) * var(--anim-stagger, 0.1s))) backwards;
		animation-timeline: auto;
		animation-range: normal;
	}
}

/* ==========================================================
   Mobile: finish scroll animations by scroll distance, not
   element height.

   Why: "cover" percentages are measured against
   (screen height + element height). Tall stacked blocks on
   phones therefore take far longer to finish.
   On phones the range runs from the element's top edge
   entering the screen to a fixed distance above the bottom.

   Tweak: --anim-end-mobile (default 25vh; lower = sooner).
   Set it on any element or parent to override.
   Load (-load) classes are unaffected (their selector is
   more specific).
   ========================================================== */
@media (max-width: 767px) and (prefers-reduced-motion: no-preference) {
	@supports (animation-timeline: view()) {
		[class^="anim-"],
		[class*=" anim-"] {
			animation-range:
				entry var(--anim-range-start)
				entry calc(var(--anim-end-mobile, 25vh) + var(--anim-range-start) / 2);
		}
	}
}