/*
 * ReduxSlider — front end.
 *
 * Everything visual is a custom property with a brand-neutral default, so a
 * child theme can restyle the slider without overriding any of the structure.
 * Defaults live in :where() so they carry zero specificity — a theme overriding
 * them with a plain .vgrs-slider rule always wins, whatever order the
 * stylesheets happen to load in.
 *
 * The two breakpoints near the bottom are hard-coded because a media query
 * condition cannot read a custom property; re-declare the query to change them.
 */

:where(.vgrs-slider)
	{
	--vgrs-ratio: 1500 / 600;
	--vgrs-ratio-mobile: 480 / 620;
	--vgrs-max-height: 600px;
	--vgrs-duration: 800ms;
	--vgrs-ease: cubic-bezier(0.65, 0, 0.35, 1);
	--vgrs-background: #000;

	/* Darkens the photo so white text stays legible. Set in the admin. */
	--vgrs-overlay: 0.2;
	--vgrs-overlay-color: 0 0 0;

	/* Slides narrower than the frame let the neighbouring images peek in. */
	--vgrs-slide-width: 92%;
	--vgrs-gap: 6px;

	/*
	 * The margin either side of the active slide. Arrows are positioned from
	 * the slide's edge rather than the frame's, which keeps them on the image
	 * at every width — an arrow sitting over the border between two slides is
	 * the one thing this must never do. Falls out to zero when a slide fills
	 * the frame, so on mobile the arrows simply overlay the photo.
	 */
	--vgrs-gutter: calc((100% - var(--vgrs-slide-width)) / 2);

	/*
	 * Where an arrow sits, measured in from the frame edge. The default tucks
	 * it just inside the active slide. Set --vgrs-arrow-x to
	 *   calc((var(--vgrs-gutter) - var(--vgrs-gap) - var(--vgrs-arrow-size)) / 2)
	 * to centre it on the neighbouring slide instead — only worth doing once
	 * the gutter is wider than the arrow, or it will cross the border.
	 */
	--vgrs-arrow-x: calc(var(--vgrs-gutter) + var(--vgrs-arrow-inset));

	/*
	 * The caption is a centred vertical stack, so the logo and the heading can
	 * never land on top of each other however long the text is or however
	 * short the frame gets. --vgrs-stack-gap is the space between them.
	 */
	/* Not a percentage: a percentage row-gap resolves against the container's
	   height, which is indefinite here, so it silently collapses to nothing. */
	--vgrs-stack-gap: clamp(12px, 2.5vw, 48px);
	--vgrs-caption-inset: 6%;
	--vgrs-caption-shift: 0px;

	--vgrs-logo-width: 36%;
	--vgrs-logo-max-width: 40vw;

	--vgrs-heading-font: inherit;
	--vgrs-heading-size: clamp(40px, 4.8vw, 72px);
	--vgrs-heading-weight: 400;
	--vgrs-heading-color: #fff;
	--vgrs-heading-shadow: none;

	--vgrs-arrow-size: 50px;
	--vgrs-arrow-color: #fff;
	--vgrs-arrow-background: transparent;
	--vgrs-arrow-inset: 80px;
	--vgrs-arrow-offset-y: 0px;
	--vgrs-arrow-opacity: 1;
	--vgrs-arrow-opacity-hover: 0.75;
	--vgrs-arrow-stroke: 3;
	}

/*
 * Covers the instant before the script sets --vgrs-viewport, and the case where
 * it never runs: the 100vw fallback is wider than the content area by the
 * scrollbar's width, which would otherwise put a scrollbar across the page.
 * `clip`, not `hidden`, so this never becomes a scroll container and position:
 * sticky elsewhere on the page keeps working.
 */
html:has(.vgrs-slider)
	{
	overflow-x: clip;
	}

.vgrs-slider
	{
	position: relative;
	aspect-ratio: var(--vgrs-ratio);
	max-height: var(--vgrs-max-height);
	overflow: hidden;
	background: var(--vgrs-background);
	}

/*
 * Full-bleed: break out of whatever column the shortcode sits in and span the
 * window. --vgrs-viewport is the document's client width, set by the script.
 * 100vw includes the vertical scrollbar, so using it alone makes the page
 * overflow sideways by the scrollbar's width; it is only the pre-script
 * fallback.
 */
.vgrs-slider--full
	{
	width: var(--vgrs-viewport, 100vw);
	max-width: var(--vgrs-viewport, 100vw);
	margin-left: calc(50% - var(--vgrs-viewport, 100vw) / 2);
	}

/*
 * Contained: stay within the column, for sliders set beside text rather than
 * spanning the page. --vgrs-max-height is a banner constraint and would crop a
 * portrait frame, so the ratio alone decides the height here.
 */
.vgrs-slider--contained
	{
	width: 100%;
	max-width: 100%;
	margin-left: 0;
	aspect-ratio: var(--vgrs-ratio-contained, 600 / 700);
	max-height: none;
	}

.vgrs-slider__slides
	{
	position: absolute;
	inset: 0;
	margin: 0;
	padding: 0;
	list-style: none;
	}

.vgrs-slider__slide
	{
	position: absolute;
	top: 0;
	bottom: 0;
	left: 50%;
	width: var(--vgrs-slide-width);
	margin: 0;
	padding: 0;
	list-style: none;
	transform: translateX(-50%);
	}

/* Fade: every slide sits centred and only opacity moves. */
.vgrs-slider--fade .vgrs-slider__slide
	{
	opacity: 0;
	transition: opacity var(--vgrs-duration) ease-in-out;
	}

