.psl-slider {
	position: relative;
	width: 100%;
	margin: 0 auto;
	overflow: hidden;
	/* No background color here on purpose. This container is empty until
	   frontend.js builds the slides into it, so any color set here becomes
	   whatever briefly shows (or persistently shows, if the JS never runs —
	   a script conflict, an error, a caching issue serving a stale copy)
	   before that happens. Leaving it transparent means the worst case is an
	   empty gap matching the page's own background, not an opaque color that
	   can look like a rendering bug even when the plugin is actually working
	   correctly and this is just a normal one-frame gap. If you want a
	   specific placeholder color while the slider loads, add
	   `.psl-slider { background: #yourcolor; }` via your theme's Additional
	   CSS — this is deliberately left to you rather than hardcoded. */
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	outline: none;
	box-sizing: border-box;
	border-style: solid;
	border-color: var(--psl-border-color, transparent);
	border-width: var(--psl-border-w, 0);
	border-radius: var(--psl-radius, 0);
	/* Establishes this element as a query container for its own rendered
	   size, so layer sizing below can react to how wide the SLIDER actually
	   is (e.g. boxed narrow inside a Gutenberg column) rather than only the
	   browser viewport — a boxed slider embedded at 400px wide on a large
	   desktop viewport still needs "mobile-ish" treatment, which a plain
	   @media query can never see. */
	container-type: inline-size;
	container-name: psl;
}
/* Tablet/mobile overrides fall back through the chain (mobile -> tablet ->
   desktop) via each var()'s own second argument, so leaving a breakpoint's
   field blank in the admin — meaning that CSS variable is never output —
   simply inherits the next size up with no extra logic needed here. */
@media (max-width: 1024px) {
	.psl-slider {
		border-width: var(--psl-border-w-tablet, var(--psl-border-w, 0));
		border-radius: var(--psl-radius-tablet, var(--psl-radius, 0));
	}
}
@media (max-width: 640px) {
	.psl-slider {
		border-width: var(--psl-border-w-mobile, var(--psl-border-w-tablet, var(--psl-border-w, 0)));
		border-radius: var(--psl-radius-mobile, var(--psl-radius-tablet, var(--psl-radius, 0)));
	}
}

.psl-track {
	position: relative;
	width: 100%;
	height: 100%;
}

/* Fullscreen mode: fills the browser window on every device, independent of
   where the shortcode sits in the document. 100dvh (with a 100vh fallback for
   older browsers) accounts for mobile browser chrome resizing on scroll.
   This is a fixed overlay — it covers everything below it, including your
   footer, for as long as it's on screen. Pairs with the Blank Canvas template. */
.psl-slider.psl-mode-fullscreen {
	position: fixed;
	inset: 0;
	width: 100vw;
	height: 100vh;
	height: 100dvh;
	max-width: none;
	aspect-ratio: auto;
	z-index: 1;
}

/* Full bleed: same full browser width & height as fullscreen, but stays in
   normal document flow (position: relative, not fixed) — so your footer and
   any content after it scroll into view underneath it as normal. The
   left:50%/margin:-50vw pair is the standard "full-bleed" technique: it
   breaks the element out to the true viewport width regardless of a parent
   page-builder row's max-width or padding, without needing that row's own
   "Stretch Row" option turned on. Requires no ancestor between this element
   and <body> to have `overflow: hidden` — that would clip the breakout. */
.psl-slider.psl-mode-fullbleed {
	position: relative;
	left: 50%;
	right: 50%;
	width: 100vw;
	margin-left: -50vw;
	margin-right: -50vw;
	height: 100vh;
	height: 100dvh;
	max-width: none;
	aspect-ratio: auto;
}

.psl-rows-fly,
.psl-curtain-fly {
	position: absolute;
	inset: 0;
	z-index: 2;
	pointer-events: none;
	overflow: hidden;
}
.psl-row-fly {
	position: absolute;
	left: 0;
	width: 100%;
	background-size: cover;
	background-repeat: no-repeat;
}
.psl-curtain-fly {
	display: flex;
}
.psl-curtain-panel {
	width: 50%;
	height: 100%;
	background-size: cover;
	background-repeat: no-repeat;
}

.psl-slide {
	position: absolute;
	inset: 0;
	visibility: hidden;
	overflow: hidden;
	will-change: transform, opacity, clip-path;
}
.psl-slide.is-active { visibility: visible; }

