/**
 * MCN Animations — Loaders
 *
 * Rebuilt from:
 *   Jenning,       "Kinetic CSS loaders"        (codepen.io/jenning/pen/LYWJdWz, MIT)
 *   Arushi Bajpai, "Newton's cradle"            (codepen.io/arushi011/pen/EXmMvx, MIT)
 *   Ekta Maurya,   "Glowing Loader Ring"        (codepen.io/Curlmuhi/pen/ExKWXKO, MIT)
 *   Pawel,         "Never-ending box / pancake" (codepen.io/pawelqcm/pen/dMqrqd, MIT)
 *   Maxoor,        "The Glowing Loader"         (codepen.io/Maxoor/pen/JZZvXJ, MIT)
 *
 * ACCESSIBILITY CONTRACT FOR EVERY LOADER
 *   1. Wrap in role="status" (implicit aria-live="polite") with real text —
 *      a visually-hidden "Loading results" is what a screen reader announces.
 *      A spinning div alone announces nothing at all.
 *   2. WCAG 2.3.1 (Level A): nothing here crosses three flashes per second.
 *      The fastest opacity cycle in this file is ~1.4Hz, and the rest are
 *      pure rotation or translation, which do not flash at any speed.
 *   3. WCAG 2.2.2 (Level A) does NOT apply to loaders that stop on their own
 *      once content arrives — but it DOES apply if you leave one spinning
 *      forever as decoration. Do not do that.
 *
 * Markup:
 *   <div class="anim-load" role="status">
 *     <span class="anim-load__ring"></span>
 *     <span class="anim-sr">Loading results</span>
 *   </div>
 *
 * @package MCN_Animations
 */

/* Visually-hidden helper — the clip-path variant, which survives display
   contexts where the old 1px-clip hack collapses. */
