/* ==========================================================================
   ALANY / BOOM — PHOTO GALLERY
   Loads on top of home.css, which owns the tokens, nav, buttons and footer.
   Everything here is the archive itself: the masthead, the film strip, the
   filter bar and the collage wall.

   The wall is a CSS grid whose rows are 8px tall; gallery.js gives each tile
   a `grid-row: span N` worked out from its own aspect ratio, which is what
   makes the columns interlock instead of sitting in neat rows. Until that
   runs the grid is a plain auto-row grid — uneven, but never broken.
   ========================================================================== */

/* ==========================================================================
   MASTHEAD
   ========================================================================== */
.gmast {
  position: relative;
  overflow: hidden;
  padding-top: calc(var(--nav-h) + clamp(1.6rem, 3.4vw, 3rem));
  padding-bottom: clamp(1.8rem, 3.4vw, 2.8rem);
  background:
    radial-gradient(110% 78% at 84% 0%, rgba(255, 107, 44, 0.11), transparent 60%),
    var(--sand);
}
/* stretch, not end: the photograph takes its height from the column of text
   beside it, so the two sides finish on the same line and the copy stays at
   the top where it belongs */
.gmast__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
  gap: clamp(1.6rem, 4vw, 4rem);
  align-items: stretch;
}
.gmast__lead {
  max-width: 54ch;
  margin-top: 1.15rem;
}

/* the counts sit on a baseline rather than in boxes — the same move the home
   hero makes, so the two pages read as one family */
.gmast__facts {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.2rem, 3vw, 2.6rem);
  margin-top: clamp(1.4rem, 2.6vw, 2rem);
}
.gmast__fact b {
  display: block;
  font-family: var(--font-d);
  font-size: clamp(1.5rem, 2.4vw, 2.1rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--ink);
}
.gmast__fact span {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  color: var(--txt-mute);
}

/* one frame to anchor the right-hand column — no aspect ratio of its own, it
   simply matches whatever height the text column ends up at */
.gmast__shot {
  position: relative;
  border-radius: 18px;
  overflow: hidden;
  min-height: clamp(260px, 26vw, 380px);
  background: var(--sand-deep);
  box-shadow: 0 30px 60px -34px rgba(22, 18, 15, 0.55);
}
.gmast__shot img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gmast__shot figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 2.6rem 1.1rem 1rem;
  font-size: 0.78rem;
  line-height: 1.45;
  color: #fff;
  background: linear-gradient(to top, rgba(12, 9, 7, 0.82), transparent);
}

@media (max-width: 900px) {
  .gmast__grid { grid-template-columns: 1fr; }
  .gmast__shot { aspect-ratio: 16 / 10; min-height: 0; }
}

/* ==========================================================================
   SECTION HEADS
   home.css sets these beside their number; on a page this dense the heading
   and its paragraph read better stacked underneath, the way programs.html
   handles the same block.
   ========================================================================== */
.sec .shead {
  grid-template-columns: 1fr;
  gap: 0.55rem;
}
.sec .shead__n { padding-top: 0; }
.sec .shead__t { max-width: 26ch; }
.sec .shead__p { max-width: 78ch; }

/* ==========================================================================
   FILM STRIP — the marquee band between masthead and wall
   ========================================================================== */
.strip {
  overflow: hidden;
  padding-block: clamp(0.8rem, 1.6vw, 1.2rem);
  background: var(--ink);
}
.strip .mq__track {
  display: flex;
  gap: 0.55rem;
  width: max-content;
  will-change: transform;
}
.strip img {
  height: clamp(96px, 12vw, 168px);
  width: auto;
  border-radius: 8px;
  opacity: 0.82;
  transition: opacity 0.4s var(--e);
}
.strip:hover img { opacity: 1; }

/* ==========================================================================
   FILTER BAR
   ========================================================================== */
.gfilter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: clamp(1.3rem, 2.4vw, 1.9rem);
}
.gfilter button {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  padding: 0.6rem 1.05rem;
  border: 0;
  border-radius: 999px;
  background: rgba(22, 18, 15, 0.06);
  color: var(--txt-soft);
  font-family: var(--font-d);
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: background 0.3s var(--e), color 0.3s var(--e), transform 0.3s var(--e);
}
.gfilter button i {
  font-style: normal;
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  opacity: 0.55;
}
.gfilter button:hover {
  background: rgba(22, 18, 15, 0.11);
  transform: translateY(-2px);
}
.gfilter button.is-on {
  background: var(--ink);
  color: var(--cream);
}
.gfilter button.is-on i { opacity: 0.6; }

