/**
 * Fullscreen gallery lightbox for variable products (konte-child).
 *
 * Layout: vertical thumbnail column on the left, active image in the main
 * stage, thin close button top-right, position counter bottom-centre.
 * Matches the supplied Ralph Lauren-style reference.
 */

/* Lock background scroll while the lightbox is open. */
body.kvl-open {
	overflow: hidden;
}

.kvl-overlay {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	background: #ffffff;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}

.kvl-overlay.is-active {
	opacity: 1;
	visibility: visible;
	transition: opacity 0.25s ease;
}

/* Left thumbnail rail ---------------------------------------------------- */
.kvl-thumbs {
	flex: 0 0 96px;
	width: 96px;
	max-height: 100%;
	overflow-y: auto;
	overflow-x: hidden;
	padding: 24px 8px 24px 16px;
	box-sizing: border-box;
	scrollbar-width: thin;
	scrollbar-color: rgba(0, 0, 0, 0.35) transparent;
}

.kvl-thumb {
	display: block;
	width: 64px;
	margin: 0 0 12px;
	padding: 0;
	border: 1px solid transparent;
	background: none;
	cursor: pointer;
	border-radius: 2px;
	overflow: hidden;
	transition: border-color 0.2s ease, opacity 0.2s ease;
	opacity: 0.7;
}

.kvl-thumb:last-child {
	margin-bottom: 0;
}

.kvl-thumb img {
	display: block;
	width: 100%;
	height: auto;
}

/* Marks a thumbnail whose slide is a video. Same triangle as the grid's play
   badge, so the two read as one language. */
.kvl-thumb--video {
	position: relative;
}

.kvl-thumb-video {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	display: flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	border: 1px solid #ffffff;
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.45);
	color: #ffffff;
	pointer-events: none;
}

.kvl-thumb-video svg {
	display: block;
	width: 11px;
	height: 11px;
	/* Nudge the triangle so it reads as centred inside the circle. */
	margin-left: 1px;
}

.kvl-thumb:hover,
.kvl-thumb:focus-visible {
	opacity: 1;
	outline: none;
}

.kvl-thumb.is-active {
	opacity: 1;
	border-color: var(--ink_text);
}

/* Mobile swipe carousel (built by JS, shown only on mobile — see the media
   query below). Hidden on desktop, where the single-image stage is used. */
.kvl-track {
	display: none;
}

/* Main stage ------------------------------------------------------------- */
.kvl-stage {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
	overflow-y: auto;
	overflow-x: hidden;
	scroll-behavior: smooth;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
	scrollbar-width: thin;
	scrollbar-color: rgba(0, 0, 0, 0.35) transparent;
}

.kvl-stage::-webkit-scrollbar {
	width: 6px;
}

.kvl-stage::-webkit-scrollbar-thumb {
	background: rgba(0, 0, 0, 0.3);
	border-radius: 4px;
}

.kvl-stage::-webkit-scrollbar-track {
	background: transparent;
}

.kvl-stage-inner {
	display: flex;
	justify-content: center;
	align-items: flex-start;
	min-height: 100%;
	padding: 24px 24px 64px;
	box-sizing: border-box;
}

.kvl-main-img {
	display: block;
	max-width: min(820px, 92%);
	width: auto;
	height: auto;
	margin: 0 auto;
	opacity: 1;
	transition: opacity 0.3s ease, transform 0.35s ease;
	transform-origin: center center;
	/* Zoom-in magnifier cursor (matches existing inline-grid zoom cursor). */
	cursor: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270%200%2024%2024%27%3E%3Ccircle cx=%2710%27 cy=%2710%27 r=%276.5%27 fill=%27white%27 fill-opacity=%270.9%27 stroke=%27%23161619%27 stroke-width=%271.5%27/%3E%3Cpath d=%27M10%207v6M7%2010h6%27 stroke=%27%23161619%27 stroke-width=%271.5%27 stroke-linecap=%27round%27/%3E%3Cpath d=%27M15.2%2015.2L20%2020%27 stroke=%27%23161619%27 stroke-width=%271.5%27 stroke-linecap=%27round%27/%3E%3C/svg%3E") 12 12, zoom-in;
	-webkit-user-drag: none;
	user-select: none;
}

.kvl-main-img.is-fading {
	opacity: 0;
}

/* A video slide replaces the stage image with a player rather than swapping its
   src, so the persistent <img> steps out of the flow entirely. */
.kvl-main-img.is-hidden {
	display: none;
}

/* Video slides ----------------------------------------------------------- *
 * Contained, never cropped: unlike a photo — where cover-cropping the edges of
 * a portrait shot costs nothing — a clip is composed to be seen whole, and this
 * is the view the shopper opened deliberately. The player therefore letterboxes
 * against the slide instead of filling it.
 *
 * The plugin's own .svi-updated-video class (absolute, inset:0, object-fit:cover)
 * is removed from the node when it is mounted here — see mountVideo() — so these
 * rules do not have to out-specify it.
 * ------------------------------------------------------------------------ */
