/* 
   animations.css — Optimized in 2026
   Author: Tymchenko Serhii (https://github.com/ts03-coder)
*/

/* ── 1. ANIMATION TOKENS ── */
:root {
	--anim-duration-fast: 0.25s;
	--anim-duration-base: 0.5s;
	--anim-duration-slow: 0.8s;

	--anim-offset-sm: 30px;
	--anim-offset-md: 60px;
	--anim-offset-lg: 100px;

	/* Classic easing */
	--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
	--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);

	/* Spring easing via linear() — stiffness ~200, damping ~20 */
	--ease-spring: linear(
		0,
		0.009,
		0.035 2.1%,
		0.141 4.4%,
		0.723 12.4%,
		0.938 16%,
		1.046,
		1.059 20.3%,
		1.051,
		1.015 27.2%,
		0.999 29.2%,
		0.999,
		1
	);

	/* Fallback for browsers that don't support linear() */
	--ease-spring-fallback: cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* ── 2. ACCESSIBILITY: Reduced Motion ── */
@media (prefers-reduced-motion: reduce) {
	[class*="animate_"] {
		animation: none !important;
		transition: none !important;
		opacity: 1 !important;
		transform: none !important;
	}
}

/* ── 3. KEYFRAMES (no vendor prefixes needed in 2025) ── */

