/*
 * Shimmer FX for Elementor - the whole effect lives here.
 *
 * Elementor's generated per-element CSS writes ONLY custom properties
 * (--sfx-colour, --sfx-duration, ...) onto the element wrapper. Custom
 * properties inherit, so they reach the shimmer layer wherever it is drawn -
 * on the element itself, or on a button inside it. That means the generated
 * CSS can never contain a layout-affecting declaration, which is what caused
 * the sizing and positioning bugs in 1.0.0 and 1.1.0.
 *
 * The layer is inset to its host's box, so it can never overflow and never
 * needs clipping.
 */

:root {
	--sfx-play-state: running;
}

/* Honour the visitor's OS-level "reduce motion" setting. */
@media ( prefers-reduced-motion: reduce ) {
	:root {
		--sfx-play-state: paused;
	}
}

/*
 * WHERE THE LAYER IS DRAWN
 *
 * `Apply To` adds one of three classes to the wrapper:
 *
 *   sfx-to-auto    (default) button widgets -> the button; everything else -> itself
 *   sfx-to-self    always the element itself
 *   sfx-to-button  always .elementor-button inside it
 *
 * Auto exists because "the element itself" is the wrong host for a Button
 * widget: the wrapper has no background of its own, so a Behind-content layer
 * drawn on it is hidden by the button's own background - visible only in
 * whatever strip of wrapper sticks out past the button, which is why it used to
 * appear on some buttons and not others.
 *
 * The self rule also matches a wrapper with NO sfx-to-* class at all, so
 * elements saved before this control existed keep working.
 */

/*
 * The layer is absolutely positioned, so its host needs to be a containing
 * block. Every Elementor target already is - `.e-con` resolves
 * `position: var( --position )`, and `.elementor-section`, `.elementor-column`,
 * `.elementor-widget` and `.elementor-button` are `position: relative` in
 * Elementor's own frontend CSS. This is only for the rare host that is static.
 *
 * `:where()` gives it zero specificity, so it can never win against anything:
 * not Elementor's `--position` on containers, not `.elementor-absolute` on
 * widgets, not a theme rule, not an inline style. Do not remove the
 * `:where()` - without it this rule overrides the Position control and
 * elements set to Absolute or Fixed snap back to relative as soon as the
 * shimmer is switched on.
 */
:where( .sfx-yes:not( .sfx-to-button ):not( .sfx-to-auto ) ),
:where( .sfx-yes.sfx-to-auto:not( .elementor-widget-button ) ),
:where( .sfx-yes.sfx-to-button .elementor-button ),
:where( .sfx-yes.sfx-to-auto.elementor-widget-button .elementor-button ) {
	position: relative;
}

/* Confines the layer's z-index and blend mode to its host. No layout effect. */
.sfx-yes:not( .sfx-to-button ):not( .sfx-to-auto ),
.sfx-yes.sfx-to-auto:not( .elementor-widget-button ),
.sfx-yes.sfx-to-button .elementor-button,
.sfx-yes.sfx-to-auto.elementor-widget-button .elementor-button {
	isolation: isolate;
}

/*
 * The shimmer layer. `border-radius: inherit` makes it follow the host's
 * corners, which is what lets it sit neatly on a pill-shaped button.
 *
 * The first block of declarations neutralises anything a theme may already
 * have put on `a::after` (link icons are the usual one), so a collision cannot
 * half-break the layer.
 */
.sfx-yes:not( .sfx-to-button ):not( .sfx-to-auto )::after,
.sfx-yes.sfx-to-auto:not( .elementor-widget-button )::after,
.sfx-yes.sfx-to-button .elementor-button::after,
.sfx-yes.sfx-to-auto.elementor-widget-button .elementor-button::after {
	content: "";
	display: block;
	width: auto;
	height: auto;
	margin: 0;
	padding: 0;
	border: 0;
	box-shadow: none;
	transform: none;
	transition: none;
	font-size: 0;

	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	border-radius: inherit;
	pointer-events: none;
	z-index: var( --sfx-z, -1 );
	opacity: var( --sfx-opacity, 0.6 );
	mix-blend-mode: var( --sfx-blend, normal );
	background-repeat: no-repeat;
	background-size: 250% 250%;
	background-image: linear-gradient(
		calc( 90deg + var( --sfx-angle, 20deg ) ),
		transparent 0%,
		transparent calc( 50% - var( --sfx-band, 6% ) ),
		var( --sfx-color, rgba( 255, 255, 255, 0.55 ) ) 50%,
		transparent calc( 50% + var( --sfx-band, 6% ) ),
		transparent 100%
	);
	animation-name: var( --sfx-name, sfx-sweep-100 );
	animation-duration: var( --sfx-duration, 3s );
	animation-direction: var( --sfx-direction, normal );
	animation-timing-function: linear;
	animation-iteration-count: infinite;
	animation-play-state: var( --sfx-play-state, running );
}

/*
 * The gradient background is 250% of the host in each axis, so at
 * background-position 0% the light band sits off the right-hand edge and at
 * 100% it sits off the left. Sweeping 100% -> 0% moves it left to right.
 * Anything outside the host's box is simply not painted.
 */
@keyframes sfx-sweep-100 {
	from { background-position: 100% 50%; }
	to   { background-position: 0% 50%; }
}

@keyframes sfx-sweep-75 {
	0%   { background-position: 100% 50%; }
	75%  { background-position: 0% 50%; }
	100% { background-position: 0% 50%; }
}

@keyframes sfx-sweep-50 {
	0%   { background-position: 100% 50%; }
	50%  { background-position: 0% 50%; }
	100% { background-position: 0% 50%; }
}

@keyframes sfx-sweep-25 {
	0%   { background-position: 100% 50%; }
	25%  { background-position: 0% 50%; }
	100% { background-position: 0% 50%; }
}
