/*
 * Username effects. Markup comes from include/name_effects.php (forum) and style/name-effects.js (chat):
 *   <span class="gidN xpn xpn-EFFECT" style="color:#c1; --c1:#c1; --c2:#c2; --xd:-1.3s">name</span>
 * --c1 / --c2 are optional; without them the group color (currentColor) and a light tint of it are used.
 * --xd offsets each name's animation phase so a page full of names does not pulse in unison.
 */

.xpn {
	--xc1: var(--c1, currentColor);
	--xc2: var(--c2, color-mix(in srgb, var(--xc1) 35%, #fff));
	position: relative;
	display: inline-block;
}

.xpn::before,
.xpn::after {
	pointer-events: none;
}

/* Text painted with a gradient instead of a flat color */
.xpn-gradient,
.xpn-shimmer,
.xpn-sparkle,
.xpn-stars,
.xpn-hearts,
.xpn-snow,
.xpn-fire,
.xpn-rainbow {
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}

.xpn-gradient {
	background-image: linear-gradient(90deg, var(--xc1), var(--xc2));
}

/* Shimmer: a light band sweeps across the name (also the base of the particle effects) */
.xpn-shimmer,
.xpn-sparkle,
.xpn-stars,
.xpn-hearts,
.xpn-snow {
	background-image: linear-gradient(110deg, var(--xc1) 0%, var(--xc1) 40%, var(--xc2) 50%, var(--xc1) 60%, var(--xc1) 100%);
	background-size: 250% 100%;
	background-position: 100% 0;
	animation: xpn-shimmer 3.5s linear infinite;
	animation-delay: var(--xd, 0s);
}

@keyframes xpn-shimmer {
	0% { background-position: 100% 0; }
	45%, 100% { background-position: 0 0; }
}

/* Particle effects share two pseudo-element slots */
.xpn-sparkle::before,
.xpn-sparkle::after,
.xpn-stars::before,
.xpn-stars::after,
.xpn-hearts::before,
.xpn-hearts::after,
.xpn-snow::before,
.xpn-snow::after {
	position: absolute;
	opacity: 0;
	color: var(--xc1);
	-webkit-text-fill-color: currentColor;
	font-family: "Segoe UI Symbol", "Apple Symbols", "DejaVu Sans", sans-serif;
	font-weight: normal;
	line-height: 1;
}

/* Sparkles: the four-point "+" from the logo */
.xpn-sparkle::before,
.xpn-sparkle::after {
	content: "";
	top: -6px;
	left: -6px;
	width: 8px;
	height: 8px;
	background:
		linear-gradient(#fff, #fff) center / 1.2px 80% no-repeat,
		linear-gradient(#fff, #fff) center / 80% 1.2px no-repeat,
		linear-gradient(var(--xc1), var(--xc1)) center / 3px 100% no-repeat,
		linear-gradient(var(--xc1), var(--xc1)) center / 100% 3px no-repeat;
	border-radius: 1px;
	filter: drop-shadow(0 0 2px var(--xc1));
	animation: xpn-twinkle 2.4s ease-in-out infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-sparkle::after {
	top: -8px;
	left: auto;
	right: -9px;
	width: 11px;
	height: 11px;
	animation-delay: calc(var(--xd, 0s) - 1.2s);
}

/* Stars: four-point stars that twinkle in and out */
.xpn-stars::before,
.xpn-stars::after {
	content: "\2726";
	top: -7px;
	left: -7px;
	font-size: 9px;
	text-shadow: 0 0 4px var(--xc1);
	animation: xpn-twinkle 2.4s ease-in-out infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-stars::after {
	top: -9px;
	left: auto;
	right: -10px;
	font-size: 12px;
	color: var(--xc2);
	animation-delay: calc(var(--xd, 0s) - 1.2s);
}

@keyframes xpn-twinkle {
	0%, 100% { opacity: 0; transform: scale(0.3) rotate(0deg); }
	50% { opacity: 1; transform: scale(1) rotate(90deg); }
}

/* Hearts: float up off the name and fade */
.xpn-hearts::before,
.xpn-hearts::after {
	content: "\2665";
	bottom: 60%;
	left: 15%;
	font-size: 9px;
	text-shadow: 0 0 4px var(--xc1);
	animation: xpn-rise 2.8s ease-out infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-hearts::after {
	left: 75%;
	font-size: 11px;
	color: var(--xc2);
	animation-delay: calc(var(--xd, 0s) - 1.4s);
}

@keyframes xpn-rise {
	0% { opacity: 0; transform: translateY(6px) scale(0.5); }
	25% { opacity: 1; }
	100% { opacity: 0; transform: translateY(-12px) scale(1.1); }
}

/* Snowflakes: drift down past the name */
.xpn-snow::before,
.xpn-snow::after {
	content: "\2744";
	top: -8px;
	left: 10%;
	font-size: 9px;
	color: #fff;
	text-shadow: 0 0 4px var(--xc1);
	animation: xpn-fall 3.2s linear infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-snow::after {
	left: 70%;
	font-size: 7px;
	animation-delay: calc(var(--xd, 0s) - 1.6s);
}

@keyframes xpn-fall {
	0% { opacity: 0; transform: translate(0, -2px) rotate(0deg); }
	20% { opacity: 1; }
	80% { opacity: 1; }
	100% { opacity: 0; transform: translate(4px, 20px) rotate(180deg); }
}

/* Lightning: electric flicker on the text with bolts flashing beside it */
.xpn-lightning {
	--xc2: var(--c2, #eaf6ff);
	animation: xpn-flicker 3.4s linear infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-lightning::before,
.xpn-lightning::after {
	content: "";
	position: absolute;
	top: -7px;
	right: -8px;
	width: 8px;
	height: 13px;
	background: var(--xc2);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 16'%3E%3Cpath d='M6.5 0 0 9h4l-1.5 7L10 6H6z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 16'%3E%3Cpath d='M6.5 0 0 9h4l-1.5 7L10 6H6z'/%3E%3C/svg%3E") center / contain no-repeat;
	filter: drop-shadow(0 0 3px var(--xc1));
	opacity: 0;
	animation: xpn-bolt 3.4s linear infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-lightning::before {
	right: auto;
	left: -7px;
	top: auto;
	bottom: -4px;
	width: 6px;
	height: 10px;
	transform: scaleX(-1);
	animation-delay: calc(var(--xd, 0s) - 1.7s);
}

@keyframes xpn-flicker {
	0%, 7%, 10%, 13%, 55%, 58%, 100% { text-shadow: 0 0 2px var(--xc1); filter: none; }
	8%, 11% { text-shadow: 0 0 4px var(--xc2), 0 0 10px var(--xc1), 0 0 18px var(--xc1); filter: brightness(1.5); }
	56% { text-shadow: 0 0 4px var(--xc2), 0 0 12px var(--xc1); filter: brightness(1.35); }
}

@keyframes xpn-bolt {
	0%, 7%, 10%, 13%, 100% { opacity: 0; }
	8%, 11% { opacity: 1; }
	9%, 12% { opacity: 0.4; }
}

/* Fire: a flame gradient rising through the letters, plus embers */
.xpn-fire {
	--xc1: var(--c1, #ff4d1a);
	--xc2: var(--c2, #ffd23f);
	background-image: linear-gradient(0deg, var(--xc1) 0%, var(--xc2) 25%, var(--xc1) 50%, var(--xc2) 75%, var(--xc1) 100%);
	background-size: 100% 200%;
	animation: xpn-flame 1.6s linear infinite, xpn-flame-glow 0.9s ease-in-out infinite alternate;
	animation-delay: var(--xd, 0s);
}
.xpn-fire::before,
.xpn-fire::after {
	content: "";
	position: absolute;
	bottom: 30%;
	left: 25%;
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: var(--xc2);
	box-shadow: 0 0 4px 1px var(--xc1);
	opacity: 0;
	animation: xpn-ember 1.8s ease-out infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-fire::after {
	left: 70%;
	width: 2px;
	height: 2px;
	animation-delay: calc(var(--xd, 0s) - 0.9s);
}

@keyframes xpn-flame {
	0% { background-position: 0 0; }
	100% { background-position: 0 -200%; }
}

@keyframes xpn-flame-glow {
	0% { filter: drop-shadow(0 0 1px var(--xc1)); }
	100% { filter: drop-shadow(0 0 4px var(--xc1)); }
}

@keyframes xpn-ember {
	0% { opacity: 0; transform: translate(0, 0); }
	20% { opacity: 1; }
	100% { opacity: 0; transform: translate(3px, -16px); }
}

/* Rainbow: the full spectrum slides through the name (ignores the chosen colors) */
.xpn-rainbow {
	background-image: linear-gradient(90deg, #ff5f6d, #ffb347, #fff275, #6cff8f, #5ecbff, #9b7bff, #ff6ad5, #ff5f6d);
	background-size: 200% 100%;
	animation: xpn-rainbow 4s linear infinite;
	animation-delay: var(--xd, 0s);
}

@keyframes xpn-rainbow {
	0% { background-position: 0 0; }
	100% { background-position: -200% 0; }
}

/* Neon glow: soft pulsing halo (second color tints the outer glow) */
.xpn-glow {
	--xg: var(--c2, var(--xc1));
	animation: xpn-glow 2.4s ease-in-out infinite;
	animation-delay: var(--xd, 0s);
}

@keyframes xpn-glow {
	0%, 100% { text-shadow: 0 0 2px var(--xc1), 0 0 4px var(--xg); }
	50% { text-shadow: 0 0 3px var(--xc1), 0 0 9px var(--xg), 0 0 16px var(--xg); }
}

/* Glitch: RGB-split copies of the name jump out of place in short bursts */
.xpn-glitch::before,
.xpn-glitch::after {
	content: attr(data-text);
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	overflow: hidden;
	opacity: 0;
}
.xpn-glitch::before {
	color: var(--c2, #ff2a6d);
	animation: xpn-glitch-a 2.6s steps(1, end) infinite;
	animation-delay: var(--xd, 0s);
}
.xpn-glitch::after {
	color: #2de2e6;
	animation: xpn-glitch-b 2.6s steps(1, end) infinite;
	animation-delay: var(--xd, 0s);
}

@keyframes xpn-glitch-a {
	0% { opacity: 1; transform: translate(-2px, 0); clip-path: inset(0 0 55% 0); }
	3% { opacity: 1; transform: translate(2px, 0); clip-path: inset(60% 0 0 0); }
	6% { opacity: 1; transform: translate(-1px, 0); clip-path: inset(30% 0 35% 0); }
	9%, 100% { opacity: 0; transform: none; clip-path: none; }
}

@keyframes xpn-glitch-b {
	0% { opacity: 1; transform: translate(2px, 0); clip-path: inset(50% 0 0 0); }
	3% { opacity: 1; transform: translate(-2px, 0); clip-path: inset(0 0 65% 0); }
	6% { opacity: 1; transform: translate(1px, 0); clip-path: inset(40% 0 20% 0); }
	9%, 100% { opacity: 0; transform: none; clip-path: none; }
}

/* Wave: letters bob one after another */
.xpn-wave {
	text-shadow: 0 0 6px var(--c2, transparent);
}
.xpn-wave .xpn-l {
	display: inline-block;
	white-space: pre;
	animation: xpn-wave 1.8s ease-in-out infinite;
	animation-delay: calc(var(--xd, 0s) + var(--i, 0) * 0.09s);
}

@keyframes xpn-wave {
	0%, 40%, 100% { transform: translateY(0); }
	20% { transform: translateY(-3px); }
}

@media (prefers-reduced-motion: reduce) {
	.xpn,
	.xpn::before,
	.xpn::after,
	.xpn .xpn-l {
		animation: none !important;
	}

	/* Still frames, so every effect stays recognisable without motion */
	.xpn-shimmer,
	.xpn-sparkle,
	.xpn-stars,
	.xpn-hearts,
	.xpn-snow {
		background-position: 50% 0;
	}
	.xpn-sparkle::before,
	.xpn-sparkle::after,
	.xpn-stars::before,
	.xpn-stars::after,
	.xpn-hearts::before,
	.xpn-hearts::after,
	.xpn-snow::before,
	.xpn-snow::after,
	.xpn-lightning::before,
	.xpn-lightning::after,
	.xpn-fire::before,
	.xpn-fire::after {
		opacity: 1;
	}
	.xpn-hearts::before,
	.xpn-hearts::after {
		transform: translateY(-4px);
	}
	.xpn-snow::after {
		transform: translate(2px, 10px);
	}
	.xpn-lightning {
		text-shadow: 0 0 4px var(--xc2), 0 0 10px var(--xc1);
	}
	.xpn-fire {
		background-position: 0 -50%;
		filter: drop-shadow(0 0 3px var(--xc1));
	}
	.xpn-fire::before {
		transform: translate(1px, -8px);
	}
	.xpn-fire::after {
		transform: translate(2px, -12px);
	}
	.xpn-glow {
		text-shadow: 0 0 3px var(--xc1), 0 0 9px var(--xg), 0 0 16px var(--xg);
	}
	.xpn-glitch {
		text-shadow: -1.5px 0 var(--c2, #ff2a6d), 1.5px 0 #2de2e6;
	}
	.xpn-wave .xpn-l:nth-child(4n+2),
	.xpn-wave .xpn-l:nth-child(4n) {
		transform: translateY(-1.5px);
	}
	.xpn-wave .xpn-l:nth-child(4n+3) {
		transform: translateY(-3px);
	}
}
