.galleryforge {
	margin: 1.5em 0;
}

.galleryforge-item-link {
	display: block;
	position: relative; /* anchors the optional video play-icon overlay */
	/* A percentage height on the .galleryforge-image inside only resolves
	   against a parent with a DEFINITE height - a plain block box with no
	   height rule of its own (the default) is content-sized instead, which
	   breaks that chain silently: the image then renders at its own
	   natural aspect ratio instead of filling (and being cropped to) its
	   cell. Height 100% here is a no-op wherever the actual cell (Grid
	   masonry) is itself content-sized - it only starts mattering, and
	   fixes real cropping, once the cell above has an explicit height
	   (Grid non-masonry's aspect-ratio, Justified/Slider's JS-set pixel
	   height). */
	height: 100%;
	line-height: 0;
	cursor: pointer;
	/* Clipping (for rounded corners and the zoom hover effect) lives here,
	   one level in from Grid/Justified's cell <figure> - a box-shadow on
	   that outer figure would otherwise get silently clipped away by its
	   own overflow:hidden if both lived on the same element. Inert for
	   Slider, which sets its own radius/overflow at the .galleryforge-slide
	   level and never has a border-radius here to inherit. */
	overflow: hidden;
	border-radius: inherit;
}

.galleryforge-image {
	display: block;
	width: 100%;
	height: auto;
	/* Defaults to dead-center (50% 50%) - identical to a browser's own
	   default crop - so an image nobody has set a focus point on renders
	   exactly as before. Grid/Justified cells override the two custom
	   properties inline per-item when a focus point has been set. */
	object-position: var( --galleryforge-focal-x, 50% ) var( --galleryforge-focal-y, 50% );
}

/* A video item's poster thumbnail gets a small centered play button so
   it reads as "click to watch" rather than "click to zoom" - purely
   decorative (pointer-events:none), the surrounding <a> handles clicks. */
.galleryforge-video-play-icon {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate( -50%, -50% );
	width: 54px;
	height: 54px;
	border-radius: 50%;
	background: rgba( 0, 0, 0, 0.55 );
	pointer-events: none;
}

.galleryforge-video-play-icon::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 54%;
	transform: translate( -50%, -50% );
	border-style: solid;
	border-width: 10px 0 10px 16px;
	border-color: transparent transparent transparent #fff;
}

.galleryforge-admin-notice {
	background: #fef7f1;
	border: 1px dashed #d63638;
	color: #d63638;
	padding: 10px 14px;
	border-radius: 4px;
	font-size: 13px;
}

/* ------------------------------------------------------------------ */
/* Grid / Masonry                                                      */
/* ------------------------------------------------------------------ */

.galleryforge-grid-inner {
	display: grid;
	grid-template-columns: repeat( var( --galleryforge-columns, 3 ), 1fr );
	gap: var( --galleryforge-gutter, 8px );
}

/* Phones and tablets: never more than 2 / 3 columns, whatever the
   gallery asks for (a 6-column grid at 360px is six 55px tap targets). */
@media ( max-width: 900px ) {
	.galleryforge-grid-inner { grid-template-columns: repeat( min( var( --galleryforge-columns, 3 ), 3 ), 1fr ); }
}
@media ( max-width: 600px ) {
	.galleryforge-grid-inner { grid-template-columns: repeat( min( var( --galleryforge-columns, 3 ), 2 ), 1fr ); }
}

.galleryforge-layout-grid.galleryforge-masonry .galleryforge-grid-inner {
	display: block;
	column-count: var( --galleryforge-columns, 3 );
	column-gap: var( --galleryforge-gutter, 8px );
}
@media ( max-width: 900px ) { .galleryforge-layout-grid.galleryforge-masonry .galleryforge-grid-inner { column-count: min( var( --galleryforge-columns, 3 ), 3 ); } }
@media ( max-width: 600px ) { .galleryforge-layout-grid.galleryforge-masonry .galleryforge-grid-inner { column-count: min( var( --galleryforge-columns, 3 ), 2 ); } }

.galleryforge-layout-grid.galleryforge-masonry .galleryforge-grid-cell {
	break-inside: avoid;
	margin-bottom: var( --galleryforge-gutter, 8px );
}

.galleryforge-grid-cell {
	margin: 0;
	position: relative; /* anchors the optional hover overlay */
	border-radius: var( --galleryforge-radius, 4px );
	box-shadow: var( --galleryforge-shadow, none );
	background: #f0f0f1;
}

.galleryforge-grid-cell .galleryforge-image {
	height: 100%;
	object-fit: cover;
}

.galleryforge-layout-grid:not(.galleryforge-masonry) .galleryforge-grid-cell {
	aspect-ratio: 1 / 1;
}

/* ------------------------------------------------------------------ */
/* Justified rows                                                      */
/* ------------------------------------------------------------------ */

.galleryforge-justified-inner {
	display: flex;
	flex-wrap: wrap;
	gap: var( --galleryforge-gutter, 8px );
}

.galleryforge-justified-cell {
	margin: 0;
	position: relative; /* anchors the optional hover overlay */
	height: var( --galleryforge-row-height, 240px );
	flex-basis: 0;
	border-radius: var( --galleryforge-radius, 4px );
	box-shadow: var( --galleryforge-shadow, none );
	background: #f0f0f1;
}

.galleryforge-justified-cell .galleryforge-image {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* ------------------------------------------------------------------ */
/* Grid / Justified: hover effects, entrance animation                */
/* ------------------------------------------------------------------ */

/* Zoom: the image scales up slightly on hover/keyboard-focus. Clipped
   cleanly by .galleryforge-item-link's own overflow:hidden, so it never
   spills past the cell's rounded corners. */
.galleryforge-hover-effect-zoom .galleryforge-grid-cell .galleryforge-image,
.galleryforge-hover-effect-zoom .galleryforge-justified-cell .galleryforge-image {
	transition: transform 0.4s ease;
}

.galleryforge-hover-effect-zoom .galleryforge-grid-cell:hover .galleryforge-image,
.galleryforge-hover-effect-zoom .galleryforge-justified-cell:hover .galleryforge-image,
.galleryforge-hover-effect-zoom .galleryforge-grid-cell:focus-within .galleryforge-image,
.galleryforge-hover-effect-zoom .galleryforge-justified-cell:focus-within .galleryforge-image {
	transform: scale( 1.08 );
}

/* Overlay: a dim scrim plus an expand icon and (if the item has one) its
   caption, faded in on hover/focus. pointer-events:none so the overlay
   is purely decorative - clicks always reach the link/lightbox trigger
   underneath it, never the scrim itself. */
.galleryforge-hover-overlay {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 12px;
	text-align: center;
	background: rgba( 0, 0, 0, 0.45 );
	color: #fff;
	opacity: 0;
	transition: opacity 0.3s ease;
	pointer-events: none;
}

.galleryforge-hover-effect-overlay .galleryforge-grid-cell:hover .galleryforge-hover-overlay,
.galleryforge-hover-effect-overlay .galleryforge-justified-cell:hover .galleryforge-hover-overlay,
.galleryforge-hover-effect-overlay .galleryforge-grid-cell:focus-within .galleryforge-hover-overlay,
.galleryforge-hover-effect-overlay .galleryforge-justified-cell:focus-within .galleryforge-hover-overlay {
	opacity: 1;
}

.galleryforge-hover-caption {
	font-size: 13px;
	line-height: 1.3;
}

/* Like button (see GF_Likes::button_html()): always visible, not only
   on hover - unlike the overlay above, a like count is only useful if a
   visitor can see it (and like something) without having to discover
   the hover effect first. z-index 4 keeps it above the Slider's own
   Hero caption/layers overlay (z-index 3, see .galleryforge-slide-layers
   further down) so it's never covered by either. */
.galleryforge-like-button {
	position: absolute;
	top: 10px;
	right: 10px;
	z-index: 4;
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 5px 10px;
	border: none;
	border-radius: 999px;
	background: rgba( 0, 0, 0, 0.55 );
	color: #fff;
	font-size: 12px;
	font-variant-numeric: tabular-nums;
	line-height: 1;
	cursor: pointer;
	transition: background 0.2s ease, transform 0.15s ease;
}

.galleryforge-like-button:hover {
	background: rgba( 0, 0, 0, 0.75 );
}

.galleryforge-like-button:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
}

.galleryforge-like-button:active {
	transform: scale( 0.92 );
}

.galleryforge-like-icon {
	flex: none;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.8;
}

.galleryforge-like-button.is-liked {
	background: rgba( 224, 55, 88, 0.92 );
}

.galleryforge-like-button.is-liked .galleryforge-like-icon {
	fill: currentColor;
	stroke: currentColor;
}

.galleryforge-like-count {
	min-width: 1ch;
}

/* The Before/After stage clips its own contents (see .galleryforge-ba-
   stage's overflow: hidden a few rules down) and the like button should
   sit relative to that clipped frame, not the outer figure - keeps it
   pinned to the visible photo regardless of the drag handle's position. */
.galleryforge-ba-stage .galleryforge-like-button {
	top: 10px;
	right: 10px;
}

/* The Slider's Fullscreen style renders full-bleed behind the page's own
   header - on a theme whose header floats transparently over the hero
   (confirmed against a real Kalium "full background menu" header, whose
   own box reserves a tall invisible hit area even past where anything is
   visibly drawn), that header sits at a far higher z-index than anything
   in the gallery and silently swallows every click aimed at the default
   top-right position before it ever reaches the button - the button still
   renders exactly where expected, it just can never be clicked. Moving it
   to the bottom-right keeps it clear of any theme's header, of any
   height, without having to guess or configure one. */
.galleryforge-slider-fullscreen .galleryforge-like-button {
	top: auto;
	bottom: 20px;
	right: 20px;
}

/* "Add to cart" tile button (Pro + WooCommerce - see GF_Shop). Bottom-left
   so it never collides with the like button above (top-right) or the
   caption/hover overlay, which both anchor to the bottom edge of a cell -
   z-index 4 matches the like button's, both sit above the hover overlay. */
.galleryforge-shop-button {
	position: absolute;
	left: 10px;
	bottom: 10px;
	z-index: 4;
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	padding: 6px 12px;
	border: none;
	border-radius: 999px;
	background: rgba( 0, 0, 0, 0.72 );
	color: #fff;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.3;
	text-decoration: none;
	cursor: pointer;
	transition: background 0.2s ease, transform 0.15s ease;
}

.galleryforge-shop-button:hover,
.galleryforge-shop-button:focus-visible {
	background: rgba( 0, 0, 0, 0.9 );
	color: #fff;
}

.galleryforge-shop-button:active {
	transform: scale( 0.96 );
}

.galleryforge-shop-price {
	font-weight: 400;
	opacity: 0.85;
}

/* Entrance: each thumbnail fades in once its own <img> actually finishes
   loading (galleryforge.js adds .galleryforge-loaded) - lazy-loaded
   images further down a long gallery get a pleasant staggered reveal as
   the visitor scrolls to them instead of popping in abruptly. */
.galleryforge-entrance .galleryforge-image {
	opacity: 0;
	transition: opacity 0.5s ease;
}

.galleryforge-entrance .galleryforge-image.galleryforge-loaded {
	opacity: 1;
}

/* ------------------------------------------------------------------ */
/* Grid / Justified: tag filtering + "Load more" pagination            */
/* ------------------------------------------------------------------ */

/* Both the filter bar and the "Load more" button are built entirely by
   galleryforge.js (see initFilterAndPaginate()) - there is no server-
   rendered fallback markup for either, so nothing here needs a
   JS-disabled fallback of its own: if the script never runs, this CSS
   simply never has anything to style, and every photo is already
   visible from the plain HTML. */

.galleryforge-item-hidden {
	display: none !important;
}

.galleryforge-filter-bar {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-bottom: 14px;
}

.galleryforge-filter-btn {
	font: inherit;
	font-size: 13px;
	line-height: 1;
	padding: 7px 14px;
	border: 1px solid rgba( 0, 0, 0, 0.15 );
	border-radius: 999px;
	background: #fff;
	/* Deliberately a fixed dark color, not `inherit` - this button's
	   background is always white regardless of the theme, so its text
	   needs to always be dark too. `inherit` looked fine on a light-theme
	   test site but produced invisible white-on-white text the moment a
	   dark theme (like this site's) set the page's ambient text color to
	   white - a real bug caught only by checking on the actual site,
	   not the local sandbox's default light theme. */
	color: #1e1e1e;
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.galleryforge-filter-btn:hover {
	border-color: rgba( 0, 0, 0, 0.35 );
}

.galleryforge-filter-btn.is-active {
	background: #1e1e1e;
	border-color: #1e1e1e;
	color: #fff;
}

.galleryforge-load-more {
	display: block;
	font: inherit;
	font-size: 14px;
	margin: 20px auto 0;
	padding: 10px 24px;
	border: 1px solid rgba( 0, 0, 0, 0.15 );
	border-radius: 4px;
	background: #fff;
	/* Fixed dark color, not `inherit` - see the comment on
	   .galleryforge-filter-btn above; same white-background-needs-dark-
	   text reasoning applies here. */
	color: #1e1e1e;
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease;
}

.galleryforge-load-more:hover {
	border-color: rgba( 0, 0, 0, 0.35 );
	background: #f7f7f7;
}

.galleryforge-search-wrap {
	margin-bottom: 14px;
}

.galleryforge-search-input {
	display: block;
	width: 100%;
	max-width: 320px;
	font: inherit;
	font-size: 14px;
	padding: 8px 14px;
	border: 1px solid rgba( 0, 0, 0, 0.15 );
	border-radius: 6px;
	/* Same fixed-white/fixed-dark reasoning as .galleryforge-filter-btn
	   above - this box is always a plain white field regardless of the
	   surrounding theme, so its text and placeholder need fixed dark
	   colors too rather than inheriting an ambient color that could turn
	   out to be white-on-white. */
	background: #fff;
	color: #1e1e1e;
}

.galleryforge-search-input::placeholder {
	color: rgba( 0, 0, 0, 0.45 );
}

.galleryforge-search-input:focus {
	outline: 2px solid #1e1e1e;
	outline-offset: 1px;
}

/* Visually-hidden utility for non-live-region elements (the search
   input's own <label>, associated by for/id rather than visible text) -
   same "clip" technique as .galleryforge-sr-announcer above, kept as a
   separate class since that one's doc comment and usage are specific to
   being an aria-live region. */
.galleryforge-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect( 0, 0, 0, 0 );
	white-space: nowrap;
	border: 0;
}

/* ------------------------------------------------------------------ */
/* Slider / Carousel                                                   */
/* ------------------------------------------------------------------ */

.galleryforge-layout-slider {
	position: relative;
	overflow: hidden;
	border-radius: 4px;
}

.galleryforge-slider-track {
	position: relative;
	height: 480px;
}

