/* ==========================================================================
   YB Product Showcase - base structural CSS.
   All colors/sizes/spacing come from Elementor controls 
   ========================================================================== */

.ybsb-showcase-wrapper {
	position: relative;
	width: 100%;
	overflow: hidden;
	background-color: #1a1a1a;
	isolation: isolate;
}

/* Stacking order. Cards get their z-index set dynamically by the
   animation script (1-3 range, so a growing/shrinking card can cross
   above or below its resting siblings). Thumbnail titles live INSIDE
   their card (see .ybsb-showcase-card-label) so they stack above
   their own card's image automatically via DOM order and need no
   z-index of their own. Everything below is a fixed layer sitting
   above that whole range, so the dim overlay, rich text panel, and
   nav controls always stay above the imagery no matter which card is
   mid-transition, and the intro cover sits above everything. */
.ybsb-showcase-overlay   { z-index: 4; }
.ybsb-showcase-contents  { z-index: 6; }
.ybsb-showcase-nav-wrap  { z-index: 7; }
.ybsb-showcase-intro-cover { z-index: 20; }

.ybsb-showcase-overlay {
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	/* Clipped short of the thumbnail rail (see render(), which sets
	   --ybsb-overlay-clip from the same width the rail itself uses)
	   so the gradient's own fade-to-transparent finishes inside this
	   narrower box - no separate transition needed, the boundary is
	   already invisible because opacity is 0 by the time it gets
	   there. */
	width: calc( 100% - var( --ybsb-overlay-clip, 0px ) );
	pointer-events: none;
}

/* ---- Cards ----
   Both the fullscreen hero image AND the thumbnails are the same
   elements - the animation script (GSAP) tweens each one's position,
   size, and border-radius between its thumbnail slot and the
   fullscreen position, exactly like the reference. CSS only supplies
   the parts GSAP doesn't touch: background image and shadow. */

.ybsb-showcase-cards {
	/* Deliberately NOT position:relative - so .ybsb-showcase-card's
	   position:absolute resolves against the wrapper (the nearest
	   positioned ancestor), matching the coordinate space the
	   animation script measures against. */
}

.ybsb-showcase-card {
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	background-color: transparent;
	will-change: left, top, width, height;
}

.ybsb-showcase-card-bg {
	position: absolute;
	inset: 0;
	background-size: cover;
	background-position: center center;
	background-repeat: no-repeat;
	filter: contrast(var(--ybsb-img-contrast, 100%)) saturate(var(--ybsb-img-saturate, 100%));
}

/* ---- Portrait photo handling ----
   A taller-than-wide source photo forced to "cover" this wide
   fullscreen frame gets scaled up until it fills the width, cropping
   away most of the top and bottom. In the thumbnail rail this isn't
   a problem - the thumbnail box itself is portrait-shaped, so a
   plain cover crop already fills it correctly - so this treatment
   only ever applies while a card is fullscreen (marked by JS via
   .ybsb-showcase-card--fullscreen, see markFullscreen() in the JS).
   When Blurred Fill is on and a card's photo is detected as portrait
   server-side (see render_card()), the fullscreen card gets a second
   background layer behind the main one: a blurred, zoomed copy that
   fills the frame, while the foreground image switches to "contain"
   so the full photo shows uncropped on top of it, letterboxed rather
   than cropped. */
.ybsb-showcase-card-bg-blur {
	position: absolute;
	inset: 0;
	background-size: cover;
	background-position: center center;
	background-repeat: no-repeat;
	filter: blur(30px) brightness(0.7) contrast(var(--ybsb-img-contrast, 100%)) saturate(var(--ybsb-img-saturate, 100%));
	transform: scale(1.15);
	opacity: 0;
}

.ybsb-showcase-card--portrait.ybsb-showcase-card--fullscreen .ybsb-showcase-card-bg-blur {
	opacity: 1;
}

.ybsb-showcase-card--portrait.ybsb-showcase-card--fullscreen .ybsb-showcase-card-bg {
	background-size: contain;
}

/* ---- Card labels (thumbnail titles) ----
   Lives INSIDE its card (see PHP render_card()), so it fills the
   card completely via inset:0 and simply inherits whatever
   position/size the animation script gives the card itself - it only
   ever needs its own opacity tweened to fade out while its card is
   fullscreen. (It previously received its own x/y/width/height tween
   on top of its parent's, which double-applied the offset and pushed
   it outside the card's clipped bounds - that's why titles were
   invisible.) */

.ybsb-showcase-card-label {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-end;
	box-sizing: border-box;
	padding: 14px;
	pointer-events: none;
	background: transparent;
	border-radius: inherit;
	overflow: hidden;
	will-change: opacity;
}

