/* ==========================================================================
   DUNESCAPE JOURNEYS — GALLERY
   1. Page header    2. Drift strip    3. Filter bar
   4. Masonry grid   5. Lightbox       6. Reduced motion
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. PAGE HEADER ADDITIONS
   -------------------------------------------------------------------------- */

.gal-header { padding-bottom: calc(var(--section-y) * 0.72); }

.gal-header h1 { max-width: 16ch; }

/* Three small facts under the lead — mono, hairline-separated */
.gal-facts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm) var(--space-md);
  margin-top: var(--space-sm);
  font-family: var(--font-label);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-inv-faint);
}

.gal-facts__item { display: inline-flex; align-items: baseline; gap: 0.6em; }
.gal-facts__n { color: var(--gold); font-size: 1.05rem; letter-spacing: 0.04em; }
.gal-facts__sep { width: 1px; height: 14px; background: var(--rule-inv); }

@media (max-width: 575px) {
  .gal-facts__sep { display: none; }
}

/* --------------------------------------------------------------------------
   2. DRIFT STRIP
   A full-bleed band of tall frames that eases sideways as the page scrolls.
   The split background lets the band straddle the dark header and the white
   page below it, so the photographs carry the seam instead of a hard edge.
   -------------------------------------------------------------------------- */

.gal-strip {
  position: relative;
  overflow: hidden;
  background: linear-gradient(to bottom, var(--deep) 46%, var(--bg) 46%);
  padding-block: 0 var(--space-md);
  --strip-h: 300px;
}

.gal-strip__track {
  display: flex;
  gap: 14px;
  width: max-content;
  padding-inline: var(--pad-x);
  will-change: transform;
}

.gal-strip__cell {
  position: relative;
  flex: none;
  width: calc(var(--strip-h) * 0.72);
  height: var(--strip-h);
  overflow: hidden;
  background: var(--charcoal);
}

.gal-strip__cell img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1s var(--ease-expo), filter 0.5s var(--ease-out);
}

.gal-strip__cell::after {
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 0 1px rgba(212, 197, 169, 0.14);
  pointer-events: none;
}

.gal-strip__cell:hover img { transform: scale(1.06); }

@media (min-width: 992px) { .gal-strip { --strip-h: 360px; } }
@media (max-width: 575px) { .gal-strip { --strip-h: 220px; } }

/* --------------------------------------------------------------------------
   3. FILTER BAR
   -------------------------------------------------------------------------- */

.gal-bar {
  position: sticky;
  top: 72px;
  z-index: 20;
  /* Near-opaque: at 0.92 the photographs scrolling underneath ghosted
     through the toolbar and read as dirt on the white. */
  background: rgba(255, 255, 255, 0.985);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  border-bottom: 1px solid var(--rule);
  transition: box-shadow var(--dur) var(--ease-out),
              top 0.5s var(--ease-out);
}

/* The header retracts on scroll-down. Without this the bar stayed pinned at
   72px and a band of photographs scrolled through the gap above it. */
.gal-bar.is-flush { top: 0; }

.gal-bar.is-stuck { box-shadow: 0 12px 30px rgba(26, 21, 16, 0.06); }

.gal-bar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding-block: 1.1rem;
}

/* One row at every width. Wrapping used to orphan the last pill onto a
   second line between roughly 992px and 1165px, where the row plus the
   tally is a few pixels wider than the container. If a row still cannot
   fit — browser zoom, a wider label — it scrolls instead of wrapping. */
.gal-filters {
  display: flex;
  gap: var(--space-2xs);
  flex-wrap: nowrap;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  padding-bottom: 2px;
}

.gal-filters::-webkit-scrollbar { display: none; }

/* Fade the trailing edge only while there is actually more to scroll to */
.gal-filters.is-scrollable {
  mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
}

.gal-filter {
  position: relative;
  flex: none;
  padding: 0.8em 1.35em;
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--ink-soft);
  border: 1px solid var(--deep-12);
  border-radius: var(--radius-pill);
  overflow: hidden;
  isolation: isolate;
  white-space: nowrap;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}

.gal-filter::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--deep);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur) var(--ease-out);
}

.gal-filter:not(:hover)::before { transform-origin: right center; }
.gal-filter:hover { color: var(--deep); border-color: var(--deep-45); }