.galleryforge-slide {
	grid-area: 1 / 1;
	height: 100%;
	/* Establishes each slide as its own positioning context so an
	   absolutely-positioned child (the Hero style's caption overlay) is
	   contained within ITS OWN slide's box, not the shared track - without
	   this, every slide's caption would resolve against the track (the
	   next positioned ancestor up) and all of them would stack on top of
	   each other regardless of which slide is currently in view. Coverflow
	   overrides this to position: absolute for its own 3D positioning. */
	position: relative;
}

.galleryforge-slide .galleryforge-image {
	width: 100%;
	height: 100%;
	object-fit: contain;
	background: #000;
}

/* Fade, Ken Burns & Morph: every slide stacks in the same grid cell.
   Fade/Ken Burns crossfade via opacity alone; Morph (galleryforge.js,
   Phase 3) additionally interpolates each pair of slides via whichever
   effect is active (cross-dissolve is itself just this same opacity
   crossfade - clip-path/liquid/mesh-warp layer extra per-slide
   transforms/canvases on top of this same stacked base). Fade Zoom and
   Fade Through Black (Pro) are members of the same fade family and
   share this stacked-grid base too, then override just the transition
   timing/transform further down. Cover and Wipe (Pro, slide family)
   also stack their slides here even though their motion is driven by
   transform/clip-path rather than opacity - see each one's own block
   below. */
.galleryforge-slider-mode-fade .galleryforge-slider-track,
.galleryforge-slider-mode-kenburns .galleryforge-slider-track,
.galleryforge-slider-mode-morph .galleryforge-slider-track,
.galleryforge-slider-mode-fade-zoom .galleryforge-slider-track,
.galleryforge-slider-mode-fade-through-black .galleryforge-slider-track,
.galleryforge-slider-mode-fade-blur .galleryforge-slider-track,
.galleryforge-slider-mode-flip .galleryforge-slider-track,
.galleryforge-slider-mode-cover .galleryforge-slider-track,
.galleryforge-slider-mode-wipe .galleryforge-slider-track,
.galleryforge-slider-mode-cube .galleryforge-slider-track,
.galleryforge-slider-mode-circle-reveal .galleryforge-slider-track,
.galleryforge-slider-mode-blinds .galleryforge-slider-track,
.galleryforge-slider-mode-random .galleryforge-slider-track {
	display: grid;
	overflow: hidden;
}

.galleryforge-slider-mode-fade .galleryforge-slide,
.galleryforge-slider-mode-kenburns .galleryforge-slide,
.galleryforge-slider-mode-morph .galleryforge-slide,
.galleryforge-slider-mode-fade-zoom .galleryforge-slide,
.galleryforge-slider-mode-fade-through-black .galleryforge-slide,
.galleryforge-slider-mode-fade-blur .galleryforge-slide,
.galleryforge-slider-mode-flip .galleryforge-slide,
.galleryforge-slider-mode-random .galleryforge-slide {
	opacity: 0;
	transition: opacity 0.7s ease;
	pointer-events: none;
	z-index: 1;
	overflow: hidden;
}

.galleryforge-slider-mode-fade .galleryforge-slide.is-active,
.galleryforge-slider-mode-kenburns .galleryforge-slide.is-active,
.galleryforge-slider-mode-morph .galleryforge-slide.is-active,
.galleryforge-slider-mode-fade-zoom .galleryforge-slide.is-active,
.galleryforge-slider-mode-fade-through-black .galleryforge-slide.is-active,
.galleryforge-slider-mode-fade-blur .galleryforge-slide.is-active,
.galleryforge-slider-mode-flip .galleryforge-slide.is-active,
.galleryforge-slider-mode-random .galleryforge-slide.is-active {
	opacity: 1;
	pointer-events: auto;
	z-index: 2;
}

/* Cube (Pro): each slide is a face of a rotating cube - see
   runCubeTransition() in galleryforge.js, which owns every transform/
   z-index/opacity change for this mode. This block only supplies the
   parts CSS should own: the 3D stage (perspective) and hiding the
   reverse of whichever face is mid-rotation. */
.galleryforge-slider-mode-cube .galleryforge-slider-track {
	perspective: 1400px;
}

.galleryforge-slider-mode-cube .galleryforge-slide {
	opacity: 0;
	pointer-events: none;
	z-index: 1;
	backface-visibility: hidden;
	overflow: hidden;
}

.galleryforge-slider-mode-cube .galleryforge-slide.is-active {
	opacity: 1;
	pointer-events: auto;
	z-index: 2;
}

/* Circle Reveal (Pro): a zero-JS iris wipe - the incoming slide's own
   clip-path grows from a pinpoint at the center to a circle guaranteed
   to cover the whole frame, revealing it over the outgoing slide sitting
   beneath at a lower z-index. Both slides stay fully opaque throughout -
   the circle itself is what hides or shows each one, not opacity.
   circle()'s <shape-radius> only accepts closest-side/farthest-side/a
   length-percentage - unlike radial-gradient(), it has no
   closest-corner/farthest-corner keyword, so asking for one here doesn't
   fall back to anything sensible, it makes the WHOLE clip-path
   declaration invalid and the browser drops it, leaving the previous
   clip-path (the 0% pinpoint below) in place - which is exactly why the
   active slide used to stay invisible all the way through. A literal
   100% reaches the same "guaranteed to cover every corner regardless of
   aspect ratio" result properly instead: percentages here resolve
   against sqrt(width^2+height^2)/sqrt(2) (the spec's own formula for a
   shape-radius percentage), which for ANY rectangle already exceeds the
   actual center-to-corner distance of sqrt(width^2+height^2)/2 - 100%
   always overshoots the farthest corner a little rather than stopping
   short of it. */
.galleryforge-slider-mode-circle-reveal .galleryforge-slide {
	opacity: 1;
	clip-path: circle( 0% at 50% 50% );
	transition: clip-path 0.7s ease;
	pointer-events: none;
	z-index: 1;
	overflow: hidden;
}

.galleryforge-slider-mode-circle-reveal .galleryforge-slide.is-active {
	clip-path: circle( 100% at 50% 50% );
	pointer-events: auto;
	z-index: 2;
}

/* Blinds (Pro): a bank of horizontal slats overlays the incoming slide
   and lifts away in a staggered wave (see runBlindsTransition() and
   ensureBlindsOverlay() in galleryforge.js, which build and animate
   them) rather than animating the slide's own image - the outgoing
   slide simply stays visible underneath at a lower z-index until the
   slats finish opening. */
.galleryforge-slider-mode-blinds .galleryforge-slide {
	opacity: 1;
	pointer-events: none;
	z-index: 1;
	overflow: hidden;
}

.galleryforge-slider-mode-blinds .galleryforge-slide.is-active {
	pointer-events: auto;
	z-index: 2;
}

.galleryforge-blinds-overlay {
	position: absolute;
	inset: 0;
	z-index: 1; /* above the image, below the caption (2) and overlay layers (3) */
	pointer-events: none;
}

.galleryforge-blinds-slat {
	position: absolute;
	left: 0;
	width: 100%;
	background: #0b0b0c;
	transform-origin: top;
	will-change: transform;
}

/* Fade Blur (Pro): the plain fade crossfade, plus a blur that sharpens
   as each slide arrives and softens as it leaves - a dreamier crossfade
   than plain Fade rather than a different kind of motion. */
.galleryforge-slider-mode-fade-blur .galleryforge-slide {
	filter: blur( 16px );
	transition: opacity 0.8s ease, filter 0.8s ease;
}

.galleryforge-slider-mode-fade-blur .galleryforge-slide.is-active {
	filter: blur( 0 );
}

/* Flip (Pro): each slide rotates in around a vertical axis as it
   crossfades, rather than simply appearing in place - perspective on
   the track gives the rotation actual depth instead of just squashing
   flat. backface-visibility keeps the reverse of a slide that's mid-
   rotation from flashing into view. */
.galleryforge-slider-mode-flip .galleryforge-slider-track {
	perspective: 1400px;
}

.galleryforge-slider-mode-flip .galleryforge-slide {
	transform: rotateY( 90deg );
	transition: opacity 0.6s ease, transform 0.6s ease;
	backface-visibility: hidden;
}

.galleryforge-slider-mode-flip .galleryforge-slide.is-active {
	transform: rotateY( 0deg );
}

/* Going backwards (prev arrow, a dot to the left): the incoming slide
   rotates in from the other side. galleryforge.js's show() toggles
   is-backward on the slider before .is-active moves. */
.galleryforge-slider-mode-flip.is-backward .galleryforge-slide {
	transform: rotateY( -90deg );
}
.galleryforge-slider-mode-flip.is-backward .galleryforge-slide.is-active {
	transform: rotateY( 0deg );
}

/* Wipe (Pro, slide family): the incoming slide reveals left-to-right
   over the outgoing one via an animated clip-path, like a curtain being
   drawn back, rather than crossfading via opacity - both slides stay
   fully opaque throughout, so this shares the grid-stacking base above
   but deliberately opts out of the shared opacity rule the fade family
   uses. */
.galleryforge-slider-mode-wipe .galleryforge-slide {
	opacity: 1;
	clip-path: inset( 0 100% 0 0 );
	transition: clip-path 0.6s ease;
	pointer-events: none;
	z-index: 1;
	overflow: hidden;
}

.galleryforge-slider-mode-wipe .galleryforge-slide.is-active {
	clip-path: inset( 0 0 0 0 );
	pointer-events: auto;
	z-index: 2;
}

/* Going backwards the curtain draws from the right instead (see Flip). */
.galleryforge-slider-mode-wipe.is-backward .galleryforge-slide {
	clip-path: inset( 0 0 0 100% );
}
.galleryforge-slider-mode-wipe.is-backward .galleryforge-slide.is-active {
	clip-path: inset( 0 0 0 0 );
}

/* Fade Zoom (Pro): the plain fade crossfade above, plus a slow scale so
   the incoming slide settles into place rather than just appearing -
   outgoing slide shrinks back down as it fades out. Declared after the
   shared rule above so its transition/transform win the cascade. */
.galleryforge-slider-mode-fade-zoom .galleryforge-slide {
	transform: scale( 1.06 );
	transition: opacity 0.9s ease, transform 0.9s ease;
}

.galleryforge-slider-mode-fade-zoom .galleryforge-slide.is-active {
	transform: scale( 1 );
}

/* Fade Through Black (Pro): rather than crossfading the two slides
   directly over each other, the outgoing slide fades out completely
   first, then the incoming slide fades in from the slider's own black
   background - a short beat of black between slides. Needs its own
   transition-delay pair rather than the shared 0.7s crossfade above. */
.galleryforge-slider-mode-fade-through-black .galleryforge-slider-track {
	background: #000; /* the "beat of black" is painted, whatever the theme's slider background */
}

.galleryforge-slider-mode-fade-through-black .galleryforge-slide {
	transition: opacity 0.35s ease;
}

.galleryforge-slider-mode-fade-through-black .galleryforge-slide.is-active {
	transition: opacity 0.35s ease 0.35s;
}

/* Cover (Pro): the incoming slide slides fully over the outgoing one
   (which stays put underneath, no motion of its own) rather than the
   whole track translating - see runCoverTransition() in
   galleryforge.js, which owns every slide's transform/z-index for this
   mode. This block only sets the parts CSS should own: no opacity
   fade (both slides are fully visible, one just covers the other) and
   pointer-events so only the active slide is interactive. */
.galleryforge-slider-mode-cover .galleryforge-slide {
	opacity: 1;
	pointer-events: none;
	overflow: hidden;
}

.galleryforge-slider-mode-cover .galleryforge-slide.is-active {
	pointer-events: auto;
}

/* Morph's clip-path/liquid/mesh-warp effects (Phase 3) work by animating
   a property on the OUTGOING slide while the incoming one fades in per
   the shared rule above, so the outgoing slide needs its own transition
   declared here rather than only the opacity one it inherits above -
   galleryforge.js sets clip-path inline and lets this transition it. */
.galleryforge-slider-mode-morph .galleryforge-slide {
	transition: opacity 0.7s ease, clip-path 0.7s ease;
}

/* Ken Burns: fills the frame (no letterboxing) so the zoom/pan always
   has room to move without ever showing black bars, then slowly scales
   and drifts while the slide is active. galleryforge.js restarts the
   animation on every slide change by toggling this class off and on. */
.galleryforge-slider-mode-kenburns .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

.galleryforge-kenburns-play {
	animation: galleryforge-kenburns 7s ease-out forwards;
}

@keyframes galleryforge-kenburns {
	from { transform: scale( 1 ) translate3d( 0, 0, 0 ); }
	to   { transform: scale( 1.12 ) translate3d( -2%, -1%, 0 ); }
}

/* Focus Zoom (Pro, per-slide - see GF_Core::normalize_item()'s
   'focus_zoom' docblock): unlike Ken Burns above, this isn't a
   Transition itself - it's driven by a per-slide data-focus-zoom
   attribute, so it plays alongside whichever Transition the slider
   actually uses instead of replacing it. Same "fill the frame" reasoning
   as Ken Burns' object-fit override (a scale animation needs real image
   past the frame's edges to reveal or hide, not letterboxing gaps), and
   transform-origin reads the very same --galleryforge-focal-x/-y custom
   properties Grid/Justified's object-position already uses (see
   GF_Layout_Base::focal_style_attr()) - defaulting to dead center for a
   slide whose focus point was never moved. galleryforge.js restarts
   whichever one of these two classes applies on every slide change, the
   same toggle-off-then-on trick restartKenBurns() uses. */
.galleryforge-slide[data-focus-zoom="in"] .galleryforge-image,
.galleryforge-slide[data-focus-zoom="out"] .galleryforge-image {
	object-fit: cover;
	transform-origin: var( --galleryforge-focal-x, 50% ) var( --galleryforge-focal-y, 50% );
}

.galleryforge-focus-zoom-in-play {
	animation: galleryforge-focus-zoom-in 7s ease-out forwards;
}

@keyframes galleryforge-focus-zoom-in {
	from { transform: scale( 1 ); }
	to   { transform: scale( 1.15 ); }
}

/* Starts already zoomed in on the focus point (the "cropped" starting
   view) and slowly reveals the rest of the photo by zooming back out to
   the normal scale( 1 ) framing every other slide starts at. */
.galleryforge-focus-zoom-out-play {
	animation: galleryforge-focus-zoom-out 7s ease-out forwards;
}

@keyframes galleryforge-focus-zoom-out {
	from { transform: scale( 1.15 ); }
	to   { transform: scale( 1 ); }
}

/* Slide: the classic sideways carousel - every slide sits side-by-side
   in a row and the whole track translates so only the active one shows. */
.galleryforge-slider-mode-slide .galleryforge-slider-track {
	display: flex;
	transition: transform 0.5s ease;
}

.galleryforge-slider-mode-slide .galleryforge-slide {
	flex: 0 0 100%;
	min-width: 100%;
}

/* Slide Vertical (Pro): the same side-by-side track as plain Slide,
   just stacked top-to-bottom and translating on the Y axis instead of
   X - see galleryforge.js's show(), which switches translateX/
   translateY based on this mode. */
