/* ==========================================================================
   Gallery (Offset), page-templates/gallery-offset.php
   --------------------------------------------------------------------------
   Everything here is scoped to .gallery-page (the template's own wrapper) or to
   .gallery-offset (its grid container). The masthead, main menu and footer are
   sitewide and are styled only by style.css, nothing in this file may reach
   them. .gallery-offset is also deliberately more specific than the bare
   .gallery rules in style.css, which still lay out the original gallery.php
   pages at 32.7% inline-block and must keep doing so.
   ========================================================================== */

.gallery-page {
	/* The point of the design: the grid runs almost to the window edge. */
	--gx-margin: clamp(10px, 2.4vw, 40px);
	--gx-gap: 8px;

	padding: 0 var(--gx-margin) clamp(40px, 6vw, 90px);
	color: var(--mm-text);
	font-weight: 300;
}

/* --------------------------------------------------------------------------
   Page head
   -------------------------------------------------------------------------- */

.gallery-page-head {
	padding: 34px 0 26px;
}

.gallery-page-head h1 {
	margin: 0;
	font-size: clamp(22px, 2.4vw, 34px);
	font-weight: 100;
	letter-spacing: 0.14em;
	line-height: 1.1;
	text-transform: uppercase;
	color: #f0ede9;
}

.gallery-page-intro {
	max-width: 100ch;
	margin: 14px 0 0;
	font-size: 15px;
	line-height: 1.6;
	color: #a9a9a9;
}

.gallery-page-intro p:last-child {
	margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   The justified grid

   Each figure carries three custom properties set inline by the template:
     --a   its aspect ratio, which also weights its share of the row
     --w   its width as a percentage of the row's usable width
     --n1  the number of gaps in its row (item count minus one)

   flex-basis puts each tile on its computed width, a whisker under the true
   value so rounding can never wrap the last tile early; flex-grow then hands
   the remainder back weighted by --a, landing them on the exact widths. Because
   widths within a row are proportional to --a and each tile's height is its
   width divided by --a, every tile in a row resolves to the same height without
   the stylesheet needing to know what that height is.
   -------------------------------------------------------------------------- */

.gallery.gallery-offset {
	display: flex;
	flex-wrap: wrap;
	/* Titles overlay the images rather than sitting under them, so rows need no
	   extra room and the gutter stays tight in both directions. */
	gap: var(--gx-gap);
	align-items: flex-start;
	margin: 0;
	overflow: visible;
	font-size: 0; /* kills the inline-block whitespace the old rules relied on */
}

.gallery-offset figure {
	flex-grow: var(--a);
	flex-shrink: 0;
	flex-basis: calc((100% - var(--gx-gap) * var(--n1)) * var(--w) / 100);
	width: auto; /* overrides the 32.7% in style.css */
	max-width: none;
	margin: 0;
	padding: 0;
	display: block;
	position: relative;
	/* The title overlay is positioned against this box; clipping guards against
	   any sub-pixel bleed past the image edges. */
	overflow: hidden;
	background: none;
}

/* The aspect ratio lives on the link rather than the figure. Either would work
   now that the title is out of flow, but keeping it on the image box means the
   figure's height is always exactly the image, which is what preserves the row
   geometry, since every image box in a row resolves to the same height. */
.gallery-offset figure > a {
	display: block;
	position: relative;
	width: 100%;
	aspect-ratio: var(--a);
	background: #1f1f1f;
	overflow: hidden;
}

/* The thumb is wrapped in <picture> for the WebP source. <picture> is inline
   with no intrinsic size, so without this the img's height:100% below would
   have nothing to resolve against and the tile would collapse. Make the
   wrapper a transparent pass-through box the same size as the link. */
.gallery-offset figure picture {
	display: block;
	width: 100%;
	height: 100%;
}

.gallery-offset figure img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Content-aware crop. --ox/--oy are computed per image per tile in the
	   template from the detected subject position and this tile's aspect ratio,
	   so the product lands in the middle of the tile rather than wherever the
	   render happened to put it. Falls back to a plain centre crop if the
	   properties are ever absent. */
	object-position: var(--ox, 50%) var(--oy, 50%);
	opacity: 1;
	transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.4s ease;
	will-change: transform;
	backface-visibility: hidden;
}

.gallery-offset figure:hover img {
	transform: scale(1.035);
	opacity: 1;
}

.gallery-offset figure > a:focus-visible {
	outline: 2px solid var(--mm-gold);
	outline-offset: -2px;
}

