/**
 * SLDB — Scroll Reveal.
 *
 * Every hidden state hangs off `html.sldb-js`, a class added by an inline
 * script in <head>. If JavaScript never runs — or the plugin's own scripts
 * fail to load, which the same inline script watches for — the class is
 * absent and nothing is ever hidden. A reveal system that can strand the
 * page blank is worse than no reveal system.
 *
 * Motion uses the INDIVIDUAL transform properties (`translate`, `scale`,
 * `rotate`) rather than `transform`. Elementor's own Advanced > Transform
 * section writes `transform` on this very same wrapper, so using `transform`
 * here would silently wipe it out; the individual properties compose with it
 * instead. `filter` and `clip-path` have no such individual form, so the two
 * blur variants do collide with Elementor's CSS Filters and the clip variants
 * clip overflowing children — both are called out in the control descriptions.
 */

.sldb-reveal {
	--sldb-rv-duration: 700ms;
	--sldb-rv-delay: 0ms;
	--sldb-rv-ease: cubic-bezier( 0.22, 1, 0.36, 1 );
	--sldb-rv-distance: 24px;
	--sldb-rv-blur: 12px;
	--sldb-rv-scale: 0.92;
	--sldb-rv-tilt: -3deg;

	transition-property: opacity, translate, scale, rotate, filter, clip-path;
	transition-duration: var( --sldb-rv-duration );
	transition-timing-function: var( --sldb-rv-ease );
	transition-delay: var( --sldb-rv-delay );
}

/* Hidden state. Scoped to html.sldb-js — see the file header. */
html.sldb-js .sldb-reveal:not( .sldb-reveal--shown ) {
	opacity: 0;
	/* Promoted only while it still has work to do; the promotion is dropped
	   again by the `--shown` class, so a long page does not keep dozens of
	   permanently-composited layers alive. */
	will-change: opacity, translate, scale, filter, clip-path;
}

/* --- Common ---------------------------------------------------------- */

html.sldb-js .sldb-reveal--fade-up:not( .sldb-reveal--shown ) {
	translate: 0 var( --sldb-rv-distance );
}

html.sldb-js .sldb-reveal--fade-down:not( .sldb-reveal--shown ) {
	translate: 0 calc( -1 * var( --sldb-rv-distance ) );
}

/* Travels leftwards, so it starts to the right of its final position. */
html.sldb-js .sldb-reveal--fade-left:not( .sldb-reveal--shown ) {
	translate: var( --sldb-rv-distance ) 0;
}

html.sldb-js .sldb-reveal--fade-right:not( .sldb-reveal--shown ) {
	translate: calc( -1 * var( --sldb-rv-distance ) ) 0;
}

html.sldb-js .sldb-reveal--zoom-in:not( .sldb-reveal--shown ) {
	scale: var( --sldb-rv-scale );
}

html.sldb-js .sldb-reveal--zoom-out:not( .sldb-reveal--shown ) {
	scale: calc( 2 - var( --sldb-rv-scale ) );
}

/* --- Advanced -------------------------------------------------------- */

html.sldb-js .sldb-reveal--blur-in:not( .sldb-reveal--shown ) {
	filter: blur( var( --sldb-rv-blur ) );
}

html.sldb-js .sldb-reveal--rise-blur:not( .sldb-reveal--shown ) {
	translate: 0 var( --sldb-rv-distance );
	filter: blur( var( --sldb-rv-blur ) );
}

html.sldb-js .sldb-reveal--rise-tilt:not( .sldb-reveal--shown ) {
	translate: 0 var( --sldb-rv-distance );
	rotate: var( --sldb-rv-tilt );
}

/*
 * Wipes. `inset()` insets are top/right/bottom/left, and the name says which
 * way the visible area GROWS: clip-down starts as a zero-height strip at the
 * top edge and grows downward, and so on. These keep full opacity — the wipe
 * itself is the reveal, and cross-fading it as well reads as a mistake.
 */
html.sldb-js .sldb-reveal--clip-down:not( .sldb-reveal--shown ),
html.sldb-js .sldb-reveal--clip-up:not( .sldb-reveal--shown ),
html.sldb-js .sldb-reveal--clip-left:not( .sldb-reveal--shown ),
html.sldb-js .sldb-reveal--clip-right:not( .sldb-reveal--shown ),
html.sldb-js .sldb-reveal--mask-sweep:not( .sldb-reveal--shown ) {
	opacity: 1;
}

html.sldb-js .sldb-reveal--clip-down:not( .sldb-reveal--shown ) {
	clip-path: inset( 0 0 100% 0 );
}

html.sldb-js .sldb-reveal--clip-up:not( .sldb-reveal--shown ) {
	clip-path: inset( 100% 0 0 0 );
}

html.sldb-js .sldb-reveal--clip-right:not( .sldb-reveal--shown ) {
	clip-path: inset( 0 100% 0 0 );
}

html.sldb-js .sldb-reveal--clip-left:not( .sldb-reveal--shown ) {
	clip-path: inset( 0 0 0 100% );
}

.sldb-reveal--clip-down,
.sldb-reveal--clip-up,
.sldb-reveal--clip-right,
.sldb-reveal--clip-left {
	clip-path: inset( 0 0 0 0 );
}

/* Diagonal sweep. Both polygons need the same point count to interpolate. */
html.sldb-js .sldb-reveal--mask-sweep:not( .sldb-reveal--shown ) {
	clip-path: polygon( 0% 0%, 0% 0%, -40% 100%, -40% 100% );
}

.sldb-reveal--mask-sweep {
	clip-path: polygon( 0% 0%, 140% 0%, 100% 100%, 0% 100% );
}

/* --- Revealed --------------------------------------------------------- */

.sldb-reveal--shown {
	opacity: 1;
	will-change: auto;
}

/*
 * A visitor who asked for less motion gets the content, not the choreography.
 * The scroll-intent gate already unlocks itself under this preference, so
 * these elements are shown on the first frame anyway; this just guarantees
 * they are never mid-transition while it happens.
 */
@media ( prefers-reduced-motion: reduce ) {
	.sldb-reveal,
	html.sldb-js .sldb-reveal:not( .sldb-reveal--shown ) {
		opacity: 1 !important;
		translate: none !important;
		scale: none !important;
		rotate: none !important;
		filter: none !important;
		clip-path: none !important;
		transition: none !important;
		will-change: auto !important;
	}
}