.galleryforge-slider-mode-slide-vertical .galleryforge-slider-track {
	display: flex;
	flex-direction: column;
	transition: transform 0.5s ease;
}

.galleryforge-slider-mode-slide-vertical .galleryforge-slide {
	flex: 0 0 100%;
	min-height: 100%;
}

/* Zoom Slide was retired in 0.58.77 (it was Slide plus a 0.6 s scale-in); saved galleries fall back to Slide. */

.galleryforge-slider-arrow {
	position: absolute;
	top: 50%;
	transform: translateY( -50% );
	background: rgba( 0, 0, 0, 0.55 );
	color: #fff;
	border: 1px solid rgba( 255, 255, 255, 0.4 );
	width: 46px;
	height: 46px;
	border-radius: 50%;
	cursor: pointer;
	font-size: 18px;
	line-height: 1;
	z-index: 3;
	transition: background 0.2s ease, transform 0.2s ease;
}

.galleryforge-slider-arrow:hover {
	background: rgba( 0, 0, 0, 0.8 );
	transform: translateY( -50% ) scale( 1.08 );
}

.galleryforge-slider-prev {
	left: 16px;
}

.galleryforge-slider-next {
	right: 16px;
}

.galleryforge-slider-dots {
	position: absolute;
	bottom: 16px;
	left: 0;
	right: 0;
	display: flex;
	justify-content: center;
	gap: 10px;
	z-index: 3;
}

.galleryforge-slider-dot {
	width: 11px;
	height: 11px;
	border-radius: 50%;
	background: rgba( 255, 255, 255, 0.5 );
	border: 1px solid rgba( 0, 0, 0, 0.3 );
	padding: 0;
	cursor: pointer;
	transition: background 0.2s ease, transform 0.2s ease;
}

.galleryforge-slider-dot:hover {
	background: rgba( 255, 255, 255, 0.8 );
}

.galleryforge-slider-dot.is-active {
	background: #fff;
	transform: scale( 1.15 );
}

/* Background music toggle - rendered only when a Music URL setting is
   set (see class-gf-layout-slider.php). Positioned top-right so it never
   collides with the arrows (vertically centered on the sides) or the
   dots (bottom-center). A single note glyph rather than a swapped icon
   communicates "there's music here"; playing vs. paused state is
   conveyed the same way .galleryforge-slider-dot.is-active already does
   it above - a background/scale change on the button itself, not a
   different glyph - so nothing here depends on an icon font being
   available on the front end. */
.galleryforge-slider-music-toggle {
	position: absolute;
	top: 16px;
	right: 16px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba( 0, 0, 0, 0.7 );
	color: #fff;
	border: 1.5px solid rgba( 255, 255, 255, 0.75 );
	width: 44px;
	height: 44px;
	border-radius: 50%;
	cursor: pointer;
	font-size: 21px;
	line-height: 1;
	z-index: 4;
	box-shadow: 0 1px 4px rgba( 0, 0, 0, 0.35 );
	transition: background 0.2s ease, transform 0.2s ease;
}

.galleryforge-slider-music-toggle:hover {
	background: rgba( 0, 0, 0, 0.8 );
	transform: scale( 1.08 );
}

.galleryforge-slider-music-toggle.is-playing {
	background: rgba( 0, 0, 0, 0.85 );
	box-shadow: 0 0 0 2px rgba( 255, 255, 255, 0.6 );
}

.galleryforge-slider-music-icon::before {
	content: '\266A'; /* ♪ - single eighth note. */
}

.galleryforge-slider-music-toggle.is-playing .galleryforge-slider-music-icon::before {
	content: '\266B'; /* ♫ - beamed eighth notes, a plain "now playing" cue. */
}

/* ------------------------------------------------------------------ */
/* Slider styles (classic / hero / cinematic / coverflow)              */
/*                                                                      */
/* This is a separate dimension from the transition modes above -      */
/* those control HOW a slide change animates; these control the        */
/* overall visual preset. Classic (the default) adds nothing here and  */
/* just uses whichever transition-mode rules already apply above.      */
/* ------------------------------------------------------------------ */

/* Full-Width Hero: a taller, edge-to-edge frame with a large gradient-
   backed caption pinned near the bottom, meant to read like a page's
   hero banner rather than a boxed-in gallery widget. */
.galleryforge-slider-style-hero {
	border-radius: 0;
}

.galleryforge-slider-style-hero .galleryforge-slider-track {
	height: 640px;
}

.galleryforge-slider-style-hero .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

.galleryforge-slider-hero-caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	padding: 60px 48px 40px;
	background: linear-gradient( to top, rgba( 0, 0, 0, 0.75 ), rgba( 0, 0, 0, 0 ) );
	color: #fff;
	/* Fluid rather than the fixed-size-plus-one-breakpoint-jump this used
	   to be - scales continuously with the viewport the same way the
	   overlay layer text below already does, bottoming out at 18px and
	   topping out at 28px so it never gets too small to read on a narrow
	   phone or disproportionately huge on an ultra-wide monitor. */
	font-size: clamp( 1.125rem, 1vw + 0.9rem, 1.75rem );
	line-height: 1.3;
	font-weight: 600;
	text-shadow: 0 1px 3px rgba( 0, 0, 0, 0.5 );
	pointer-events: none;
}

@media ( max-width: 782px ) {
	.galleryforge-slider-style-hero .galleryforge-slider-track {
		height: 380px;
	}

	.galleryforge-slider-hero-caption {
		padding: 32px 20px 24px;
	}
}

/* Hero caption + overlay layers, both on the same slide: both are
   bottom-anchored, so left alone they visually collide. Resolved by
   giving the layers container extra bottom clearance rather than hiding
   either one - class-gf-layout-slider.php only adds this modifier class
   to a slide that actually has BOTH a non-empty Hero caption AND at
   least one overlay layer, so a slide with just one of the two renders
   exactly as it always has. The clearance is sized to clear the Hero
   caption's worst-case height (its own padding plus a couple of lines of
   its text at the top of its now-fluid clamp() range) rather than the
   caption's exact rendered height, since a pure-CSS rule can't read that
   at paint time. */
.galleryforge-slide-caption-and-layers .galleryforge-slide-layers {
	padding-bottom: clamp( 120px, 20vw, 200px );
}

@media ( max-width: 782px ) {
	.galleryforge-slide-caption-and-layers .galleryforge-slide-layers {
		padding-bottom: clamp( 90px, 24vw, 140px );
	}
}

/* Cinematic / Ultra-Wide: a short, wide letterboxed frame reminiscent
   of an anamorphic film frame - object-fit: contain (rather than the
   Hero style's cover) so a tall source photo still fits inside the
   frame instead of being cropped down to almost nothing. */
.galleryforge-slider-style-cinematic .galleryforge-slider-track {
	height: auto;
	aspect-ratio: 21 / 9;
}

.galleryforge-slider-style-cinematic .galleryforge-slide .galleryforge-image {
	object-fit: contain;
	background: #000;
}

@media ( max-width: 782px ) {
	.galleryforge-slider-style-cinematic .galleryforge-slider-track {
		aspect-ratio: 16 / 9;
	}
}

/* 3D Coverflow: every slide is positioned absolutely and stacked via a
   perspective transform (galleryforge.js computes each slide's
   translateX/rotateY/scale/opacity/z-index based on its distance from
   the active slide) rather than the flex/grid track mechanics the other
   styles use, so the track itself becomes a plain positioning context. */
.galleryforge-slider-style-coverflow .galleryforge-slider-track {
	display: block;
	perspective: 1400px;
	overflow: visible;
}

/* Each card is 58% of the gallery's own width, not the full 100% every
   other style uses - centered via left: 21% (half of the 42% left
   over). A real coverflow fan needs neighboring cards to have somewhere
   to sit beside the active one; at 100% width, galleryforge.js's
   translateX(...%) positioning (a CSS transform percentage is always
   relative to the element's OWN box) would have to shift each neighbor
   by more than a full gallery-width to look like a fan at all, which is
   exactly what used to blow out the page's own layout - see
   positionCoverflow()'s own comment in galleryforge.js for the numbers.
   Keep this in sync with the JS constant there if either one changes. */
.galleryforge-slider-style-coverflow .galleryforge-slide {
	position: absolute;
	top: 0;
	left: 21%;
	width: 58%;
	/* A gallery keeps whatever 'transition' value it last had even after
	   its Slider Style is switched to Coverflow (the admin UI just hides
	   that dropdown - see the "ignores the Transition setting" hint in
	   class-gf-admin.php - it doesn't clear the stored value), so the
	   corresponding galleryforge-slider-mode-* class is still present
	   alongside galleryforge-slider-style-coverflow on the same element.
	   Slide, Zoom Slide, and Slide Vertical's own slide rules (above) set
	   min-width: 100%/flex: 0 0 100%, and min-width silently overrides a
	   plain width regardless of which rule's more specific or later in
	   the file - without resetting it back here, every card (not just
	   the active one) renders at the FULL track width no matter what
	   width: 58% above says, which was silently defeating this rule
	   entirely under the default 'slide' transition every new gallery
	   starts with (confirmed via a Playwright measurement: the active
	   slide's own rendered width matched the track's 1604px, not
	   58% of it). Same same-specificity, later-in-file override pattern
	   as the pointer-events rule below. */
	min-width: 0;
	flex: 0 0 auto;
	height: 100%;
	transition: transform 0.5s ease, opacity 0.5s ease;
	will-change: transform, opacity;
	cursor: pointer;
	/* Off-center slides must stay clickable (so galleryforge.js's
	   capture-phase handler can bring them to front) even when the
	   saved Transition setting is 'fade' or 'kenburns' - those modes'
	   rules above set pointer-events: none on non-active slides, which
	   this same-specificity, later-in-file rule overrides back to auto. */
	pointer-events: auto;
}

.galleryforge-slider-style-coverflow .galleryforge-slide .galleryforge-image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	box-shadow: 0 10px 40px rgba( 0, 0, 0, 0.35 );
	border-radius: 6px;
}

/* Coverflow's fan needs off-center slides to be able to peek past the
   gallery's own original edges - plain overflow: visible (what this
   used to be) let them peek arbitrarily far, with nothing bounding how
   far a translateX/rotateY combination could ever put one, which is
   exactly what let this blow out a page's own width rather than just
   the gallery's. Instead this widens the gallery's own clipping box by
   20% of its own width on each side (negative margin pulls the box out
   that far; equal padding pushes the actual content - the track, and
   through it every slide's absolute-positioning parent - back to
   exactly where it was, so the active slide's own size and position are
   unaffected) and clips there with a real overflow: hidden. A peeking
   slide gets that fixed, generous amount of room to show in - comfortably
   more than positionCoverflow()'s own translateX figures above ever
   call for at rest - and anything past it (a farther slide mid-transition,
   or any future change to that math) is guaranteed to cost this gallery's
   own extra 20%-a-side at most, never the page's. */
.galleryforge-layout-slider.galleryforge-slider-style-coverflow {
	overflow: hidden;
	margin-left: -20%;
	margin-right: -20%;
	padding-left: 20%;
	padding-right: 20%;
}

/* The arrows are positioned (see .galleryforge-slider-prev/-next above)
   relative to this same element the padding above just widened - without
   this, 16px from its edge would land 20% of the gallery's own width
   into the peek zone instead of just outside the active slide, same
   distance an every other style's arrow sits from ITS unpadded edge. */
.galleryforge-layout-slider.galleryforge-slider-style-coverflow .galleryforge-slider-prev {
	left: calc( 20% + 16px );
}

.galleryforge-layout-slider.galleryforge-slider-style-coverflow .galleryforge-slider-next {
	right: calc( 20% + 16px );
}

/* A phone-width column has no side margin worth calling one, and 3D
   perspective on top makes even a well-proportioned peek (see above)
   land at least partly off-screen instead of gracefully absorbed by
   page padding the way it would be on tablet/desktop. Collapses to just
   the active slide, full width, no peek or rotation - the same "no room
   for this effect" fallback Split/Duo already uses below for its
   side-by-side pane. transform/opacity need !important here because
   galleryforge.js's positionCoverflow() sets both inline, and an inline
   style otherwise always wins over a plain (non-!important) rule
   regardless of media query or specificity. */
@media ( max-width: 600px ) {
	.galleryforge-slider-style-coverflow .galleryforge-slide {
		left: 0;
		width: 100%;
		transform: none !important;
		opacity: 0 !important;
	}

	.galleryforge-slider-style-coverflow .galleryforge-slide.is-active {
		opacity: 1 !important;
	}
}

/* Split / Duo (Pro): the active slide and the one right after it (see
   updateDuoSecondary() in galleryforge.js, which is also what handles
   the wraparound past the last slide) sit side by side in a two-column
   row, each getting its own frame - a plain flex layout rather than the
   grid-stack overlap the mode-driven styles above use, since here two
   slides are meant to be visible at once rather than one crossfading
   into the other. Supplies its own layout and ignores the Transition
   setting entirely, same as Coverflow. */
.galleryforge-slider-style-split .galleryforge-slider-track {
	display: flex;
	gap: 12px;
}

.galleryforge-slider-style-split .galleryforge-slide {
	display: none;
	flex: 1 1 50%;
	min-width: 0;
	height: 100%;
}

.galleryforge-slider-style-split .galleryforge-slide.is-active {
	display: block;
	order: 1;
}

.galleryforge-slider-style-split .galleryforge-slide.is-duo-secondary {
	display: block;
	order: 2;
	opacity: 0.72;
	filter: saturate( 0.85 );
}

.galleryforge-slider-style-split .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

@media ( max-width: 600px ) {
	/* A single narrow column has no room for two side-by-side panes -
	   fall back to showing only the active slide, same as every other
	   style does on a small screen. */
	.galleryforge-slider-style-split .galleryforge-slide.is-duo-secondary {
		display: none;
	}
}

/* Stacked Cards (Pro): a fanned-back deck behind the active card - see
   positionStackedCards() in galleryforge.js, which owns every slide's
   transform/opacity/z-index here (the wraparound distance math mirrors
   positionCoverflow()'s own). Like Coverflow, this replaces the track's
   normal layout entirely and ignores the Transition setting. */
.galleryforge-slider-style-stacked-cards .galleryforge-slider-track {
	display: block;
	overflow: visible;
	/* positionStackedCards() sets z-index up to 100 on the front card so
	   the deck orders correctly against ITSELF - without this, that
	   would also outrank the prev/next arrows and dots (z-index: 3),
	   which are the track's own siblings, not its children, and would
	   intercept clicks meant for them. An explicit z-index (position is
	   already relative, from the base .galleryforge-slider-track rule)
	   gives the track its own stacking context, so those high internal
	   values are only ever compared against each other and never against
	   anything outside the track. */
	position: relative;
	z-index: 0;
}

.galleryforge-slider-style-stacked-cards .galleryforge-slide {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	transition: transform 0.4s ease, opacity 0.4s ease;
	will-change: transform, opacity;
	cursor: pointer;
	pointer-events: auto;
}