/* --------------------------------------------------------------------------
   Index badge

   A new class name on purpose: style.css pins the original .gallery-number
   with !important rules that cannot be overridden from here.

   Always visible, flush to the top-right corner. It sits over backdrop rather
   than product, the subject occupies roughly 10%-90% of a tile's width and
   starts ~8% down, so the top-right corner is empty studio sweep in every
   render. The translucent dark chip is there so it still reads if this template
   is ever pointed at images that do fill the corner.
   -------------------------------------------------------------------------- */

.gallery-offset .gx-num {
	position: absolute;
	top: 0;
	right: 0;
	z-index: 2;
	padding: 5px 9px;
	font-size: 11px;
	line-height: 1;
	font-weight: 400;
	letter-spacing: 0.09em;
	font-variant-numeric: tabular-nums;
	color: rgba(255, 255, 255, 0.92);
	background: rgba(20, 20, 20, 0.55);
	backdrop-filter: blur(2px);
	-webkit-backdrop-filter: blur(2px);
	pointer-events: none;
	transition: background 0.25s ease;
}

.gallery-offset figure:hover .gx-num,
.gallery-offset figure:focus-within .gx-num {
	background: rgba(20, 20, 20, 0.78);
}

/* --------------------------------------------------------------------------
   Tile label

   The attachment title, overlaid across the bottom of the image. It stays a
   direct child of <figure> rather than moving inside the <a>, because
   PhotoSwipe reads figureEl.children[1] for the lightbox caption, so it is
   taken out of flow and positioned instead. With the <a> then the only in-flow
   child, the figure's height collapses back to exactly the image box, which is
   what lets the row gutters stay tight.

   The renders are light, so the text needs its own scrim to stay legible; the
   gradient is carried on this element rather than a separate overlay node.
   font-size is reset here because the flex container zeroes it.
   -------------------------------------------------------------------------- */

.gallery-offset .gx-cap {
	/* Required: style.css carries a bare `figcaption { display: none }` that
	   otherwise hides this outright. */
	display: block;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 3;
	margin: 0;
	/* Deep top padding gives the gradient room to fade out before it reaches
	   the product. */
	padding: 40px 15px 13px;
	background: linear-gradient(
		to top,
		rgba(12, 12, 12, 0.84) 0%,
		rgba(12, 12, 12, 0.58) 45%,
		rgba(12, 12, 12, 0) 100%
	);
	font-size: 12px;
	line-height: 1.4;
	font-weight: 300;
	letter-spacing: 0.055em;
	text-transform: uppercase;
	color: #fff;
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
	/* The whole tile reads as one clickable surface; the label must not put a
	   text caret over it. Clicks still reach the figure, which is what
	   PhotoSwipe binds to. */
	pointer-events: none;
}

/*
 * Hover-to-reveal is gated on the device actually having a hover-capable
 * pointer. On a touch screen there is no hover, so without this the titles
 * would simply never appear on phones and tablets, there they stay visible.
 */
@media (hover: hover) {
	.gallery-offset .gx-cap {
		opacity: 0;
		transition: opacity 0.3s ease;
	}

	.gallery-offset figure:hover .gx-cap,
	.gallery-offset figure:focus-within .gx-cap {
		opacity: 1;
	}
}

/* Optional second line, shown only when the page's `captions` flag is on and
   the image actually has a caption. */
.gallery-offset .gx-sub {
	display: block;
	margin-top: 3px;
	font-size: 11px;
	letter-spacing: 0.03em;
	text-transform: none;
	color: rgba(255, 255, 255, 0.76);
}

/* --------------------------------------------------------------------------
   Responsive

   Below the breakpoints the offset pattern stops being legible, the tiles get
   too narrow for the crop to flatter the product, so the layout falls back to
   two-up and then one-up at the source's own 2:1, which needs no cropping.
   These override the inline --w/--a via the cascade, so no !important is needed.
   -------------------------------------------------------------------------- */

@media (max-width: 1024px) {
	.gallery-offset figure {
		flex-grow: 0;
		flex-basis: calc((100% - var(--gx-gap)) / 2);
	}

	.gallery-offset figure > a {
		aspect-ratio: 1.25;
	}
}

@media (max-width: 560px) {
	.gallery-page {
		--gx-gap: 6px;
	}

	.gallery-offset figure {
		flex-basis: 100%;
	}

	.gallery-offset figure > a {
		aspect-ratio: 1.7;
	}

	.gallery-page-head {
		padding: 24px 0 18px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.gallery-offset figure img,
	.gallery-offset .gx-cap,
	.gallery-offset .gx-num {
		transition: none;
	}

	.gallery-offset figure:hover img {
		transform: none;
	}
}
