/* ============================================================
   LS Gallery — widget styles
   Three interchangeable layouts (Grid / Masonry / Carousel) sharing
   one visual language — image "frame", hover effect, caption and
   lightbox — so switching the Style dropdown never looks like a
   different widget. Scoped entirely under .ls-gallery.
   ============================================================ */

.ls-gallery {
	--ls-gallery-cols: 3;
	--ls-gallery-per-view: 4;
	--ls-gallery-gap: 16px;
	--ls-gallery-radius: 3px;
	--ls-gallery-border: rgba(244, 246, 245, .14);
	--ls-gallery-overlay: rgba(5, 9, 13, .45);
	position: relative;
}

/* ---------- shared "frame" — every image, in every layout ---------- */
.ls-gallery__frame {
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: var(--ls-gallery-radius);
	border: 1px solid var(--ls-gallery-border);
	background: #0B1622;
	cursor: default;
	/* Links are natively draggable too, same reason as the img rule
	   below — draggable="false" on the element itself (see
	   class-gallery-widget.php) is the real fix, this is backup. */
	-webkit-user-drag: none;
}

a.ls-gallery__frame {
	cursor: pointer;
}

.ls-gallery__frame img {
	display: block;
	width: 100%;
	height: 300px;
	/* Images are natively draggable in every browser — left alone, a
	   mouse-drag on a carousel slide (meant for the custom swipe-to-
	   navigate gesture in script.js) gets hijacked into the browser's
	   own image drag-and-drop instead, and the swipe never happens.
	   draggable="false" on the <img> itself (see class-gallery-
	   widget.php) is the real fix; these two are defensive backup for
	   any element/browser that ignores it. */
	-webkit-user-drag: none;
	user-select: none;
	/* Natural height by default ("Image Ratio: Original") — the frame
	   just wraps whatever height that produces, no forced stretching.
	   When a fixed Image Ratio is chosen, the Style control sets
	   `aspect-ratio` directly on this <img> (not the frame), which is
	   enough on its own to give a replaced element like <img> a definite
	   height from a definite width — no dependency on the frame, a flex
	   ancestor, or any height:100% trick, so it can't be thrown off by a
	   caption sitting above/below it or by mismatched row heights. */
}

.ls-gallery__overlay {
	position: absolute;
	inset: 0;
	background: var(--ls-gallery-overlay);
	opacity: 0;
	transition: opacity .35s var(--ls-ease, cubic-bezier(.22, .88, .3, 1));
	pointer-events: none;
}

.ls-gallery__zoom {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	color: #FFFFFF;
	opacity: 0;
	transform: scale(.85);
	transition: opacity .35s ease, transform .35s ease;
	pointer-events: none;
}

.ls-gallery__zoom svg {
	width: 26px;
	height: 26px;
	filter: drop-shadow(0 1px 4px rgba(0, 0, 0, .5));
}

/* ---------- image number badge ("01, 02, 03…") ---------- */
.ls-gallery__index {
	position: absolute;
	top: 10px;
	left: 10px;
	z-index: 1;
	padding: 4px 8px;
	font-family: var(--ls-font-mono, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
	font-size: 11px;
	letter-spacing: .04em;
	line-height: 1;
	color: #FFFFFF;
	background: rgba(5, 9, 13, .55);
	border-radius: 2px;
	pointer-events: none;
}

/* ---------- hover effects ---------- */
.ls-gallery--hover-zoom .ls-gallery__frame img {
	transition: transform .6s var(--ls-ease, cubic-bezier(.22, .88, .3, 1));
}
.ls-gallery--hover-zoom a.ls-gallery__frame:hover img {
	transform: scale(1.06);
}
.ls-gallery--hover-zoom a.ls-gallery__frame:hover .ls-gallery__overlay {
	opacity: .5;
}

.ls-gallery--hover-darken a.ls-gallery__frame:hover .ls-gallery__overlay {
	opacity: 1;
}

.ls-gallery--hover-lift .ls-gallery__frame {
	transition: transform .35s var(--ls-ease, cubic-bezier(.22, .88, .3, 1)), box-shadow .35s ease;
}
.ls-gallery--hover-lift a.ls-gallery__frame:hover {
	transform: translateY(-6px);
	box-shadow: 0 18px 34px rgba(0, 0, 0, .35);
}

a.ls-gallery__frame:hover .ls-gallery__zoom {
	opacity: 1;
	transform: scale(1);
}

/* ---------- caption ---------- */
.ls-gallery__caption {
	font-size: 10.5px;
	text-transform: uppercase;
	line-height: 1.4;
	color: #FFFFFF;
	background: rgba(5, 9, 13, .72);
}

.ls-gallery--caption-below .ls-gallery__frame {
	border-radius: var(--ls-gallery-radius) var(--ls-gallery-radius) 0 0;
}
.ls-gallery--caption-below .ls-gallery__caption {
	display: block;
	position: absolute;
	width: stretch;
	bottom: 0;
	right: 0;
	padding: 10px 12px;
	border: 1px solid var(--ls-gallery-border);
	border-top: none;
	border-radius: 0 0 var(--ls-gallery-radius) var(--ls-gallery-radius);
}

.ls-gallery--caption-hover .ls-gallery__caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 20px 14px 12px;
	background: linear-gradient(to top, rgba(5, 9, 13, .85), transparent);
	transform: translateY(100%);
	opacity: 0;
	transition: transform .3s var(--ls-ease, cubic-bezier(.22, .88, .3, 1)), opacity .3s ease;
}
.ls-gallery--caption-hover .ls-gallery__frame:hover .ls-gallery__caption,
.ls-gallery--caption-hover .ls-gallery__frame:focus-visible .ls-gallery__caption {
	transform: translateY(0);
	opacity: 1;
}