.gal-filter.is-active {
  color: var(--sand);
  border-color: var(--deep);
}

.gal-filter.is-active::before { transform: scaleX(1); }

.gal-filter__count {
  margin-left: 0.6em;
  opacity: 0.55;
  font-size: 0.9em;
  font-variant-numeric: tabular-nums;
}

.gal-tally {
  flex: none;
  font-family: var(--font-label);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.gal-tally b { color: var(--gold-deep); font-weight: 500; }

.gal-tally__mini { display: none; }

/* Below 1200px the sentence costs more room than the pills can spare,
   so it shrinks to the bare count rather than pushing the row apart. */
@media (max-width: 1200px) {
  .gal-tally__full { display: none; }
  .gal-tally__mini { display: inline; }
  .gal-filter { padding-inline: 1.15em; }
}

/* The last stretch before the layout stacks: buy the row its final pixels */
@media (max-width: 1100px) {
  .gal-filter { padding-inline: 1em; }
  .gal-bar__inner { gap: var(--space-sm); }
}

@media (max-width: 991px) {
  .gal-bar { top: 64px; }
  .gal-bar.is-flush { top: 0; }
  .gal-bar__inner { flex-direction: column; align-items: flex-start; gap: 0.9rem; padding-block: 0.9rem; }

  /* One swipeable row that runs edge to edge rather than stopping short */
  .gal-filters {
    width: calc(100% + var(--pad-x) * 2);
    margin-inline: calc(var(--pad-x) * -1);
    padding-inline: var(--pad-x);
  }
}

/* On a phone the pill counts already carry the tally — drop the sentence
   so the sticky bar does not eat an eighth of the screen. */
@media (max-width: 575px) {
  .gal-tally { display: none; }
  .gal-bar__inner { gap: 0; }
}

/* --------------------------------------------------------------------------
   4. MASONRY GRID
   CSS columns keep mixed portrait/landscape frames flush with no ragged
   gaps. Filtering only toggles display, so the columns re-flow for free.
   -------------------------------------------------------------------------- */

.gal-wrap { padding-block: var(--space-lg) var(--section-y); }

.gal-grid {
  column-count: 3;
  column-gap: var(--gutter);
}

@media (max-width: 1100px) { .gal-grid { column-count: 2; } }
@media (max-width: 600px)  { .gal-grid { column-count: 1; } }

.gal-item {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  margin-bottom: var(--gutter);
}

.gal-item.is-hidden { display: none; }

.gal-item__btn {
  display: block;
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--sand-dim);
  cursor: pointer;
  isolation: isolate;
}

.gal-item__btn img {
  width: 100%;
  height: auto;
  display: block;
  opacity: 0;
  transform: scale(1.03);
  transition: opacity 0.7s var(--ease-out),
              transform 1s var(--ease-expo),
              filter 0.6s var(--ease-out);
}

.gal-item__btn img.is-loaded { opacity: 1; transform: scale(1); }

.gal-item__btn:hover img,
.gal-item__btn:focus-visible img { transform: scale(1.045); }

/* Warm wash so a wall of holiday snapshots reads as one palette */
.gal-item__btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgba(26, 21, 16, 0.16);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
  pointer-events: none;
}

.gal-item__btn:hover::before,
.gal-item__btn:focus-visible::before { opacity: 1; }

/* Gold hairline that draws itself around the frame on hover */
.gal-item__btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  box-shadow: inset 0 0 0 1px var(--gold-line);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
  pointer-events: none;
}

.gal-item__btn:hover::after,
.gal-item__btn:focus-visible::after { opacity: 1; }

/* Hover mark. The photographs carry their own subject, so nothing is
   written over them — the expand glyph is the whole affordance, and the
   title and place are read in the viewer instead. */
