/**
 * SignUpEngine Gallery - front end.
 *
 * THE ONE IDEA WORTH KNOWING
 * -------------------------
 * There is a single DOM for both presentations. On desktop `.sueg` is a row of
 * `.sueg-col` boxes, each a vertical stack. On mobile the columns become
 * `display: contents`, which dissolves them completely and promotes every
 * `.sueg-item` to be a direct child of `.sueg` - which is by then a horizontal
 * scroll rail. `order` puts the items back into the editor's sequence, because
 * column-major DOM order would otherwise deal them out like cards.
 *
 * That is why there is no second "mobile gallery" to build any more, and why
 * the images are downloaded once rather than twice.
 *
 * HOW THE COLUMNS COME OUT FLUSH
 * ------------------------------
 * PHP works out an aspect ratio per image such that the columns are as close to
 * equal as the crop budget allows (see class-sue-gallery-layout.php), and hands
 * each item a flex-grow weight. The columns stretch to the tallest one, and the
 * shorter columns' spare height is shared out by those weights. So the server
 * gets it nearly right at a nominal width and the browser finishes it exactly,
 * at whatever the real width and real gap turn out to be. No JavaScript
 * measures anything, and the gallery is at its final size on first paint.
 */

.sueg-wrap {
	--sueg-gap: 16px;
	--sueg-radius: 0px;
	--sueg-peek: 82%;
	--sueg-mobile-ar: 1.3333;
	--sueg-brand: var(--primary-color, #102d52);
	--sueg-on-brand: #ffffff;
	--sueg-ink: var(--body-text-color, #23282d);
	--sueg-muted: rgba(35, 40, 45, 0.62);
	--sueg-shade: rgba(16, 45, 82, 0.08);

	position: relative;
}

/* The theme sets `figure { margin: 1em 0 }` and `img { height: auto }` as bare
   element rules. Both would quietly wreck the layout, and both are beaten by a
   single class - but only if it is actually written down. */
.sueg-item {
	margin: 0;
	padding: 0;
	position: relative;
	overflow: hidden;
	border-radius: var(--sueg-radius);
	background: var(--sueg-shade);
	min-width: 0;
	min-height: 0;
}

.sueg-img {
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: cover;
	/* object-position is set per image from the focal point picker, so a crop
	   the engine applies to balance the columns still keeps the subject. */
	object-position: 50% 50%;
}

/* ------------------------------------------------------------------
   Desktop: the balanced masonry
   ------------------------------------------------------------------ */

.sueg {
	display: flex;
	align-items: stretch;
	gap: var(--sueg-gap);
}

.sueg-col {
	display: flex;
	flex-direction: column;
	gap: var(--sueg-gap);
	flex: 1 1 0;
	min-width: 0;
}

.sueg .sueg-item {
	/* aspect-ratio gives the intrinsic height; flex-grow takes up whatever is
	   left over in a column that came out short. flex-shrink stays 0 so a long
	   column is never squashed to match a short one. */
	aspect-ratio: var(--sueg-ar, 1.5);
	flex: var(--sueg-grow, 1) 0 auto;
}

/* ------------------------------------------------------------------
   Per-image visibility

   One gallery, two audiences. A Highlights section with little copy might
   only want four images to balance against it on a desktop, while a phone -
   where the rail is swiped rather than taken in at a glance - happily carries
   eight. Rather than maintain two galleries again, images can opt out of
   either presentation.

   display:none, not visibility:hidden: a hidden item must leave the flex flow
   completely, or it would still take a share of its column's height and the
   balancing would be computed against images nobody can see.
   ------------------------------------------------------------------ */

.sueg-item--mobile-only {
	display: none;
}

/* A column holding nothing but phone-only images would still claim its 1fr of
   the desktop row and squeeze the real columns. */
.sueg-col--mobile-only {
	display: none;
}

/* ------------------------------------------------------------------
   Lightbox affordance
   ------------------------------------------------------------------ */

.sueg-open {
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	cursor: zoom-in;
	overflow: hidden;
	border-radius: inherit;
	-webkit-appearance: none;
	appearance: none;
}

.sueg-open:focus-visible {
	outline: 3px solid var(--sueg-brand);
	outline-offset: -3px;
}

.sueg-open .sueg-img {
	transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.sueg-zoom {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.35) 100%);
	opacity: 0;
	transition: opacity 0.35s ease;
	pointer-events: none;
}

@media (hover: hover) {
	.sueg-open:hover .sueg-img {
		transform: scale(1.045);
	}

	.sueg-open:hover .sueg-zoom {
		opacity: 1;
	}
}

@media (prefers-reduced-motion: reduce) {
	.sueg-open .sueg-img,
	.sueg-zoom {
		transition: none;
	}

	.sueg-open:hover .sueg-img {
		transform: none;
	}
}

/* ------------------------------------------------------------------
   Captions
   ------------------------------------------------------------------ */

.sueg-cap {
	margin: 0;
	padding: 10px 12px 0;
	font-size: 0.82rem;
	line-height: 1.4;
	color: var(--sueg-muted);
}

.sueg--captions-hover .sueg-cap {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 26px 14px 12px;
	margin: 0;
	color: #fff;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.72) 100%);
	opacity: 0;
	transform: translateY(6px);
	transition: opacity 0.3s ease, transform 0.3s ease;
	pointer-events: none;
}

@media (hover: hover) {
	.sueg--captions-hover .sueg-item:hover .sueg-cap,
	.sueg--captions-hover .sueg-open:focus-visible + .sueg-cap {
		opacity: 1;
		transform: none;
	}
}

/* A hover caption is unreachable on a touch screen, so show it outright. */
@media (hover: none) {
	.sueg--captions-hover .sueg-cap {
		position: static;
		opacity: 1;
		transform: none;
		padding: 10px 12px 0;
		color: var(--sueg-muted);
		background: none;
	}
}

/* A caption below the image is content, not part of the picture, so it must not
   be swallowed by the item's fixed aspect ratio. */
.sueg--captions-below .sueg-item {
	aspect-ratio: auto;
	display: flex;
	flex-direction: column;
	overflow: visible;
	background: none;
}

.sueg--captions-below .sueg-open,
.sueg--captions-below .sueg-item > .sueg-img {
	aspect-ratio: var(--sueg-ar, 1.5);
	flex: 1 1 auto;
	border-radius: var(--sueg-radius);
	background: var(--sueg-shade);
	overflow: hidden;
}

.sueg--captions-below .sueg-cap {
	flex: 0 0 auto;
}

/* ------------------------------------------------------------------
   Slider chrome. Desktop hides it; the mobile block below turns it on.
   ------------------------------------------------------------------ */

.sueg-nav,
.sueg-dots,
.sueg-count {
	display: none;
}

.sueg-arrow {
	width: 46px;
	height: 46px;
	border: 0;
	padding: 0;
	cursor: pointer;
	background: var(--sueg-brand);
	color: var(--sueg-on-brand);
	border-radius: 4px;
	position: relative;
	transition: opacity 0.2s ease;
}

.sueg-arrow[disabled] {
	opacity: 0.32;
	cursor: default;
}

/* Chevrons drawn from a rotated border, so the plugin ships no icon files and
   the arrows inherit the brand colour rather than baking it into an image. */
.sueg-arrow::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 10px;
	height: 10px;
	border-top: 2px solid currentColor;
	border-right: 2px solid currentColor;
}