/* ============================================================
   GRID
   ============================================================ */
.ls-gallery--grid .ls-gallery__grid {
	display: grid;
	grid-template-columns: repeat(var(--ls-gallery-cols), 1fr);
	gap: var(--ls-gallery-gap);
}

/* Plain block stacking — frame, then caption (when "below") sit one
   after the other. With Image Ratio: Original and Image Fit: Contain,
   each image keeps its own natural height (uneven rows). Choosing
   Cover there instead reveals an explicit "Image Height" control (see
   the Layout section in the editor), which sets a plain `height` +
   `object-fit: cover` directly on the <img> via Elementor's own
   'selectors' mechanism — the same mechanism every other size/spacing
   control in this plugin already uses. That's a flat, direct value
   with no dependency on flexbox stretch, row content, or any custom
   class, so every image ends up exactly that tall, deterministically,
   regardless of what else is on the page. A fixed Image Ratio (Square,
   4:3, …) works the same way, just via `aspect-ratio` instead of a
   literal height — see that control below. */

/* ============================================================
   MASONRY — CSS multi-column, no JS reflow needed. Column order
   runs top-to-bottom-then-next-column (standard CSS columns
   behaviour) rather than a strict shortest-column packing, which
   is the accepted trade-off for a zero-dependency masonry.
   ============================================================ */
.ls-gallery--masonry .ls-gallery__grid {
	column-count: var(--ls-gallery-cols);
	column-gap: var(--ls-gallery-gap);
}

.ls-gallery--masonry .ls-gallery__item {
	break-inside: avoid;
	margin-bottom: var(--ls-gallery-gap);
	display: inline-block;
	width: 100%;
}

/* ============================================================
   CAROUSEL
   ============================================================ */
.ls-gallery--carousel {
	padding: 0 4px;
}

.ls-gallery__viewport {
	overflow: hidden;
}

.ls-gallery__track {
	display: flex;
	gap: var(--ls-gallery-gap);
	will-change: transform;
}

.ls-gallery__slide {
	flex: 0 0 calc((100% - (var(--ls-gallery-per-view) - 1) * var(--ls-gallery-gap)) / var(--ls-gallery-per-view));
	min-width: 0;
	position: relative;
}

.ls-gallery__arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid rgba(244, 246, 245, .2);
	background: rgba(11, 22, 34, .75);
	color: #FFFFFF;
	transition: background .25s ease, border-color .25s ease, transform .25s ease;
}
.ls-gallery__arrow:hover {
	border-color: rgba(244, 246, 245, .5);
	transform: translateY(-50%) scale(1.06);
}
.ls-gallery__arrow svg {
	width: 18px;
	height: 18px;
}
.ls-gallery__arrow--prev {
	left: -6px;
}
.ls-gallery__arrow--next {
	right: -6px;
}
@media (max-width: 767px) {
	.ls-gallery__arrow {
		width: 36px;
		height: 36px;
	}
	.ls-gallery__arrow--prev { left: 2px; }
	.ls-gallery__arrow--next { right: 2px; }
}

.ls-gallery__dots {
	display: flex;
	justify-content: center;
	gap: 8px;
	margin-top: 18px;
}
.ls-gallery__dots button {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: rgba(244, 246, 245, .3);
	padding: 0;
	transition: background .25s ease, transform .25s ease;
}
.ls-gallery__dots button.active {
	background: #E8A33D;
	transform: scale(1.25);
}

/* dragging feedback */
.ls-gallery--carousel.is-dragging .ls-gallery__track {
	cursor: grabbing;
}
.ls-gallery--carousel .ls-gallery__track {
	cursor: grab;
}

/* ============================================================
   LIGHTBOX
   Built and appended to <body> by script.js (so it always sits
   above Elementor's own DOM, unaffected by any ancestor's
   transform/overflow), one instance per gallery that has it
   enabled. Colors read from custom properties set on this
   widget's own wrapper by the Style tab, copied onto the
   lightbox root when it's created.
   ============================================================ */