.kvl-video {
	display: block;
	max-width: 100%;
	/* Viewport units, not 100%: .kvl-stage-inner has min-height rather than a
	   definite height, so a percentage max-height there resolves to none and a
	   tall clip would overflow into the stage's scroll — the one thing "shown
	   whole" must not do. (A photo overflowing and scrolling is deliberate; a
	   video running past the fold is not.) */
	max-height: 100vh;
	width: auto;
	height: auto;
	/* Auto margins absorb the free space in both axes, so the player centres in
	   the stage even though .kvl-stage-inner aligns its items to flex-start. */
	margin: auto;
	background: #000000;
	outline: none;
}

/* An embed (YouTube/Vimeo) is an iframe inside a wrapper, and the plugin's
   iframe rule positions it against that wrapper — so unlike a <video>, which
   carries its own intrinsic size, the wrapper needs an explicit box. */
.kvl-video.svi-updated-video-embed {
	position: relative;
	width: min(100%, 1280px);
	aspect-ratio: 16 / 9;
	max-height: 100%;
}

.kvl-main-img.is-zoomed {
	max-width: none;
	transform: scale(1.6);
	cursor: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270%200%2024%2024%27%3E%3Ccircle cx=%2710%27 cy=%2710%27 r=%276.5%27 fill=%27white%27 fill-opacity=%270.9%27 stroke=%27%23161619%27 stroke-width=%271.5%27/%3E%3Cpath d=%27M7%2010h6%27 stroke=%27%23161619%27 stroke-width=%271.5%27 stroke-linecap=%27round%27/%3E%3Cpath d=%27M15.2%2015.2L20%2020%27 stroke=%27%23161619%27 stroke-width=%271.5%27 stroke-linecap=%27round%27/%3E%3C/svg%3E") 12 12, zoom-out;
}

/* Close button (thin X, top-right) -------------------------------------- */
.kvl-close {
	position: absolute;
	top: 18px;
	right: 22px;
	width: 40px;
	height: 40px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--ink_text);
	font-size: 26px;
	line-height: 40px;
	text-align: center;
	cursor: pointer;
	z-index: 3;
	transition: opacity 0.2s ease;
	opacity: 0.85;
}

.kvl-close:hover,
.kvl-close:focus-visible {
	opacity: 1;
	outline: none;
}

/* Position counter (bottom-centre) -------------------------------------- */
.kvl-counter {
	position: absolute;
	left: 50%;
	bottom: 22px;
	transform: translateX(-50%);
	z-index: 3;
	font-size: 13px;
	letter-spacing: 0.04em;
	color: var(--ink_text);
	background: rgba(255, 255, 255, 0.85);
	padding: 6px 14px;
	border-radius: 999px;
	pointer-events: none;
}

/* Mobile progress indicator (dots + active pill) ------------------------- */
/* Base: hidden on desktop, so crossing the 992px breakpoint needs no JS. */
.kvl-dots {
	display: none;
}

/* Mobile tap-to-zoom affordance. Base: hidden on desktop (which advertises
   zoom with a magnifier cursor instead) and hidden once used, so crossing the
   992px breakpoint needs no JS. Shown by the mobile block below. */
.kvl-zoom-hint,
.kvl-zoom-hint.is-hidden {
	display: none;
}

/* Responsive ------------------------------------------------------------- */
/* Desktop lightbox: the photo runs edge-to-edge across the full viewport, with
   the thumbnail rail floating on top of it at the left (rather than sitting in
   a reserved column beside it). A portrait product photo is far taller than the
   viewport at that width, so only its upper part is in frame and the rest
   scrolls — .kvl-stage is already overflow-y:auto with align-items:flex-start,
   and setActive() resets stage scrollTop on every image swap. */
@media (min-width: 992px) {
	/* Out of the flex flow so .kvl-stage (flex:1 1 auto) can span the whole
	   viewport; the base `flex: 0 0 96px` is what reserved a column. .kvl-overlay
	   is position:fixed, so it is already the containing block. */
	.kvl-thumbs {
		position: absolute;
		top: 0;
		left: 0;
		bottom: 0;
		z-index: 2;
		max-height: none;
		/* Long image lists still scroll, but the bar would sit over the photo. */
		scrollbar-width: none;
	}

	.kvl-thumbs::-webkit-scrollbar {
		display: none;
	}

	/* Side/bottom gutters would hold the image off the viewport edges. */
	.kvl-stage-inner {
		padding: 0;
	}

	/* Replaces the max-width: min(820px, 92%) cap that left the image sitting as
	   a narrow centred column. height stays auto, so the aspect ratio holds and
	   the image simply becomes tall. */
	.kvl-main-img {
		width: 100%;
		max-width: 100%;
		margin: 0;
	}

	/* The X now overlays the photo instead of empty white margin, so it needs a
	   backing to stay legible over dark image areas. Square corners per the
	   design (the mobile rule below uses a pill). */
	.kvl-close {
		background: #ffffff;
	}

	/* No counter pill in the design. Hidden visually, not removed, so the
	   "N / N" position is still announced to assistive tech (same treatment the
	   mobile block applies). */
	.kvl-counter {
		width: 1px;
		height: 1px;
		padding: 0;
		margin: 0;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
		border: 0;
		background: none;
	}
}

