/**
 * Abibitumi Motion System — stylesheet
 *
 * Every selector is scoped under `.abi-motion` on <body>. That class only
 * exists while this plugin is active, so deactivation removes the anchor for
 * all of it at once and the site renders exactly as it did before.
 *
 * Durations and easings below are measured from obadelekambon.com, not
 * invented. See REFERENCE-MOTION-AUDIT.md §K.
 */

:root {
	/* Durations ------------------------------------------------------- */
	--abi-motion-fast: 250ms;      /* hover, cards, list rows            */
	--abi-motion-header: 350ms;    /* header state change                */
	--abi-motion-wipe-out: 460ms;  /* page cover                         */
	--abi-motion-wipe-in: 720ms;   /* page reveal                        */
	--abi-motion-reveal: 1050ms;   /* section entrance                   */
	--abi-motion-settle: 1250ms;   /* clip-path tail on layered items    */

	/* Easings --------------------------------------------------------- */
	--abi-ease-wipe: cubic-bezier( .76, 0, .24, 1 );
	--abi-ease-reveal: cubic-bezier( .16, 1, .3, 1 );

	/* Wipe palette ---------------------------------------------------- *
	 * Abibitumi's own brand values, read from the homepage's --red,
	 * --black and --green custom properties on .ab-start.              */
	--abi-wipe-1: #c01219;
	--abi-wipe-2: #0e0e0e;
	--abi-wipe-3: #1b6b38;

	/* Per-element values written by JS. Declared here so the transform
	 * is always valid even before the first rAF frame runs.            */
	--abi-y: 0px;
	--abi-scale: 1;
	--abi-opacity: 1;
	--abi-delay: 0ms;
}

/* ===================================================================== *
 * Entrance reveals
 * ===================================================================== */

.abi-motion [data-abi-reveal] {
	transition-property: opacity, transform, clip-path;
	transition-duration: var( --abi-motion-reveal );
	transition-timing-function: var( --abi-ease-reveal );
	transition-delay: var( --abi-delay, 0ms );
	will-change: opacity, transform;
}

.abi-motion [data-abi-reveal]:not(.is-seen) {
	opacity: 0;
}

/* Default: rise. */
.abi-motion [data-abi-reveal="up"]:not(.is-seen),
.abi-motion [data-abi-reveal=""]:not(.is-seen) {
	transform: translateY( 92px ) scale( .965 );
}

/* Paired opposing horizontals — the characteristic move of the reference.
 * Use "left" on the media and "right" on its copy, or vice versa. */
.abi-motion [data-abi-reveal="left"]:not(.is-seen) {
	transform: translateX( -13vw ) scale( .92 );
}

.abi-motion [data-abi-reveal="right"]:not(.is-seen) {
	transform: translateX( 13vw ) scale( .95 );
}

/* Section headings: horizontal sweep with a slight skew. */
.abi-motion [data-abi-reveal="skew"]:not(.is-seen) {
	transform: translateX( -12vw ) skewX( -3deg );
}

/* Layered image arrival — opacity, transform and clip settle at different
 * rates so the element assembles rather than appearing. */
.abi-motion [data-abi-reveal="mask"]:not(.is-seen) {
	clip-path: inset( 12% 0 );
	transform: translateY( 70px ) scale( .965 );
}

.abi-motion [data-abi-reveal="mask"].is-seen {
	clip-path: inset( 0 );
	transition-duration: var( --abi-motion-reveal );
	transition-property: opacity, transform, clip-path;
	transition-timing-function: var( --abi-ease-reveal );
}

.abi-motion [data-abi-reveal].is-seen {
	opacity: 1;
	transform: none;
}

/* Stop reserving compositor memory once the entrance is done. */
.abi-motion [data-abi-reveal].is-seen {
	will-change: auto;
}

/* ===================================================================== *
 * Scroll-linked parallax
 * ===================================================================== */

.abi-motion [data-abi-parallax] {
	transform: translate3d( 0, var( --abi-y, 0px ), 0 ) scale( var( --abi-scale, 1 ) );
	opacity: var( --abi-opacity, 1 );
	will-change: transform;
}

/**
 * Overscan.
 *
 * An image that translates inside its container must be larger than the
 * container or the edge shows. The reference uses 110–116%; anything less
 * and the movement has to be cut back until it stops reading as depth.
 */