/* ==========================================================================
   THE WALL
   ========================================================================== */
/* Every cell in the wall is the same 4:3 box, so the photographs line up in
   true rows and columns with no ragged edge anywhere. The variety comes from
   a few tiles claiming 2x2 and from portrait frames claiming 1x2 — gallery.js
   places every tile explicitly, which is what guarantees there is never an
   empty cell, including on the last row. */
.gwall {
  display: grid;
  grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr));
  gap: var(--gap, 12px);
  align-items: stretch;
}
.gtile {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  border-radius: 12px;
  overflow: hidden;
  background: var(--sand-deep);
  cursor: pointer;
  isolation: isolate;
  /* before the script runs (or if it never does) the wall is still a clean
     uniform grid — just without the accents */
  aspect-ratio: 4 / 3;
}
/* once the tiles are placed, height comes from the grid rows instead */
.gwall.is-set .gtile { aspect-ratio: auto; }
/* The entrance — tiles settle in as they scroll into view. The hidden state
   is scoped to .is-anim, which gallery.js only sets once it has an observer
   ready to take it off again: if that script never runs, the wall is simply
   visible rather than 133 invisible buttons. */
.gwall.is-anim .gtile {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s var(--e), transform 0.7s var(--e);
}
.gwall.is-anim .gtile.is-in {
  opacity: 1;
  transform: none;
}

.gtile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.85s var(--e);
}

/* caption scrim — off the bottom edge until the tile is hovered or focused */
.gtile__c {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: 2.4rem 0.85rem 0.8rem;
  text-align: left;
  background: linear-gradient(to top, rgba(12, 9, 7, 0.88) 12%, transparent);
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.4s var(--e), transform 0.5s var(--e);
}
.gtile__c b {
  display: block;
  font-family: var(--font-d);
  font-size: 0.82rem;
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: -0.015em;
  color: #fff;
}
.gtile__c i {
  display: block;
  margin-top: 0.25rem;
  font-style: normal;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--orange-2);
}

/* the corner glyph is the only thing showing at rest — it says "this opens" */
.gtile::after {
  content: "";
  position: absolute;
  z-index: 3;
  top: 0.6rem;
  right: 0.6rem;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(12, 9, 7, 0.45) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 3h6v6M9 21H3v-6M21 3l-8 8M3 21l8-8'/%3E%3C/svg%3E") center / 13px no-repeat;
  opacity: 0;
  transform: scale(0.7);
  transition: opacity 0.35s var(--e), transform 0.35s var(--e);
}

.gtile:hover img,
.gtile:focus-visible img { transform: scale(1.07); }
.gtile:hover .gtile__c,
.gtile:focus-visible .gtile__c { opacity: 1; transform: none; }
.gtile:hover::after,
.gtile:focus-visible::after { opacity: 1; transform: none; }
.gtile:focus-visible { outline: 3px solid var(--orange); outline-offset: 3px; }

/* filtered out — the lightbox skips anything that is not laid out */
.gtile.is-off { display: none; }

/* empty state, in case a filter ever comes back with nothing */
.gwall__none {
  display: none;
  padding: clamp(2rem, 5vw, 3.4rem) 0;
  text-align: center;
  color: var(--txt-mute);
}
.gwall.is-empty + .gwall__none { display: block; }

.gnote {
  margin-top: clamp(1.4rem, 2.6vw, 2rem);
  font-size: 0.82rem;
  color: var(--txt-mute);
  max-width: 68ch;
}

/* ---------- column counts ---------- */
@media (min-width: 1401px) { .gwall { --cols: 5; --gap: 14px; } }
@media (max-width: 1400px) { .gwall { --cols: 4; } }
@media (max-width: 1080px) { .gwall { --cols: 3; } }
@media (max-width: 760px)  { .gwall { --cols: 2; --gap: 9px; } }
@media (max-width: 420px)  { .gwall { --gap: 7px; } .gtile { border-radius: 9px; } }

/* on touch there is no hover, so the caption rides along at all times */
@media (hover: none) {
  .gtile__c { opacity: 1; transform: none; }
  .gtile::after { opacity: 0.85; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .gwall.is-anim .gtile { opacity: 1; transform: none; transition: none; }
  .gtile img { transition: none; }
}
