/* ══════════════════════════════════════════════════════════════════════
   SLIDE HERO

   LAYERING
   The widget is a positioned stage with three layers:
     .sh-stage    the photographs, absolutely positioned, stacked
     .sh-overlay  one per slide — the tint that keeps text readable
     .sh-content  the Elementor container creative builds in, above both

   Content sits in normal flow and the stage is absolute, so the container
   drives the hero's height while the images fill whatever it comes to.

   TRANSITIONS
   Every transition moves opacity and transform only — never width, height
   or position — so the browser can composite them on the GPU without
   re-laying-out the page on each frame. That matters here more than in most
   widgets, because a hero is large and usually animating during the exact
   moment the page is still settling.
═══════════════════════════════════════════════════════════════════════ */

.sh {
	--sh-transition: 800ms;
	--sh-text-transition: 250ms;
	--sh-dot: rgba(255, 255, 255, 0.45);
	--sh-dot-active: #ffffff;
	--sh-dot-size: 10px;
	--sh-dots-align: flex-start;
	--sh-arrow-size: 44px;
	--sh-ease: cubic-bezier(0.4, 0, 0.2, 1);

	position: relative;
	display: flex;
	width: 100%;
	overflow: hidden;
	isolation: isolate;
}

.sh *,
.sh *::before,
.sh *::after {
	box-sizing: border-box;
}

/* ── Stage ─────────────────────────────────────────────────────────── */

.sh-stage {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
}

.sh-slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	/* Hidden slides are taken out of the paint and hit-testing entirely.
	   With eight-plus layered images, leaving them at opacity 0 still costs
	   compositing work on every frame of every transition. */
	visibility: hidden;
	transition:
		opacity var(--sh-transition) var(--sh-ease),
		transform var(--sh-transition) var(--sh-ease),
		visibility 0s linear var(--sh-transition);
}

.sh-slide.is-active {
	opacity: 1;
	visibility: visible;
	transform: none;
	transition:
		opacity var(--sh-transition) var(--sh-ease),
		transform var(--sh-transition) var(--sh-ease),
		visibility 0s;
	z-index: 1;
}

.sh-pic,
.sh-slide img {
	display: block;
	width: 100%;
	height: 100%;
}

.sh-slide img {
	object-fit: cover;
	object-position: center center;
}

.sh-overlay {
	position: absolute;
	inset: 0;
	background-color: rgba(0, 0, 0, 0.45);
}

/* ── Transitions ───────────────────────────────────────────────────── */

/* Fade is the default and needs no transform at all. */

.sh--slide_left  .sh-slide:not(.is-active) { transform: translateX(6%); }
.sh--slide_right .sh-slide:not(.is-active) { transform: translateX(-6%); }
.sh--slide_up    .sh-slide:not(.is-active) { transform: translateY(6%); }
.sh--slide_down  .sh-slide:not(.is-active) { transform: translateY(-6%); }
.sh--zoom        .sh-slide:not(.is-active) { transform: scale(1.08); }

.sh--none .sh-slide {
	transition: none;
}

/* ── Ken Burns ─────────────────────────────────────────────────────────
   Applied to the image rather than the slide, so it composes with the
   slide's own transform instead of fighting it. */
@keyframes sh-kb-in  { from { transform: scale(1)    translate3d(0,0,0); }
                       to   { transform: scale(1.12) translate3d(1.5%, -1.5%, 0); } }
@keyframes sh-kb-out { from { transform: scale(1.12) translate3d(-1.5%, 1.5%, 0); }
                       to   { transform: scale(1)    translate3d(0,0,0); } }

.sh--kb .sh-slide.is-active img {
	animation-duration: 12s;
	animation-timing-function: linear;
	animation-fill-mode: both;
}

.sh--kb.sh--kb-in  .sh-slide.is-active img { animation-name: sh-kb-in; }
.sh--kb.sh--kb-out .sh-slide.is-active img { animation-name: sh-kb-out; }