.abi-motion [data-abi-parallax][data-abi-overscan] {
	height: 116%;
	width: 100%;
	object-fit: cover;
}

.abi-motion [data-abi-frame] {
	overflow: hidden;
	position: relative;
}

/* ===================================================================== *
 * Page wipe
 * ===================================================================== */

.abi-wipe {
	position: fixed;
	inset: 0;
	z-index: 99999;
	pointer-events: none;
	transform: translateX( -101% );
	background: linear-gradient(
		90deg,
		var( --abi-wipe-1 ) 0,
		var( --abi-wipe-1 ) 33.333%,
		var( --abi-wipe-2 ) 33.333%,
		var( --abi-wipe-2 ) 66.666%,
		var( --abi-wipe-3 ) 66.666%,
		var( --abi-wipe-3 ) 100%
	);
}

/* Arriving: the panel continues out to the left. It never reverses, so the
 * cover and the reveal read as one object crossing the navigation. */
.abi-wipe.is-arriving {
	animation: abiWipeReveal var( --abi-motion-wipe-in ) var( --abi-ease-wipe ) forwards;
}

/* Leaving: enters from the right. Faster than the reveal — nobody should
 * wait to watch a transition. */
.abi-wipe.is-leaving {
	animation: abiWipeCover var( --abi-motion-wipe-out ) var( --abi-ease-wipe ) forwards;
}

@keyframes abiWipeCover {
	from { transform: translateX( 101% ); }
	to   { transform: translateX( 0 ); }
}

@keyframes abiWipeReveal {
	from { transform: translateX( 0 ); }
	to   { transform: translateX( -101% ); }
}

/* ===================================================================== *
 * Micro-interactions
 * ===================================================================== */

.abi-motion [data-abi-hover] {
	transition: transform var( --abi-motion-fast ) var( --abi-ease-reveal ),
	            box-shadow var( --abi-motion-fast ) var( --abi-ease-reveal );
}

.abi-motion [data-abi-hover]:hover {
	transform: translateY( -4px );
}

.abi-motion [data-abi-frame] [data-abi-hover-zoom] {
	transition: transform var( --abi-motion-header ) var( --abi-ease-reveal );
}

.abi-motion [data-abi-frame]:hover [data-abi-hover-zoom] {
	transform: scale( 1.06 );
}

/* Never remove a focus ring without replacing it. */
.abi-motion a:focus-visible,
.abi-motion button:focus-visible,
.abi-motion [tabindex]:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

/* ===================================================================== *
 * Mobile profile
 *
 * Mid-ground parallax is switched off rather than scaled down, matching the
 * reference. Entrances are kept but shortened — they are what gives a phone
 * page its life, and they cost nothing.
 * ===================================================================== */

@media ( max-width: 900px ) {
	.abi-motion [data-abi-parallax] {
		transform: none;
		will-change: auto;
	}

	.abi-motion [data-abi-parallax][data-abi-overscan] {
		height: 108%;
	}

	.abi-motion [data-abi-reveal] {
		transition-duration: 780ms;
	}

	/* Horizontal sweeps become vertical: a 13vw slide on a narrow screen
	 * either overflows or looks like a glitch. */
	.abi-motion [data-abi-reveal="left"]:not(.is-seen),
	.abi-motion [data-abi-reveal="right"]:not(.is-seen),
	.abi-motion [data-abi-reveal="skew"]:not(.is-seen) {
		transform: translateY( 48px );
	}
}

/* ===================================================================== *
 * Reduced motion
 *
 * Content visible immediately. No parallax, no scrubbing, no wipe, no
 * decorative animation. This block is deliberately last and deliberately
 * uses !important — it must beat anything authored later.
 * ===================================================================== */

@media ( prefers-reduced-motion: reduce ) {
	.abi-wipe {
		display: none !important;
	}

	.abi-motion [data-abi-reveal],
	.abi-motion [data-abi-reveal]:not(.is-seen),
	.abi-motion [data-abi-parallax] {
		opacity: 1 !important;
		transform: none !important;
		translate: none !important;
		clip-path: none !important;
		animation: none !important;
		transition: none !important;
		will-change: auto !important;
	}

	.abi-motion [data-abi-parallax][data-abi-overscan] {
		height: 100% !important;
	}

	.abi-motion [data-abi-hover]:hover,
	.abi-motion [data-abi-frame]:hover [data-abi-hover-zoom] {
		transform: none !important;
	}
}
