/**
 * MCN Animations — Buttons
 *
 * Rebuilt from:
 *   Jake Giles-Phillips, "Animated CSS Mail Button" (codepen.io/jakegilesphillips/pen/MveNLe, MIT)
 *   David East,          "Single Keyframe Tricks"   (codepen.io/davideast/pen/MWxvzjm, MIT)
 *   Jamie Coulter,       "CSS Fizzy Button"         (codepen.io/jcoulterdesign/pen/xVJWvz, MIT)
 *   LukyVJ,              "Fun 3D button"            (codepen.io/LukyVj/pen/oNPJrdy, MIT)
 *   LukyVJ,              "Lil rainbow gradient button" (codepen.io/LukyVj/pen/LYJBdYo, MIT)
 *   jwktje,              "Andreas Storm button"     (codepen.io/jwktje/pen/JjBaJBv, MIT)
 *
 * Every effect here attaches to a real <button> or <a>. The fizzy original
 * drives its state from a hidden checkbox + label, which reports the wrong
 * role to assistive tech (a checkbox that is really a submit button) — that
 * has been replaced with a plain button plus a JS-toggled .is-busy class.
 *
 * @package MCN_Animations
 */

/* --------------------------------------------------------------------------
 * Attention keyframes (from "Single Keyframe Tricks")
 *
 * Applied by adding .anim-btn--shake etc. and toggling .is-playing, or by
 * setting data-anim-play="shake" and letting the JS fire it on click.
 *
 * WCAG 2.3.1 (Level A): none of these flash. Glitch/skew is a transform, not
 * a luminance flash, so it stays under the three-flashes threshold by design.
 * ----------------------------------------------------------------------- */

.anim-fx {
	animation-duration: var(--anim-fx-duration, 500ms);
	animation-timing-function: var(--anim-ease);
	animation-iteration-count: var(--anim-fx-count, 1);
	animation-fill-mode: both;
}

.anim-fx--shake  { animation-name: anim-fx-shake; }
.anim-fx--pulse  { animation-name: anim-fx-pulse; }
.anim-fx--glitch { animation-name: anim-fx-glitch; }
.anim-fx--flip   { animation-name: anim-fx-flip; }
.anim-fx--fill   { animation-name: anim-fx-fill; }
.anim-fx--glow   { animation-name: anim-fx-glow; }
.anim-fx--blur   { animation-name: anim-fx-blur; }
.anim-fx--spin   { animation-name: anim-fx-spin; }

@keyframes anim-fx-shake {
	0%, 100% { transform: none; }
	20%      { transform: translate3d(-8px, 0, 0); }
	40%      { transform: translate3d(8px, 0, 0); }
	60%      { transform: translate3d(-5px, 0, 0); }
	80%      { transform: translate3d(5px, 0, 0); }
}

@keyframes anim-fx-pulse {
	50% { transform: scale(1.12); }
}

@keyframes anim-fx-glitch {
	20% { transform: skewX(12deg); }
	40% { transform: skewX(-10deg); }
	60% { transform: skewX(6deg); }
	80% { transform: skewX(-3deg); }
	100% { transform: none; }
}

@keyframes anim-fx-flip {
	100% { transform: rotateY(180deg); }
}

@keyframes anim-fx-fill {
	50%  { transform: translateX(-4%); }
	100% { transform: none; }
}

/* Glow tops out well below a flash — the box-shadow eases in and out over
   half a second, nowhere near 3Hz. */
@keyframes anim-fx-glow {
	50% { box-shadow: 0 0 32px -4px var(--anim-accent); }
}

@keyframes anim-fx-blur {
	50%  { filter: blur(6px); transform: skewX(18deg); }
	100% { filter: none; transform: none; }
}

@keyframes anim-fx-spin {
	50%, 100% { transform: rotate(900deg); }
}

/* --------------------------------------------------------------------------
 * Rainbow gradient button
 *
 * The original animates a real conic gradient behind a blurred pseudo. We use
 * @property so --bg-angle is an interpolatable <angle> — without the
 * @property registration the browser treats it as a string and the rotation
 * snaps instead of sweeping.
 * ----------------------------------------------------------------------- */