/* Page-builder themes (Uncode, and others built on WPBakery/similar builders)
   often add global link underline animations via ::before/::after pseudo
   elements and text-decoration rules. Scope those back out inside the
   slider/CTA so theme link styling doesn't visually clash with layer
   buttons, arrows, or dots. */
.psl-slider a,
.psl-cta a,
.psl-fullscreen-block a {
	text-decoration: none;
}
.psl-slider a::before,
.psl-slider a::after,
.psl-cta a::before,
.psl-cta a::after,
.psl-fullscreen-block a::before,
.psl-fullscreen-block a::after {
	display: none !important;
	content: none !important;
}

/* inset: 0 (it used to be -12%). The old oversizing made the background
   ~24% larger than the slide, which silently cropped every image and meant
   a chosen position like "top" or "left" could never actually reach the
   image's real edge. Ken Burns doesn't need the extra room: it zooms in
   (scale 1 → 1.15) faster than it pans (≤3%), so no edge is ever exposed. */
.psl-bg-layer {
	position: absolute;
	inset: 0;
	z-index: 0;
	background-size: cover;
	background-position: center;
	will-change: transform;
}
.psl-bg-overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	/* The slide's chosen style replaces this inline (see overlay.js); this
	   is the original look, kept for the fullscreen block. */
	background: linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,0.55) 100%);
	pointer-events: none;
}
/* Spotlight on a stacked slide: a glow that travels with the layer group.
   The stack is its own stacking context (z-index 3), so z-index -1 puts the
   glow behind the layers but still above the slide's background. */
.psl-stack-inner { position: relative; }
.psl-stack-glow {
	position: absolute;
	inset: calc(-50% - 2cqw) calc(-50% - 3cqw);
	z-index: -1;
	pointer-events: none;
}
/* Panel overlay: a frosted card behind the stacked layer group. Padding and
   radius scale with the fit factor, so the card shrinks with the text. */
.psl-stack-inner.psl-stack-panel {
	box-sizing: border-box;
	padding: calc(clamp(12px, 2.6cqw, 36px) * var(--psl-fit, 1)) calc(clamp(16px, 3.4cqw, 48px) * var(--psl-fit, 1));
	border-radius: calc(clamp(8px, 1.2cqw, 16px) * var(--psl-fit, 1));
	-webkit-backdrop-filter: blur(10px) saturate(1.1);
	backdrop-filter: blur(10px) saturate(1.1);
	box-shadow: 0 10px 40px rgba(0,0,0,0.18);
}
.psl-stack-inner.psl-stack-panel.psl-panel-light { box-shadow: 0 10px 40px rgba(0,0,0,0.12), inset 0 0 0 1px rgba(255,255,255,0.4); }

.psl-layer-pos {
	position: absolute;
	z-index: 3;
	max-width: 90%;
	/* No line box of its own: a button (inline-block) would otherwise sit on
	   the baseline of the page's 16px line, pushing small buttons down on
	   phones. Every layer sets its own line-height, so nothing inherits this. */
	line-height: 0;
}
/* The alignment anchor transform lives here, on the wrapper — never on
   .psl-layer itself, since that element's own `transform` is already used
   by the entrance animation (translateX/Y for slide-in, scale for zoom-in).
   Putting both on the same element would mean the last one applied wins,
   silently breaking either the alignment or the animation. */

.psl-layer,
.psl-layer-link-wrap {
	margin: 0;
	line-height: 1.25;
	will-change: transform, opacity;
}
.psl-layer-link-wrap {
	display: block;
	text-decoration: none;
}

h2.psl-layer {
	font-weight: 700;
	letter-spacing: -0.01em;
}
p.psl-layer {
	opacity: 0.9;
}
img.psl-layer {
	display: block;
	max-width: 100%;
	height: auto;
}
a.psl-btn.psl-layer {
	display: inline-block;
	vertical-align: top;
	/* em, not px: the padding scales with the button's (fluid) text size, so
	   a button keeps its shape on small screens instead of becoming a big
	   padded box around tiny text. Same as the old 12px × 26px at 16px. */
	padding: 0.75em 1.6em;
	line-height: 1.2;
	white-space: nowrap;
	/* Scales with the text (1.5px at 16px), so a small button isn't
	   relatively heavier; never thinner than 1px. */
	border: max(1px, 0.094em) solid currentColor;
	border-radius: 3px;
	text-decoration: none;
	font-weight: 600;
	letter-spacing: 0.02em;
	transition: background-color .2s ease, color .2s ease;
}
/* :not(.psl-hv-custom) is the important part here, not decoration — a
   per-layer custom hover color/background is applied as a separate
   generated rule (see PSLSlider._applyHoverStyle in frontend.js), and that
   rule targets a plain class selector with lower specificity than this one.
   Both need !important to override the inline color set from the layer's
   own color field, and when two !important declarations for the same
   property collide, the more specific selector always wins regardless of
   source order — which would silently make a custom hover color
   ineffective on buttons specifically. Excluding .psl-hv-custom here means
   this rule simply doesn't match at all on a layer with a custom hover
   style, so there's no specificity contest to lose. */