.sueg-arrow--prev::before {
	transform: translate(-35%, -50%) rotate(-135deg);
}

.sueg-arrow--next::before {
	transform: translate(-65%, -50%) rotate(45deg);
}

.sueg-dot {
	width: 9px;
	height: 9px;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: var(--sueg-shade);
	cursor: pointer;
	transition: width 0.3s ease, background-color 0.3s ease;
}

.sueg-dot.is-active {
	width: 26px;
	background: var(--sueg-brand);
}

.sueg-count {
	font-size: 0.82rem;
	color: var(--sueg-muted);
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------
   Mobile: the same images, as a peek rail
   ------------------------------------------------------------------ */

@media screen and (max-width: 767px) {

	.sueg-wrap--slider .sueg {
		display: flex;
		flex-direction: row;
		align-items: flex-start;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		/* The rail is edge to edge, but the module it sits in has padding, so
		   pull it out and put the padding back as scroll padding. Otherwise the
		   first slide starts inset and the peek on the right is lost. */
		padding-bottom: 2px;
	}

	.sueg-wrap--slider .sueg::-webkit-scrollbar {
		display: none;
	}

	/* The columns dissolve. Everything inside them becomes a slide. */
	.sueg-wrap--slider .sueg-col {
		display: contents;
	}

	.sueg-wrap--slider .sueg .sueg-item {
		order: var(--sueg-order, 0);
		flex: 0 0 var(--sueg-peek);
		/* One shared ratio across the rail: mixed ratios make the snap points
		   land at different heights and the whole rail jumps as you swipe. The
		   focal point decides what stays in frame, which is exactly what makes
		   a separate mobile gallery unnecessary. */
		aspect-ratio: var(--sueg-mobile-ar, 1.3333);
		scroll-snap-align: start;
		scroll-snap-stop: always;
	}

	.sueg-wrap--slider .sueg--captions-below .sueg-item {
		aspect-ratio: auto;
	}

	/* The other half of the swap. */
	.sueg-item--desktop-only {
		display: none;
	}

	.sueg-item--mobile-only {
		display: block;
	}

	.sueg-col--mobile-only {
		display: contents;
	}

	.sueg-wrap--slider .sueg--captions-below .sueg-open {
		aspect-ratio: var(--sueg-mobile-ar, 1.3333);
	}

	/* Arrows sit above the rail, not on top of the photographs. The plugin this
	   replaces overlays them, where they cover a face on every slide. */
	.sueg-wrap--slider .sueg-nav {
		display: flex;
		gap: 10px;
		margin-bottom: 18px;
	}

	.sueg-wrap--slider .sueg-dots {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 7px;
		margin-top: 18px;
	}

	.sueg-wrap--slider .sueg-count {
		display: block;
		text-align: center;
		margin-top: 14px;
	}

	/* The other two mobile modes keep the grid, just narrower. */
	.sueg--mobile-stack {
		flex-direction: column;
	}

	.sueg--mobile-stack .sueg-col {
		display: contents;
	}

	.sueg--mobile-stack .sueg-item {
		order: var(--sueg-order, 0);
		flex: 0 0 auto;
		width: 100%;
	}

	.sueg--mobile-stack .sueg-item--mobile-only,
	.sueg--mobile-grid .sueg-item--mobile-only {
		display: block;
	}

	.sueg--mobile-stack .sueg-item--desktop-only,
	.sueg--mobile-grid .sueg-item--desktop-only {
		display: none;
	}
}

/* Between the phone rail and the full desktop layout the highlights module has
   already stacked, so the gallery has the whole container. Three or four
   columns get too thin there. */
@media screen and (min-width: 768px) and (max-width: 1024px) {
	.sueg--cols-4 {
		flex-wrap: wrap;
	}

	.sueg--cols-4 > .sueg-col {
		flex: 1 1 calc(50% - var(--sueg-gap));
	}
}

/* ------------------------------------------------------------------
   Lightbox
   ------------------------------------------------------------------ */

.sueg-lb {
	position: fixed;
	inset: 0;
	z-index: 100050;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(8, 10, 14, 0.94);
	opacity: 0;

	/* A CLOSED LIGHTBOX IS STILL A FULL-VIEWPORT FIXED ELEMENT.
	   Fading it to opacity 0 hides it from the eye and from nothing else: it
	   goes on covering the page and swallowing every click and touch, so the
	   gallery underneath stops opening, the rail will not swipe and the arrows
	   do nothing - with no visible cause and no way out but a reload. It is
	   only ever built on the first open, which is why the first open works and
	   nothing afterwards does.

	   Both properties are needed, and neither is redundant. `visibility` is
	   what takes it out of hit testing, the tab order and the accessibility
	   tree - but it is inherited, so any descendant setting `visibility:
	   visible` would climb back out on its own. `pointer-events` is inherited
	   too and a child can only escape it by saying so explicitly, which none
	   of ours do. */
	visibility: hidden;
	pointer-events: none;

	/* Opening flips visibility at once; closing waits for the fade to finish,
	   so the transition is not cut off half way. */
	transition: opacity 0.28s ease, visibility 0s linear 0.28s;
	touch-action: pan-y;
}

/* Above the slide-in panel and the search modal, both of which sit at 99999.
   A dropdown that opens behind a panel is a bug this codebase has already had
   once, in the phone country picker - it looks like "nothing happens". */
.sueg-lb.is-open {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transition: opacity 0.28s ease, visibility 0s;
}

.sueg-lb-stage {
	position: relative;
	width: min(94vw, 1400px);
	height: min(88vh, 900px);
	display: flex;
	align-items: center;
	justify-content: center;
}

.sueg-lb-img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	display: block;
	object-fit: contain;
	border-radius: 2px;
	transition: opacity 0.2s ease;
}

