/* =========================================================================
   GALLERY — shared styles for the photo system.

   Three parts:
     1. Lightbox      moved verbatim out of gallery.html's inline <style> so
                      the homepage strip can reuse the same viewer.
     2. Tile          the frame every photo sits in — hover zoom + the
                      ground-plane shadow language from the newsletter
                      coverflow, and the fade-in the render script triggers.
     3. Homepage strip masonry columns and the faded/blurred lower edge.

   Easing is the site token cubic-bezier(0.22, 1, 0.36, 1) throughout.
   ========================================================================= */

/* ═══════════════════ 1. Lightbox ═══════════════════ */
.gallery-img img { cursor: zoom-in; }
.lightbox {
  position: fixed; inset: 0;
  background: rgba(10, 8, 8, 0.94);
  z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}
.lightbox.is-open { opacity: 1; pointer-events: auto; }
.lightbox-stage {
  position: relative;
  max-width: 1200px; width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.lightbox-img {
  max-width: 100%; max-height: 78vh;
  object-fit: contain;
  box-shadow: 0 24px 60px rgba(0,0,0,0.55);
  background: #111;
}
.lightbox-caption {
  color: rgba(255,255,255,0.88);
  font-family: var(--font-sans);
  font-size: 15px;
  text-align: center;
  max-width: 720px;
  line-height: 1.5;
}
.lightbox-counter {
  color: rgba(255,255,255,0.55);
  font-family: var(--font-sans-cond);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.lightbox-btn {
  position: absolute;
  background: rgba(255,255,255,0.08);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.18);
  width: 52px; height: 52px;
  border-radius: 50%;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.25s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
              border-color 0.25s;
  z-index: 2;
}
.lightbox-btn:hover { background: rgba(255,255,255,0.2); border-color: rgba(255,255,255,0.4); }
.lightbox-close { top: 24px; right: 24px; }
.lightbox-prev { top: 50%; left: 24px; transform: translateY(-50%); }
.lightbox-next { top: 50%; right: 24px; transform: translateY(-50%); }
.lightbox-prev:hover { transform: translateY(-50%) translateX(-3px); }
.lightbox-next:hover { transform: translateY(-50%) translateX(3px); }
body.lightbox-open { overflow: hidden; }
@media (max-width: 640px) {
  .lightbox-btn { width: 44px; height: 44px; font-size: 22px; }
  .lightbox-close { top: 12px; right: 12px; }
  .lightbox-prev { left: 8px; }
  .lightbox-next { right: 8px; }
}

/* ═══════════════════ 2. Tile ═══════════════════ */
/* Scoped to the homepage strip on purpose. /gallery.html's category tabs are
   gone — it is now one grid of every photo, mixing 49 page-local tiles with the
   rest rendered from the shared list — and that grid keeps the square, flat,
   un-animated tile look it always had. To upgrade it, widen these selectors to
   `.gallery-all .gallery-img`, which restyles the whole grid at once. */
.gallery-strip-frame .gallery-img {
  position: relative;
  border-radius: 8px;
  border: 1px solid rgba(120, 90, 70, 0.14);
  overflow: hidden;
  background: var(--color-bg-alt);
  /* Ground-plane shadow — pools downward only, matching the coverflow.
     Contact + ambient layers at rest; the distant pool arrives on hover. */
  box-shadow:
    0 1px 2px -1px rgba(60, 40, 20, 0.10),
    0 6px 10px -6px rgba(60, 40, 20, 0.10);
  transition:
    box-shadow 700ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 800ms cubic-bezier(0.22, 1, 0.36, 1) var(--gal-delay, 0ms),
    transform 800ms cubic-bezier(0.22, 1, 0.36, 1) var(--gal-delay, 0ms);
}
/* Rise-in on scroll (IntersectionObserver in gallery-render.js). 24px of
   travel — 10px was too small to register as motion, which is what made the
   strip look static. */
.gallery-strip-frame .gallery-img {
  opacity: 0;
  transform: translateY(24px);
}
.gallery-strip-frame .gallery-img.is-in {
  opacity: 1;
  transform: none;
}
.gallery-strip-frame .gallery-img img {
  transition:
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1),
    filter 700ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
/* Hover: image zooms inside the clipped frame, shadow lifts off the page. */
@media (hover: hover) {
  .gallery-strip-frame .gallery-img:hover {
    box-shadow:
      0 2px 4px -1px rgba(60, 40, 20, 0.12),
      0 14px 22px -8px rgba(60, 40, 20, 0.16),
      0 30px 44px -18px rgba(60, 40, 20, 0.10);
  }
  .gallery-strip-frame .gallery-img:hover img {
    transform: scale(1.05);
    filter: saturate(1.05);
  }
}
.gallery-strip-frame .gallery-img img:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ═══════════════════ 3. Homepage strip ═══════════════════ */
/* Real CSS columns: the browser balances column heights, so tiles of mixed
   height interlock and pack tight. Hand-built flex columns could not do this
   — they left ragged bottoms and read as three loose stacks. */
.gallery-strip-masonry {
  columns: 3;
  column-gap: 14px;
  /* Belt and braces against the old mobile horizontal-swipe bug: the column
     box can never exceed its container. */
  max-width: 100%;
  overflow-x: clip;
  padding-right: 10px;   /* clearance so tiles never sit under the scrollbar */
  padding-bottom: 4px;
}
.gallery-strip-frame .gallery-img {
  /* A tile must never be split across a column break. */
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  display: block;
  width: 100%;
  margin-bottom: 14px;   /* the vertical rhythm — matches column-gap so the
                            mosaic reads evenly spaced in both axes */
}
@media (max-width: 900px) {
  .gallery-strip-masonry { columns: 2; column-gap: 12px; }
  .gallery-strip-frame .gallery-img { margin-bottom: 12px; }
}
/* Two columns hold all the way down to 320px. One column showed barely two
   photos inside the band, which reads sparse — exactly what this pass is
   fixing. At 320 the tiles land ~134px wide: small, but a mosaic. */

/* Soft blur over the dissolving rows, masked so it only bites near the floor.
   Static (no looping animation behind it), so a backdrop blur is cheap here. */
/* The blur veil was removed when the strip became a scrolling window: a
   veil pinned inside a scroll box scrolls away with the content. The frame's
   own edge masks do the dissolving now. */

.gallery-strip-frame {
  position: relative;
  /* A fixed window: the masonry scrolls INSIDE it, so the page does not grow
     with the photo count. Height is tuned to show ~2.5 rows — clearly more
     below, without swallowing the screen. */
  height: 680px;
  overflow-y: auto;
  /* HARD RULE — the page must never swipe sideways. This box is the classic
     cause of that bug, so horizontal scrolling is clipped here, clipped on the
     masonry inside it, and the finger is restricted to the vertical axis.
     (fix/mobile-horizontal-overflow) */
  overflow-x: hidden;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  /* Deliberately NO overscroll-behavior: contain — scroll chaining is what
     lets the page keep moving once the window bottoms out, so the section
     never traps the reader. */

  /* Bottom edge only. The top stays fully opaque so the first row of photos
     is crisp and sits cleanly under the GALLERY label — an earlier version
     faded the top 8% too, which read as a white wash over the images. The
     bottom fade doubles as the scroll affordance. Masks paint against the
     element box, not the content, so it stays pinned to the window edge
     while the photos move underneath. */
  -webkit-mask-image: linear-gradient(180deg,
    #000 0%, #000 85%, rgba(0, 0, 0, 0.72) 94%, rgba(0, 0, 0, 0) 100%);
  mask-image: linear-gradient(180deg,
    #000 0%, #000 85%, rgba(0, 0, 0, 0.72) 94%, rgba(0, 0, 0, 0) 100%);

  /* Thin, brand-tinted scrollbar — an intentional detail, not an OS slab. */
  scrollbar-width: thin;
  scrollbar-color: rgba(158, 27, 50, 0.32) transparent;
}
.gallery-strip-frame::-webkit-scrollbar { width: 6px; }
.gallery-strip-frame::-webkit-scrollbar-track { background: transparent; }
.gallery-strip-frame::-webkit-scrollbar-thumb {
  background: rgba(158, 27, 50, 0.30);
  border-radius: 999px;
}
.gallery-strip-frame::-webkit-scrollbar-thumb:hover { background: rgba(158, 27, 50, 0.52); }
.gallery-strip-frame:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}
@media (max-width: 900px) { .gallery-strip-frame { height: 520px; } }
@media (max-width: 560px) { .gallery-strip-frame { height: 440px; } }

.gallery-strip-foot {
  display: flex;
  justify-content: center;
  margin-top: 26px;
}

/* Reduced motion: no drift, no zoom — tiles simply are. */
@media (prefers-reduced-motion: reduce) {
  .gallery-strip-frame .gallery-img {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .gallery-strip-frame .gallery-img img { transition: none; }
  .gallery-strip-frame .gallery-img:hover img { transform: none; }
}

/* ═══════════════════ 4. "Happening" section rhythm ═══════════════════ */
/* Quiet dividers under the one section heading — deliberately NOT eyebrow
   red or heading scale, so they read as labels rather than as competing
   headings. */
.happening-sub {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin: 26px 0 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--color-border);
}
.happening-sub--news { margin-top: 30px; }   /* the gap that used to be a gulf */
.happening-sub-label {
  font-family: var(--font-sans-cond);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.gallery-strip-foot {
  /* Right-aligned so it stacks flush with "All News →" in the NEWS sub-label
     below — both links share .container-main, so flex-end puts them on the
     same right edge. */
  justify-content: flex-end;
  margin-top: 14px;
}
@media (max-width: 640px) {
  .happening-sub { margin: 20px 0 12px; }
  .happening-sub--news { margin-top: 24px; }
}