/* Optional bottom-up darkening gradient behind the title, independent
   of the title's own text-shadow - toggled by the "Darken Behind
   Title" control. Sits behind the title in DOM order so the text
   always paints on top of it. */
.ybsb-showcase-card-label-scrim {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 65%;
	pointer-events: none;
}

.ybsb-showcase-card-label-marker {
	position: relative;
	height: 3px;
	width: 30px;
	margin-bottom: 8px;
	border-radius: 2px;
	background-color: #ffffff;
	flex-shrink: 0;
}

.ybsb-showcase-card-label-title {
	position: relative;
	font-weight: 700;
	text-transform: uppercase;
	line-height: 1.15;
}

/* ---- Content (text + buttons) - separate layer from the images ---- */

.ybsb-showcase-contents {
	position: absolute;
	inset: 0;
	pointer-events: none;
}

.ybsb-showcase-content {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
	opacity: 0;
	visibility: hidden;
	transition-property: opacity, visibility;
	transition-duration: 0.4s;
	transition-timing-function: ease-out;
	padding: 60px;
	box-sizing: border-box;
	/* Transparent box the size of the whole slide - stays
	   click-through so it never blocks the thumbnail rail
	   underneath. Only the actual interactive children (buttons)
	   re-enable pointer events on themselves. */
	pointer-events: none;
}

.ybsb-showcase-content.ybsb-showcase-content-active {
	opacity: 1;
	visibility: visible;
}

/* ---- Text entry: each line/element fades in and rises slightly,
   sliding in from the left, staggered in DOM order (eyebrow, title,
   price, chips, description, buttons). ---- */