.sueg-lb-img.is-loading {
	opacity: 0.35;
}

.sueg-lb-cap {
	position: absolute;
	left: 0;
	right: 0;
	bottom: -2.4em;
	text-align: center;
	color: rgba(255, 255, 255, 0.86);
	font-size: 0.88rem;
	line-height: 1.4;
}

.sueg-lb-btn {
	position: absolute;
	border: 0;
	padding: 0;
	background: rgba(255, 255, 255, 0.1);
	color: #fff;
	width: 52px;
	height: 52px;
	border-radius: 999px;
	cursor: pointer;
	transition: background-color 0.2s ease;
}

.sueg-lb-btn:hover,
.sueg-lb-btn:focus-visible {
	background: rgba(255, 255, 255, 0.24);
}

.sueg-lb-btn[disabled] {
	opacity: 0.25;
	cursor: default;
}

.sueg-lb-close {
	top: 22px;
	right: 22px;
}

.sueg-lb-close::before,
.sueg-lb-close::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 18px;
	height: 2px;
	background: currentColor;
}

.sueg-lb-close::before {
	transform: translate(-50%, -50%) rotate(45deg);
}

.sueg-lb-close::after {
	transform: translate(-50%, -50%) rotate(-45deg);
}

.sueg-lb-prev {
	left: 22px;
	top: 50%;
	transform: translateY(-50%);
}

