/* ============================================================================
 * BRIEFLY — GALLERY SHAPE PACK. Five structurally distinct shapes.
 *
 * ── THE WORST DUPLICATION IN THE SUITE ──────────────────────────────────────
 * 31 gallery-family renderers across 23 themes resolve to 15 distinct
 * skeletons — a ratio of 0.56, the lowest of any content type except blog
 * teasers. A photographer's portfolio, a restaurant's dishes, a builder's past
 * jobs and a salon's lookbook are the same three-column grid of rounded cards.
 *
 * ── AND THE ONE PLACE THE EMPTY STATE IS FATAL ──────────────────────────────
 * A gallery is one hundred per cent images. Every other section still reads
 * with an unfilled slot; a gallery with no photographs is a grid of grey boxes
 * and nothing else, and an evaluator ALWAYS starts from an empty media library.
 * So the registry marks media as genuinely required and tells the planner not
 * to place a gallery at all when there is nothing to put in it — a missing
 * section is invisible, an empty one is the screenshot.
 *
 * ── WHAT IS KEPT ────────────────────────────────────────────────────────────
 * Aperture's .ap-wall is real work: a span-based mosaic on grid-auto-flow:dense
 * with a documented reason for collapsing to a single column rather than
 * shrinking tiles into illegible fragments. It is generalised here as the
 * mosaic shape, driven by nth-child rhythm rather than per-item classes so it
 * works at any item count without the renderer assigning them.
 * ========================================================================== */

/* ── SHARED GROUND ───────────────────────────────────────────────────────── */

.bfy-gal { padding: var(--bfy-sect, clamp(3rem, 5vw, 4.5rem)) var(--bfy-gut, clamp(1.5rem, 4vw, 3rem)); box-sizing: border-box; }
.bfy-gal__inner { max-width: var(--bfy-head-measure-wide, 1160px); margin: 0 auto; }
.bfy-gal__list { list-style: none; margin: 0; padding: 0; }

/* Every frame locks its ratio. An unlocked gallery reflows the whole page as
   each image decodes, which is the single largest CLS contributor a template
   can ship, and it is worst here because there are a dozen of them. */
.bfy-gal__item {
	position: relative;
	margin: 0;
	overflow: hidden;
	border-radius: var(--bfy-gal-radius, 12px);
	background: var(--bfy-gal-frame, rgba(18, 24, 28, 0.05));
	aspect-ratio: var(--bfy-gal-ratio, 4 / 3);
	min-width: 0;
}
.bfy-gal__item img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Caption sits ON the image in the shapes where a tile is the unit, and BELOW
   it where the caption is content. The gradient is a legibility device, not a
   mood one — it has to hold against a photograph we did not choose. */
