/*
 * Elementor Horizontal Scroll — frontend styles.
 *
 * Markup printed by the plugin around the Elementor container:
 *
 *   <div class="ehs-wrapper">      <- tall element that provides the scroll room
 *     <div class="ehs-sticky">     <- pinned 100vh viewport, clips the overflow
 *       <div class="e-con ehs-track"> ... </div>   <- the Elementor container
 *     </div>
 *   </div>
 *
 * Everything is inert until the script adds .ehs-active, so with JS disabled
 * (or on excluded breakpoints) the container keeps its normal vertical layout.
 */

.ehs-wrapper {
	position: relative;
	width: 100%;
	/* Activation (and later remeasures) reshapes everything inside the
	   wrapper. Scroll anchoring would follow whatever element the browser
	   had anchored to and shift the page scroll away from where the reader
	   was; the script already keeps the pinned position itself (compensate),
	   so keep the browser out of it for nodes inside the wrapper. */
	overflow-anchor: none;
}

/* Until the script has measured and activated the wrapper it would paint in
   its plain vertical layout (gallery wrapped into rows, full height) and then
   jump into the pinned row. When the script is going to run (html.ehs-js,
   set by the inline flag the plugin prints with this stylesheet) keep the
   wrapper invisible — layout intact, so the measurement is unaffected —
   until the script adds .ehs-ready after the first refresh. The animation is
   a safety net: if the script never runs (blocked, JS error) the wrapper
   becomes visible anyway after 3s. Without JS the flag is never set and
   nothing is hidden. */
html.ehs-js .ehs-wrapper:not(.ehs-ready) {
	visibility: hidden;
	animation: ehs-reveal 0s linear 3s forwards;
}

@keyframes ehs-reveal {
	to {
		visibility: visible;
	}
}

/* Performance/optimizer plugins sometimes tag sections with
   content-visibility: auto. Applied to these nodes it would collapse the tall
   wrapper or blank the pinned content, so pin them to the default. */
.ehs-wrapper,
.ehs-wrapper .ehs-sticky,
.ehs-wrapper .ehs-track {
	content-visibility: visible !important;
}

.ehs-wrapper.ehs-active > .ehs-sticky {
	position: -webkit-sticky;
	position: sticky;
	top: 0; /* the script overrides this with the Top Offset setting */
	height: 100vh;
	/* clip, not hidden: a hidden overflow is still a scroll container, and
	   the browser scrolls it horizontally to bring a URL fragment (or
	   scrollIntoView target) that lives in a later panel into view — an
	   offset the script knows nothing about, which leaves the first panels
	   unreachable. clip makes the box unscrollable; hidden stays as the
	   fallback for browsers without clip (the script resets any scroll). */
	overflow: hidden;
	overflow: clip;
	display: flex;
	align-items: center;
}

/* The Elementor container becomes the horizontally moving track. It is itself
   a flex item inside .ehs-sticky: without flex-shrink 0 its box would collapse
   to the viewport width (content overflowing it), hiding container backgrounds
   and blinding the ResizeObserver to content growth. */
.ehs-wrapper.ehs-active > .ehs-sticky > .ehs-track {
	--flex-direction: row;
	--flex-wrap: nowrap;
	flex-direction: row !important;
	flex-wrap: nowrap !important;
	flex-shrink: 0;
	width: -moz-max-content;
	width: max-content;
	min-width: 100%;
	max-width: none !important;
	will-change: transform;
}

/* Boxed containers render their children inside .e-con-inner. */
.ehs-wrapper.ehs-active > .ehs-sticky > .ehs-track > .e-con-inner {
	flex-direction: row !important;
	flex-wrap: nowrap !important;
	flex-shrink: 0;
	width: -moz-max-content;
	width: max-content;
	min-width: 100%;
	max-width: none !important;
}

/* Panels must keep their width instead of shrinking to fit the viewport. */
.ehs-wrapper.ehs-active > .ehs-sticky > .ehs-track > *,
.ehs-wrapper.ehs-active > .ehs-sticky > .ehs-track > .e-con-inner > * {
	flex-shrink: 0;
}

/*
 * Compositor-driven mode (browsers with CSS scroll-driven animations).
 *
 * The script adds .ehs-css-timeline and sets, per instance, the inline
 * view-timeline-inset (Top Offset) and the --ehs-x-from/--ehs-x-to custom
 * properties (0 / -distance, swapped when reversed). The `contain` range with
 * a top inset equal to the offset starts exactly when the sticky pins
 * (wrapper top = offset) and ends when the pin releases (wrapper bottom =
 * viewport bottom) — the same mapping as the JS fallback, but computed by the
 * compositor so it follows the real scroll position even while the main
 * thread is busy decoding images or running scripts.
 */
.ehs-wrapper.ehs-css-timeline {
	view-timeline: --ehs-view block;
}

.ehs-wrapper.ehs-css-timeline.ehs-active > .ehs-sticky > .ehs-track {
	animation-name: ehs-scroll;
	animation-duration: 1s; /* normalized across the scroll timeline; not time-based */
	animation-timing-function: linear;
	animation-fill-mode: both;
	animation-timeline: --ehs-view;
	animation-range: contain 0% contain 100%;
}

@keyframes ehs-scroll {
	from {
		transform: translate3d(var(--ehs-x-from, 0px), 0, 0);
	}
	to {
		transform: translate3d(var(--ehs-x-to, 0px), 0, 0);
	}
}

/*
 * Parallax nodes (elements with a speed multiplier and gallery images with
 * crop parallax). The script tags them with .ehs-fx and sets the per-node
 * --ehs-fx-* custom properties; their offsets are linear in the same pin
 * progress as the track, so one shared keyframe pair drives them all from
 * the same view timeline.
 */
.ehs-wrapper.ehs-active .ehs-fx {
	will-change: transform;
}

/* While the script measures, fx transforms would pollute the geometry (a
   lagging element translated past the track's right edge inflates
   scrollWidth, and item rects would include their own offset). !important
   beats both inline styles and running animations for the measurement. */
.ehs-wrapper.ehs-measuring .ehs-fx {
	animation: none !important;
	transform: none !important;
}

.ehs-wrapper.ehs-css-timeline.ehs-active .ehs-fx {
	animation-name: ehs-fx;
	animation-duration: 1s; /* normalized across the scroll timeline; not time-based */
	animation-timing-function: linear;
	animation-fill-mode: both;
	animation-timeline: --ehs-view;
	animation-range: contain 0% contain 100%;
}

@keyframes ehs-fx {
	from {
		transform: translate3d(var(--ehs-fx-from, 0px), 0, 0) scale(var(--ehs-fx-scale, 1));
	}
	to {
		transform: translate3d(var(--ehs-fx-to, 0px), 0, 0) scale(var(--ehs-fx-scale, 1));
	}
}