.anim-sr {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.anim-load {
	display: inline-flex;
	align-items: center;
	gap: 0.6em;
	color: var(--anim-accent);
}

/* --------------------------------------------------------------------------
 * Ring
 * ----------------------------------------------------------------------- */

.anim-load__ring {
	width: var(--load-size, 34px);
	height: var(--load-size, 34px);
	border-radius: 50%;
	border: var(--load-weight, 3px) solid currentColor;
	border-right-color: transparent;
	animation: anim-load-spin 800ms linear infinite;
}

/* Glowing variant — a second counter-rotating ring plus a travelling dot. */
.anim-load__ring--glow {
	position: relative;
	border-color: currentColor transparent currentColor transparent;
	filter: drop-shadow(0 0 6px currentColor);
	animation-duration: 1.4s;
	animation-timing-function: var(--anim-ease);
}

.anim-load__ring--glow::after {
	content: "";
	position: absolute;
	top: calc(var(--load-weight, 3px) * -1);
	left: 50%;
	width: calc(var(--load-weight, 3px) * 2);
	height: calc(var(--load-weight, 3px) * 2);
	border-radius: 50%;
	background: currentColor;
	box-shadow: 0 0 10px 2px currentColor;
}

@keyframes anim-load-spin {
	to { transform: rotate(360deg); }
}

/* --------------------------------------------------------------------------
 * Kinetic bars
 * ----------------------------------------------------------------------- */

.anim-load__bars {
	display: inline-flex;
	align-items: flex-end;
	gap: 4px;
	height: var(--load-size, 34px);
}

.anim-load__bars > span {
	width: 5px;
	height: 100%;
	background: currentColor;
	border-radius: 2px;
	transform-origin: bottom;
	animation: anim-load-bar 1s var(--anim-ease) infinite;
}

.anim-load__bars > span:nth-child(2) { animation-delay: 120ms; }
.anim-load__bars > span:nth-child(3) { animation-delay: 240ms; }
.anim-load__bars > span:nth-child(4) { animation-delay: 360ms; }

@keyframes anim-load-bar {
	0%, 100% { transform: scaleY(0.35); }
	50%      { transform: scaleY(1); }
}

/* --------------------------------------------------------------------------
 * Kinetic square — the "never-ending box" folding cube
 * ----------------------------------------------------------------------- */

.anim-load__box {
	position: relative;
	width: var(--load-size, 34px);
	height: var(--load-size, 34px);
	transform: rotate(45deg);
}

.anim-load__box > span {
	position: absolute;
	width: 50%;
	height: 50%;
	background: currentColor;
	animation: anim-load-box 1.8s var(--anim-ease) infinite;
}

.anim-load__box > span:nth-child(1) { top: 0;   left: 0;   animation-delay: 0ms; }
.anim-load__box > span:nth-child(2) { top: 0;   left: 50%; animation-delay: 150ms; }
.anim-load__box > span:nth-child(3) { top: 50%; left: 50%; animation-delay: 300ms; }
.anim-load__box > span:nth-child(4) { top: 50%; left: 0;   animation-delay: 450ms; }

@keyframes anim-load-box {
	0%, 70%, 100% { transform: scale(1); opacity: 1; }
	35%           { transform: scale(0.4); opacity: 0.45; }
}

/* --------------------------------------------------------------------------
 * Pendulum / cradle
 *
 * Only the outer two bobs move; the middle ones stay still. That is what
 * sells it as a Newton's cradle rather than a row of swinging dots.
 * ----------------------------------------------------------------------- */

.anim-load__cradle {
	display: inline-flex;
	height: var(--load-size, 34px);
	align-items: flex-start;
}

.anim-load__cradle > span {
	position: relative;
	width: 10px;
	height: 100%;
	transform-origin: top center;
}

.anim-load__cradle > span::after {
	content: "";
	position: absolute;
	bottom: 0;
	left: 50%;
	translate: -50% 0;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: currentColor;
}

.anim-load__cradle > span::before {
	content: "";
	position: absolute;
	top: 0;
	left: 50%;
	width: 1px;
	height: calc(100% - 10px);
	background: currentColor;
	opacity: 0.5;
}

.anim-load__cradle > span:first-child {
	animation: anim-cradle-left 1.2s var(--anim-ease) infinite;
}

.anim-load__cradle > span:last-child {
	animation: anim-cradle-right 1.2s var(--anim-ease) infinite;
}

@keyframes anim-cradle-left {
	0%, 50%, 100% { transform: rotate(0deg); }
	25%           { transform: rotate(-42deg); }
}

@keyframes anim-cradle-right {
	0%, 50%, 100% { transform: rotate(0deg); }
	75%           { transform: rotate(42deg); }
}

/* --------------------------------------------------------------------------
 * Progress bar (indeterminate)
 *
 * Pair with role="progressbar". When you know the percentage, set
 * aria-valuenow and use --load-progress instead of the indeterminate sweep —
 * a real value is always better for AT than an endless animation.
 * ----------------------------------------------------------------------- */

.anim-load__bar {
	position: relative;
	width: 100%;
	height: var(--load-weight, 4px);
	border-radius: 999px;
	background: color-mix(in srgb, currentColor 20%, transparent);
	overflow: hidden;
}

.anim-load__bar::after {
	content: "";
	position: absolute;
	inset: 0 auto 0 0;
	width: var(--load-progress, 35%);
	border-radius: inherit;
	background: currentColor;
	animation: anim-load-sweep 1.4s var(--anim-ease) infinite;
}

.anim-load__bar[aria-valuenow]::after {
	animation: none;
	width: var(--load-progress, 0%);
	transition: width var(--anim-duration) var(--anim-ease);
}

@keyframes anim-load-sweep {
	0%   { transform: translateX(-100%); }
	100% { transform: translateX(320%); }
}

/* --------------------------------------------------------------------------
 * Reduced motion
 *
 * A loader must still read as "busy" with motion removed, so we do not simply
 * kill the animation — we slow it far below any vestibular trigger and drop
 * the scaling. A frozen spinner would tell the user the page had hung.
 * ----------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

	.anim-load__ring,
	.anim-load__ring--glow {
		animation-duration: 2.4s !important;
		animation-timing-function: linear !important;
	}

	.anim-load__bars > span,
	.anim-load__box > span {
		animation-duration: 3s !important;
	}

	.anim-load__cradle > span {
		animation: none !important;
	}

	.anim-load__bar::after {
		animation-duration: 3s !important;
	}
}