.bfy-gal__cap {
	position: absolute;
	inset: auto 0 0 0;
	padding: 0.9rem 1rem 0.75rem;
	font-size: var(--bfy-gal-cap, 0.85rem);
	line-height: 1.35;
	color: var(--bfy-gal-cap-ink, #FFFFFF);
	background: linear-gradient(to top, rgba(8, 10, 14, 0.82), rgba(8, 10, 14, 0.32) 55%, transparent);
}

/* A gallery item that links somewhere real. Never the raw image file: opening
   a bare JPEG is a dead end with no way back and no page furniture. */
.bfy-gal__link { display: block; width: 100%; height: 100%; }
.bfy-gal__link:focus-visible {
	outline: 3px solid var(--wp--preset--color--primary, currentColor);
	outline-offset: -3px;
}


/* ── 1. GRID ─────────────────────────────────────────────────────────────────
 * Even tiles, equal weight. Right when the set IS uniform — product shots,
 * team headshots, a menu of dishes — and no single image leads.
 * -------------------------------------------------------------------------- */

.bfy-gal--grid .bfy-gal__list {
	display: grid;
	grid-template-columns: var(--bfy-gal-cols, repeat(auto-fit, minmax(min(100%, 240px), 1fr)));
	gap: var(--bfy-gal-gap, clamp(0.5rem, 1.2vw, 0.9rem));
}


/* ── 2. MOSAIC ───────────────────────────────────────────────────────────────
 * A span-based wall on dense flow. Aperture's shape, generalised.
 *
 * Tiles take different spans on a repeating seven-step rhythm, so the wall
 * looks composed rather than tiled and never repeats its pattern within one
 * screen. `dense` backfills the holes that unequal spans leave, which is what
 * stops it looking like a grid with bites out of it.
 *
 * THE SINGLE-COLUMN COLLAPSE IS DELIBERATE AND IS ALREADY DOCUMENTED IN
 * APERTURE: below the breakpoint the wall becomes one full-width column rather
 * than shrinking tiles into illegibly small random fragments. A mosaic squeezed
 * onto a phone is not a smaller mosaic, it is confetti.
 * -------------------------------------------------------------------------- */

.bfy-gal--mosaic .bfy-gal__list {
	display: grid;
	grid-template-columns: 1fr;
	grid-auto-rows: var(--bfy-gal-mosaic-row-sm, 34vw);
	gap: var(--bfy-gal-mosaic-gap, 4px);
}
/* The frame ratio is set by the grid span here, not by aspect-ratio. */
.bfy-gal--mosaic .bfy-gal__item { aspect-ratio: auto; }

@media (min-width: 700px) {
	.bfy-gal--mosaic .bfy-gal__list {
		grid-template-columns: repeat(var(--bfy-gal-mosaic-cols, 6), 1fr);
		grid-auto-rows: var(--bfy-gal-mosaic-row, 130px);
		grid-auto-flow: dense;
		gap: var(--bfy-gal-mosaic-gap-md, 6px);
	}
	/* Seven-step rhythm, applied by position so it never depends on how many
	   images the owner uploaded or what order they are in. */
	.bfy-gal--mosaic .bfy-gal__item                { grid-column: span 2; grid-row: span 2; }
	.bfy-gal--mosaic .bfy-gal__item:nth-child(7n+1) { grid-column: span 3; grid-row: span 2; }
	.bfy-gal--mosaic .bfy-gal__item:nth-child(7n+3) { grid-column: span 2; grid-row: span 3; }
	.bfy-gal--mosaic .bfy-gal__item:nth-child(7n+4) { grid-column: span 3; grid-row: span 3; }
	.bfy-gal--mosaic .bfy-gal__item:nth-child(7n+6) { grid-column: span 4; grid-row: span 2; }
	.bfy-gal--mosaic .bfy-gal__item:nth-child(7n)   { grid-column: span 2; grid-row: span 4; }
}
@media (min-width: 1100px) {
	.bfy-gal--mosaic .bfy-gal__list {
		grid-template-columns: repeat(var(--bfy-gal-mosaic-cols-lg, 8), 1fr);
		grid-auto-rows: var(--bfy-gal-mosaic-row-lg, 110px);
	}
}


/* ── 3. RAIL ─────────────────────────────────────────────────────────────────
 * A tall scroll-snap strip with a running count.
 *
 * The counter is a CSS counter, not JavaScript. It is the honest version of the
 * "1 / 12" a carousel would show, and it cannot fail to initialise — the same
 * reasoning that made Firstborn's before/after a CSS wipe rather than a slider
 * after the Hub's JS sliders were repeatedly reported broken.
 * -------------------------------------------------------------------------- */

.bfy-gal--rail .bfy-gal__list {
	counter-reset: bfy-gal;
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: var(--bfy-gal-rail-w, clamp(240px, 30vw, 380px));
	gap: var(--bfy-gal-gap, clamp(0.5rem, 1.2vw, 0.9rem));
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-padding-left: var(--bfy-gut, clamp(1.5rem, 4vw, 3rem));
	margin-right: var(--bfy-rail-bleed, calc(50% - 50vw));
	padding-right: var(--bfy-gut, clamp(1.5rem, 4vw, 3rem));
	padding-bottom: 0.5rem;
	scrollbar-width: thin;
	overscroll-behavior-x: contain;
}
.bfy-gal--rail .bfy-gal__item {
	counter-increment: bfy-gal;
	scroll-snap-align: start;
	aspect-ratio: var(--bfy-gal-rail-ratio, 3 / 4);
}
.bfy-gal--rail .bfy-gal__item::after {
	content: counter(bfy-gal);
	position: absolute;
	top: 0.6rem;
	left: 0.7rem;
	font-size: var(--bfy-gal-count, 0.72rem);
	font-weight: 600;
	letter-spacing: 0.08em;
	font-variant-numeric: tabular-nums;
	color: var(--bfy-gal-cap-ink, #FFFFFF);
	background: rgba(8, 10, 14, 0.55);
	padding: 0.2rem 0.5rem;
	border-radius: 999px;
	pointer-events: none;
}
.bfy-gal--rail .bfy-gal__list:focus-visible {
	outline: 3px solid var(--wp--preset--color--primary, currentColor);
	outline-offset: 4px;
}


/* ── 4. BENTO ────────────────────────────────────────────────────────────────
 * One lead image with four supporting tiles, on named areas.
 *
 * The shape for a set where ONE image is genuinely the best — a hero dish, a
 * finished room, a flagship project — and the rest are supporting evidence. A
 * uniform grid actively destroys that, because it asserts every image is worth
 * the same and lets the weakest one set the impression.
 * -------------------------------------------------------------------------- */

.bfy-gal--bento .bfy-gal__list {
	display: grid;
	grid-template-columns: var(--bfy-gal-bento-cols, repeat(4, minmax(0, 1fr)));
	grid-template-areas:
		"lead lead a b"
		"lead lead c d";
	gap: var(--bfy-gal-gap, clamp(0.5rem, 1.2vw, 0.9rem));
}
.bfy-gal--bento .bfy-gal__item { aspect-ratio: auto; min-height: var(--bfy-gal-bento-min, 150px); }
.bfy-gal--bento .bfy-gal__item:nth-child(1) { grid-area: lead; }
.bfy-gal--bento .bfy-gal__item:nth-child(2) { grid-area: a; }
.bfy-gal--bento .bfy-gal__item:nth-child(3) { grid-area: b; }
.bfy-gal--bento .bfy-gal__item:nth-child(4) { grid-area: c; }
.bfy-gal--bento .bfy-gal__item:nth-child(5) { grid-area: d; }
/* Anything past the fifth flows on below rather than being dropped — the
   renderer caps the list, but a filter or a future caller might not, and a
   silently discarded photograph is worse than an extra row. */
.bfy-gal--bento .bfy-gal__item:nth-child(n+6) { grid-area: auto; aspect-ratio: var(--bfy-gal-ratio, 4 / 3); }


/* ── 5. STACK ────────────────────────────────────────────────────────────────
 * Three or four plates overlapping at offsets, deliberately imperfect.
 *
 * The most hand-made shape in the pack and the least like a page builder. It is
 * for a small, chosen set — a before/during/after, three room angles, a
 * lookbook triptych — where the arrangement itself says a person placed these.
 *
 * Offsets are per-position and asymmetric on purpose. A regular offset reads as
 * a stack of cards; an irregular one reads as photographs laid on a table.
 * -------------------------------------------------------------------------- */

.bfy-gal--stack .bfy-gal__list {
	display: grid;
	grid-template-columns: var(--bfy-gal-stack-cols, repeat(3, minmax(0, 1fr)));
	gap: 0;
	align-items: start;
	padding-block: var(--bfy-gal-stack-pad, 2.5rem);
}
.bfy-gal--stack .bfy-gal__item {
	aspect-ratio: var(--bfy-gal-stack-ratio, 3 / 4);
	box-shadow: var(--bfy-gal-stack-shadow, 0 18px 44px rgba(18, 24, 28, 0.16));
	border: var(--bfy-gal-stack-border, 6px solid #FFFFFF);
	box-sizing: border-box;
}
.bfy-gal--stack .bfy-gal__item:nth-child(1) { transform: translateY(var(--bfy-gal-stack-y1, 1.75rem)); z-index: 1; margin-right: var(--bfy-gal-stack-lap, -14%); }
.bfy-gal--stack .bfy-gal__item:nth-child(2) { z-index: 3; }
.bfy-gal--stack .bfy-gal__item:nth-child(3) { transform: translateY(var(--bfy-gal-stack-y3, 2.75rem)); z-index: 2; margin-left: var(--bfy-gal-stack-lap, -14%); }
.bfy-gal--stack .bfy-gal__item:nth-child(n+4) { display: none; }


/* ── EMPTY STATE ─────────────────────────────────────────────────────────────
 * A gallery is entirely images, so an unfilled one is the single worst-looking
 * section a build can produce. render-guards.css already tints unfilled slots
 * from the brand-colour chain; this adds the one thing a GALLERY needs on top —
 * a frame that still holds its ratio, so an empty gallery reads as a designed
 * placeholder grid rather than as a collapsed section.
 *
 * Deliberately NOT hidden from logged-in editors. The free tier's empty-slot
 * treatment is skipped for anyone who can edit, which means the owner never
 * sees what a visitor sees.
 * -------------------------------------------------------------------------- */

.bfy-gal__item--empty {
	background:
		linear-gradient(135deg,
			color-mix(in srgb, var(--bfy-gal-empty-tint, var(--wp--preset--color--primary, #0F4C5C)) 9%, transparent),
			color-mix(in srgb, var(--bfy-gal-empty-tint, var(--wp--preset--color--primary, #0F4C5C)) 3%, transparent));
	border: 1px dashed color-mix(in srgb, var(--bfy-gal-empty-tint, var(--wp--preset--color--primary, #0F4C5C)) 28%, transparent);
	display: grid;
	place-items: center;
}
@supports not (color: color-mix(in srgb, red 50%, blue)) {
	.bfy-gal__item--empty {
		background: rgba(18, 24, 28, 0.05);
		border: 1px dashed rgba(18, 24, 28, 0.20);
	}
}
.bfy-gal__item--empty span {
	font-size: var(--bfy-eyebrow-size, 0.75rem);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--bfy-lede-ink, var(--wp--preset--color--foreground, #55606B));
}


/* ── RESPONSIVE ──────────────────────────────────────────────────────────── */

@media (max-width: 760px) {
	/* The stack unstacks. Overlapping plates on a 360px screen are photographs
	   covering each other, not composition. */
	.bfy-gal--stack .bfy-gal__list { grid-template-columns: 1fr; gap: var(--bfy-gal-gap, 0.75rem); padding-block: 0; }
	.bfy-gal--stack .bfy-gal__item { transform: none; margin: 0; border-width: 4px; }
	.bfy-gal--stack .bfy-gal__item:nth-child(n+4) { display: block; }

	.bfy-gal--bento .bfy-gal__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		grid-template-areas: "lead lead" "a b" "c d";
	}
	.bfy-gal--bento .bfy-gal__item { min-height: 0; aspect-ratio: var(--bfy-gal-ratio, 4 / 3); }
	.bfy-gal--bento .bfy-gal__item:nth-child(1) { aspect-ratio: 4 / 3; }
}


/* ── QUALITY FLOOR ───────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
	.bfy-gal__list { scroll-behavior: auto; }
	.bfy-gal, .bfy-gal * { animation: none !important; transition: none !important; }
}

@media (forced-colors: active) {
	.bfy-gal__item { border: 1px solid CanvasText; }
	.bfy-gal__cap { background: Canvas; color: CanvasText; }
	.bfy-gal--rail .bfy-gal__item::after { background: Canvas; color: CanvasText; border: 1px solid CanvasText; }
}

@media print {
	.bfy-gal--rail .bfy-gal__list { display: grid; grid-auto-flow: row; overflow: visible; }
	.bfy-gal--stack .bfy-gal__item { transform: none; margin: 0; box-shadow: none; }
}
