/**
 * Block Animator — animation engine
 *
 * Design notes:
 * - Every animated element gets ONE shared class (.gba-animate) that reads
 *   its timing from CSS custom properties set inline per-block. This keeps
 *   the stylesheet small and cacheable instead of generating a class per
 *   possible duration/delay/easing combination.
 * - Directional variants (Up/Down/Left/Right) reuse a single @keyframes
 *   definition and only change the --gba-x/--gba-y/--gba-deg custom
 *   properties, again to avoid duplicated keyframe blocks.
 * - `animation-fill-mode: both` means the paused/scroll-triggered state
 *   (see .gba-trigger-scroll) automatically shows the animation's 0% frame
 *   before it plays — no separate "hidden" class or extra JS is needed.
 */

.gba-animate {
	animation-name: none;
	animation-duration: var(--gba-duration, 1s);
	animation-delay: var(--gba-delay, 0s);
	animation-timing-function: var(--gba-easing, ease);
	animation-iteration-count: var(--gba-iteration, 1);
	animation-direction: var(--gba-direction, normal);
	animation-fill-mode: both;
	will-change: transform, opacity;
}

/* Scroll-triggered animations start paused; frontend.js adds .gba-in-view
   the first time the element crosses into the viewport. */
.gba-trigger-scroll {
	animation-play-state: paused;
}
.gba-trigger-scroll.gba-in-view {
	animation-play-state: running;
}

/* Respect reduced-motion preferences: play once, instantly, no motion. */
@media (prefers-reduced-motion: reduce) {
	.gba-animate {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
	}
}

/* -----------------------------------------------------------------
 * Fading
 * --------------------------------------------------------------- */
@keyframes gba-fade {
	from { opacity: 0; }
	to   { opacity: 1; }
}
@keyframes gba-fade-move {
	from { opacity: 0; transform: translate3d(var(--gba-x, 0), var(--gba-y, 0), 0); }
	to   { opacity: 1; transform: translate3d(0, 0, 0); }
}
@keyframes gba-fade-out {
	from { opacity: 1; }
	to   { opacity: 0; }
}
@keyframes gba-fade-out-move {
	from { opacity: 1; transform: translate3d(0, 0, 0); }
	to   { opacity: 0; transform: translate3d(var(--gba-x, 0), var(--gba-y, 0), 0); }
}

.gba-anim-fadeIn      { animation-name: gba-fade; }
.gba-anim-fadeInUp    { animation-name: gba-fade-move; --gba-y: 40px; }
.gba-anim-fadeInDown  { animation-name: gba-fade-move; --gba-y: -40px; }
.gba-anim-fadeInLeft  { animation-name: gba-fade-move; --gba-x: -40px; }
.gba-anim-fadeInRight { animation-name: gba-fade-move; --gba-x: 40px; }
.gba-anim-fadeOut     { animation-name: gba-fade-out; }
.gba-anim-fadeOutUp   { animation-name: gba-fade-out-move; --gba-y: -40px; }
.gba-anim-fadeOutDown { animation-name: gba-fade-out-move; --gba-y: 40px; }

/* -----------------------------------------------------------------
 * Sliding (pure transform, no opacity change)
 * --------------------------------------------------------------- */
@keyframes gba-slide {
	from { transform: translate3d(var(--gba-x, 0), var(--gba-y, 0), 0); }
	to   { transform: translate3d(0, 0, 0); }
}
.gba-anim-slideInUp    { animation-name: gba-slide; --gba-y: 60px; }
.gba-anim-slideInDown  { animation-name: gba-slide; --gba-y: -60px; }
.gba-anim-slideInLeft  { animation-name: gba-slide; --gba-x: -60px; }
.gba-anim-slideInRight { animation-name: gba-slide; --gba-x: 60px; }

/* -----------------------------------------------------------------
 * Zooming
 * --------------------------------------------------------------- */
@keyframes gba-zoom {
	from { opacity: 0; transform: scale3d(var(--gba-scale, 0.3), var(--gba-scale, 0.3), 1) translate3d(var(--gba-x, 0), var(--gba-y, 0), 0); }
	to   { opacity: 1; transform: scale3d(1, 1, 1) translate3d(0, 0, 0); }
}
@keyframes gba-zoom-out {
	from { opacity: 1; transform: scale3d(1, 1, 1); }
	to   { opacity: 0; transform: scale3d(var(--gba-scale, 0.3), var(--gba-scale, 0.3), 1); }
}
.gba-anim-zoomIn     { animation-name: gba-zoom; --gba-scale: 0.3; }
.gba-anim-zoomInUp   { animation-name: gba-zoom; --gba-scale: 0.5; --gba-y: 60px; }
.gba-anim-zoomInDown { animation-name: gba-zoom; --gba-scale: 0.5; --gba-y: -60px; }
.gba-anim-zoomOut    { animation-name: gba-zoom-out; --gba-scale: 0.3; }