.ls-gallery-lightbox {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--ls-lightbox-bg, rgba(5, 9, 13, .96));
	opacity: 0;
	visibility: hidden;
	transition: opacity .3s ease;
}
.ls-gallery-lightbox.is-open {
	opacity: 1;
	visibility: visible;
}

.ls-gallery-lightbox__figure {
	position: relative;
	max-width: min(1200px, 92vw);
	max-height: 86vh;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 14px;
}

.ls-gallery-lightbox__img {
	max-width: 100%;
	max-height: 78vh;
	object-fit: contain;
	border-radius: 3px;
	opacity: 0;
	transform: scale(.97);
	transition: opacity .25s ease, transform .25s ease;
}
.ls-gallery-lightbox__img.is-loaded {
	opacity: 1;
	transform: none;
}

.ls-gallery-lightbox__caption {
	font-size: 13px;
	color: var(--ls-lightbox-ui, #FFFFFF);
	opacity: .75;
	text-align: center;
}

.ls-gallery-lightbox__counter {
	font-family: var(--ls-font-mono, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
	font-size: 11px;
	letter-spacing: .05em;
	color: var(--ls-lightbox-ui, #FFFFFF);
	opacity: .5;
}

.ls-gallery-lightbox__close,
.ls-gallery-lightbox__nav {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--ls-lightbox-ui, #FFFFFF);
	background: rgba(255, 255, 255, .2);
	transition: opacity .2s ease, transform .2s ease;
	opacity: .7;
	border: 0;
	border-radius: 50%;
}
.ls-gallery-lightbox__close:hover,
.ls-gallery-lightbox__nav:hover {
	opacity: 1;
}

.ls-gallery-lightbox__close {
	top: 22px;
	right: 22px;
	width: 40px;
	height: 40px;
	border: 0;
}
.ls-gallery-lightbox__close svg {
	width: 22px;
	height: 22px;
}

.ls-gallery-lightbox__nav {
	top: 50%;
	transform: translateY(-50%);
	width: 52px;
	height: 52px;
}
.ls-gallery-lightbox__nav:hover, 
.ls-gallery-lightbox__close:hover {
	transform: translateY(-50%) scale(1.08);
}
.ls-gallery-lightbox__nav svg {
	width: 26px;
	height: 26px;
}
.ls-gallery-lightbox__nav--prev {
	left: 12px;
}
.ls-gallery-lightbox__nav--next {
	right: 12px;
}
@media (max-width: 767px) {
	.ls-gallery-lightbox__nav {
		width: 40px;
		height: 40px;
	}
	.ls-gallery-lightbox__nav--prev { left: 4px; }
	.ls-gallery-lightbox__nav--next { right: 4px; }
}

/* ---------- scroll-in reveal ---------- */
.ls-gallery.ls-gallery--animate .ls-gallery__item,
.ls-gallery.ls-gallery--animate .ls-gallery__slide {
	opacity: 0;
	transform: translateY(20px);
	transition: opacity .7s cubic-bezier(.22, .88, .3, 1), transform .7s cubic-bezier(.22, .88, .3, 1);
}
.ls-gallery.ls-gallery--animate.in .ls-gallery__item,
.ls-gallery.ls-gallery--animate.in .ls-gallery__slide {
	opacity: 1;
	transform: none;
}
.ls-gallery.ls-gallery--animate .ls-gallery__item:nth-child(2),
.ls-gallery.ls-gallery--animate .ls-gallery__slide:nth-child(2) { transition-delay: .05s; }
.ls-gallery.ls-gallery--animate .ls-gallery__item:nth-child(3),
.ls-gallery.ls-gallery--animate .ls-gallery__slide:nth-child(3) { transition-delay: .1s; }
.ls-gallery.ls-gallery--animate .ls-gallery__item:nth-child(4),
.ls-gallery.ls-gallery--animate .ls-gallery__slide:nth-child(4) { transition-delay: .15s; }
.ls-gallery.ls-gallery--animate .ls-gallery__item:nth-child(5),
.ls-gallery.ls-gallery--animate .ls-gallery__slide:nth-child(5) { transition-delay: .2s; }
.ls-gallery.ls-gallery--animate .ls-gallery__item:nth-child(6),
.ls-gallery.ls-gallery--animate .ls-gallery__slide:nth-child(6) { transition-delay: .25s; }

@media (prefers-reduced-motion: reduce) {
	.ls-gallery.ls-gallery--animate .ls-gallery__item,
	.ls-gallery.ls-gallery--animate .ls-gallery__slide {
		opacity: 1;
		transform: none;
		transition: none;
	}
	.ls-gallery--hover-zoom .ls-gallery__frame img,
	.ls-gallery--hover-lift .ls-gallery__frame {
		transition: none;
	}
}

/* Column/visible-slide counts per breakpoint are handled by Elementor's
   own responsive control system (tablet/mobile defaults on the Columns
   and Visible Slides controls), which emits its own media queries for
   --ls-gallery-cols / --ls-gallery-per-view — nothing extra needed here. */
