/* ==================== [ Glow Card Start ] ==================== */
/* Pointer-following rainbow glow around a card's edge. Markup comes from
   the <x-glow-ring /> Blade component, placed inside a `.has-glow` host;
   the pointer tracking lives in js/glow-card.js. */

/* Angles have to be registered, otherwise the browser cannot interpolate
   them and the glow would jump instead of travel. They must inherit: the
   angles are set on the ring but consumed by the mask and colour wheel
   nested inside it. */
@property --glow-angle {
	syntax: "<angle>";
	initial-value: 0deg;
	inherits: true;
}

/* Half-width of the lit arc. */
@property --glow-spread {
	syntax: "<angle>";
	initial-value: 45deg;
	inherits: true;
}

/* Extra reach added to both ends of the arc. Zero while the glow follows
   the pointer; the hover intro shrinks it to a spark and stretches it into
   a comet tail. */
@property --glow-reveal {
	syntax: "<angle>";
	initial-value: 0deg;
	inherits: true;
}

/* Hosts set --glow-radius to their own corner radius; 16px if they don't.
   `.has-glow` lights up on hover and follows the pointer; `.has-glow-loop`
   (the <x-glow-loop /> component, driven by js/glow-loop.js) is always lit
   and runs round on its own. */
.has-glow,
.has-glow-loop {
	position: relative;
	isolation: isolate;
}

/* Layer that holds the travelling light. It sits just outside the card;
   it never takes the pointer, so the card underneath stays clickable. */
.glow-ring {
	/* A thin 2px thread hugging the outside of the card's edge, with no
	   gap between the two. */
	--glow-width: 2px;
	--glow-inset: -2px;
	--glow-angle: 0deg;
	--glow-spread: 45deg;
	--glow-reveal: 0deg;

	position: absolute;
	inset: var(--glow-inset);
	z-index: 2;
	/* Grown by the inset so its inner edge follows the card's corners. */
	border-radius: calc(var(--glow-radius, 16px) - var(--glow-inset));
	pointer-events: none;
	opacity: 0;
	/* Both custom angles ease toward the pointer instead of snapping: a
	   short, sharply decelerating curve, so the light keeps up with the
	   pointer instead of trailing behind it. */
	transition:
		opacity 0.383s cubic-bezier(0.38, 0.72, 0, 1),
		--glow-angle 0.383s cubic-bezier(0.38, 0.72, 0, 1),
		--glow-spread 0.383s cubic-bezier(0.38, 0.72, 0, 1),
		--glow-reveal 0.383s cubic-bezier(0.38, 0.72, 0, 1);
}

.has-glow:hover > .glow-ring,
.has-glow:focus-within > .glow-ring {
	opacity: 1;
}

/* The loop is placed afresh every frame, so easing would only make the
   light lag behind where it should be. */
.glow-ring.is-loop {
	opacity: 1;
	transition: none;
}

/* Always on show, usually over a photo or dark banner, so the loop gets
   a fuller bloom than the hover glow. */
.glow-ring.is-loop .glow-halo {
	opacity: 0.85;
}

/* The loop's arc is laid out by js/glow-loop.js in pixels along the
   outline: it hands over the angle of every fade stop and colour stop, so
   the streak keeps one length and even hues wherever it is on a long pill.
   (Spreading them evenly by angle, as the hover glow does, crams them into
   a few pixels mid-way along the long edges.) The fallbacks are an even
   60deg arc at the top, shown until the script takes over. */
.glow-ring.is-loop .glow-mask {
	-webkit-mask-image: conic-gradient(from var(--loop-start, 0deg),
			transparent 0deg,
			rgba(0, 0, 0, 0.2) var(--loop-m1, 10deg),
			#000 var(--loop-m2, 25deg),
			#000 var(--loop-m3, 35deg),
			rgba(0, 0, 0, 0.2) var(--loop-m4, 50deg),
			transparent var(--loop-m5, 60deg),
			transparent 360deg);
	mask-image: conic-gradient(from var(--loop-start, 0deg),
			transparent 0deg,
			rgba(0, 0, 0, 0.2) var(--loop-m1, 10deg),
			#000 var(--loop-m2, 25deg),
			#000 var(--loop-m3, 35deg),
			rgba(0, 0, 0, 0.2) var(--loop-m4, 50deg),
			transparent var(--loop-m5, 60deg),
			transparent 360deg);
}