.galleryforge-slider-style-stacked-cards .galleryforge-slide .galleryforge-image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	box-shadow: 0 10px 40px rgba( 0, 0, 0, 0.35 );
	border-radius: 8px;
}

/* Stacked Cards' peeking layers need the overflow visible for the same
   reason Coverflow's fan does above. */
.galleryforge-layout-slider.galleryforge-slider-style-stacked-cards {
	overflow: visible;
}

/* Full-Width Slideshow: a plain breakout preset with no other chrome -
   object-fit: cover like Hero, but no caption gradient/typography of its
   own (a slide's overlay layers, if any, still render normally). The
   actual breakout-to-100vw mechanics are shared with the independent
   'full_width' boolean setting below, since either one should look and
   behave identically. */
.galleryforge-slider-style-full-width {
	border-radius: 0;
}

.galleryforge-slider-style-full-width .galleryforge-slider-track {
	height: 70vh;
	min-height: 320px;
}

.galleryforge-slider-style-full-width .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

/* Full-Screen Slideshow: the same plain preset, but filling the entire
   viewport rather than just breaking out to full width - shares the
   'full_screen' boolean's mechanics below. */
.galleryforge-slider-style-full-screen {
	border-radius: 0;
}

.galleryforge-slider-style-full-screen .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

/* Portrait (Pro): a tall, narrow frame suited to portrait/headshot/wedding
   photography where the subject is naturally taller than it is wide -
   object-fit: cover, same crop behavior as Hero/Full-Width, just a
   different aspect ratio. */
.galleryforge-slider-style-portrait .galleryforge-slider-track {
	height: auto;
	aspect-ratio: 4 / 5;
	max-width: 480px;
	margin: 0 auto;
}

.galleryforge-slider-style-portrait .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

@media ( max-width: 782px ) {
	.galleryforge-slider-style-portrait .galleryforge-slider-track {
		max-width: 100%;
	}
}

/* Square (Pro): a 1:1 frame for a consistent, Instagram-style grid feel
   even in the single-image-at-a-time slider layout. */
.galleryforge-slider-style-square .galleryforge-slider-track {
	height: auto;
	aspect-ratio: 1 / 1;
	max-width: 560px;
	margin: 0 auto;
}

.galleryforge-slider-style-square .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

@media ( max-width: 782px ) {
	.galleryforge-slider-style-square .galleryforge-slider-track {
		max-width: 100%;
	}
}

/* Framed (Pro): the one boxed, padded preset - Classic sits flush with no
   chrome of its own and Full-Width/Full-Screen deliberately break out
   edge-to-edge, so this is the only style that reads like a card sitting
   on the page rather than either extreme. The padding lives on the
   gallery wrapper itself (not the track) so the border/shadow frame the
   whole slider, arrows and dots included, not just the image area. */
.galleryforge-slider-style-framed {
	padding: 16px;
	background: #fff;
	border: 1px solid #e2e2e2;
	border-radius: 8px;
	box-shadow: 0 4px 24px rgba( 0, 0, 0, 0.12 );
}

.galleryforge-slider-style-framed .galleryforge-slider-track {
	border-radius: 4px;
}

.galleryforge-slider-style-framed .galleryforge-slide .galleryforge-image {
	object-fit: cover;
}

@media ( max-width: 782px ) {
	.galleryforge-slider-style-framed {
		padding: 8px;
	}
}

/* The two independent breakout booleans (see GF_Core::get_default_settings())
   - these apply on top of ANY slider_style, including Hero/Cinematic/
   Coverflow, using the standard CSS "full-bleed" technique: pull the
   element out to the edges of the viewport with negative margins sized
   off its own offset from the left edge, regardless of how deeply it's
   nested inside a theme's boxed content column.

   !important is deliberate here, not a specificity shortcut taken for
   convenience: a block theme's own "is-layout-constrained" layout CSS
   centers its direct children with `margin-left/right: auto !important`
   and a fixed max-width, which otherwise silently wins over a plain
   (non-!important) rule of equal or lower specificity and leaves the
   slider stuck at the theme's normal content width - exactly the
   opposite of what turning this setting on asked for. The 'alignfull'
   class GF_Layout_Slider also adds already satisfies that same theme
   CSS on its own in a block theme (see there); these rules are what
   make the setting work correctly EVERYWHERE ELSE too - classic themes,
   page builder columns, or a block theme's alignfull support disabled. */
.galleryforge-slider-fullwidth,
.galleryforge-slider-fullscreen {
	width: 100vw !important;
	max-width: 100vw !important;
	position: relative;
	left: 50% !important;
	right: 50% !important;
	margin-left: -50vw !important;
	margin-right: -50vw !important;
	border-radius: 0;
}

.galleryforge-slider-fullscreen {
	height: 100vh;
}

.galleryforge-slider-fullscreen .galleryforge-slider-track {
	height: 100vh;
}

/* ------------------------------------------------------------------ */
/* Overlay layers (heading / text / button) drawn on top of a slide     */
/*                                                                      */
/* Positioned to cover the whole slide but pointer-events: none by      */
/* default so the image/lightbox link underneath one stays clickable -  */
/* only a button layer (which needs to be clickable itself) turns       */
/* pointer-events back on for itself specifically.                      */
/* ------------------------------------------------------------------ */

.galleryforge-slide-layers {
	position: absolute;
	inset: 0;
	z-index: 3;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-end;
	gap: clamp( 6px, 1.5vw, 14px );
	padding: clamp( 16px, 4vw, 56px );
	pointer-events: none;
}

.galleryforge-layer {
	margin: 0;
	color: #fff;
	text-shadow: 0 1px 3px rgba( 0, 0, 0, 0.6 );
	opacity: 0;
	transition-property: opacity, transform;
	transition-duration: 0.6s;
	transition-timing-function: ease;
}

/* Entrance animations: each sets the layer's OFF-screen/hidden starting
   transform; .galleryforge-layer-in (added by galleryforge.js, Phase 3,
   when the slide becomes .is-active) animates every one of them back to
   opacity: 1/transform: none via the shared transition above. Removed
   again when .is-active leaves the slide so the animation is ready to
   replay next time the slide comes back around. */
.galleryforge-layer-anim-fade-up {
	transform: translateY( 24px );
}

.galleryforge-layer-anim-fade-down {
	transform: translateY( -24px );
}

.galleryforge-layer-anim-fade-in {
	transform: none;
}

.galleryforge-layer-anim-zoom-in {
	transform: scale( 0.85 );
}

.galleryforge-layer-anim-slide-left {
	transform: translateX( -60px );
}

.galleryforge-layer-anim-slide-right {
	transform: translateX( 60px );
}

.galleryforge-layer-in {
	opacity: 1;
	transform: none;
}

/* galleryforge.js toggles this on for one frame when a slide loses
   .is-active, so its layers snap straight back to hidden instead of
   animating out over the normal transition duration - see hideLayers(). */
.galleryforge-layer-resetting {
	transition: none !important;
}

/* The WebGL morph engine's single overlay canvas (liquid/mesh-warp only -
   see runWebGLMorph() in galleryforge.js), sized and positioned to cover
   the track for exactly the duration of one slide transition, then
   removed entirely. */
.galleryforge-morph-canvas {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 5;
	pointer-events: none;
}

/* Screen-reader-only live region galleryforge.js writes each slide's
   aria-label into on a slide change (see announceSlide() in
   galleryforge.js) - visually hidden via the standard "clip" technique
   rather than display:none/visibility:hidden, both of which would also
   hide it from assistive tech, defeating the point. */
.galleryforge-sr-announcer {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect( 0, 0, 0, 0 );
	white-space: nowrap;
	border: 0;
}

/* Scoped under .galleryforge-slide-layers (every layer's real parent -
   see GF_Layout_Base::layers_html()) rather than bare .galleryforge-
   layer-heading/-text/-button, even though nothing else on the page
   needs the ancestor to tell these apart. A block theme's global styles
   (its own #global-styles-inline-css) reset h1-h6 via a
   ":root :where(h3)"-shaped rule specifically so plugin/theme CSS can
   win by matching normal specificity rules - but "normal specificity"
   for a single class selector (0,1,0) TIES that reset's own (0,1,0), so
   which one actually wins ends up depending on which stylesheet happens
   to print later in <head>, which is outside this plugin's control and
   isn't reliable. Two classes (0,2,0) wins outright regardless of print
   order - the fix WordPress's own docs recommend for exactly this
   situation, rather than something to leave to enqueue-order luck. */
.galleryforge-slide-layers .galleryforge-layer-heading {
	font-size: clamp( 1.25rem, 1.5vw + 1rem, 2.75rem );
	line-height: 1.2;
	font-weight: 700;
}

.galleryforge-slide-layers .galleryforge-layer-text {
	font-size: clamp( 0.9rem, 0.5vw + 0.8rem, 1.25rem );
	line-height: 1.5;
	max-width: 46ch;
}

.galleryforge-slide-layers .galleryforge-layer-button {
	display: inline-block;
	pointer-events: auto;
	text-decoration: none;
	text-shadow: none;
	color: #1e1e1e;
	background: #fff;
	font-weight: 600;
	font-size: clamp( 0.85rem, 0.3vw + 0.8rem, 1.05rem );
	padding: clamp( 8px, 1vw, 14px ) clamp( 16px, 2vw, 28px );
	border-radius: 999px;
	transition: opacity 0.6s ease, transform 0.6s ease, background 0.15s ease;
}

.galleryforge-slide-layers .galleryforge-layer-button:hover {
	background: #f0f0f1;
}

@media ( max-width: 600px ) {
	.galleryforge-slide-layers {
		gap: 6px;
		padding: 16px;
	}

	.galleryforge-slide-layers .galleryforge-layer-text {
		max-width: 100%;
	}

	/* An admin's optional per-layer manual override (see
	   GF_Layout_Base::layers_html(), which sets --gf-layer-mobile-
	   font-size as an inline custom property only on a layer that has
	   one) - falls back to the same fluid clamp() every layer already
	   uses above when no override was set, so this changes nothing for
	   the vast majority of layers that don't have one. Kept at the same
	   .galleryforge-slide-layers-scoped specificity as the base rules
	   above, for the same reason those are scoped that way. */
	.galleryforge-slide-layers .galleryforge-layer-heading {
		font-size: var( --gf-layer-mobile-font-size, clamp( 1.25rem, 1.5vw + 1rem, 2.75rem ) );
	}

	.galleryforge-slide-layers .galleryforge-layer-text {
		font-size: var( --gf-layer-mobile-font-size, clamp( 0.9rem, 0.5vw + 0.8rem, 1.25rem ) );
	}

	.galleryforge-slide-layers .galleryforge-layer-button {
		font-size: var( --gf-layer-mobile-font-size, clamp( 0.85rem, 0.3vw + 0.8rem, 1.05rem ) );
	}
}

/* ------------------------------------------------------------------ */
/* Autoplay progress bar                                                */
/*                                                                      */
/* Static scaffold only - galleryforge.js (Phase 3) sets the bar's      */
/* transition-duration to the gallery's autoplay-speed, toggles it      */
/* between 0% and 100% width, and restarts it on every show().          */
/* ------------------------------------------------------------------ */

.galleryforge-slider-progress {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 3px;
	background: rgba( 255, 255, 255, 0.25 );
	z-index: 4;
}

.galleryforge-slider-progress-bar {
	height: 100%;
	width: 0%;
	background: #fff;
}

/* ------------------------------------------------------------------ */
/* Before / After comparison                                           */
/* ------------------------------------------------------------------ */

.galleryforge-ba-pair {
	margin: 0 0 1.5em;
}

.galleryforge-ba-stage {
	position: relative;
	overflow: hidden;
	border-radius: 4px;
	user-select: none;
	touch-action: pan-y; /* the browser keeps vertical scrolling; the handle takes horizontal drags */
}

.galleryforge-layout-before_after[data-orientation="vertical"] .galleryforge-ba-handle {
	touch-action: none; /* a vertical comparison drags along the scroll axis, so the handle itself must own the touch */
}

.galleryforge-ba-after-wrap,
.galleryforge-ba-before-wrap {
	position: relative;
}

.galleryforge-ba-after-wrap .galleryforge-image,
.galleryforge-ba-before-wrap .galleryforge-image {
	width: 100%;
	display: block;
}

.galleryforge-ba-before-wrap {
	/* Covers the whole stage (so the "before" photo is the same size as
	   the "after" one) and is clipped at the divider - the old approach of
	   shrinking the wrapper squashed the before image instead of clipping it. */
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	overflow: hidden;
	clip-path: inset( 0 calc( 100% - var( --galleryforge-ba-start, 50% ) ) 0 0 );
}

.galleryforge-layout-before_after[data-orientation="vertical"] .galleryforge-ba-before-wrap {
	clip-path: inset( 0 0 calc( 100% - var( --galleryforge-ba-start, 50% ) ) 0 );
}