.sueg-lb-next {
	right: 22px;
	top: 50%;
	transform: translateY(-50%);
}

.sueg-lb-prev::before,
.sueg-lb-next::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 12px;
	height: 12px;
	border-top: 2px solid currentColor;
	border-right: 2px solid currentColor;
}

.sueg-lb-prev::before {
	transform: translate(-30%, -50%) rotate(-135deg);
}

.sueg-lb-next::before {
	transform: translate(-70%, -50%) rotate(45deg);
}

.sueg-lb-counter {
	position: absolute;
	top: 30px;
	left: 26px;
	color: rgba(255, 255, 255, 0.7);
	font-size: 0.85rem;
	font-variant-numeric: tabular-nums;
}

@media screen and (max-width: 767px) {
	.sueg-lb-prev,
	.sueg-lb-next {
		top: auto;
		bottom: 18px;
		transform: none;
	}

	.sueg-lb-stage {
		height: min(74vh, 900px);
	}

	.sueg-lb-cap {
		bottom: -3.6em;
	}
}

@media (prefers-reduced-motion: reduce) {
	.sueg-lb,
	/* Listed explicitly: `.sueg-lb.is-open` outranks a bare `.sueg-lb`, so
	   without this the open state would keep its transition here. */
	.sueg-lb.is-open,
	.sueg-lb-img {
		transition: none;
	}
}

/* Stops the page behind scrolling while the lightbox is open. Set on <html> so
   it survives themes that put their own overflow rules on <body>. */
html.sueg-lb-open {
	overflow: hidden;
}