/* ── Content ───────────────────────────────────────────────────────────
   THE HERO CONTENT CONTAINER MUST FILL THE HERO.

   This is what makes alignment work. Previously .sh-content was a plain
   block with no height, so the Hero Content container inside it hugged its
   own content — which left nothing to align WITHIN. Its Justify and Align
   controls were present and did nothing useful, and content sat stuck to
   the top left. Aligning from the outer container could never help either,
   since alignment applies to a container's own children and the content is
   two levels down.

   Stretching both means the Hero Content container's own controls behave
   exactly as they would on any container:
     column direction -> Justify positions vertically, Align horizontally
     row direction    -> the reverse

   So centring is done by selecting "Hero Content" and setting its alignment,
   not the container above it. */

.sh-content {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	width: 100%;
	min-width: 0;
}

.sh-content > .e-con {
	flex: 1 1 auto;
	width: 100%;
}

/* ── The swapping text ─────────────────────────────────────────────────
   Inline-block so it can be transformed; a plain inline box ignores
   translate. */
.sh-token {
	display: inline-block;
	transition:
		opacity var(--sh-text-transition) var(--sh-ease),
		transform var(--sh-text-transition) var(--sh-ease);
}

.sh-token.is-changing {
	opacity: 0;
}

.sh--text-slide_up .sh-token.is-changing {
	transform: translateY(-0.35em);
}

.sh--text-none .sh-token {
	transition: none;
}

/* An sh-link on a slide with no URL is hidden outright, per the brief. The
   attribute is set server-side for the first slide and by script after. */
.sh-content [hidden] {
	display: none !important;
}

/* ── Arrows ────────────────────────────────────────────────────────── */

.sh-arrow {
	position: absolute;
	top: 50%;
	z-index: 3;
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--sh-arrow-size);
	height: var(--sh-arrow-size);
	margin: 0;
	padding: 0;
	transform: translateY(-50%);
	border: 0;
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.35);
	color: #fff;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	transition: opacity 0.2s linear;
}

/* Themes style bare `button`, and `button:hover` (0,0,1,1) outranks a lone
   class. The interactive states are claimed explicitly so a theme cannot
   repaint the controls — the same trap that caught Flip Deck. */
.sh-arrow,
.sh-arrow:hover,
.sh-arrow:focus,
.sh-arrow:active,
.sh-dot,
.sh-dot:hover,
.sh-dot:focus,
.sh-dot:active {
	text-decoration: none;
	box-shadow: none;
	white-space: normal;
	-webkit-user-select: none;
	user-select: none;
}

.sh-arrow:hover { opacity: 0.8; }
.sh-arrow--prev { left: 18px; }
.sh-arrow--next { right: 18px; }

.sh-arrow svg {
	width: 55%;
	height: 55%;
}

.sh-arrow:focus-visible,
.sh-dot:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

/* ── Dots ──────────────────────────────────────────────────────────── */

.sh-dots {
	position: absolute;
	right: 0;
	bottom: 18px;
	left: 0;
	z-index: 3;
	display: flex;
	gap: 8px;
	justify-content: var(--sh-dots-align);
	padding: 0 24px;
}

.sh-dot {
	width: var(--sh-dot-size);
	height: var(--sh-dot-size);
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--sh-dot);
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	transition: background-color 0.25s linear, transform 0.25s var(--sh-ease);
}

.sh-dot.is-active {
	background: var(--sh-dot-active);
	transform: scale(1.25);
}

/* ── Reduced motion ────────────────────────────────────────────────────
   The script stops auto-advancing entirely; this removes the animation
   from any change the visitor makes themselves via dots or arrows. */
@media (prefers-reduced-motion: reduce) {
	.sh-slide,
	.sh-slide.is-active,
	.sh-token,
	.sh-dot {
		transition: none !important;
	}

	.sh--kb .sh-slide.is-active img {
		animation: none !important;
	}
}