.glow-ring.is-loop .glow-spin {
	background: conic-gradient(from var(--loop-start, 0deg),
			#3186ff 0deg,
			#9378ff var(--loop-c1, 5deg),
			#f96bd6 var(--loop-c2, 10deg),
			#fc413d var(--loop-c3, 15deg),
			#ff6b2b var(--loop-c4, 20deg),
			#fec700 var(--loop-c5, 25deg),
			#ffdb0f var(--loop-c6, 30deg),
			#88de42 var(--loop-c7, 35deg),
			#0ebc5f var(--loop-c8, 40deg),
			#2eaab2 var(--loop-c9, 45deg),
			#00a9bb var(--loop-c10, 50deg),
			#1f9bff var(--loop-c11, 55deg),
			#3186ff var(--loop-c12, 60deg),
			#3186ff 360deg);
}

/* Keeps the light on the rim only: the fill is punched out so just a thin
   band around the edge survives. */
.glow-clip {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	padding: var(--glow-width);
	-webkit-mask:
		linear-gradient(#000 0 0) content-box,
		linear-gradient(#000 0 0);
	mask:
		linear-gradient(#000 0 0) content-box,
		linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
}

/* The crisp copy is held back and the blurred one does most of the work,
   so the glow reads as haze rather than a drawn line. */
.glow-layer {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	opacity: 0.75;
}

.glow-layer.is-soft {
	opacity: 0.8;
	filter: blur(2.5px) saturate(1.3);
}

/* The haze above is trapped inside the thin rim band, so this copy of the
   band is blurred as a whole from outside the clip, letting the light
   bloom out around the edge. It sits beneath the thread.

   The box is grown by --halo-room so the blur has space to spread, and
   padded back to the card's own edge so the mask (applied after the blur)
   can punch the inside out - the bloom only ever shows outside the card,
   never over its content. */
.glow-halo {
	--glow-width: 4px;
	--halo-room: 16px;

	position: absolute;
	inset: calc(var(--halo-room) * -1);
	padding: calc(var(--halo-room) - var(--glow-inset));
	border-radius: calc(var(--glow-radius, 16px) + var(--halo-room) - var(--glow-inset));
	opacity: 0.55;
	filter: blur(8px) saturate(1.3);
	-webkit-mask:
		linear-gradient(#000 0 0) content-box,
		linear-gradient(#000 0 0);
	mask:
		linear-gradient(#000 0 0) content-box,
		linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
}

/* Puts the bloom's band back on the rim, where the thread is. */
.glow-halo > .glow-clip {
	inset: var(--halo-room);
	border-radius: calc(var(--glow-radius, 16px) - var(--glow-inset));
}

/* Cuts the full ring down to one arc with a short bright core and long
   feathered tails, so it fades into the rim instead of stopping dead. */
.glow-mask {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	-webkit-mask-image:
		conic-gradient(from calc(var(--glow-angle) - 180deg),
			transparent 0deg,
			transparent calc(180deg - var(--glow-spread) - var(--glow-reveal)),
			rgba(0, 0, 0, 0.2) calc(180deg - var(--glow-spread) * 0.66 - var(--glow-reveal)),
			#000 calc(180deg - var(--glow-spread) * 0.18 - var(--glow-reveal)),
			#000 calc(180deg + var(--glow-spread) * 0.18 + var(--glow-reveal)),
			rgba(0, 0, 0, 0.2) calc(180deg + var(--glow-spread) * 0.66 + var(--glow-reveal)),
			transparent calc(180deg + var(--glow-spread) + var(--glow-reveal)),
			transparent 360deg);
	mask-image:
		conic-gradient(from calc(var(--glow-angle) - 180deg),
			transparent 0deg,
			transparent calc(180deg - var(--glow-spread) - var(--glow-reveal)),
			rgba(0, 0, 0, 0.2) calc(180deg - var(--glow-spread) * 0.66 - var(--glow-reveal)),
			#000 calc(180deg - var(--glow-spread) * 0.18 - var(--glow-reveal)),
			#000 calc(180deg + var(--glow-spread) * 0.18 + var(--glow-reveal)),
			rgba(0, 0, 0, 0.2) calc(180deg + var(--glow-spread) * 0.66 + var(--glow-reveal)),
			transparent calc(180deg + var(--glow-spread) + var(--glow-reveal)),
			transparent 360deg);
}

/* The whole spectrum is packed into the lit arc itself, not spread around
   the full wheel - otherwise only one or two hues would ever fall under
   the short arc. Each colour gets an equal share of the arc's span
   (2 * --glow-spread), so all twelve appear at once, in order.

   The stops stay at fixed offsets from 0 and the whole wheel is rotated by
   `from` to follow the pointer. Offsetting each stop by --glow-angle
   instead breaks near 0 and 360deg: Chrome clamps the positions and the
   arc collapses to a flat blue.

   The spectrum repeats around the rest of the wheel, so when the intro
   stretches the arc into a longer tail it keeps running through the
   colours instead of trailing off into a flat blue. */
.glow-spin {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: repeating-conic-gradient(from calc(var(--glow-angle) - var(--glow-spread)),
			#3186ff 0deg,
			#9378ff calc(var(--glow-spread) * 2 * 0.08333),
			#f96bd6 calc(var(--glow-spread) * 2 * 0.16667),
			#fc413d calc(var(--glow-spread) * 2 * 0.25),
			#ff6b2b calc(var(--glow-spread) * 2 * 0.33333),
			#fec700 calc(var(--glow-spread) * 2 * 0.41667),
			#ffdb0f calc(var(--glow-spread) * 2 * 0.5),
			#88de42 calc(var(--glow-spread) * 2 * 0.58333),
			#0ebc5f calc(var(--glow-spread) * 2 * 0.66667),
			#2eaab2 calc(var(--glow-spread) * 2 * 0.75),
			#00a9bb calc(var(--glow-spread) * 2 * 0.83333),
			#1f9bff calc(var(--glow-spread) * 2 * 0.91667),
			#3186ff calc(var(--glow-spread) * 2));
	backface-visibility: hidden;
	transform: translateZ(0);
}

@media (prefers-reduced-motion: reduce) {
	.glow-ring {
		transition: opacity 0.2s linear;
	}
}

/* ==================== [ Glow Card End ] ==================== */