a.psl-btn.psl-layer:not(.psl-btn--filled):hover:not(.psl-hv-custom) {
	background-color: currentColor;
	color: #111 !important;
}

.psl-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 10;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid rgba(255,255,255,0.65);
	background: rgba(0,0,0,0.25);
	color: #fff;
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background-color .2s ease;
}
.psl-arrow:hover { background: rgba(0,0,0,0.55); }
.psl-arrow-prev { left: 18px; }
.psl-arrow-next { right: 18px; }

.psl-dots {
	position: absolute;
	bottom: 18px;
	left: 50%;
	transform: translateX(-50%);
	z-index: 10;
	display: flex;
	gap: 8px;
}
.psl-dot {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	border: 1px solid rgba(255,255,255,0.8);
	background: transparent;
	padding: 0;
	cursor: pointer;
	transition: background-color .2s ease;
}
.psl-dot.is-active { background: #fff; }

.psl-progress {
	position: absolute;
	left: 0; bottom: 0;
	width: 100%;
	height: 3px;
	background: rgba(255,255,255,0.15);
	z-index: 10;
}
.psl-progress-bar {
	height: 100%;
	width: 0%;
	background: rgba(255,255,255,0.85);
}

.psl-cta {
	padding: 20px 16px;
	text-align: center;
}
.psl-cta-btn-container {
	display: block;
	margin-bottom: 12px;
}
.psl-cta-caption {
	font-size: 15px;
	line-height: 1.5;
	display: inline-block;
}
.psl-cta-btn {
	display: inline-block;
	padding: 12px 28px;
	border: 1.5px solid currentColor;
	border-radius: 3px;
	text-decoration: none;
	font-weight: 600;
	font-size: 14px;
	letter-spacing: 0.02em;
	color: inherit;
	transition: background-color .2s ease, color .2s ease;
}
.psl-cta-btn:hover {
	background-color: currentColor;
	color: #111;
}

/* Sits as a caption/CTA bar under a fullscreen slider (which is position:fixed and
   therefore removes itself from normal document flow) without needing the page
   to scroll — pairs with the slider's "Full screen" display mode. */
.psl-cta.psl-cta-overlay-bottom {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 5;
	padding: 26px 16px 30px;
	color: #fff;
	background: linear-gradient(0deg, rgba(0,0,0,0.6) 0%, rgba(0,0,0,0) 100%);
	pointer-events: none;
}
.psl-cta.psl-cta-overlay-bottom .psl-cta-btn,
.psl-cta.psl-cta-overlay-bottom .psl-cta-caption {
	pointer-events: auto;
}

/* A standalone fullscreen block (not tied to the slider) — same viewport-filling
   approach as the slider's Full screen display mode, with a button + caption
   pinned to the bottom of the viewport. */
.psl-fullscreen-block {
	position: fixed;
	inset: 0;
	width: 100vw;
	height: 100vh;
	height: 100dvh;
	overflow: hidden;
	z-index: 1;
}
.psl-fullscreen-cta {
	position: absolute;
	inset: 0;
	z-index: 3;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-end;
	padding: 30px 16px 40px;
	text-align: center;
	color: #fff;
}
.psl-fullscreen-cta.psl-fullscreen-cta--center {
	justify-content: center;
	padding: 20px;
}

@media (max-width: 640px) {
	.psl-arrow { width: 36px; height: 36px; font-size: 16px; }
	.psl-layer-pos { max-width: 82%; }
	.psl-cta.psl-cta-overlay-bottom { padding: 18px 14px 22px; }
	.psl-cta-caption { font-size: 14px; }
	.psl-fullscreen-cta { padding: 20px 14px 28px; }
}

/* Container-query equivalent of the viewport media query above, but reacting
   to the SLIDER's own rendered width instead of the browser window. This is
   what makes a boxed slider embedded narrow — e.g. inside a Gutenberg column
   or a sidebar widget — get sensible sizing even on a wide desktop viewport,
   which a @media query can never detect since it only ever sees the browser
   window's width. Layered on top of (not instead of) the @media rule above
   as a fallback for older browsers without container query support. */
@supports (container-type: inline-size) {
	@container psl (max-width: 640px) {
		.psl-arrow { width: 36px; height: 36px; font-size: 16px; }
		.psl-layer-pos { max-width: 82%; }
	}
	@container psl (max-width: 420px) {
		.psl-arrow { width: 30px; height: 30px; font-size: 14px; }
		.psl-dots { bottom: 10px; }
		.psl-layer-pos { max-width: 88%; }
	}
}

@media (prefers-reduced-motion: reduce) {
	.psl-slide, .psl-layer, .psl-layer-link-wrap { transition: none !important; }
}

/* ---------- Theme-proofing ----------
   On a real page the slider sits inside the theme's content area, where
   rules like `.entry-content h2 { margin-bottom: 1.5em }` would otherwise
   add stray spacing to layers. Two classes outrank those selectors. */
.psl-slider .psl-layer { margin: 0; }
.psl-slider h2.psl-layer,
.psl-slider p.psl-layer { padding: 0; line-height: 1.25; }

/* Filled buttons (a Button background is set): the default hover can't
   invert like an outline button, so it brightens instead. */
a.psl-btn.psl-btn--filled { transition: filter .2s ease, background-color .2s ease, color .2s ease; }
a.psl-btn.psl-btn--filled:hover:not(.psl-hv-custom) { filter: brightness(1.12); }

/* ---------- Stacked layout ----------
   Layers flow top to bottom inside one group, so they can't overlap. The
   group is placed by the slide's "where the layers sit" setting. Padding
   keeps it clear of the arrows (sides) and dots (bottom); max() keeps that
   clearance on small screens where a % alone would be too thin. */
.psl-stack {
	position: absolute;
	inset: 0;
	z-index: 3;
	display: flex;
	flex-direction: column;
	box-sizing: border-box;
	padding: max(6%, 24px) max(7%, 60px) max(7%, 52px);
}
.psl-stack--v-top    { justify-content: flex-start; }
.psl-stack--v-middle { justify-content: center; }
.psl-stack--v-bottom { justify-content: flex-end; }

.psl-stack-inner {
	display: flex;
	flex-direction: column;
	max-width: 100%;
	min-width: 0;
	gap: calc(clamp(6px, 2cqw, 22px) * var(--psl-fit, 1));
}
.psl-stack--h-left   .psl-stack-inner { align-self: flex-start; align-items: flex-start; text-align: left; }
.psl-stack--h-center .psl-stack-inner { align-self: center;     align-items: center;     text-align: center; }
.psl-stack--h-right  .psl-stack-inner { align-self: flex-end;   align-items: flex-end;   text-align: right; }

.psl-slider .psl-layer-pos.psl-layer-flow {
	position: relative;
	left: auto;
	top: auto;
	z-index: auto;
	transform: none;
	max-width: 100%;
	min-width: 0;
}
.psl-layer-flow .psl-layer { overflow-wrap: break-word; }

/* Neighbouring buttons sit side by side and wrap onto a new line only if
   the row runs out of room. */
.psl-btn-row {
	display: flex;
	flex-wrap: wrap;
	gap: calc(clamp(6px, 1.4cqw, 16px) * var(--psl-fit, 1));
	max-width: 100%;
}
.psl-stack--h-left   .psl-btn-row { justify-content: flex-start; }
.psl-stack--h-center .psl-btn-row { justify-content: center; }
.psl-stack--h-right  .psl-btn-row { justify-content: flex-end; }

/* Small sliders: the arrows and dots shrink (see the 420px container rule
   above), so the stacked group can use more of the width. */
@supports (container-type: inline-size) {
	@container psl (max-width: 420px) {
		.psl-stack { padding: 20px 54px 36px; } /* arrows here: 30px wide, 18px in = 48px */
	}
}

/* Exact scaling (Free layout): the phone-only 82% width cap above would
   make text wrap differently on phones than on desktop. Keep the desktop
   wrapping width so the arrangement is identical at every size. */
.psl-slider.psl-exact .psl-layer-pos:not(.psl-layer-flow) { max-width: 90%; }
.psl-slider.psl-exact .psl-layer-pos:not(.psl-layer-flow) > img.psl-layer { width: 100%; }