.gal-item__zoom {
  position: absolute;
  right: 1.15rem;
  bottom: 1.15rem;
  z-index: 2;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid var(--gold-line);
  border-radius: var(--radius-pill);
  color: var(--gold);
  background: rgba(26, 21, 16, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transform: translateY(8px) scale(0.94);
  transition: opacity var(--dur) var(--ease-out), transform 0.5s var(--ease-expo);
  pointer-events: none;
}

.gal-item__btn:hover .gal-item__zoom,
.gal-item__btn:focus-visible .gal-item__zoom {
  opacity: 1;
  transform: none;
}

.gal-item__zoom svg { width: 15px; height: 15px; stroke-width: 1.6; }

/* Empty state */
.gal-empty {
  padding: var(--space-xl) 0;
  text-align: center;
  color: var(--ink-faint);
  font-family: var(--font-label);
  font-size: var(--fs-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   5. LIGHTBOX
   -------------------------------------------------------------------------- */

.gal-box {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  background: rgba(14, 11, 8, 0.97);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s var(--ease-out), visibility 0.45s;
}

.gal-box.is-open { opacity: 1; visibility: visible; }

.gal-box__bar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: 1rem var(--pad-x);
  border-bottom: 1px solid var(--rule-inv);
}

.gal-box__counter {
  font-family: var(--font-label);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-inv-faint);
  font-variant-numeric: tabular-nums;
}

.gal-box__counter b { color: var(--gold); font-weight: 500; }

.gal-box__close {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule-inv);
  border-radius: var(--radius-pill);
  color: var(--ink-inv-soft);
  transition: color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out);
}

.gal-box__close:hover {
  color: var(--deep);
  background: var(--gold);
  border-color: var(--gold);
  transform: rotate(90deg);
}

.gal-box__close svg { width: 16px; height: 16px; stroke-width: 1.6; }

.gal-box__stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: center;
  padding: var(--space-sm) calc(var(--pad-x) + 56px);
}

.gal-box__figure {
  position: relative;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}

.gal-box__img {
  max-width: 100%;
  max-height: calc(100vh - 208px);
  width: auto;
  height: auto;
  object-fit: contain;
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.55);
  transition: opacity 0.35s var(--ease-out), transform 0.5s var(--ease-expo);
}

.gal-box__img.is-swapping { opacity: 0; transform: scale(0.985); }

.gal-box__cap {
  text-align: center;
  max-width: 60ch;
}

/* Only worth saying where there are no arrows to click */
.gal-box__hint {
  display: none;
  margin-top: 0.75rem;
  font-family: var(--font-label);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-inv-faint);
}

@media (hover: none) and (pointer: coarse) {
  .gal-box__hint { display: block; }
}

/* --- Prev / next --- */
.gal-box__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  color: var(--ink-inv-soft);
  border: 1px solid var(--rule-inv);
  border-radius: var(--radius-pill);
  background: rgba(26, 21, 16, 0.5);
  transition: color var(--dur) var(--ease-out),
              background-color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
}

.gal-box__nav:hover {
  color: var(--deep);
  background: var(--gold);
  border-color: var(--gold);
}

.gal-box__nav--prev { left: var(--pad-x); }
.gal-box__nav--next { right: var(--pad-x); }
.gal-box__nav svg { width: 18px; height: 18px; stroke-width: 1.5; }

/* --- Filmstrip --- */
.gal-box__strip {
  flex: none;
  display: flex;
  gap: 8px;
  padding: 0.9rem var(--pad-x);
  overflow-x: auto;
  border-top: 1px solid var(--rule-inv);
  scrollbar-width: none;
}

.gal-box__strip::-webkit-scrollbar { display: none; }

.gal-box__thumb {
  flex: none;
  width: 72px;
  height: 54px;
  overflow: hidden;
  /* Thumbs load lazily; without this an unloaded slot is a hole in the rail */
  background: var(--charcoal);
  opacity: 0.38;
  filter: grayscale(0.4);
  transition: opacity var(--dur) var(--ease-out),
              filter var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}

.gal-box__thumb img { width: 100%; height: 100%; object-fit: cover; }
.gal-box__thumb:hover { opacity: 0.8; filter: none; }

.gal-box__thumb.is-current {
  opacity: 1;
  filter: none;
  box-shadow: inset 0 0 0 2px var(--gold);
}

@media (max-width: 767px) {
  .gal-box__stage { padding-inline: var(--gutter); }
  .gal-box__nav { display: none; }
  .gal-box__img { max-height: calc(100vh - 200px); }
  .gal-box__strip { display: none; }
  .gal-box__cap { padding-inline: var(--gutter); }
}

/* --------------------------------------------------------------------------
   6. REDUCED MOTION
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .gal-item__btn img { opacity: 1; transform: none; }
  .gal-strip__track { transform: none !important; }
}