/* Mobile lightbox: a native horizontal scroll-snap carousel (.kvl-track) in
   place of the single-image fade stage — drag-follows-finger with both images
   visible mid-swipe, instant open, no blank between images. The thumbnail rail
   and text counter are dropped for a full-bleed swipeable image with dots. */
@media (max-width: 991px) {
	.kvl-thumbs {
		display: none;
	}

	/* Replace the single-image fade stage with the swipe carousel on mobile. */
	.kvl-stage {
		display: none;
	}

	.kvl-track {
		/* Magnification applied on tap, relative to the 1x height the image
		   occupies. Declared once here and consumed by .kvl-slide.is-zoomed img
		   below; konte-variable-lightbox.js reads no zoom factor of its own —
		   it derives the pan offsets by measuring the zoomed box. */
		--kvl-zoom: 2.5;
		display: flex;
		width: 100%;
		height: 100%;
		overflow-x: auto;
		overflow-y: hidden;
		scroll-snap-type: x mandatory;
		/* auto, not smooth: the open-jump to the tapped image must be instant.
		   (.kvl-stage uses smooth; it must not leak onto the track.) */
		scroll-behavior: auto;
		overscroll-behavior-x: contain;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	.kvl-track::-webkit-scrollbar {
		display: none;
	}

	.kvl-slide {
		flex: 0 0 100%;
		scroll-snap-align: start;
		scroll-snap-stop: always;
		display: flex;
		align-items: center;
		justify-content: center;
		box-sizing: border-box;
	}

	.kvl-slide img {
		/* Fill the fullscreen slide edge-to-edge (like Mango). A portrait product
		   photo never matches a tall phone aspect, so cover scales it to fill and
		   crops the overflow (the sides here) — preserving aspect ratio, no
		   distortion. Needs a definite box (width/height:100%), not max-*, or
		   there is nothing to crop. */
		width: 100%;
		height: 100%;
		object-fit: cover;
		object-position: center;
		user-select: none;
		-webkit-user-drag: none;
		/* Zoom is a discrete state change, not something to animate: the geometry
		   swaps from a cover-fit box to a 2.5x intrinsic-ratio one, and JS sets
		   the pan offsets in the same frame. Transitioning it would fight that. */
		cursor: zoom-in;
	}

	/* Video slides. Must come AFTER the .kvl-slide img rule above: both selectors
	   score the same, so source order is what decides — and cover-cropping the
	   poster behind a letterboxed player showed a *different* framing of the photo
	   in the bars above and below it. */
	.kvl-slide--video {
		position: relative;
		background: #000000;
	}

	/* The poster is the same frame the player fills, so it is invisible once the
	   player mounts — and while the slide is only being swiped towards, it shows
	   the whole photo instead of a crop the video is about to replace. */
	.kvl-slide--video img {
		object-fit: contain;
		cursor: default;
	}

	/* Once the player is up the poster has done its job. Hidden rather than
	   removed: photo and clip are letterboxed independently, so unless their
	   aspect ratios match exactly a sliver of the photo shows past the player's
	   edges — which reads as a rendering fault, not as a poster. */
	.kvl-slide--video.kvl-has-player img {
		visibility: hidden;
	}

	/* Laid over the poster, which stays in flow so the slide still paints
	   instantly while it is being swiped towards (its player is only mounted once
	   it becomes the active slide). inset:0 + auto margins is what centres a
	   replaced element of intrinsic size; the size caps come from .kvl-video. */
	.kvl-slide .kvl-video {
		position: absolute;
		inset: 0;
		z-index: 1;
		/* The slide is a definite box here, so a percentage cap is exact — and
		   safer than 100vh, which mobile browsers measure against the viewport
		   *without* the address bar. */
		max-height: 100%;
	}

	/* Tap-to-zoom ---------------------------------------------------------- *
	 * The zoomed slide becomes its own scroll container in both axes, so panning
	 * is the browser's native inertial scroll — no touchmove handlers, no
	 * preventDefault. konte-variable-lightbox.js only toggles the classes and
	 * sets the initial scroll offsets.
	 * ---------------------------------------------------------------------- */
	.kvl-slide.is-zoomed {
		overflow: auto;
		/* Load-bearing. Without it, a pan that reaches the image's left/right
		   edge chains to .kvl-track and flips to the next image mid-gesture. */
		overscroll-behavior: contain;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		/* `safe` keeps an image narrower than the viewport centred without the
		   flex overflow-unreachable bug. Browsers without safe alignment fall
		   back to plain center, which only matters for images that do not
		   overflow — and at 2.5x a product photo always does. */
		justify-content: safe center;
		align-items: safe center;
	}

	.kvl-slide.is-zoomed::-webkit-scrollbar {
		display: none;
	}

	.kvl-slide.is-zoomed img {
		/* height + auto width renders the img at its intrinsic aspect ratio, so
		   the whole frame is present (nothing cropped) and it is --kvl-zoom times
		   the height it occupied under `cover`. One rule delivers both the
		   magnification and the areas `cover` cut off at 1x. */
		flex: none;
		width: auto;
		height: calc(100% * var(--kvl-zoom, 2.5));
		max-width: none;
		object-fit: fill; /* inert: the box already matches the intrinsic ratio */
		cursor: zoom-out;
	}

	/* Suspend snapping while zoomed so the outer carousel cannot re-snap during
	   a pan. Does not touch scrollLeft, so the carousel resumes on the same
	   slide. Deliberately NOT `touch-action: none` here — touch-action is
	   intersected up the ancestor chain, which would also kill panning inside
	   the zoomed slide. */
	.kvl-track.is-zoomed {
		scroll-snap-type: none;
	}

	/* Zoom affordance: without it the capability is invisible (the desktop stage
	   advertises itself with a magnifier cursor, which a phone has no equivalent
	   of). Reuses the .kvl-counter pill treatment. Removed for good once the
	   shopper has zoomed once in this page view. */
	.kvl-zoom-hint {
		position: absolute;
		right: 14px;
		bottom: 16px;
		z-index: 3;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 34px;
		height: 34px;
		border-radius: 999px;
		background: rgba(255, 255, 255, 0.85);
		color: var(--ink_text);
		pointer-events: none;
		opacity: 1;
		transition: opacity 0.25s ease;
	}

	.kvl-zoom-hint svg {
		display: block;
		width: 17px;
		height: 17px;
	}

	/* A video slide does not zoom, so the affordance must not advertise it. Not
	   .is-hidden: that one is permanent, this comes back on the next photo. */
	.kvl-zoom-hint.kvl-hint-off {
		display: none;
	}

	.kvl-close {
		top: 12px;
		right: 12px;
		/* Subtle backing so the X stays legible over dark image areas. */
		background: rgba(255, 255, 255, 0.85);
		/*border-radius: 999px;*/
	}

	/* Keep the position readout for assistive tech, but hide it visually — the
	   dots replace it on screen. */
	.kvl-counter {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
		border: 0;
		background: none;
	}

	.kvl-dots {
		display: flex;
		position: absolute;
		left: 50%;
		bottom: 18px;
		transform: translateX(-50%);
		align-items: center;
		gap: 6px;
		z-index: 3;
		pointer-events: none;
	}

	/* Dark markers: the lightbox background is white, so the PDP carousel's
	   white markers would be invisible here. */
	.kvl-dot {
		display: block;
		width: 6px;
		height: 6px;
		border-radius: 999px;
		background: rgba(22, 22, 25, 0.28);
		transition: width 0.25s ease, background-color 0.25s ease;
	}

	.kvl-dot.is-active {
		width: 18px;
		background: var(--ink_text);
	}

	/* Which slide is the video, for a shopper deciding whether to keep swiping.
	   Slightly larger with a play triangle inside; it still grows into the same
	   active pill, so the rhythm of the row is unchanged. */
	.kvl-dot--video,
	.kvl-dot--video.is-active {
		/* The image is repeated in both rules on purpose: .kvl-dot.is-active sets
		   `background` as a shorthand, which resets background-image to none. */
		background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M8 5v14l11-7z%27 fill=%27white%27/%3E%3C/svg%3E");
		background-repeat: no-repeat;
		background-position: 55% center;
		background-size: 6px 6px;
	}

	.kvl-dot--video {
		width: 10px;
		height: 10px;
		background-color: rgba(22, 22, 25, 0.45);
	}

	.kvl-dot--video.is-active {
		width: 18px;
		background-color: var(--ink_text);
	}
}

/* Respect reduced-motion preferences. */
@media (prefers-reduced-motion: reduce) {
	.kvl-overlay,
	.kvl-main-img,
	.kvl-stage,
	.kvl-dot,
	.kvl-zoom-hint {
		transition: none;
		scroll-behavior: auto;
	}
}