/* -----------------------------------------------------------------
 * Bouncing
 * --------------------------------------------------------------- */
@keyframes gba-bounce-in {
	0%   { opacity: 0; transform: scale3d(0.3, 0.3, 0.3); }
	20%  { transform: scale3d(1.1, 1.1, 1.1); }
	40%  { transform: scale3d(0.9, 0.9, 0.9); }
	60%  { opacity: 1; transform: scale3d(1.03, 1.03, 1.03); }
	80%  { transform: scale3d(0.97, 0.97, 0.97); }
	100% { opacity: 1; transform: scale3d(1, 1, 1); }
}
@keyframes gba-bounce-in-move {
	0%   { opacity: 0; transform: translate3d(var(--gba-x, 0), var(--gba-y, 0), 0); }
	60%  { opacity: 1; transform: translate3d(calc(var(--gba-x, 0) * -0.05), calc(var(--gba-y, 0) * -0.05), 0); }
	75%  { transform: translate3d(calc(var(--gba-x, 0) * 0.02), calc(var(--gba-y, 0) * 0.02), 0); }
	90%  { transform: translate3d(calc(var(--gba-x, 0) * -0.01), calc(var(--gba-y, 0) * -0.01), 0); }
	100% { opacity: 1; transform: translate3d(0, 0, 0); }
}
.gba-anim-bounceIn      { animation-name: gba-bounce-in; }
.gba-anim-bounceInUp    { animation-name: gba-bounce-in-move; --gba-y: 200px; }
.gba-anim-bounceInDown  { animation-name: gba-bounce-in-move; --gba-y: -200px; }
.gba-anim-bounceInLeft  { animation-name: gba-bounce-in-move; --gba-x: -300px; }
.gba-anim-bounceInRight { animation-name: gba-bounce-in-move; --gba-x: 300px; }

/* -----------------------------------------------------------------
 * Rotating
 * --------------------------------------------------------------- */
@keyframes gba-rotate-in {
	from {
		opacity: 0;
		transform-origin: var(--gba-origin, center);
		transform: rotate3d(var(--gba-rx, 0), var(--gba-ry, 0), var(--gba-rz, 1), var(--gba-deg, -200deg));
	}
	to {
		opacity: 1;
		transform-origin: var(--gba-origin, center);
		transform: none;
	}
}
.gba-anim-rotateIn          { animation-name: gba-rotate-in; --gba-deg: -200deg; }
.gba-anim-rotateInDownLeft  { animation-name: gba-rotate-in; --gba-origin: left bottom; --gba-deg: -45deg; }
.gba-anim-rotateInDownRight { animation-name: gba-rotate-in; --gba-origin: right bottom; --gba-deg: 45deg; }
.gba-anim-rotateInUpLeft    { animation-name: gba-rotate-in; --gba-origin: left bottom; --gba-deg: 45deg; }
.gba-anim-rotateInUpRight   { animation-name: gba-rotate-in; --gba-origin: right bottom; --gba-deg: -90deg; }

/* -----------------------------------------------------------------
 * Flipping
 * --------------------------------------------------------------- */
@keyframes gba-flip-in-x {
	0%   { opacity: 0; transform: perspective(400px) rotate3d(1, 0, 0, 90deg); }
	40%  { transform: perspective(400px) rotate3d(1, 0, 0, -20deg); }
	60%  { opacity: 1; transform: perspective(400px) rotate3d(1, 0, 0, 10deg); }
	80%  { transform: perspective(400px) rotate3d(1, 0, 0, -5deg); }
	100% { opacity: 1; transform: perspective(400px); }
}
@keyframes gba-flip-in-y {
	0%   { opacity: 0; transform: perspective(400px) rotate3d(0, 1, 0, 90deg); }
	40%  { transform: perspective(400px) rotate3d(0, 1, 0, -20deg); }
	60%  { opacity: 1; transform: perspective(400px) rotate3d(0, 1, 0, 10deg); }
	80%  { transform: perspective(400px) rotate3d(0, 1, 0, -5deg); }
	100% { opacity: 1; transform: perspective(400px); }
}
.gba-anim-flipInX { animation-name: gba-flip-in-x; }
.gba-anim-flipInY { animation-name: gba-flip-in-y; }

/* -----------------------------------------------------------------
 * Attention seekers (loop-friendly, don't rely on a hidden starting state)
 * --------------------------------------------------------------- */