.galleryforge-ba-label {
	position: absolute;
	top: 10px;
	padding: 3px 10px;
	background: rgba( 0, 0, 0, 0.55 );
	color: #fff;
	font-size: 12px;
	border-radius: 3px;
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.galleryforge-ba-label-before {
	left: 10px;
}

.galleryforge-ba-label-after {
	right: 10px;
}

.galleryforge-ba-handle {
	position: absolute;
	top: 0;
	left: var( --galleryforge-ba-start, 50% );
	transform: translateX( -50% );
	width: 40px;
	height: 100%;
	cursor: ew-resize;
	display: flex;
	align-items: center;
	justify-content: center;
}

.galleryforge-layout-before_after[data-orientation="vertical"] .galleryforge-ba-handle {
	left: 0;
	top: var( --galleryforge-ba-start, 50% );
	transform: translateY( -50% );
	width: 100%;
	height: 40px;
	cursor: ns-resize;
}

.galleryforge-ba-handle::before {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 50%;
	width: 2px;
	background: #fff;
}

.galleryforge-layout-before_after[data-orientation="vertical"] .galleryforge-ba-handle::before {
	left: 0;
	right: 0;
	top: 50%;
	bottom: auto;
	width: auto;
	height: 2px;
}

.galleryforge-ba-handle-grip {
	position: relative;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 4px rgba( 0, 0, 0, 0.4 );
}

.galleryforge-ba-caption {
	margin-top: 6px;
	font-size: 13px;
	color: #50575e;
	text-align: center;
}

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

.galleryforge-lightbox-overlay {
	position: fixed;
	inset: 0;
	background: rgba( 0, 0, 0, 0.9 );
	z-index: 100000;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 40px;
}

.galleryforge-lightbox-figure {
	max-width: 100%;
	max-height: 100%;
	margin: 0;
	text-align: center;
}

.galleryforge-lightbox-figure img {
	max-width: 100%;
	/* A shorter cap than the no-strip 80vh, leaving room below for the
	   thumbnail filmstrip without the two ever fighting for space. When
	   the strip is hidden (single-image gallery, or turned off) this is a
	   little more conservative than it needs to be, but not enough to be
	   worth a second, strip-aware value. */
	max-height: 75vh;
	display: block;
	margin: 0 auto;
}

.galleryforge-lightbox-caption {
	color: #fff;
	margin-top: 12px;
	font-size: 14px;
}

/* "Add to cart" in the lightbox (Pro + WooCommerce - see GF_Shop) - a
   plain block under the caption/EXIF line rather than a toolbar icon,
   since it needs to carry real text (label + price), not just an icon. */
.galleryforge-lightbox-shop {
	margin-top: 12px;
}

.galleryforge-lightbox-shop-button {
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	padding: 10px 20px;
	border-radius: 999px;
	background: #fff;
	color: #1d2327;
	font-size: 14px;
	font-weight: 700;
	text-decoration: none;
	transition: transform 0.15s ease, opacity 0.2s ease;
}

.galleryforge-lightbox-shop-button:hover,
.galleryforge-lightbox-shop-button:focus-visible {
	opacity: 0.85;
}

.galleryforge-lightbox-shop-button:active {
	transform: scale( 0.97 );
}

.galleryforge-lightbox-theme-light .galleryforge-lightbox-shop-button {
	background: #1d2327;
	color: #fff;
}

/* ---- Thumbnail filmstrip ------------------------------------------- */

.galleryforge-lightbox-thumbs {
	display: flex;
	gap: 8px;
	margin-top: 16px;
	max-width: 100%;
	overflow-x: auto;
	padding: 4px 2px 8px;
}

.galleryforge-lightbox-thumb {
	flex: 0 0 auto;
	width: 56px;
	height: 56px;
	padding: 0;
	border: 2px solid transparent;
	border-radius: 4px;
	overflow: hidden;
	background: rgba( 255, 255, 255, 0.08 );
	cursor: pointer;
	opacity: 0.6;
	transition: opacity 0.2s ease, border-color 0.2s ease;
}

.galleryforge-lightbox-thumb:hover {
	opacity: 0.9;
}

.galleryforge-lightbox-thumb.is-active {
	opacity: 1;
	border-color: #fff;
}

.galleryforge-lightbox-thumb img {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}

.galleryforge-lightbox-close,
.galleryforge-lightbox-fullscreen,
.galleryforge-lightbox-prev,
.galleryforge-lightbox-next {
	position: fixed;
	background: rgba( 255, 255, 255, 0.12 );
	color: #fff;
	border: none;
	cursor: pointer;
	z-index: 100001;
	transition: background 0.2s ease;
}

.galleryforge-lightbox-close:hover,
.galleryforge-lightbox-fullscreen:hover,
.galleryforge-lightbox-prev:hover,
.galleryforge-lightbox-next:hover {
	background: rgba( 255, 255, 255, 0.28 );
}

.galleryforge-lightbox-close {
	top: 20px;
	right: 20px;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	font-size: 18px;
}

.galleryforge-lightbox-fullscreen {
	top: 20px;
	right: 70px;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	font-size: 15px;
}

.galleryforge-lightbox-prev,
.galleryforge-lightbox-next {
	top: 50%;
	transform: translateY( -50% );
	width: 48px;
	height: 48px;
	border-radius: 50%;
	font-size: 18px;
}

.galleryforge-lightbox-prev {
	left: 20px;
}

.galleryforge-lightbox-next {
	right: 20px;
}

body.galleryforge-lightbox-open {
	overflow: hidden;
}

/*
 * Image protection (deterrent only - see galleryforge.js's
 * initImageProtection() comment). The JS handles right-click and
 * drag-to-save; these two properties cover what JS event handlers can't:
 * iOS/Android's long-press "save image" callout, and the visual
 * distraction of an image's own alt text getting selected/highlighted
 * when a visitor tries to drag it.
 */
.galleryforge[data-protect-images="true"] img {
	-webkit-touch-callout: none;
	user-select: none;
}

.galleryforge-lightbox-overlay.galleryforge-protect-images .galleryforge-lightbox-figure img {
	-webkit-touch-callout: none;
	user-select: none;
}

/* Video items swap the lightbox's <img> for this wrap (an <iframe> for
   YouTube/Vimeo, a <video> for a direct file URL) - fixed 16:9 box since,
   unlike a photo, neither embed type has an intrinsic size CSS can use
   the way max-width/max-height work on img. */
.galleryforge-lightbox-video-wrap {
	width: min( 90vw, 960px );
	max-height: 75vh;
	aspect-ratio: 16 / 9;
	margin: 0 auto;
}

.galleryforge-lightbox-video-wrap iframe,
.galleryforge-lightbox-video-wrap video {
	width: 100%;
	height: 100%;
	display: block;
	border: 0;
	background: #000;
}

/* ------------------------------------------------------------------ */
/* Albums                                                              */
/* ------------------------------------------------------------------ */

/* Optional intro/summary text (0.57.14), typed in the album editor,
   shown above the cover tiles. Deliberately minimal styling - inherits
   the theme's own paragraph/heading look rather than imposing one, same
   "don't fight the theme" spirit as the rest of this stylesheet. */
.galleryforge-album-description {
	margin-bottom: 20px;
}
.galleryforge-album-description p:last-child {
	margin-bottom: 0;
}

.galleryforge-album-tiles {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( 150px, 1fr ) );
	gap: 12px;
	margin-bottom: 28px;
}

/* A fixed "Tiles per row" (album editor's Layout box, 0.57.2) - same
   "custom property + min() per breakpoint" shape as the Grid layout's
   own Columns setting, so a fixed count still narrows sensibly on
   phones/tablets instead of squeezing every column onto a small screen. */
.galleryforge-album-tiles.galleryforge-album-tiles-fixed {
	grid-template-columns: repeat( var( --galleryforge-album-columns, 4 ), 1fr );
}

@media ( max-width: 900px ) {
	.galleryforge-album-tiles.galleryforge-album-tiles-fixed { grid-template-columns: repeat( min( var( --galleryforge-album-columns, 4 ), 3 ), 1fr ); }
}

@media ( max-width: 600px ) {
	.galleryforge-album-tiles.galleryforge-album-tiles-fixed { grid-template-columns: repeat( min( var( --galleryforge-album-columns, 4 ), 2 ), 1fr ); }
}

.galleryforge-album-tile {
	position: relative;
	display: block;
	aspect-ratio: 1 / 1;
	border-radius: 6px;
	overflow: hidden;
	background: #f0f0f1;
	text-decoration: none;
	box-shadow: 0 0 0 0 transparent;
	transition: box-shadow 0.2s ease;
}