@property --anim-bg-angle {
	syntax: "<angle>";
	inherits: false;
	initial-value: 0deg;
}

.anim-btn--rainbow {
	position: relative;
	isolation: isolate;
	border: 0;
	color: #fff;
	background: transparent;
}

.anim-btn--rainbow::before,
.anim-btn--rainbow::after {
	content: "";
	position: absolute;
	inset: -2px;
	z-index: -1;
	border-radius: inherit;
	background: conic-gradient(
		from var(--anim-bg-angle),
		#ff4d4d, #f9cb28, #4ade80, #38bdf8, #a78bfa, #ff4d4d
	);
	animation: anim-bg-spin 5s linear infinite;
}

/* The second copy, blurred, is the glow. Cheaper than a box-shadow that has
   to track six colour stops. */
.anim-btn--rainbow::after {
	filter: blur(14px);
	opacity: 0.55;
	transition: opacity var(--anim-duration) var(--anim-ease);
}

.anim-btn--rainbow:hover::after,
.anim-btn--rainbow:focus-visible::after {
	opacity: 0.9;
}

.anim-btn--rainbow > * {
	position: relative;
	display: block;
	padding: 0.75em 1.5em;
	border-radius: inherit;
	/* Inner plate — this is what keeps the gradient as a rim rather than a
	   wash behind the label, so text contrast stays predictable (1.4.3). */
	background: var(--anim-btn-plate, #14141c);
}

@keyframes anim-bg-spin {
	to { --anim-bg-angle: 360deg; }
}

/* --------------------------------------------------------------------------
 * Storm / voltage button
 *
 * The original strokes two SVG paths with animated stroke-dashoffset and
 * floats sparks upward. We keep the dash animation (it is the effect) and
 * replace the spark divs with pseudo-elements.
 * ----------------------------------------------------------------------- */

.anim-btn--storm {
	position: relative;
	isolation: isolate;
	background: var(--anim-storm-bg, #0f1c53);
	color: #fff;
	border: 0;
	overflow: visible;
}

.anim-btn--storm__svg {
	position: absolute;
	inset: -2px;
	width: calc(100% + 4px);
	height: calc(100% + 4px);
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--anim-duration) var(--anim-ease);
	z-index: -1;
}

.anim-btn--storm:hover .anim-btn--storm__svg,
.anim-btn--storm:focus-visible .anim-btn--storm__svg {
	opacity: 1;
}

.anim-btn--storm__svg path {
	stroke: var(--anim-accent);
	stroke-width: 2;
	fill: none;
	stroke-dasharray: 100 900;
	filter: drop-shadow(0 0 6px var(--anim-accent));
}

.anim-btn--storm__svg path:nth-child(1) { animation: anim-spark-1 3s linear infinite; }
.anim-btn--storm__svg path:nth-child(2) { animation: anim-spark-2 3s linear infinite; }

@keyframes anim-spark-1 { to { stroke-dashoffset: -1000; } }
@keyframes anim-spark-2 { to { stroke-dashoffset: -500; } }

/* --------------------------------------------------------------------------
 * Fizzy button
 *
 * Particles rise from the button while it is in its busy state. The original
 * runs ten hand-numbered @keyframes (spot-1 … spot-10); one keyframe plus
 * per-particle custom properties does the same job.
 * ----------------------------------------------------------------------- */

.anim-btn--fizzy {
	position: relative;
	overflow: visible;
	transition:
		background-color var(--anim-duration) var(--anim-ease),
		color var(--anim-duration) var(--anim-ease);
}

.anim-btn--fizzy__spots {
	position: absolute;
	inset: 0;
	pointer-events: none;
	overflow: visible;
}

.anim-btn--fizzy__spots > i {
	position: absolute;
	bottom: 0.5em;
	left: var(--x, 50%);
	width: var(--size, 5px);
	height: var(--size, 5px);
	border-radius: 50%;
	background: var(--anim-accent);
	opacity: 0;
}

.anim-btn--fizzy.is-busy .anim-btn--fizzy__spots > i {
	animation: anim-fizz var(--speed, 700ms) linear infinite;
	animation-delay: calc(var(--anim-index, 0) * 60ms);
}

@keyframes anim-fizz {
	0%   { opacity: 0; transform: translateY(0) scale(0.6); }
	30%  { opacity: 0.7; }
	100% { opacity: 0; transform: translateY(-30px) scale(1); }
}

/* --------------------------------------------------------------------------
 * Mail button
 *
 * Envelope opens and the letter slides out on hover. Rebuilt with a
 * two-element envelope instead of the original's seven divs.
 * ----------------------------------------------------------------------- */

.anim-mail {
	position: relative;
	display: inline-block;
	width: var(--mail-w, 200px);
	height: calc(var(--mail-w, 200px) * 0.62);
	perspective: 700px;
}

.anim-mail__letter {
	position: absolute;
	left: 8%;
	bottom: 12%;
	width: 84%;
	height: 62%;
	background: var(--mail-letter-bg, #fff);
	border-radius: 3px;
	box-shadow: 0 2px 8px -4px rgb(0 0 0 / 0.4);
	transform: translateY(0);
	transition: transform var(--anim-duration-slow) var(--anim-ease);
	z-index: 1;
}

.anim-mail__body {
	position: absolute;
	inset: 0;
	background: var(--mail-bg, #e2e5f0);
	border-radius: 6px;
	z-index: 2;
	/* Clip the letter behind the envelope front. */
	clip-path: polygon(0 38%, 100% 38%, 100% 100%, 0 100%);
}

.anim-mail__flap {
	position: absolute;
	inset: 0 0 auto 0;
	height: 44%;
	background: var(--mail-flap, #cbd0e3);
	transform-origin: top center;
	transform: rotateX(0deg);
	transition: transform var(--anim-duration-slow) var(--anim-ease);
	clip-path: polygon(0 0, 100% 0, 50% 100%);
	z-index: 3;
}

.anim-mail:hover .anim-mail__flap,
.anim-mail:focus-within .anim-mail__flap {
	transform: rotateX(180deg);
	z-index: 0;
}

.anim-mail:hover .anim-mail__letter,
.anim-mail:focus-within .anim-mail__letter {
	transform: translateY(-58%);
}

/* --------------------------------------------------------------------------
 * 3D press button
 * ----------------------------------------------------------------------- */

.anim-btn--3d {
	--btn-depth: 5px;
	position: relative;
	border: 0;
	border-radius: 10px;
	background: var(--anim-btn-face, #6d5bd0);
	color: #fff;
	box-shadow: 0 var(--btn-depth) 0 var(--anim-btn-shade, #4b3da3);
	transition:
		transform var(--anim-duration-fast) var(--anim-ease),
		box-shadow var(--anim-duration-fast) var(--anim-ease);
}

.anim-btn--3d:hover,
.anim-btn--3d:focus-visible {
	transform: translateY(-2px);
	box-shadow: 0 calc(var(--btn-depth) + 2px) 0 var(--anim-btn-shade, #4b3da3);
}

.anim-btn--3d:active {
	transform: translateY(var(--btn-depth));
	box-shadow: 0 0 0 var(--anim-btn-shade, #4b3da3);
}

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

	.anim-fx,
	.anim-btn--rainbow::before,
	.anim-btn--rainbow::after,
	.anim-btn--storm__svg path,
	.anim-btn--fizzy.is-busy .anim-btn--fizzy__spots > i {
		animation: none !important;
	}

	.anim-mail__flap,
	.anim-mail__letter,
	.anim-btn--3d {
		transition: none !important;
	}

	/* The rainbow rim is the button's identity, so keep it — just hold it
	   at a fixed angle instead of sweeping. */
	.anim-btn--rainbow::before,
	.anim-btn--rainbow::after {
		--anim-bg-angle: 45deg;
	}
}