.ybsb-showcase-content > * {
	opacity: 0;
	transform: translate(-32px, 18px);
	transition-property: opacity, transform;
	transition-duration: 0.7s;
	transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

.ybsb-showcase-content.ybsb-showcase-content-active > * {
	opacity: 1;
	transform: translate(0, 0);
}

.ybsb-showcase-content.ybsb-showcase-content-active > *:nth-child(1) { transition-delay: 0.05s; }
.ybsb-showcase-content.ybsb-showcase-content-active > *:nth-child(2) { transition-delay: 0.15s; }
.ybsb-showcase-content.ybsb-showcase-content-active > *:nth-child(3) { transition-delay: 0.25s; }
.ybsb-showcase-content.ybsb-showcase-content-active > *:nth-child(4) { transition-delay: 0.35s; }
.ybsb-showcase-content.ybsb-showcase-content-active > *:nth-child(5) { transition-delay: 0.45s; }
.ybsb-showcase-content.ybsb-showcase-content-active > *:nth-child(6) { transition-delay: 0.55s; }

.ybsb-showcase-category {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	width: fit-content;
}

.ybsb-showcase-category-marker {
	height: 4px;
	width: 30px;
	border-radius: 99px;
	margin-bottom: 14px;
	flex-shrink: 0;
}

.ybsb-showcase-title-wrap {
	overflow: hidden;
}

.ybsb-showcase-title {
	margin: 0;
	line-height: 1.05;
}

.ybsb-showcase-price {
	width: fit-content;
	line-height: 1.2;
}

.ybsb-showcase-price del {
	font-weight: 400;
	margin-right: 8px;
	opacity: 0.6;
	text-decoration: line-through;
}

.ybsb-showcase-price ins {
	text-decoration: none;
}

.ybsb-showcase-chips {
	display: flex;
	flex-wrap: wrap;
}

.ybsb-showcase-chip {
	display: inline-flex;
	align-items: center;
	white-space: nowrap;
	line-height: 1;
}

.ybsb-showcase-description {
	margin: 0;
}

/* ---- Buttons row  ---- */

.ybsb-showcase-buttons {
	display: flex;
	align-items: stretch;
	pointer-events: auto;
}

.ybsb-showcase-icon-button {
	flex-shrink: 0;
	background-color: #1a1a1a;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-decoration: none;
	position: relative;
	transition-property: background-color, color;
	transition-timing-function: ease-in-out;
}

.ybsb-showcase-icon-button.ybsb-showcase-style-icon_only {
	flex-direction: row;
}

.ybsb-showcase-icon-button.ybsb-showcase-style-text_icon {
	width: auto;
	height: auto;
	white-space: nowrap;
}

.ybsb-showcase-btn-text {
	position: relative;
	z-index: 1;
	line-height: 1;
	transition: color var(--ybsb-btn-hover-duration, 300ms) ease-in-out;
}

.ybsb-showcase-icon-button-icon {
	display: inline-flex;
	align-items: center;
	line-height: 1;
	position: relative;
	z-index: 1;
	color: #ffffff;
	transition: transform var(--ybsb-btn-hover-duration, 300ms) ease-in-out;
}

.ybsb-showcase-icon-button.ybsb-showcase-icon-hover-grow:hover .ybsb-showcase-icon-button-icon {
	transform: scale(var(--ybsb-icon-hover-scale, 1.25));
}

.ybsb-showcase-icon-button.ybsb-showcase-icon-hover-rotate:hover .ybsb-showcase-icon-button-icon {
	transform: rotate(var(--ybsb-icon-hover-rotate, 90deg));
}

.ybsb-showcase-icon-button-icon svg,
.ybsb-showcase-icon-button-icon i {
	display: block;
}

.ybsb-showcase-icon-button-icon svg {
	fill: #ffffff;
	width: 18px;
	height: 18px;
}

.ybsb-showcase-icon-button-icon i {
	font-size: 18px;
}

.ybsb-showcase-icon-button[data-tooltip] {
	position: relative;
}

.ybsb-showcase-icon-button[data-tooltip]::after {
	content: attr(data-tooltip);
	position: absolute;
	bottom: calc(100% + 8px);
	left: 50%;
	transform: translateX(-50%) translateY(4px);
	background-color: #1a1a1a;
	color: #ffffff;
	font-size: 12px;
	line-height: 1.4;
	white-space: nowrap;
	padding: 6px 10px;
	border-radius: 4px;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0.2s;
	z-index: 10;
}

.ybsb-showcase-icon-button[data-tooltip]:hover::after,
.ybsb-showcase-icon-button[data-tooltip]:focus-visible::after {
	opacity: 1;
	visibility: visible;
	transform: translateX(-50%) translateY(0);
	transition: opacity 0.2s ease, transform 0.2s ease;
}

/* Slide-sweep hover mechanic - identical to the Grid widget's buttons.
   Uses an animatable clip-path reveal on a box that stays at its
   true full size the whole time, rather than scaling the box itself
   from 0. Scaling a box that carries a large border-radius shrinks
   its rendered width/height while the radius stays a fixed pixel
   value, so at small scale factors the corners become
   disproportionately round - the box reads as a rounded pill "flying
   in" instead of a flat color wipe, worse the larger the radius.
   clip-path progressively reveals the real, correctly-rounded box
   instead of resizing it, so the corners are always correct - and
   unlike a translateX/Y version of the same fix, it needs no
   overflow:hidden on the button (which would otherwise clip the
   tooltip above, positioned outside the button's own box). */
.ybsb-showcase-icon-button[class*="ybsb-showcase-slide-"]::before {
	content: '';
	position: absolute;
	inset: 0;
	background-color: var(--ybsb-btn-slide-color, transparent);
	border-radius: inherit;
	z-index: 0;
	transition: clip-path var(--ybsb-btn-hover-duration, 300ms) ease-in-out;
}

.ybsb-showcase-icon-button.ybsb-showcase-slide-left::before {
	clip-path: inset( 0 100% 0 0 );
}
.ybsb-showcase-icon-button.ybsb-showcase-slide-left:hover::before {
	clip-path: inset( 0 0 0 0 );
}

.ybsb-showcase-icon-button.ybsb-showcase-slide-right::before {
	clip-path: inset( 0 0 0 100% );
}
.ybsb-showcase-icon-button.ybsb-showcase-slide-right:hover::before {
	clip-path: inset( 0 0 0 0 );
}

.ybsb-showcase-icon-button.ybsb-showcase-slide-top::before {
	clip-path: inset( 0 0 100% 0 );
}
.ybsb-showcase-icon-button.ybsb-showcase-slide-top:hover::before {
	clip-path: inset( 0 0 0 0 );
}

.ybsb-showcase-icon-button.ybsb-showcase-slide-bottom::before {
	clip-path: inset( 100% 0 0 0 );
}
.ybsb-showcase-icon-button.ybsb-showcase-slide-bottom:hover::before {
	clip-path: inset( 0 0 0 0 );
}


.ybsb-showcase-nav-wrap {
	position: absolute;
	right: 60px;
	bottom: 40px;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	opacity: 0;
	transform: translate(40px, 24px);
	transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1), transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
	transition-delay: 0.15s;
}

.ybsb-showcase-wrapper.ybsb-showcase-revealed .ybsb-showcase-nav-wrap {
	opacity: 1;
	transform: translate(0, 0);
}

/* ---- Intro cover ----
   Plain white panel over the whole slider on first load. JS adds
   .ybsb-showcase-revealed on the next animation frame after the
   initial (unanimated) layout is in place, which slides this cover
   away and, at the same time, brings the nav/text in from off-screen
   (see .ybsb-showcase-nav-wrap and .ybsb-showcase-content-active
   above). Never intercepts clicks, even mid-slide. */
.ybsb-showcase-intro-cover {
	position: absolute;
	inset: 0;
	background-color: #ffffff;
	pointer-events: none;
	transform: translateX(0);
	transition: transform 0.9s cubic-bezier(0.65, 0, 0.35, 1);
}