.galleryforge-album-tile.is-active {
	box-shadow: 0 0 0 3px var( --galleryforge-album-accent, #1e1e1e );
}

.galleryforge-album-tile-cover {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.galleryforge-album-tile-cover-empty {
	display: block;
	width: 100%;
	height: 100%;
}

/* A password-protected or private member gallery's tile - no cover photo
   leaks through, just a plain lock glyph on the tile's own neutral
   background (see .galleryforge-album-tile above), same spirit as the
   plain empty-gallery placeholder just above. */
.galleryforge-album-tile-cover-locked {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
}

.galleryforge-album-tile-cover-locked::before {
	content: '\1F512';
	font-size: 28px;
	opacity: 0.35;
}

.galleryforge-album-tile-title {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 8px 10px;
	background: linear-gradient( to top, rgba( 0, 0, 0, 0.75 ), rgba( 0, 0, 0, 0 ) );
	color: #fff;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
}

.galleryforge-album-section-title {
	margin: 0 0 12px;
}

.galleryforge-album-section-hidden {
	display: none;
}

/* ------------------------------------------------------------------ */
/* Accessibility overrides                                             */
/*                                                                      */
/* Deliberately placed at the very end of this stylesheet, after every  */
/* rule either block might need to override. A media-query block's     */
/* rules take their position in the cascade from where they SIT in the  */
/* source, not from matching a query - so an earlier reduced-motion/    */
/* forced-colors rule can still lose to a later, equal-specificity      */
/* unconditional rule even while its query is actively matching. That   */
/* exact bug was caught here (the forced-colors progress-bar override   */
/* was silently losing to the plain .galleryforge-slider-progress rule  */
/* declared further down the file) and fixed by moving both blocks      */
/* below every selector they touch, rather than by raising specificity  */
/* with extra !important flags. Keep any future accessibility override  */
/* down here too, after whatever base rule it overrides.                */
/* ------------------------------------------------------------------ */

/* Respects the visitor's OS-level "reduce motion" preference across every
   animated mechanic Phases 1-3 added: Ken Burns' zoom/pan, the Morph
   engine's clip-path wipe and WebGL liquid/mesh-warp shaders, and each
   overlay layer's staggered entrance. Nothing here removes the underlying
   STATE changes (a slide still becomes .is-active, a layer still becomes
   .galleryforge-layer-in) - only the animated transition between states,
   so the slider still functions identically, just without motion. */
@media ( prefers-reduced-motion: reduce ) {
	/* Ken Burns: stop the zoom/pan keyframe animation outright rather than
	   merely shortening it - a still image at 1x scale, not a slower zoom. */
	.galleryforge-kenburns-play {
		animation: none;
	}

	/* Focus Zoom: same reasoning as Ken Burns above - freeze at rest
	   (scale(1) via the base .galleryforge-image rule, since neither
	   -play class ever applies its keyframe) rather than play a
	   shortened version of the ambient zoom. */
	.galleryforge-focus-zoom-in-play,
	.galleryforge-focus-zoom-out-play {
		animation: none;
	}

	/* Morph: skip WebGL and the clip-path wipe, falling back to the same
	   flat opacity crossfade cross-dissolve already uses. galleryforge.js
	   also checks this preference before ever calling runWebGLMorph()/
	   runClipPathMorph() (see galleryforge.js) so no canvas is created and
	   no clip-path is set in the first place; this rule is the CSS-only
	   backstop in case JS is slow to apply it or the two ever drift. */
	.galleryforge-slider-mode-morph .galleryforge-slide {
		transition: opacity 0.7s ease;
		clip-path: none !important;
	}

	/* Fade Zoom: drop the scale component and fall back to the same plain
	   opacity crossfade plain Fade uses - the zoom is the motion this
	   preference asks to remove, the crossfade itself is left alone (see
	   the plain slide/fade precedent above this media query). */
	.galleryforge-slider-mode-fade-zoom .galleryforge-slide {
		transform: none;
		transition: opacity 0.7s ease;
	}

	/* Cover / Wipe / Fade Blur (0.58.77): the same plain crossfade every
	   other suppressed mode falls back to. Cover and Wipe's motion lives
	   in inline styles / clip-path on the slide (not the track), so the
	   track rule at the bottom of this file never reached them; the JS
	   side (runCoverTransition/runCubeTransition) also returns early. */
	.galleryforge-slider-mode-cover .galleryforge-slide,
	.galleryforge-slider-mode-wipe .galleryforge-slide {
		transform: none !important;
		clip-path: none !important;
		opacity: 0;
		transition: opacity 0.7s ease;
	}
	.galleryforge-slider-mode-cover .galleryforge-slide.is-active,
	.galleryforge-slider-mode-wipe .galleryforge-slide.is-active {
		opacity: 1;
	}
	.galleryforge-slider-mode-fade-blur .galleryforge-slide {
		filter: none !important;
		transition: opacity 0.7s ease;
	}

	/* Flip: rotation is exactly the kind of motion this preference asks
	   to remove, so fall back to the same plain opacity crossfade plain
	   Fade uses rather than rotating in. */
	.galleryforge-slider-mode-flip .galleryforge-slide {
		transform: none;
		transition: opacity 0.7s ease;
	}

	/* Overlay layers: no stagger, no motion - appear/disappear instantly
	   in their final state. transition: none on BOTH the base class and
	   .galleryforge-layer-in is required since the base class is what
	   declares the transition-property this would otherwise still run. */
	.galleryforge-layer {
		transition: none !important;
		opacity: 1;
		transform: none;
	}

	/* Cube: rotation is exactly the kind of motion this preference asks
	   to remove, same rationale as Flip above - fall back to the shared
	   plain opacity crossfade instead of turning. */
	.galleryforge-slider-mode-cube .galleryforge-slide {
		transform: none !important;
		transition: opacity 0.7s ease;
	}

	/* Circle Reveal: an expanding circle is still motion even though it
	   never moves anything's position - collapse it to the same plain
	   opacity crossfade the fade family uses rather than growing a ring. */
	.galleryforge-slider-mode-circle-reveal .galleryforge-slide {
		clip-path: none !important;
		opacity: 0;
		transition: opacity 0.7s ease;
	}

	.galleryforge-slider-mode-circle-reveal .galleryforge-slide.is-active {
		opacity: 1;
	}

	/* Blinds: galleryforge.js's runBlindsTransition() already skips the
	   staggered opening animation once this preference is set (see
	   PREFERS_REDUCED_MOTION there); this is the CSS-only backstop for
	   the same reason Morph keeps one above - so a slat is never left
	   mid-animation if this preference changes before that check runs. */
	.galleryforge-blinds-slat {
		transition: none !important;
		transform: scaleY( 0 ) !important;
	}
}

/* Windows High Contrast Mode / forced-colors: the browser already
   overrides most author colors with the active system palette, which is
   normally enough to keep plain text and borders legible on its own. What
   it can't fix by itself is anything relying purely on a translucent
   rgba() background for visibility - forced-colors flattens those, and
   without an explicit system-color fallback the arrows, dots, and
   progress bar below would each collapse to a single flat Canvas color,
   some of them disappearing entirely against their surroundings.
   forced-color-adjust: none opts each one back into using the specific
   system colors declared here instead of the browser's default
   flattening. Only the elements that actually depended on translucency
   are touched - text, layer, and other already-opaque colors elsewhere
   in this stylesheet are left to the browser's own forced-colors
   handling, which already renders them correctly. */
@media ( forced-colors: active ) {
	.galleryforge-slider-arrow {
		background: Canvas;
		color: CanvasText;
		border: 1px solid CanvasText;
		forced-color-adjust: none;
	}

	.galleryforge-slider-arrow:hover {
		background: Highlight;
		color: HighlightText;
	}

	.galleryforge-slider-dot {
		background: Canvas;
		border: 1px solid CanvasText;
		forced-color-adjust: none;
	}

	.galleryforge-slider-dot:hover {
		background: Highlight;
	}

	.galleryforge-slider-dot.is-active {
		background: CanvasText;
	}

	.galleryforge-slider-music-toggle {
		background: Canvas;
		color: CanvasText;
		border: 1px solid CanvasText;
		forced-color-adjust: none;
	}

	.galleryforge-slider-music-toggle:hover,
	.galleryforge-slider-music-toggle.is-playing {
		background: Highlight;
		color: HighlightText;
	}

	/* Without forced-color-adjust: none here, the track and its fill
	   would both flatten to the same system Canvas color and the whole
	   bar would visually disappear - GrayText for the empty track keeps
	   it distinguishable from the CanvasText-colored fill. */
	.galleryforge-slider-progress {
		background: GrayText;
		forced-color-adjust: none;
	}

	.galleryforge-slider-progress-bar {
		background: CanvasText;
		forced-color-adjust: none;
	}

	/* An explicit, guaranteed outline on the slide container itself when
	   it receives focus (see galleryforge.js's userInitiated focus
	   management) - belt-and-suspenders alongside whatever outline the
	   browser's own forced-colors handling already supplies by default,
	   since relying solely on that default leaves how visible it actually
	   is to however consistently each browser/OS combination renders it.
	   Highlight is the forced-colors-reserved color for "this is the
	   selected/focused thing," so it reads unambiguously as a focus
	   indicator rather than blending into the plain CanvasText borders
	   used above. A negative outline-offset draws it INSIDE the slide's
	   own box rather than outside, so it can't be clipped by the
	   overflow:hidden the stacked transition modes put on the track. */
	.galleryforge-slide:focus {
		outline: 3px solid Highlight;
		outline-offset: -3px;
	}
}

/* -------------------------------------------------------------- */
/* Access control: the password prompt / private-gallery message a  */
/* visitor sees INSTEAD OF the gallery when GF_Core::is_locked()    */
/* says they can't view it yet (see GF_Render::locked_html()).      */
/* Deliberately plain, fixed light colors rather than `inherit` -   */
/* same reasoning as .galleryforge-filter-btn above: this card's    */
/* own background is always white regardless of the surrounding     */
/* theme (including a dark one), so its text needs to always be     */
/* dark too rather than silently inheriting an unreadable color.    */
/* -------------------------------------------------------------- */

.galleryforge-locked {
	max-width: 420px;
	margin: 0 auto;
	padding: 28px 24px;
	border: 1px solid rgba( 0, 0, 0, 0.15 );
	border-radius: 8px;
	background: #fff;
	color: #1e1e1e;
	text-align: center;
	font-size: 14px;
	line-height: 1.6;
}

.galleryforge-locked-message {
	margin: 0;
}

.galleryforge-locked-message a {
	color: #1e1e1e;
	text-decoration: underline;
}

/* WordPress core's own get_the_password_form() markup - a plain <form>,
   <p>, <label> and two <input>s with no classes of its own beyond
   .post-password-form, so every rule here targets that core class
   directly rather than anything GalleryForge added. */
.galleryforge-locked-password .post-password-form p {
	margin: 0 0 14px;
}

.galleryforge-locked-password .post-password-form label {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	font-weight: 600;
}

.galleryforge-locked-password .post-password-form input[type="password"] {
	width: 100%;
	max-width: 240px;
	padding: 8px 12px;
	border: 1px solid rgba( 0, 0, 0, 0.25 );
	border-radius: 6px;
	font: inherit;
	font-size: 14px;
	color: #1e1e1e;
	background: #fff;
}

.galleryforge-locked-password .post-password-form input[type="submit"] {
	margin-top: 4px;
	padding: 8px 20px;
	border: none;
	border-radius: 999px;
	background: #1e1e1e;
	color: #fff;
	font: inherit;
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.2s ease;
}

.galleryforge-locked-password .post-password-form input[type="submit"]:hover {
	background: #3a3a3a;
}

/* Download slideshow video (Pro) */
.galleryforge-video-download { margin: 14px 0 0; text-align: center; }
.galleryforge-video-download-button { display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; border-radius: 999px; background: #1d2327; color: #fff !important; text-decoration: none !important; font-size: 14px; font-weight: 600; letter-spacing: .01em; transition: background .15s, transform .15s; }
.galleryforge-video-download-button:hover { background: #2271b1; transform: translateY(-1px); }
.galleryforge-video-download-button svg { flex: 0 0 auto; }

/* ---- Slider navigation choices (0.50.0): arrow styles, dot styles, accent ---- */
.galleryforge-slider { --galleryforge-gf-accent: #fff; }
.galleryforge-slider-arrow { display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.galleryforge-slider-arrow svg { width: 55%; height: 55%; }
.galleryforge-slider[data-arrow-size="small"] .galleryforge-slider-arrow { width: 34px; height: 34px; }
.galleryforge-slider[data-arrow-size="large"] .galleryforge-slider-arrow { width: 62px; height: 62px; }
.galleryforge-slider[data-arrow-style="minimal"] .galleryforge-slider-arrow { background: transparent; border: 0; filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); }
.galleryforge-slider[data-arrow-style="minimal"] .galleryforge-slider-arrow svg { width: 80%; height: 80%; stroke-width: 1.6; }
.galleryforge-slider[data-arrow-style="minimal"] .galleryforge-slider-arrow:hover { background: transparent; color: var(--galleryforge-gf-accent); }
.galleryforge-slider[data-arrow-style="square"] .galleryforge-slider-arrow { border-radius: 4px; border: 0; background: rgba(0,0,0,.6); }
.galleryforge-slider[data-arrow-style="square"] .galleryforge-slider-prev { left: 0; border-radius: 0 4px 4px 0; }
.galleryforge-slider[data-arrow-style="square"] .galleryforge-slider-next { right: 0; border-radius: 4px 0 0 4px; }
.galleryforge-slider[data-arrow-style="outside"] { padding-left: 56px; padding-right: 56px; }
.galleryforge-slider[data-arrow-style="outside"] .galleryforge-slider-arrow { background: transparent; border: 1px solid currentColor; color: inherit; }
.galleryforge-slider[data-arrow-style="outside"] .galleryforge-slider-prev { left: 0; } .galleryforge-slider[data-arrow-style="outside"] .galleryforge-slider-next { right: 0; }
.galleryforge-slider[data-arrow-style="outside"] .galleryforge-slider-arrow:hover { background: var(--galleryforge-gf-accent); color: #000; }
@media (max-width: 600px) { .galleryforge-slider[data-arrow-style="outside"] { padding-left: 40px; padding-right: 40px; } }
.galleryforge-slider[data-arrow-show="hover"] .galleryforge-slider-arrow { opacity: 0; transition: opacity .25s, background .2s, transform .2s; }
.galleryforge-slider[data-arrow-show="hover"]:hover .galleryforge-slider-arrow, .galleryforge-slider[data-arrow-show="hover"]:focus-within .galleryforge-slider-arrow { opacity: 1; }
@media (hover: none) { .galleryforge-slider[data-arrow-show="hover"] .galleryforge-slider-arrow { opacity: 1; } }
.galleryforge-slider-arrow:hover { border-color: var(--galleryforge-gf-accent); }
.galleryforge-slider-dot.is-active { background: var(--galleryforge-gf-accent); }
/* dots: lines */
.galleryforge-slider-dots--lines { gap: 6px; }
.galleryforge-slider-dots--lines .galleryforge-slider-dot { width: 28px; height: 4px; border-radius: 2px; border: 0; background: rgba(255,255,255,.45); }
.galleryforge-slider-dots--lines .galleryforge-slider-dot.is-active { transform: none; width: 44px; background: var(--galleryforge-gf-accent); }
/* dots: numbers */
.galleryforge-slider-dots--numbers { gap: 6px; }
.galleryforge-slider-dots--numbers .galleryforge-slider-dot { width: auto; min-width: 28px; height: 28px; padding: 0 8px; border-radius: 14px; background: rgba(0,0,0,.5); color: #fff; border: 1px solid rgba(255,255,255,.35); font-size: 12px; font-weight: 600; line-height: 26px; font-variant-numeric: tabular-nums; }
.galleryforge-slider-dots--numbers .galleryforge-slider-dot.is-active { transform: none; background: var(--galleryforge-gf-accent); color: #000; border-color: transparent; }
/* dots: thumbnails */
.galleryforge-slider-dots--thumbs { gap: 6px; flex-wrap: nowrap; overflow-x: auto; justify-content: safe center; padding: 0 12px; scrollbar-width: none; }
.galleryforge-slider-dots--thumbs::-webkit-scrollbar { display: none; }
.galleryforge-slider-dots--thumbs .galleryforge-slider-dot { width: 56px; height: 40px; border-radius: 3px; border: 2px solid transparent; background: #222; overflow: hidden; flex: 0 0 auto; opacity: .6; transition: opacity .2s, border-color .2s; }
.galleryforge-slider-dots--thumbs .galleryforge-slider-dot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.galleryforge-slider-dots--thumbs .galleryforge-slider-dot.is-active { transform: none; opacity: 1; border-color: var(--galleryforge-gf-accent); }
/* dots below the image instead of over it */
.galleryforge-slider[data-dots-position="below"] { padding-bottom: 44px; }
.galleryforge-slider[data-dots-position="below"] .galleryforge-slider-dots { bottom: 8px; }
.galleryforge-slider[data-dots-position="below"] .galleryforge-slider-dot { background: rgba(120,120,120,.4); border-color: transparent; }
.galleryforge-slider[data-dots-position="below"] .galleryforge-slider-dots--numbers .galleryforge-slider-dot { background: rgba(120,120,120,.25); color: inherit; }
.galleryforge-slider[data-dots-position="below"].galleryforge-slider[data-dots-position="below"] .galleryforge-slider-dots--thumbs { bottom: 0; }
.galleryforge-slider[data-dots-position="below"]:has(.galleryforge-slider-dots--thumbs) { padding-bottom: 52px; }
/* counter "3 / 12" */
.galleryforge-slider-counter { position: absolute; right: 16px; bottom: 16px; z-index: 3; background: rgba(0,0,0,.55); color: #fff; font-size: 12px; font-variant-numeric: tabular-nums; padding: 4px 10px; border-radius: 999px; letter-spacing: .04em; }
.galleryforge-slider[data-dots-position="below"] .galleryforge-slider-counter { bottom: 10px; background: transparent; color: inherit; opacity: .7; }
.galleryforge-slider .galleryforge-slider-progress-bar { background: var(--galleryforge-gf-accent); }

/* ---- Grid / Justified: more hover effects (0.50.1) ---- */
.galleryforge-hover-effect-fade .galleryforge-grid-cell .galleryforge-image, .galleryforge-hover-effect-fade .galleryforge-justified-cell .galleryforge-image { transition: opacity .3s ease; }
.galleryforge-hover-effect-fade .galleryforge-grid-cell:hover .galleryforge-image, .galleryforge-hover-effect-fade .galleryforge-justified-cell:hover .galleryforge-image { opacity: .72; }
.galleryforge-hover-effect-lift .galleryforge-grid-cell, .galleryforge-hover-effect-lift .galleryforge-justified-cell { transition: transform .25s ease, box-shadow .25s ease; }
.galleryforge-hover-effect-lift .galleryforge-grid-cell:hover, .galleryforge-hover-effect-lift .galleryforge-justified-cell:hover { transform: translateY(-6px); box-shadow: 0 14px 28px rgba(0,0,0,.22); z-index: 2; }
.galleryforge-hover-effect-grayscale .galleryforge-grid-cell .galleryforge-image, .galleryforge-hover-effect-grayscale .galleryforge-justified-cell .galleryforge-image { filter: grayscale(1); transition: filter .4s ease, transform .4s ease; }
.galleryforge-hover-effect-grayscale .galleryforge-grid-cell:hover .galleryforge-image, .galleryforge-hover-effect-grayscale .galleryforge-justified-cell:hover .galleryforge-image { filter: grayscale(0); transform: scale(1.03); }
.galleryforge-hover-effect-blur .galleryforge-grid-cell .galleryforge-image, .galleryforge-hover-effect-blur .galleryforge-justified-cell .galleryforge-image { transition: filter .35s ease, opacity .35s ease; }
.galleryforge-hover-effect-blur:hover .galleryforge-grid-cell:not(:hover) .galleryforge-image, .galleryforge-hover-effect-blur:hover .galleryforge-justified-cell:not(:hover) .galleryforge-image { filter: blur(3px) brightness(.85); opacity: .75; }
.galleryforge-hover-effect-frame .galleryforge-grid-cell::before, .galleryforge-hover-effect-frame .galleryforge-justified-cell::before { content: ""; position: absolute; inset: 12px; border: 1px solid rgba(255,255,255,.85); opacity: 0; transform: scale(1.06); transition: opacity .3s ease, transform .3s ease; pointer-events: none; z-index: 2; }
.galleryforge-hover-effect-frame .galleryforge-grid-cell:hover::before, .galleryforge-hover-effect-frame .galleryforge-justified-cell:hover::before { opacity: 1; transform: scale(1); }
.galleryforge-hover-effect-tilt .galleryforge-grid-inner, .galleryforge-hover-effect-tilt { perspective: 900px; }
.galleryforge-hover-effect-tilt .galleryforge-grid-cell, .galleryforge-hover-effect-tilt .galleryforge-justified-cell { transition: transform .3s ease, box-shadow .3s ease; transform-style: preserve-3d; }
.galleryforge-hover-effect-tilt .galleryforge-grid-cell:hover, .galleryforge-hover-effect-tilt .galleryforge-justified-cell:hover { transform: rotateX(4deg) rotateY(-6deg) scale(1.03); box-shadow: 0 16px 30px rgba(0,0,0,.25); z-index: 2; }
@media (prefers-reduced-motion: reduce) { .galleryforge-hover-effect-lift .galleryforge-grid-cell:hover, .galleryforge-hover-effect-lift .galleryforge-justified-cell:hover, .galleryforge-hover-effect-tilt .galleryforge-grid-cell:hover, .galleryforge-hover-effect-tilt .galleryforge-justified-cell:hover { transform: none; } }

/* ---- Grid / Justified: captions (0.50.1) ---- */
.galleryforge-cell-caption { margin: 0; font-size: 13px; line-height: 1.35; }
/* over the photo (hover / always) */
.galleryforge-captions-hover .galleryforge-cell-caption, .galleryforge-captions-always .galleryforge-cell-caption, .galleryforge-layout-justified .galleryforge-captions-below .galleryforge-cell-caption, .galleryforge-captions-below.galleryforge-layout-justified .galleryforge-cell-caption { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 22px 12px 10px; color: #fff; pointer-events: none; }
.galleryforge-captions-hover .galleryforge-cell-caption { opacity: 0; transform: translateY(6px); transition: opacity .3s ease, transform .3s ease; }
.galleryforge-captions-hover .galleryforge-grid-cell:hover .galleryforge-cell-caption, .galleryforge-captions-hover .galleryforge-justified-cell:hover .galleryforge-cell-caption, .galleryforge-captions-hover .galleryforge-grid-cell:focus-within .galleryforge-cell-caption, .galleryforge-captions-hover .galleryforge-justified-cell:focus-within .galleryforge-cell-caption { opacity: 1; transform: none; }
@media (hover: none) { .galleryforge-captions-hover .galleryforge-cell-caption { opacity: 1; transform: none; } }
/* backgrounds for captions over the photo */
.galleryforge-captions-bg-gradient .galleryforge-cell-caption { background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.65) 100%); }
.galleryforge-captions-bg-dark .galleryforge-cell-caption { background: rgba(0,0,0,.7); padding-top: 8px; }
.galleryforge-captions-bg-light .galleryforge-cell-caption { background: rgba(255,255,255,.88); color: #1d2327; padding-top: 8px; }
.galleryforge-captions-bg-none .galleryforge-cell-caption { background: transparent; text-shadow: 0 1px 3px rgba(0,0,0,.8); padding-top: 8px; }
/* below the photo (grid only; justified falls back to over-the-photo above) */
.galleryforge-layout-grid.galleryforge-captions-below .galleryforge-cell-caption { position: static; padding: 8px 2px 4px; color: inherit; background: none; text-shadow: none; opacity: 1; transform: none; pointer-events: auto; }
.galleryforge-layout-grid.galleryforge-captions-below .galleryforge-grid-cell { background: transparent; box-shadow: none; }
.galleryforge-layout-grid.galleryforge-captions-below .galleryforge-grid-cell .galleryforge-item-link { border-radius: var( --galleryforge-radius, 4px ); box-shadow: var( --galleryforge-shadow, none ); overflow: hidden; }
/* alignment */
.galleryforge-captions-align-left .galleryforge-cell-caption { text-align: left; }
.galleryforge-captions-align-center .galleryforge-cell-caption { text-align: center; }
.galleryforge-captions-align-right .galleryforge-cell-caption { text-align: right; }
.galleryforge-layout-grid.galleryforge-captions-below:not(.galleryforge-masonry) .galleryforge-grid-cell { aspect-ratio: auto; }
.galleryforge-layout-grid.galleryforge-captions-below:not(.galleryforge-masonry) .galleryforge-grid-cell .galleryforge-item-link { display: block; aspect-ratio: 1 / 1; }
.galleryforge-layout-grid.galleryforge-captions-below:not(.galleryforge-masonry) .galleryforge-grid-cell .galleryforge-item-link .galleryforge-image { width: 100%; height: 100%; object-fit: cover; }

/* ---- Lightbox set (0.51.0): themes, caption panel, buttons, counter, zoom, transitions ---- */
.galleryforge-lightbox-theme-light { background: rgba(250, 250, 250, .96); }
.galleryforge-lightbox-theme-light .galleryforge-lightbox-caption, .galleryforge-lightbox-theme-light .galleryforge-lightbox-counter { color: #1d2327; }
.galleryforge-lightbox-theme-light .galleryforge-lightbox-figure img { box-shadow: 0 10px 40px rgba(0,0,0,.18); }
.galleryforge-lightbox-theme-blur { background: rgba(10, 10, 12, .55); backdrop-filter: blur(18px) saturate(1.1); -webkit-backdrop-filter: blur(18px) saturate(1.1); }
body.galleryforge-lightbox-open:has(.galleryforge-lightbox-theme-light) .galleryforge-lightbox-tool { background: rgba(0,0,0,.08); color: #1d2327; }
body.galleryforge-lightbox-open:has(.galleryforge-lightbox-theme-light) .galleryforge-lightbox-tool:hover { background: rgba(0,0,0,.16); }
/* toolbar + tool buttons */
.galleryforge-lightbox-toolbar { position: fixed; top: 16px; right: 16px; z-index: 100002; display: flex; gap: 8px; align-items: center; }
.galleryforge-lightbox-tool { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 50%; border: 0; padding: 0; background: rgba(255,255,255,.12); color: #fff; cursor: pointer; transition: background .2s ease, transform .15s ease; text-decoration: none; }
.galleryforge-lightbox-tool:hover { background: rgba(255,255,255,.28); }
.galleryforge-lightbox-tool.is-done { background: #2f8f4e; }
.galleryforge-lightbox-toolbar .galleryforge-lightbox-close, .galleryforge-lightbox-toolbar .galleryforge-lightbox-fullscreen { position: static; top: auto; right: auto; }
.galleryforge-lightbox-prev, .galleryforge-lightbox-next { display: inline-flex; align-items: center; justify-content: center; }
body.galleryforge-lightbox-open .galleryforge-lightbox-toolbar.galleryforge-lightbox-buttons-minimal .galleryforge-lightbox-tool, body.galleryforge-lightbox-open:has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-prev, body.galleryforge-lightbox-open:has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-next { background: transparent; filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); }
body.galleryforge-lightbox-open .galleryforge-lightbox-toolbar.galleryforge-lightbox-buttons-minimal .galleryforge-lightbox-tool:hover, body.galleryforge-lightbox-open:has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-prev:hover, body.galleryforge-lightbox-open:has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-next:hover { background: transparent; transform: scale(1.12); }
body.galleryforge-lightbox-open:has(.galleryforge-lightbox-theme-light):has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-prev, body.galleryforge-lightbox-open:has(.galleryforge-lightbox-theme-light):has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-next { color: #1d2327; filter: none; }
body:has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-prev svg, body:has(.galleryforge-lightbox-buttons-minimal) .galleryforge-lightbox-next svg { width: 34px; height: 34px; stroke-width: 1.4; }
/* counter */
.galleryforge-lightbox-counter { position: fixed; top: 24px; left: 20px; z-index: 100002; color: #fff; font-size: 13px; letter-spacing: .06em; font-variant-numeric: tabular-nums; opacity: .8; }
/* caption side panel */
.galleryforge-lightbox-caption-side { flex-direction: row; flex-wrap: wrap; align-content: center; gap: 24px; padding: 56px 56px 32px; }
.galleryforge-lightbox-caption-side .galleryforge-lightbox-figure { flex: 1 1 0; min-width: 0; }
.galleryforge-lightbox-caption-side .galleryforge-lightbox-figure img { max-height: 72vh; }
.galleryforge-lightbox-caption-side .galleryforge-lightbox-thumbs { flex-basis: 100%; justify-content: center; margin-top: 0; }
.galleryforge-lightbox-panel { flex: 0 0 280px; max-width: 32vw; align-self: center; padding: 22px 22px; background: rgba(255,255,255,.06); border-radius: 10px; color: #fff; }
.galleryforge-lightbox-theme-light .galleryforge-lightbox-panel { background: #fff; box-shadow: 0 6px 24px rgba(0,0,0,.12); }
.galleryforge-lightbox-panel .galleryforge-lightbox-caption { margin: 0; font-size: 16px; line-height: 1.5; text-align: left; }
.galleryforge-lightbox-panel .galleryforge-lightbox-exif { margin-top: 12px; font-size: 13px; }
@media (max-width: 800px) {
	/* Phones: the photo on top, the caption panel under it, the filmstrip
	   last - a single column that never wraps sideways off the screen. */
	.galleryforge-lightbox-caption-side { flex-direction: column; flex-wrap: nowrap; justify-content: center; align-items: stretch; gap: 12px; padding: 56px 12px 12px; }
	.galleryforge-lightbox-caption-side .galleryforge-lightbox-figure { flex: 0 1 auto; width: 100%; }
	.galleryforge-lightbox-caption-side .galleryforge-lightbox-figure img { max-height: 55vh; max-width: 100%; }
	.galleryforge-lightbox-panel { flex: 0 0 auto; max-width: 100%; width: 100%; padding: 12px 14px; order: 2; }
	.galleryforge-lightbox-caption-side .galleryforge-lightbox-thumbs { order: 3; flex-basis: auto; }
}
.galleryforge-lightbox-caption-none .galleryforge-lightbox-caption { display: none !important; }
/* zoom */
.galleryforge-lightbox-overlay.is-zoomed { cursor: zoom-out; }
.galleryforge-lightbox-overlay .galleryforge-lightbox-figure img { cursor: zoom-in; }
.galleryforge-lightbox-overlay:not(.is-zoomed) .galleryforge-lightbox-figure img { cursor: default; }
.galleryforge-lightbox-overlay.galleryforge-lightbox-zoomable:not(.is-zoomed) .galleryforge-lightbox-figure img { cursor: zoom-in; }
.galleryforge-lightbox-overlay.is-zoomed .galleryforge-lightbox-figure { overflow: auto; max-width: 100%; max-height: 100%; cursor: grab; scrollbar-width: none; }
.galleryforge-lightbox-overlay.is-zoomed .galleryforge-lightbox-figure::-webkit-scrollbar { display: none; }
.galleryforge-lightbox-overlay.is-zoomed .galleryforge-lightbox-figure img { max-width: none; max-height: none; width: auto; height: auto; cursor: grab; }
.galleryforge-lightbox-overlay.is-zoomed .galleryforge-lightbox-caption, .galleryforge-lightbox-overlay.is-zoomed .galleryforge-lightbox-thumbs { display: none; }
/* transitions between photos */
@keyframes gf-lb-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes gf-lb-slide { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: none; } }
@keyframes gf-lb-zoom { from { opacity: 0; transform: scale(.94); } to { opacity: 1; transform: none; } }
.galleryforge-lightbox-fx-fade .galleryforge-lightbox-figure.is-entering { animation: gf-lb-fade .35s ease; }
.galleryforge-lightbox-fx-slide .galleryforge-lightbox-figure.is-entering { animation: gf-lb-slide .35s ease; }
.galleryforge-lightbox-fx-zoom .galleryforge-lightbox-figure.is-entering { animation: gf-lb-zoom .35s ease; }
@media (prefers-reduced-motion: reduce) { .galleryforge-lightbox-figure.is-entering { animation: none !important; } }
/* slideshow progress hint */
.galleryforge-lightbox-overlay.is-playing .galleryforge-lightbox-play { color: #ffb066; }

/* ---- Slider captions (0.51.1): position, size, background ---- */
.galleryforge-slider .galleryforge-slider-caption { left: 0; right: 0; bottom: 0; top: auto; text-align: left; z-index: 2; }
.galleryforge-slider[data-caption-position$="-center"] .galleryforge-slider-caption { text-align: center; }
.galleryforge-slider[data-caption-position$="-right"] .galleryforge-slider-caption { text-align: right; }
.galleryforge-slider[data-caption-position^="top"] .galleryforge-slider-caption { top: 0; bottom: auto; padding: 40px 48px 60px; }
.galleryforge-slider[data-caption-position^="top"][data-caption-bg="gradient"] .galleryforge-slider-caption { background: linear-gradient( to bottom, rgba(0,0,0,.75), rgba(0,0,0,0) ); }
.galleryforge-slider[data-caption-position="center"] .galleryforge-slider-caption { top: 50%; bottom: auto; transform: translateY(-50%); text-align: center; padding: 24px 48px; background: none; }
.galleryforge-slider[data-caption-position="center"][data-caption-bg="gradient"] .galleryforge-slider-caption { background: radial-gradient( ellipse at center, rgba(0,0,0,.45), rgba(0,0,0,0) 70% ); }
.galleryforge-slider[data-caption-size="small"] .galleryforge-slider-caption { font-size: clamp( .9rem, .6vw + .7rem, 1.1rem ); font-weight: 500; }
.galleryforge-slider[data-caption-size="large"] .galleryforge-slider-caption { font-size: clamp( 1.5rem, 2vw + 1rem, 2.75rem ); }
.galleryforge-slider[data-caption-bg="dark"] .galleryforge-slider-caption { background: rgba(0,0,0,.72); padding: 16px 32px; text-shadow: none; }
.galleryforge-slider[data-caption-bg="light"] .galleryforge-slider-caption { background: rgba(255,255,255,.9); color: #1d2327; padding: 16px 32px; text-shadow: none; }
.galleryforge-slider[data-caption-bg="none"] .galleryforge-slider-caption { background: none; }
.galleryforge-slider[data-caption-bg="box"] .galleryforge-slider-caption { left: 32px; right: auto; bottom: 32px; max-width: min(60%, 520px); background: rgba(0,0,0,.65); padding: 14px 20px; border-radius: 6px; backdrop-filter: blur(6px); text-shadow: none; }
.galleryforge-slider[data-caption-bg="box"][data-caption-position$="-right"] .galleryforge-slider-caption { left: auto; right: 32px; }
.galleryforge-slider[data-caption-bg="box"][data-caption-position$="-center"] .galleryforge-slider-caption { left: 50%; right: auto; transform: translateX(-50%); }
.galleryforge-slider[data-caption-bg="box"][data-caption-position^="top"] .galleryforge-slider-caption { top: 32px; bottom: auto; padding: 14px 20px; }
.galleryforge-slider[data-caption-bg="box"][data-caption-position="center"] .galleryforge-slider-caption { left: 50%; top: 50%; right: auto; bottom: auto; transform: translate(-50%, -50%); }
/* below the slide: the caption sits in a bar under the image */
.galleryforge-slider[data-caption-position="below"] { padding-bottom: 56px; }
.galleryforge-slider[data-caption-position="below"] .galleryforge-slider-caption { top: 100%; bottom: auto; transform: translateY(-56px); padding: 14px 8px 0; background: none; color: inherit; text-shadow: none; text-align: left; font-size: 1rem; font-weight: 500; }
.galleryforge-slider[data-caption-position="below"][data-dots-position="below"] { padding-bottom: 92px; }
.galleryforge-slider[data-caption-position="below"][data-dots-position="below"] .galleryforge-slider-dots { bottom: 8px; }
@media (max-width: 600px) { .galleryforge-slider .galleryforge-slider-caption { padding-left: 20px; padding-right: 20px; } .galleryforge-slider[data-caption-bg="box"] .galleryforge-slider-caption { left: 12px; right: 12px; max-width: none; bottom: 16px; } }

/* ---- Accessibility & touch pass (0.53.1) ---- */
.galleryforge-slider-pause { position: absolute; right: 12px; top: 12px; z-index: 5; width: 36px; height: 36px; border-radius: 50%; border: 0; background: rgba(0,0,0,.55); color: #fff; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; }
.galleryforge-slider-pause:hover { background: rgba(0,0,0,.75); }
/* Bigger dots on touch screens (11px is not a tap target) */
@media (hover: none), (pointer: coarse) {
	.galleryforge-slider-dot { width: 14px; height: 14px; }
	.galleryforge-slider-dots { gap: 12px; }
	.galleryforge-slider-dot::after { content: ""; position: absolute; inset: -8px; }
	.galleryforge-like-button { min-height: 32px; padding: 6px 12px; }
	.galleryforge-lightbox-close, .galleryforge-lightbox-toolbar .galleryforge-lightbox-tool { width: 44px; height: 44px; }
	/* the "overlay" hover effect (scrim + caption) has no hover on a phone: show it, lighter, all the time */
	.galleryforge-hover-effect-overlay .galleryforge-hover-overlay { opacity: 1; background: linear-gradient(to top, rgba(0,0,0,.6), rgba(0,0,0,0) 60%); justify-content: flex-end; }
}
.galleryforge-slider-dot { position: relative; }
/* Focus is visible on every control (arrows, dots, lightbox tools, filmstrip, handle, album tiles) */
.galleryforge-slider-arrow:focus-visible, .galleryforge-slider-dot:focus-visible, .galleryforge-slider-pause:focus-visible, .galleryforge-lightbox-tool:focus-visible, .galleryforge-lightbox-close:focus-visible, .galleryforge-lightbox-prev:focus-visible, .galleryforge-lightbox-next:focus-visible, .galleryforge-lightbox-thumbs button:focus-visible, .galleryforge-ba-handle:focus-visible, .galleryforge-album-tile:focus-visible, .galleryforge-item-link:focus-visible { outline: 3px solid #fff; outline-offset: 2px; box-shadow: 0 0 0 5px rgba(0,0,0,.6); }
.galleryforge-item-link:focus-visible { outline-color: #2271b1; box-shadow: 0 0 0 5px #fff; }
/* Active dot stays visible even with no accent colour set */
.galleryforge-slider-dot.is-active { background: var(--galleryforge-gf-accent, #fff); transform: scale(1.25); }
/* Light lightbox theme without :has(): controls must still be visible */
.galleryforge-lightbox-theme-light .galleryforge-lightbox-tool, .galleryforge-lightbox-theme-light .galleryforge-lightbox-prev, .galleryforge-lightbox-theme-light .galleryforge-lightbox-next, .galleryforge-lightbox-theme-light .galleryforge-lightbox-close { color: #111; background: rgba(255,255,255,.85); border-color: rgba(0,0,0,.15); }
.galleryforge-lightbox-theme-light .galleryforge-lightbox-thumbs button.is-active { border-color: #111; }
/* Phones: the lightbox uses the room it has, and the full-screen slider fits the real viewport */
@media (max-width: 600px) {
	.galleryforge-lightbox-overlay { padding: 56px 8px 8px; }
	.galleryforge-slider-fullscreen, .galleryforge-slider-fullscreen .galleryforge-slider-track { height: 100dvh; }
}
/* Reduced motion: no sliding/zooming tracks, no coverflow fan, no hover scale, no smooth scroll */
@media (prefers-reduced-motion: reduce) {
	.galleryforge-slider-track, .galleryforge-slider-style-coverflow .galleryforge-slide, .galleryforge-slider-style-stacked-cards .galleryforge-slide, .galleryforge-hover-effect-zoom .galleryforge-image, .galleryforge-hover-effect-grayscale .galleryforge-image, .galleryforge-hover-effect-frame .galleryforge-image { transition: none !important; }
	.galleryforge-hover-effect-zoom .galleryforge-grid-cell:hover .galleryforge-image, .galleryforge-hover-effect-zoom .galleryforge-justified-cell:hover .galleryforge-image, .galleryforge-hover-effect-grayscale .galleryforge-grid-cell:hover .galleryforge-image, .galleryforge-hover-effect-frame .galleryforge-grid-cell:hover .galleryforge-image { transform: none !important; }
	.galleryforge { animation: none !important; }
	.galleryforge-lightbox-figure.is-entering { animation: none !important; }
}
.galleryforge-lightbox-overlay { overscroll-behavior: contain; }
.galleryforge-sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* ---- Theme hardening (0.53.3): explicit resets so a theme's own link /
   image / button / figure styling can't leak into the gallery ---- */
.galleryforge, .galleryforge *, .galleryforge *::before, .galleryforge *::after,
.galleryforge-lightbox-overlay, .galleryforge-lightbox-overlay * { box-sizing: border-box; }
.galleryforge .galleryforge-item-link, .galleryforge .galleryforge-item-link:hover, .galleryforge .galleryforge-item-link:focus,
.galleryforge a.galleryforge-item-link { text-decoration: none; border: 0; box-shadow: none; background: transparent; color: inherit; outline-offset: 2px; }
.galleryforge .galleryforge-image, .galleryforge img.galleryforge-image { margin: 0; padding: 0; border: 0; box-shadow: none; border-radius: 0; max-width: 100%; vertical-align: top; }
.galleryforge-grid-cell .galleryforge-image, .galleryforge-justified-cell .galleryforge-image { height: 100% !important; /* beats a theme's img { height:auto !important } */ }
.galleryforge figure.galleryforge-grid-cell, .galleryforge figure.galleryforge-justified-cell, .galleryforge figure.galleryforge-ba-pair { padding: 0; border: 0; background: none; }
.galleryforge figcaption { margin: 0; padding: 0; font-style: normal; }
.galleryforge ul, .galleryforge ol { list-style: none; margin: 0; padding: 0; }
.galleryforge button, .galleryforge-lightbox-overlay button { margin: 0; font-family: inherit; text-transform: none; letter-spacing: normal; min-height: 0; min-width: 0; box-shadow: none; appearance: none; -webkit-appearance: none; }
.galleryforge-like-button, .galleryforge-slider-dot, .galleryforge-slider-arrow, .galleryforge-slider-pause, .galleryforge-filter-btn, .galleryforge-load-more { text-transform: none; letter-spacing: normal; font-family: inherit; box-shadow: none; }
/* Full-bleed sliders: 100vw includes the scrollbar on Windows browsers and forces a horizontal page scroll */
.galleryforge-slider-fullwidth, .galleryforge-slider-fullscreen { width: calc( 100vw - ( 100vw - 100% ) ) !important; max-width: none !important; margin-left: calc( -50vw + ( 100vw - 100% ) / 2 ) !important; }
/* Mobile browser chrome: the real visible height (browsers without dvh keep the 100vh above) */
.galleryforge-slider-fullscreen, .galleryforge-slider-fullscreen .galleryforge-slider-track { height: 100dvh !important; }
/* Lightbox "minimal" buttons without :has() (controls live inside the overlay since 0.53.1) */
.galleryforge-lightbox-overlay.galleryforge-lightbox-buttons-minimal .galleryforge-lightbox-prev, .galleryforge-lightbox-overlay.galleryforge-lightbox-buttons-minimal .galleryforge-lightbox-next { background: transparent; filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); }
.galleryforge-lightbox-overlay.galleryforge-lightbox-buttons-minimal .galleryforge-lightbox-prev svg, .galleryforge-lightbox-overlay.galleryforge-lightbox-buttons-minimal .galleryforge-lightbox-next svg { width: 34px; height: 34px; stroke-width: 1.4; }
/* RTL sites: mirrored controls */
[dir="rtl"] .galleryforge-like-button { right: auto; left: 10px; }
[dir="rtl"] .galleryforge-slider-pause { right: auto; left: 12px; }
[dir="rtl"] .galleryforge-lightbox-toolbar { right: auto; left: 16px; }
[dir="rtl"] .galleryforge-lightbox-counter { left: auto; right: 20px; }
[dir="rtl"] .galleryforge-justified-inner, [dir="rtl"] .galleryforge-slider-track { direction: ltr; }
[dir="rtl"] .galleryforge-lightbox-panel .galleryforge-lightbox-caption { text-align: right; }

/* ---- Arrow position & dot alignment (0.54.0) ---- */
.galleryforge-slider[data-dots-align="left"] .galleryforge-slider-dots { justify-content: flex-start; padding-left: 16px; }
.galleryforge-slider[data-dots-align="right"] .galleryforge-slider-dots { justify-content: flex-end; padding-right: 16px; }
/* the arrows as a pair in one corner (or bottom centre) instead of one on each side */
.galleryforge-slider[data-arrow-position]:not([data-arrow-position="sides"]) .galleryforge-slider-arrow { top: auto; transform: none; }
.galleryforge-slider[data-arrow-position]:not([data-arrow-position="sides"]) .galleryforge-slider-arrow:hover { transform: scale( 1.08 ); }
.galleryforge-slider[data-arrow-position^="bottom"]:not([data-arrow-position="sides"]) .galleryforge-slider-arrow { bottom: 16px; }
.galleryforge-slider[data-arrow-position^="top"]:not([data-arrow-position="sides"]) .galleryforge-slider-arrow { top: 16px; bottom: auto; }
.galleryforge-slider[data-arrow-position$="right"] .galleryforge-slider-prev { left: auto; right: calc( 16px + var( --galleryforge-arrow-size, 44px ) + 8px ); }
.galleryforge-slider[data-arrow-position$="right"] .galleryforge-slider-next { right: 16px; }
.galleryforge-slider[data-arrow-position$="left"] .galleryforge-slider-prev { left: 16px; }
.galleryforge-slider[data-arrow-position$="left"] .galleryforge-slider-next { right: auto; left: calc( 16px + var( --galleryforge-arrow-size, 44px ) + 8px ); }
.galleryforge-slider[data-arrow-position="bottom-center"] .galleryforge-slider-prev { left: calc( 50% - var( --galleryforge-arrow-size, 44px ) - 4px ); right: auto; }
.galleryforge-slider[data-arrow-position="bottom-center"] .galleryforge-slider-next { right: calc( 50% - var( --galleryforge-arrow-size, 44px ) - 4px ); left: auto; }
.galleryforge-slider[data-arrow-size="small"] { --galleryforge-arrow-size: 34px; }
.galleryforge-slider[data-arrow-size="large"] { --galleryforge-arrow-size: 62px; }
/* dots move out of the way of a bottom pair on the same side */
.galleryforge-slider[data-arrow-position="bottom-right"][data-dots-position="inside"] .galleryforge-slider-dots { padding-right: calc( 2 * var( --galleryforge-arrow-size, 44px ) + 40px ); }
.galleryforge-slider[data-arrow-position="bottom-left"][data-dots-position="inside"] .galleryforge-slider-dots { padding-left: calc( 2 * var( --galleryforge-arrow-size, 44px ) + 40px ); }
.galleryforge-slider[data-arrow-position="bottom-center"][data-dots-position="inside"] .galleryforge-slider-dots { bottom: calc( 16px + var( --galleryforge-arrow-size, 44px ) + 8px ); }
.galleryforge-slider[data-arrow-position^="top"][data-arrow-position$="left"] .galleryforge-slider-pause { top: auto; bottom: 12px; }
.galleryforge-slider[data-arrow-position="bottom-right"] .galleryforge-slider-counter { right: calc( 2 * var( --galleryforge-arrow-size, 44px ) + 40px ); }
.galleryforge-slider[data-arrow-position="bottom-center"] .galleryforge-slider-counter { bottom: calc( 16px + var( --galleryforge-arrow-size, 44px ) + 8px ); }

/* pause sits next to the music note (both top-right); like button / counter keep clear of a bottom-right arrow pair */
.galleryforge-slider:has(.galleryforge-slider-music-toggle) .galleryforge-slider-pause { right: 64px; }
.galleryforge-slider-fullscreen[data-arrow-position="bottom-right"] .galleryforge-like-button, .galleryforge-slider[data-arrow-position="bottom-right"] .galleryforge-like-button { bottom: calc( 20px + var( --galleryforge-arrow-size, 44px ) + 12px ); right: 20px; top: auto; }
.galleryforge-slider[data-arrow-position^="top"][data-arrow-position$="right"] .galleryforge-slider-pause, .galleryforge-slider[data-arrow-position^="top"][data-arrow-position$="right"] .galleryforge-slider-music-toggle { top: calc( 16px + var( --galleryforge-arrow-size, 44px ) + 10px ); }
/* arrows flanking the dots, in the dots row */
.galleryforge-slider-dots--flanked { align-items: center; }
.galleryforge-slider-dots--flanked .galleryforge-slider-arrow { position: static; transform: none; width: 34px; height: 34px; margin: 0 6px; flex: 0 0 auto; }
.galleryforge-slider-dots--flanked .galleryforge-slider-arrow:hover { transform: scale( 1.08 ); }
.galleryforge-slider[data-arrow-size="large"] .galleryforge-slider-dots--flanked .galleryforge-slider-arrow { width: 44px; height: 44px; }
.galleryforge-slider[data-arrow-size="small"] .galleryforge-slider-dots--flanked .galleryforge-slider-arrow { width: 28px; height: 28px; }
.galleryforge-slider[data-arrow-position="dots"][data-dots-position="below"] .galleryforge-slider-dots--flanked .galleryforge-slider-arrow { background: rgba(120,120,120,.25); color: inherit; border: 0; }

/* 0.58.87: the lightbox photo fills the screen (Nissim: clients "don't like
   ... not filling up the screen"). Before: 40 px padding all round and
   max-height 75vh left a quarter of the screen empty. Now the overlay has
   no padding, the figure takes the whole height, and the photo is as big
   as its own proportions allow - object-fit: contain, never stretched.
   Caption and filmstrip (when present) take only the space they need and
   the photo shrinks around them. Toolbar/arrows/counter are fixed and
   float over the photo. Phones keep their own padding (media query below
   in the 0.55 block still applies at <= 782 px). */
.galleryforge-lightbox-overlay { padding: 0; }
.galleryforge-lightbox-overlay:not(.galleryforge-lightbox-caption-side) .galleryforge-lightbox-figure { flex: 1 1 auto; min-height: 0; width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.galleryforge-lightbox-overlay:not(.galleryforge-lightbox-caption-side):not(.is-zoomed) .galleryforge-lightbox-figure img { flex: 0 1 auto; min-height: 0; width: auto; height: auto; max-width: 100vw; max-height: 100%; object-fit: contain; }
.galleryforge-lightbox-overlay:not(.galleryforge-lightbox-caption-side) .galleryforge-lightbox-caption { flex: 0 0 auto; padding: 0 16px; }
.galleryforge-lightbox-overlay .galleryforge-lightbox-thumbs { flex: 0 0 auto; margin: 8px 0 0; padding: 4px 8px 8px; }
.galleryforge-lightbox-caption-side .galleryforge-lightbox-figure img { max-height: calc( 100vh - 96px ); }
/* Fullscreen (the toolbar's expand button): nothing but the photo - filmstrip and caption hidden, toolbar stays over it. */
.galleryforge-lightbox-overlay:fullscreen .galleryforge-lightbox-thumbs, .galleryforge-lightbox-overlay:fullscreen .galleryforge-lightbox-caption { display: none; }
.galleryforge-lightbox-overlay:fullscreen .galleryforge-lightbox-figure img { max-width: 100vw; max-height: 100vh; }
@media (max-width: 782px) { .galleryforge-lightbox-overlay { padding: 48px 0 6px; } .galleryforge-lightbox-overlay:not(.galleryforge-lightbox-caption-side):not(.is-zoomed) .galleryforge-lightbox-figure img { max-height: 100%; } }

/* 0.58.90: lightbox dots (one per photo, click to jump) + music button; both stay visible in fullscreen. */
.galleryforge-lightbox-dots { position: fixed; left: 0; right: 0; bottom: 14px; z-index: 100002; display: flex; justify-content: center; gap: 6px; flex-wrap: wrap; padding: 0 60px; pointer-events: none; }
.galleryforge-lightbox-dots button { pointer-events: auto; width: 9px; height: 9px; padding: 0; border: 0; border-radius: 50%; background: rgba(255,255,255,.45); cursor: pointer; transition: transform .15s, background .15s; }
.galleryforge-lightbox-dots button:hover { background: rgba(255,255,255,.8); }
.galleryforge-lightbox-dots button.is-active { background: #fff; transform: scale(1.35); }
.galleryforge-lightbox-theme-light .galleryforge-lightbox-dots button { background: rgba(0,0,0,.3); } .galleryforge-lightbox-theme-light .galleryforge-lightbox-dots button.is-active { background: #1d2327; }
.galleryforge-lightbox-overlay.is-zoomed .galleryforge-lightbox-dots { display: none; }
.galleryforge-lightbox-music.is-off { opacity: .6; }