/* Scale from center */
@keyframes anim-scale-in {
	from {
		opacity: 0;
		transform: scale(0.2);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

/* Slide from left */
@keyframes anim-slide-left {
	from {
		opacity: 0;
		transform: translateX(calc(var(--anim-offset-lg) * -1));
	}
	to {
		opacity: 1;
		transform: translateX(0);
	}
}

/* Slide from right */
@keyframes anim-slide-right {
	from {
		opacity: 0;
		transform: translateX(var(--anim-offset-lg));
	}
	to {
		opacity: 1;
		transform: translateX(0);
	}
}

/* Slide from top */
@keyframes anim-slide-top {
	from {
		opacity: 0;
		transform: translateY(calc(var(--anim-offset-lg) * -1));
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* Slide from bottom */
@keyframes anim-slide-bottom {
	from {
		opacity: 0;
		transform: translateY(var(--anim-offset-lg));
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* Width expand */
@keyframes anim-width-expand {
	from {
		opacity: 0;
		transform: scaleX(0.01);
	}
	to {
		opacity: 1;
		transform: scaleX(1);
	}
}

/* Height expand */
@keyframes anim-height-expand {
	from {
		opacity: 0;
		transform: scaleY(0.01);
	}
	to {
		opacity: 1;
		transform: scaleY(1);
	}
}

/* Rotate from center */
@keyframes anim-rotate-center {
	from {
		opacity: 0;
		transform: scale(0.01) rotate(360deg);
	}
	to {
		opacity: 1;
		transform: scale(1) rotate(0deg);
	}
}

/* Rotate from left */
@keyframes anim-rotate-left {
	from {
		opacity: 0;
		transform: translateX(calc(var(--anim-offset-lg) * -1)) rotate(-180deg);
	}
	to {
		opacity: 1;
		transform: translateX(0) rotate(0deg);
	}
}

/* Rotate from right */
@keyframes anim-rotate-right {
	from {
		opacity: 0;
		transform: translateX(var(--anim-offset-lg)) rotate(180deg);
	}
	to {
		opacity: 1;
		transform: translateX(0) rotate(0deg);
	}
}

/* ── 4. ANIMATION CLASSES ── */

/* Base hidden state — use will-change for GPU compositing */
[class*="animate_afc"],
[class*="animate_afl"],
[class*="animate_afr"],
[class*="animate_aft"],
[class*="animate_afb"],
[class*="animate_wfc"],
[class*="animate_hfc"],
[class*="animate_rfc"],
[class*="animate_rfl"],
[class*="animate_rfr"] {
	opacity: 0;
	will-change: transform, opacity;
}

/* Remove will-change after animation completes to free GPU memory */
[class*="animate_start"] {
	opacity: 1;
	will-change: auto;
}

/* Scale from center */
.animate_afc.animate_start {
	animation: var(--anim-duration-slow) var(--ease-out-expo) both 1 anim-scale-in;
}

/* Slide from left */
.animate_afl.animate_start {
	animation: var(--anim-duration-base) var(--ease-out-expo) both 1 anim-slide-left;
}

/* Slide from right */
.animate_afr.animate_start {
	animation: var(--anim-duration-slow) var(--ease-out-expo) both 1 anim-slide-right;
}

/* Slide from top */
.animate_aft.animate_start {
	animation: var(--anim-duration-slow) var(--ease-out-expo) both 1 anim-slide-top;
}

/* Slide from bottom */
.animate_afb.animate_start {
	animation: var(--anim-duration-slow) var(--ease-out-expo) both 1 anim-slide-bottom;
}

/* Width expand */
.animate_wfc.animate_start {
	animation: var(--anim-duration-slow) var(--ease-out-expo) both 1 anim-width-expand;
}

/* Height expand */
.animate_hfc.animate_start {
	animation: var(--anim-duration-slow) var(--ease-out-expo) both 1 anim-height-expand;
}

/* Rotate center */
.animate_rfc.animate_start {
	animation: var(--anim-duration-slow) var(--ease-spring-fallback) both 1 anim-rotate-center;
	/* Spring easing for browsers that support linear() */
	@supports (animation-timing-function: linear(0, 1)) {
		animation-timing-function: var(--ease-spring);
	}
}

/* Rotate from left */
.animate_rfl.animate_start {
	animation: var(--anim-duration-slow) var(--ease-spring-fallback) both 1 anim-rotate-left;
	@supports (animation-timing-function: linear(0, 1)) {
		animation-timing-function: var(--ease-spring);
	}
}

/* Rotate from right */
.animate_rfr.animate_start {
	animation: var(--anim-duration-slow) var(--ease-spring-fallback) both 1 anim-rotate-right;
	@supports (animation-timing-function: linear(0, 1)) {
		animation-timing-function: var(--ease-spring);
	}
}

/* ── 5. STAGGER DELAYS — CSS custom property approach ── */
/* Використовуй: style="--stagger-i: 1" замість .d1, .d2 */
.animate_start {
	animation-delay: calc(var(--stagger-i, 0) * 0.2s);
}

/* Старі класи (backward compatibility) */
.d1.animate_start {
	animation-delay: 0.2s;
}
.d2.animate_start {
	animation-delay: 0.4s;
}
.d3.animate_start {
	animation-delay: 0.6s;
}
.d4.animate_start {
	animation-delay: 0.8s;
}
.d5.animate_start {
	animation-delay: 1s;
}
.d6.animate_start {
	animation-delay: 1.2s;
}

/* ── 6. SCROLL-DRIVEN ANIMATIONS (Chrome 115+, Safari 26+) ── */
/* Автоматичний reveal при скролі — без JavaScript! */
@supports (animation-timeline: view()) {
	.scroll-reveal {
		animation: anim-slide-bottom var(--anim-duration-slow) var(--ease-out-expo) both;
		animation-timeline: view();
		animation-range: entry 0% entry 40%;
	}

	.scroll-fade {
		animation: anim-scale-in var(--anim-duration-slow) var(--ease-out-expo) both;
		animation-timeline: view();
		animation-range: entry 5% entry 45%;
	}
}

/* ── 7. @starting-style — вхідні анімації без JS (Chrome 117+, Firefox 129+, Safari 17.5+) ── */
/* Анімуй елементи при першій появі в DOM (display: none → block) */
.anim-enter {
	transition:
		opacity var(--anim-duration-base) var(--ease-out-expo),
		transform var(--anim-duration-base) var(--ease-out-expo);
	opacity: 1;
	transform: translateY(0);

	@starting-style {
		opacity: 0;
		transform: translateY(var(--anim-offset-sm));
	}
}

/* ── 8. transition-behavior: allow-discrete (Chrome 117+, Firefox 129+) ── */
/* Анімуй display: none ↔ block плавно */
.anim-toggle {
	transition:
		opacity var(--anim-duration-fast) var(--ease-out-expo),
		display var(--anim-duration-fast) allow-discrete;
	opacity: 1;
	display: block;

	&.hidden {
		display: none;
		opacity: 0;

		@starting-style {
			opacity: 1;
		}
	}
}