@keyframes gba-pulse {
	0%, 100% { transform: scale3d(1, 1, 1); }
	50%      { transform: scale3d(1.05, 1.05, 1.05); }
}
@keyframes gba-shake {
	0%, 100% { transform: translate3d(0, 0, 0); }
	10%, 30%, 50%, 70%, 90% { transform: translate3d(-8px, 0, 0); }
	20%, 40%, 60%, 80%      { transform: translate3d(8px, 0, 0); }
}
@keyframes gba-swing {
	20% { transform: rotate3d(0, 0, 1, 12deg); }
	40% { transform: rotate3d(0, 0, 1, -8deg); }
	60% { transform: rotate3d(0, 0, 1, 4deg); }
	80% { transform: rotate3d(0, 0, 1, -2deg); }
	100% { transform: rotate3d(0, 0, 1, 0deg); }
}
.gba-anim-swing { transform-origin: top center; }
@keyframes gba-tada {
	0%   { transform: scale3d(1, 1, 1); }
	10%, 20% { transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); }
	30%, 50%, 70%, 90% { transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); }
	40%, 60%, 80% { transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); }
	100% { transform: scale3d(1, 1, 1); }
}
@keyframes gba-wobble {
	0% { transform: translate3d(0, 0, 0); }
	15% { transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); }
	30% { transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); }
	45% { transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); }
	60% { transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); }
	75% { transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); }
	100% { transform: translate3d(0, 0, 0); }
}
@keyframes gba-jello {
	0%, 11.1%, 100% { transform: translate3d(0, 0, 0); }
	22.2% { transform: skewX(-12.5deg) skewY(-12.5deg); }
	33.3% { transform: skewX(6.25deg) skewY(6.25deg); }
	44.4% { transform: skewX(-3.125deg) skewY(-3.125deg); }
	55.5% { transform: skewX(1.5625deg) skewY(1.5625deg); }
	66.6% { transform: skewX(-0.78125deg) skewY(-0.78125deg); }
	77.7% { transform: skewX(0.390625deg) skewY(0.390625deg); }
	88.8% { transform: skewX(-0.1953125deg) skewY(-0.1953125deg); }
}
@keyframes gba-heartbeat {
	0%   { transform: scale(1); }
	14%  { transform: scale(1.3); }
	28%  { transform: scale(1); }
	42%  { transform: scale(1.3); }
	70%  { transform: scale(1); }
}
@keyframes gba-headshake {
	0%   { transform: translateX(0); }
	6.5% { transform: translateX(-6px) rotateY(-9deg); }
	18.5% { transform: translateX(5px) rotateY(7deg); }
	31.5% { transform: translateX(-3px) rotateY(-5deg); }
	43.5% { transform: translateX(2px) rotateY(3deg); }
	50%  { transform: translateX(0); }
}
@keyframes gba-rubberband {
	0%   { transform: scale3d(1, 1, 1); }
	30%  { transform: scale3d(1.25, 0.75, 1); }
	40%  { transform: scale3d(0.75, 1.25, 1); }
	50%  { transform: scale3d(1.15, 0.85, 1); }
	65%  { transform: scale3d(0.95, 1.05, 1); }
	75%  { transform: scale3d(1.05, 0.95, 1); }
	100% { transform: scale3d(1, 1, 1); }
}
@keyframes gba-flash {
	0%, 50%, 100% { opacity: 1; }
	25%, 75%      { opacity: 0; }
}

.gba-anim-pulse      { animation-name: gba-pulse; }
.gba-anim-shake      { animation-name: gba-shake; }
.gba-anim-swing      { animation-name: gba-swing; }
.gba-anim-tada       { animation-name: gba-tada; }
.gba-anim-wobble     { animation-name: gba-wobble; }
.gba-anim-jello      { animation-name: gba-jello; }
.gba-anim-heartBeat  { animation-name: gba-heartbeat; }
.gba-anim-headShake  { animation-name: gba-headshake; }
.gba-anim-rubberBand { animation-name: gba-rubberband; }
.gba-anim-flash      { animation-name: gba-flash; }

/* -----------------------------------------------------------------
 * Specials
 * --------------------------------------------------------------- */
@keyframes gba-roll-in {
	from { opacity: 0; transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); }
	to   { opacity: 1; transform: translate3d(0, 0, 0); }
}
@keyframes gba-light-speed-in {
	from { opacity: 0; transform: translate3d(100px, 0, 0) skewX(-30deg); }
	60%  { opacity: 1; transform: skewX(20deg); }
	80%  { transform: skewX(-5deg); }
	100% { transform: none; }
}
@keyframes gba-back-in {
	0%   { opacity: 0; transform: translate3d(var(--gba-x, 0), var(--gba-y, 0), 0) scale3d(0.7, 0.7, 0.7); }
	80%  { opacity: 0.7; transform: scale3d(0.7, 0.7, 0.7); }
	100% { opacity: 1; transform: scale3d(1, 1, 1); }
}
.gba-anim-rollIn       { animation-name: gba-roll-in; }
.gba-anim-lightSpeedIn { animation-name: gba-light-speed-in; }
.gba-anim-backInUp     { animation-name: gba-back-in; --gba-y: 200px; }
.gba-anim-backInDown   { animation-name: gba-back-in; --gba-y: -200px; }
.gba-anim-backInLeft   { animation-name: gba-back-in; --gba-x: -200px; }
.gba-anim-backInRight  { animation-name: gba-back-in; --gba-x: 200px; }
