/* ---------------------------------------------------------------
   Video in place of the first slide of the Savoy product gallery.

   Two shapes of behaviour:

   .svfi-fit-cover
   .svfi-fit-contain - the video is pinned over the featured image, so it
                      inherits that image's shape exactly (square photos give
                      a square video) and the page layout never changes.
                      Cover crops to fill; contain shows the whole frame.
   .svfi-fit-video   - the slide takes the video's own shape instead. The
                      featured image is pulled out of the flow so it can't
                      fight it, and the gallery height follows the video.
   --------------------------------------------------------------- */
.woocommerce-product-gallery__image.svfi-has-video {
	position: relative;
	overflow: hidden;
	border-radius: var(--nm--border-radius-image, 0);
}

.svfi-video {
	background-color: #000;
	overflow: hidden;
	border-radius: var(--nm--border-radius-image, 0);
}

/* ------------------------------------------------------------------
   Video-shaped slide: an in-flow box sized by aspect-ratio, so the slide
   (and therefore the gallery) is exactly as tall as the video needs.
   --svfi-ratio is written into the HTML server-side.
   ------------------------------------------------------------------ */
.svfi-fit-video .svfi-video,
.svfi-no-image .svfi-video {
	position: relative;
	width: 100%;
	aspect-ratio: var(--svfi-ratio, 16 / 9);
}

/* The featured image still has to be in the DOM - it's the gallery
   thumbnail and the first lightbox image - but it must not contribute
   any height, so it's pulled out of the flow and hidden behind. */
.svfi-fit-video > a,
.svfi-fit-video > img,
.svfi-fit-video > .woocommerce-product-gallery__image__placeholder {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: auto;
	opacity: 0;
	pointer-events: none;
}

/* Old browsers without aspect-ratio: fall back to 16/9 padding. */
@supports not ( aspect-ratio: 1 / 1 ) {
	.svfi-fit-video .svfi-video,
	.svfi-no-image .svfi-video {
		height: 0;
		padding-bottom: 100%; /* square; the JS corrects it from the video */
	}
}

/* ------------------------------------------------------------------
   Cover / contain: overlay pinned to the image's box.
   ------------------------------------------------------------------ */
.svfi-fit-cover .svfi-video,
.svfi-fit-contain .svfi-video {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 5; /* above EasyZoom's flyout and the lightbox link */
}

/* ------------------------------------------------------------------
   The player itself fills whichever box it was given.
   ------------------------------------------------------------------ */
.svfi-video .svplite-wrap,
.svfi-video .plyr,
.svfi-video .plyr__video-wrapper {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	margin: 0;
	padding-bottom: 0 !important; /* Plyr writes its ratio padding inline */
	aspect-ratio: auto !important; /* ...and adds a fixed-ratio class */
	background: transparent;
}

/* Sites often pin Plyr to a fixed width in Additional CSS to tame a player
   embedded in the product description, e.g.

     body.single-product .plyr--video { width: 300px; }

   That selector also catches the gallery player and leaves it stranded in a
   black box. Match its specificity (and beat it on cascade order, since this
   stylesheet loads after the Customizer's) so the gallery player always fills
   its slide, whatever the site CSS says. A width set on the player in the
   description tab still applies there. */
body.single-product .svfi-video .plyr,
body.single-product .svfi-video .plyr--video,
body .svfi-video .svplite-wrap {
	width: 100% !important;
	min-width: 0 !important;
	max-width: none !important;
}

/* The video element has to fill the box exactly, or object-fit has nothing
   to crop. Two other rules are competing for it and both are more specific
   than a plain `.svfi-video video`:

     .svplite-wrap .svplite-video { height: auto }   (the player plugin)
     .plyr video                  { height: 100% }   (Plyr)

   So match the player plugin's own selector and mark the sizing important -
   that way it holds no matter which stylesheet loads first, and it survives
   an update to either of them. */
.svfi-video .svplite-wrap .svplite-video,
.svfi-video .plyr video,
.svfi-video video {
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	max-height: none !important;
	object-position: center center;
}