.ybsb-showcase-wrapper.ybsb-showcase-revealed .ybsb-showcase-intro-cover {
	transform: translateX(101%);
}

@media (prefers-reduced-motion: reduce) {
	.ybsb-showcase-intro-cover {
		transition-duration: 1ms;
	}
}

/* ---- Thumbnail rail anchor ----
   An empty placeholder that reserves the rail's footprint in the
   normal flex layout (bottom-right, above the nav-cluster row) so the
   animation script has a stable, CSS-positioned rectangle to measure
   via getBoundingClientRect() as the "home" position for thumbnail
   slot 0. The actual thumbnail cards live elsewhere in the DOM (see
   .ybsb-showcase-card / .ybsb-showcase-card-label) and are positioned
   with real pixel coordinates by the animation script - this element
   never shows anything itself. */
.ybsb-showcase-thumbnails {
	height: 300px;
}

/* ---- Autoplay timer bar (top edge of the whole slider) ---- */

.ybsb-showcase-timer-bar {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 5;
	overflow: hidden;
}

.ybsb-showcase-timer-fill {
	height: 100%;
	width: 0%;
}

/* JS toggles this class while the fill animates up to 100% over the
   autoplay duration; instant (no transition) when a slide changes so
   the bar doesn't visibly sweep backward first. */
.ybsb-showcase-timer-fill.ybsb-showcase-timer-animating {
	transition: width linear;
}

/* ---- Arrows + progress + counter row ---- */

.ybsb-showcase-nav-cluster {
	display: inline-flex;
	align-items: center;
}

.ybsb-showcase-arrow-group {
	display: inline-flex;
	align-items: center;
}

.ybsb-showcase-arrow {
	border: none;
	background: none;
	cursor: pointer;
	display: grid;
	place-items: center;
	padding: 0;
	box-sizing: border-box;
	transition: background-color 0.2s ease;
}

.ybsb-showcase-arrow svg,
.ybsb-showcase-arrow i {
	display: block;
	line-height: 1;
	fill: currentColor;
}

.ybsb-showcase-arrow-disabled {
	opacity: 0.35;
	pointer-events: none;
}

.ybsb-showcase-icon-button.ybsb-showcase-adding {
	opacity: 0.6;
	pointer-events: none;
}

.ybsb-showcase-icon-button.ybsb-showcase-added {
	opacity: 1;
}

/* Overall-progress bar (current slide ÷ total) - width changes in
   discrete steps as you navigate, so it gets a normal eased transition
   rather than the timer bar's linear autoplay-duration animation. */
.ybsb-showcase-progress-track {
	position: relative;
	overflow: hidden;
	flex-shrink: 0;
}

.ybsb-showcase-progress-fill {
	position: absolute;
	left: 0;
	top: 0;
	width: 0%;
	transition: width 0.4s ease;
}

.ybsb-showcase-counter {
	position: relative;
	overflow: hidden;
	flex-shrink: 0;
}

.ybsb-showcase-counter-track {
	position: relative;
	width: 100%;
	height: 100%;
}

.ybsb-showcase-counter-number {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	opacity: 0;
	transform: translateX(100%);
	transition-property: opacity, transform;
	transition-duration: 0.5s;
	transition-timing-function: ease-in-out;
}

.ybsb-showcase-counter-number.ybsb-showcase-counter-active {
	opacity: 1;
	transform: translateX(0);
}

/* Outgoing number on Next: slides/fades left, off toward the
   progress bar, while the incoming number (default state above,
   off-screen right) slides in to take its place - both are visible
   mid-crossing. */
.ybsb-showcase-counter-number.ybsb-showcase-counter-exit-left {
	opacity: 0;
	transform: translateX(-100%);
}

/* Outgoing number on Prev (mirror of the above): slides/fades right. */
.ybsb-showcase-counter-number.ybsb-showcase-counter-exit-right {
	opacity: 0;
	transform: translateX(100%);
}

/* Incoming number on Prev needs to start from the left instead of
   the default right-side resting position. */
.ybsb-showcase-counter-number.ybsb-showcase-counter-enter-left {
	opacity: 0;
	transform: translateX(-100%);
}

/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
	.ybsb-showcase-content,
	.ybsb-showcase-content > *,
	.ybsb-showcase-card-bg,
	.ybsb-showcase-icon-button,
	.ybsb-showcase-icon-button-icon,
	.ybsb-showcase-counter-number,
	.ybsb-showcase-nav-wrap {
		transition-duration: 1ms !important;
	}
}

/* Tablet & Mobile layout (text starting higher, nav row centered,
   top padding) is generated per-instance in render(), using this
   widget's real active breakpoints rather than a hardcoded value
   here - see get_breakpoints_px() and the <style> block in render(). */