.vgrs-slider--fade .vgrs-slider__slide.is-active
	{
	opacity: 1;
	}

/*
 * Slide: the script parks each slide left or right of the frame and animates
 * the transform. Positions are written as translateX percentages of the slide's
 * own width, so they hold at any --vgrs-slide-width.
 */
.vgrs-slider--slide .vgrs-slider__slide
	{
	transform: translateX(calc(50% + var(--vgrs-gap)));
	transition: transform var(--vgrs-duration) var(--vgrs-ease);
	}

.vgrs-slider--slide .vgrs-slider__slide.is-active
	{
	transform: translateX(-50%);
	}

/*
 * Deliberately three classes deep. Themes routinely ship a broad image reset —
 * Jupiter has `.theme-content img, .vc_row-fluid img { height: auto }` at (0,2,0)
 * — which otherwise wins and leaves the image sized by its own aspect ratio
 * instead of filling the frame, so object-fit never gets to do its job.
 */
.vgrs-slider .vgrs-slider__slide .vgrs-slider__image
	{
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	min-height: 0;
	max-width: none;
	max-height: none;
	margin: 0;
	object-fit: cover;
	object-position: var(--vgrs-image-position, center center);
	}

/* Sits over the photo, under the caption. */
.vgrs-slider__slide::after
	{
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: rgb(var(--vgrs-overlay-color) / var(--vgrs-overlay));
	pointer-events: none;
	}

.vgrs-slider__caption
	{
	position: absolute;
	inset: 0;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--vgrs-stack-gap);
	padding: var(--vgrs-caption-inset);
	transform: translateY(var(--vgrs-caption-shift));
	pointer-events: none;
	}

.vgrs-slider .vgrs-slider__slide .vgrs-slider__logo
	{
	flex: 0 0 auto;
	width: var(--vgrs-logo-width);
	max-width: var(--vgrs-logo-max-width);
	height: auto;
	margin: 0;
	}

.vgrs-slider__heading
	{
	flex: 0 0 auto;
	max-width: 100%;
	margin: 0;
	color: var(--vgrs-heading-color);
	font-family: var(--vgrs-heading-font);
	font-size: var(--vgrs-heading-size);
	font-weight: var(--vgrs-heading-weight);
	line-height: 1;
	text-align: center;
	text-shadow: var(--vgrs-heading-shadow);
	white-space: pre-line;
	}

.vgrs-slider__nav
	{
	position: absolute;
	top: calc(50% + var(--vgrs-arrow-offset-y));
	z-index: 2;
	display: grid;
	place-items: center;
	width: var(--vgrs-arrow-size);
	height: var(--vgrs-arrow-size);
	padding: 0;
	transform: translateY(-50%);
	border: 0;
	border-radius: 0;
	background: var(--vgrs-arrow-background);
	box-shadow: none;
	color: var(--vgrs-arrow-color);
	opacity: var(--vgrs-arrow-opacity);
	cursor: pointer;
	transition: opacity 300ms ease;
	}

.vgrs-slider__nav:hover,
.vgrs-slider__nav:focus-visible
	{
	background: var(--vgrs-arrow-background);
	opacity: var(--vgrs-arrow-opacity-hover);
	}

.vgrs-slider__nav:focus-visible
	{
	outline: 2px solid currentColor;
	outline-offset: 4px;
	}

.vgrs-slider__nav--prev
	{
	left: var(--vgrs-arrow-x-start, var(--vgrs-arrow-x));
	}

.vgrs-slider__nav--next
	{
	right: var(--vgrs-arrow-x-end, var(--vgrs-arrow-x));
	}

.vgrs-slider__nav svg
	{
	width: 100%;
	height: 100%;
	fill: none;
	stroke: currentColor;
	stroke-width: var(--vgrs-arrow-stroke);
	stroke-linecap: square;
	}

/*
 * A contained slider has no gutter to put arrows in — centred on the sides they
 * would sit over the photo's focal point. Pair them in the bottom-right corner
 * instead, scaled down to suit the smaller frame.
 */
.vgrs-slider--contained .vgrs-slider__nav
	{
	--vgrs-arrow-size: var(--vgrs-arrow-size-contained, 34px);
	top: auto;
	bottom: var(--vgrs-arrow-inset-contained, 12px);
	transform: none;
	}

.vgrs-slider--contained .vgrs-slider__nav--prev
	{
	left: auto;
	right: calc(var(--vgrs-arrow-inset-contained, 12px) + var(--vgrs-arrow-size) + var(--vgrs-arrow-gap-contained, 6px));
	}

.vgrs-slider--contained .vgrs-slider__nav--next
	{
	right: var(--vgrs-arrow-inset-contained, 12px);
	}

/*
 * Small screens go edge to edge: there is no room for a gutter, so the slide
 * fills the frame and the arrows sit on top of the photo, scaled down.
 * In :where() so a theme's own mobile block still wins.
 */
@media (max-width: 767px)
	{
	:where(.vgrs-slider)
		{
		--vgrs-slide-width: 100%;
		--vgrs-gap: 0px;
		--vgrs-arrow-size: 36px;
		--vgrs-arrow-inset: 8px;
		--vgrs-arrow-offset-y: 0px;
		}
	}

@media (max-width: 480px)
	{
	.vgrs-slider--full
		{
		aspect-ratio: var(--vgrs-ratio-mobile);
		}
	}

@media (prefers-reduced-motion: reduce)
	{
	.vgrs-slider__slide
		{
		transition: none;
		}
	}