.svfi-video .plyr__poster {
	width: 100%;
	height: 100%;
}

/* In video mode the box already matches the video, so cover only ever
   trims a rounding error rather than real picture. */
.svfi-video[data-fit="video"] .svplite-wrap .svplite-video,
.svfi-video[data-fit="video"] .plyr video,
.svfi-video[data-fit="video"] video,
.svfi-video[data-fit="cover"] .svplite-wrap .svplite-video,
.svfi-video[data-fit="cover"] .plyr video,
.svfi-video[data-fit="cover"] video {
	object-fit: cover !important;
}

.svfi-video[data-fit="video"] .plyr__poster,
.svfi-video[data-fit="cover"] .plyr__poster {
	background-size: cover !important;
}

.svfi-video[data-fit="contain"] .svplite-wrap .svplite-video,
.svfi-video[data-fit="contain"] .plyr video,
.svfi-video[data-fit="contain"] video {
	object-fit: contain !important;
}

.svfi-video[data-fit="contain"] .plyr__poster {
	background-size: contain !important;
}

/* Savoy's hover zoom must not float over the player. */
.svfi-has-video .easyzoom-flyout,
.svfi-has-video .easyzoom-notice {
	display: none !important;
}

.svfi-has-video > a {
	cursor: default !important;
}

/* ------------------------------------------------------------------
   Reshaping between the video's shape and the photos' shape.

   Savoy positions every gallery slide absolutely except the first, so the
   first slide alone decides how tall the wrapper is. With the video in that
   slot the gallery is stuck at the video's height forever - measuring slides
   in JS and re-setting the height each time fights that instead of fixing it.

   So the wrapper gets an explicit height of its own: zero height plus a
   percentage `padding-bottom`, which resolves against the wrapper's WIDTH and
   therefore behaves exactly like an aspect ratio. Which percentage applies is
   chosen by :has() - the video's while the video slide is showing, the
   photos' otherwise - and percentages animate, so the change eases.

   No measuring, no observers, no timing. The browser does all of it.
   ------------------------------------------------------------------ */
.svfi-gallery-reshape .woocommerce-product-gallery__wrapper {
	position: relative;
	overflow: hidden;
	/* Starts on the video's shape, because the video is slide one. */
	height: 0 !important; /* beats the inline height Savoy's JS writes */
	padding-bottom: var( --svfi-pad-video, 100% );

	/* This element is also FlexSlider's slide track - the one it translates
	   left and right. FlexSlider sets only `transition-duration` inline and
	   lets `transition-property` fall back to `all`, so declaring a shorthand
	   here would narrow that list to padding-bottom alone and strip the
	   sliding animation. Naming `transform` too keeps the slide intact, and
	   FlexSlider's inline duration still drives both - which is what we want:
	   the reshape runs exactly when, and for as long as, a slide change does. */
	transition-property: padding-bottom, transform;
	transition-duration: var( --svfi-reshape-speed, 300ms );
	transition-timing-function: ease;
}

/* A photo is showing: take the photos' shape. The class is the fallback for
   browsers without :has(), set by gallery-video.js. */
.svfi-gallery-reshape .woocommerce-product-gallery__wrapper:has( > .woocommerce-product-gallery__image.flex-active-slide:not( .svfi-fit-video ) ),
.svfi-gallery-reshape .woocommerce-product-gallery__wrapper.svfi-photo-active {
	padding-bottom: var( --svfi-pad-image, 100% );
}

/* The slides sit inside that box rather than defining it. */
.svfi-gallery-reshape .woocommerce-product-gallery__image:first-child {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
}

/* Reshaping changes the wrapper's box on every frame, which means layout, not
   just compositing. Containment stops that work spilling into the slides and
   the player while the gallery is moving. */
.svfi-gallery-reshape .woocommerce-product-gallery__wrapper {
	contain: layout;
}

@media ( prefers-reduced-motion: reduce ) {
	.svfi-gallery-reshape .woocommerce-product-gallery__wrapper {
		transition-duration: 0s;
	}
}
