/* ============================================================
   KDMN GALLERY PAGE — Canvas foundation
   ============================================================
   This file currently defines ONLY the page's master canvas:
   the coordinate system and background that every future section
   (hero, "This Month", "B.T.S", contact/map footer, etc.) will be
   built on top of, matching Final_Goal.pdf 1:1.

   SOURCE ASSET: Canvas_Background.png (uploaded reference)
     - Actual pixel bounds: 2474 x 8000
     - Sampled color: solid #FFFFFF across every pixel (verified,
       zero variance, no texture/grain)
     - Confirmed intentional by Tebogo: flat white/cream, not a
       placeholder or wrong upload.

   ENGINEERING DECISION — rendered as a CSS color, not an <img>:
     The source file is a flat, textureless 2474x8000 raster
     (117KB). Serving it as a literal background-image would cost
     real page weight for a result pixel-identical to a one-line
     CSS color. The canvas is therefore implemented as a CSS
     background-color sampled directly from the asset, with the
     bounds preserved as the coordinate system for future
     absolutely-positioned assets (same pattern the homepage uses
     per-section, e.g. .pain-note-wrap's exact px offsets).
     Original file is archived at
     /gallery/design-reference/Canvas_Background.png for future
     crop reference — it is NOT linked/served to the browser.

   DESKTOP ONLY (per project instruction). No mobile/tablet rules
   are included in this file.
   ============================================================ */

@font-face { font-family:'Impacted'; src:url(../../assets/fonts/9ebff8be2e9e08c5.woff2) format('woff2'); }

:root {
  --gallery-canvas-w: 2474px;   /* master artboard width  */
  --gallery-canvas-h: 8000px;   /* master artboard's original nominal
                                    height. No longer used as a min-height
                                    on .gallery-canvas (removed — see the
                                    collapsible-sections comment below for
                                    why) — kept here only as a reference
                                    figure for the master design file. */
  --gallery-canvas-bg: #FFFFFF; /* sampled 1:1 from Canvas_Background.png */
  --gallery-nav-h: 184px;       /* derived from Navbar_Background.png's own aspect
                                    ratio (6000x446) scaled to the 2474px canvas
                                    width: 446 * (2474/6000) = 183.9px */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  background: var(--gallery-canvas-bg);
  /* overflow-x:auto removed — superseded by .gallery-canvas's own
     zoom-based uniform scaling below, which keeps the canvas within
     the viewport at every width, making horizontal scroll unnecessary.
     Home's own html{overflow-x:hidden} (styles.css, unmodified) applies
     here again, exactly as it does on Home itself. */
}

/* html's overflow-x:auto override (previously here to make the
   fixed-width canvas horizontally reachable when narrower than the
   viewport) has been removed — now that .gallery-canvas scales
   uniformly to match the effective viewport at every zoom level (see
   its own rule below), the canvas never exceeds the viewport width,
   so there's nothing left to scroll to. Home's own html{overflow-x:
   hidden} (styles.css, unmodified) applies here again unmodified,
   exactly as it does on Home itself. */

body {
  font-family: 'Patrick Hand', cursive;
}

/* ---------- MASTER CANVAS ----------
   Every future gallery section/asset is positioned inside this
   element using absolute top/left/width/height values that map
   1:1 to the master design file's own coordinates (matching
   Canvas_Background.png's 2474 x 8000 bounds). Do not add section
   markup outside .gallery-canvas. */
.gallery-canvas {
  position: relative;
  width: var(--gallery-canvas-w);
  margin: 0 auto;
  background: var(--gallery-canvas-bg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  zoom: calc(100vw / 2474px); /* Uniformly scales the whole 2474px
                    canvas to match the effective viewport at every
                    browser zoom level — no min(1,...) clamp. The
                    clamped version left the canvas at native 2474px
                    (zoom:1) whenever 100vw exceeded 2474px, which
                    happens not only on genuinely wide screens but
                    also whenever the browser is zoomed OUT (zooming
                    out widens the effective CSS viewport) — CSS vw
                    units can't tell those two cases apart. That
                    caused large white margins at low zoom levels
                    (measured: 1672px of white space at 33% zoom).
                    Removing the clamp matches Home/CTA's own
                    behavior exactly (unconstrained, always-100vw-
                    relative — verified identical at every tested
                    zoom level from 33% to 150%). zoom (not transform)
                    specifically because #galleryNav is position:fixed
                    nested inside this element — transform would make
                    it a containing block for fixed descendants,
                    breaking nav's genuine viewport-relative pinning;
                    zoom does not, and is layout-affecting, so
                    .contact (CTA) below automatically follows the
                    scaled height with no manual height math needed.
                    Division must use matching units (2474px, not
                    2474) or this silently resolves to zoom:1 with no
                    error. */
}

/* ============================================================
   MOBILE ACCESSIBILITY BLOCKER FIX (architecture only — not a
   mobile design pass)
   ============================================================
   Confirmed via audit: .gallery-canvas's fixed 2474px width, at
   viewports <=700px, combined with the Home-derived styles.css's
   global `html, body { overflow-x:hidden }`, silently trapped the
   whole document at 2474px wide with no way to reach content past
   the viewport edge (not scrollable — overflow-x:hidden blocks
   the scroll gesture entirely) or scroll down to anything below
   the canvas (contact/map/modals).

   Minimum fix: cap the canvas to the viewport width at <=700px so
   it stops forcing document width past what's reachable. Children
   keep their existing fixed px positioning/sizing untouched (nav,
   banner, tape, teal, BTS are NOT being reworked here) — they will
   simply be clipped by .gallery-canvas's own existing
   overflow:hidden within this narrower box, same clipping
   mechanism already in place, just now bounded to the viewport.
   That clipping is visually incomplete for mobile (expected — a
   real mobile design pass comes later) but no longer makes the
   canvas, or anything after it in the document, unreachable.

   Desktop (>700px) is completely untouched: this rule only exists
   inside the media query below. Gallery-specific rule only —
   styles.css is not modified.
   ============================================================ */
@media (max-width: 700px) {
  .gallery-canvas {
    width: 100%;
  }
}

/* ============================================================
   MOBILE NAVIGATION
   ============================================================
   Directly adapted from Home's own mobile nav (styles.css) — same
   structure, same values (clamp() sizing, colors, transforms), same
   three assets. Lives outside .gallery-canvas (see index.html), so
   none of this is affected by the canvas's zoom; sizing here is
   therefore genuine mobile-native px/vw/vh, not scaled-down desktop
   sizing. Hidden entirely above 700px — #galleryNav (existing desktop
   nav, inside the zoomed canvas) is hidden at that same breakpoint
   below, so exactly one nav is visible at any given width.
   ============================================================ */
.gallery-mobile-menu-toggle {
  display: none; /* shown only ≤700px, below */
  position: fixed;
  top: 14px;
  right: 16px;
  z-index: 410; /* above galleryNav's 400 — moot once that's hidden at
                    this width, but keeps a sane stacking order regardless */
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  line-height: 0;
}
.gallery-mobile-menu-toggle img { height: 40px; width: auto; display: block; }

.gallery-mobile-nav-panel {
  display: none; /* toggled to block via .is-open — same instant
                     show/hide as Home's own implementation; Home's
                     source has no slide transition on this panel
                     itself (only the shadow graphic's rotation
                     differs by side), so none is introduced here either */
  position: fixed;
  top: 0;
  bottom: 0;
  width: 70vw;
  z-index: 409;
  background: rgba(0, 0, 0, 0.60);
  overflow: visible;
}
.gallery-mobile-nav-panel.is-open { display: block; }
.gallery-mobile-nav-panel.panel-right { right: 0; }
.gallery-mobile-nav-panel.panel-left { left: 0; }
.gallery-mobile-nav-content {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  box-sizing: border-box;
  padding: 0 clamp(16px, 6vw, 32px) clamp(16px, 5vh, 32px);
}
.gallery-mobile-nav-edge {
  position: absolute;
  top: 0;
  height: 100%;
  width: 0;
  z-index: 1;
  pointer-events: none;
  overflow: visible;
}
.gallery-mobile-nav-panel.panel-right .gallery-mobile-nav-edge { left: 0; }
.gallery-mobile-nav-panel.panel-left .gallery-mobile-nav-edge { right: 0; }
.gallery-mobile-nav-shadow {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100vh;
  height: auto;
  display: block;
  transform-origin: center center;
}
.gallery-mobile-nav-panel.panel-right .gallery-mobile-nav-shadow { transform: translate(-50%, -50%) rotate(90deg); }
.gallery-mobile-nav-panel.panel-left .gallery-mobile-nav-shadow { transform: translate(-50%, -50%) rotate(-90deg); }
.gallery-mobile-nav-links { display: flex; flex-direction: column-reverse; }
.gallery-mobile-nav-panel .gallery-mobile-nav-links a {
  font-family: 'Impacted', sans-serif;
  text-decoration: none;
  font-size: clamp(30px, 8.5vw, 38px);
  padding: clamp(7px, 2.2vh, 12px) 4px;
  text-shadow: 1px 2px 4px rgba(0, 0, 0, 0.7);
  color: #fff;
  display: block;
}
.gallery-mobile-nav-panel .gallery-mobile-nav-links a:nth-child(1) { color: #e9c46a; }
.gallery-mobile-nav-panel .gallery-mobile-nav-links a:nth-child(2) { color: #e76f51; }
.gallery-mobile-nav-panel .gallery-mobile-nav-links a:nth-child(3) { color: #2a9d8f; }
.gallery-mobile-nav-panel .gallery-mobile-nav-links a:nth-child(4) { color: #73ba9b; }

@media (max-width: 700px) {
  .gallery-mobile-menu-toggle { display: block; }
  #galleryNav {
    display: none; /* desktop nav lives inside the zoomed canvas and
                       would be illegibly tiny at this width (confirmed
                       directly in the mobile audit) — the mobile nav
                       above is its true-scale replacement at this
                       breakpoint, not a duplicate. */
  }
}

/* ============================================================
   MASTHEAD / NAVBAR
   ============================================================
   SOURCE ASSETS:
     - Navbar_Background.png (6000x446): flat solid #000000, zero
       texture (verified, same situation as Canvas_Background.png).
       Implemented as a CSS background-color for the same reason —
       no visual difference, no dead raster weight. Its own aspect
       ratio is preserved via --gallery-nav-h above. Archived at
       /gallery/design-reference/Navbar_Background.png, not served.
     - Navbar_Logo.png (963x974): real artwork, served as an <img>
       at assets/images/navbar-logo.png.

   Position/size values below were reconstructed from Final_Goal.pdf
   (pixel-cluster analysis of the reference screenshot, scaled to
   this canvas's 2474px width) — visually approved before build.

   Behavior matches the homepage's .kdmn-nav 1:1 (fixed, hides on
   scroll-down, reappears on scroll-up; logo scale+rotate hover;
   per-link accent hover colors) — see gallery.js.

   Fixed positioning here is centered under the 2474px canvas
   (left:50% + translateX(-50%)) rather than full-viewport-width,
   since this page's coordinate system is the fixed-width canvas,
   not the fluid viewport the homepage nav uses.
   ============================================================ */

.gallery-nav-spacer { height: var(--gallery-nav-h); }

.gallery-nav {
  position: fixed;
  top: 0;
  left: 50%;
  width: var(--gallery-canvas-w);
  height: var(--gallery-nav-h);
  background: #000;
  z-index: 400;
  transform: translateX(-50%);
  transition: transform .35s ease;
}
.gallery-nav.nav-hidden {
  transform: translateX(-50%) translateY(-100%);
}

.gallery-nav-logo-btn {
  position: absolute;
  top: 0;
  left: 628px;
  width: 334px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  line-height: 0;
  display: block;
  z-index: 20;
}
.gallery-nav-logo-btn img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform .3s ease;
}
.gallery-nav-logo-btn:hover img {
  transform: scale(1.2) rotate(-10deg);
}

.gallery-nav-links {
  position: absolute;
  top: 0;
  left: 1150px;
  height: var(--gallery-nav-h);
  width: 1300px;
  display: flex;
  align-items: center;
  gap: 60px;
  z-index: 15;
}
.gallery-nav-links a {
  font-family: 'Impacted', sans-serif;
  color: #fff;
  text-decoration: none;
  font-size: 56px;
  letter-spacing: 1px;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color .2s ease;
}
.gallery-nav-links a:nth-child(1):hover { color: #e9c46a; }
.gallery-nav-links a:nth-child(2):hover { color: #e76f51; }
.gallery-nav-links a:nth-child(3):hover { color: #2a9d8f; }
.gallery-nav-links a:nth-child(4):hover { color: #73ba9b; }

/* ============================================================
   GALLERY BANNER (reworked: split assets, tape sandwiched behind torn edge)
   ============================================================
   SOURCE ASSETS (supplied pre-split, used unmodified — no crop/
   redraw/re-encode per explicit instruction):
     - BlueBacking.png (3100x8000, RGB, solid teal from its own
       top edge downward) — back layer.
     - Gallery_Banner.png (6375x3799, RGBA) — front layer; opaque
       photo/title/torn-edge on top, fully transparent below the
       tear (verified: alpha 0 at the bottom rows at a sampled
       column), which is what lets the backing/tape show through
       beneath the torn edge.

   Previous combined asset (GalleryBanner_Bluebacking.png, and its
   derived gallery-banner.webp crop) is retired — removed from
   assets/images/, replaced by this three-layer stack.

   STACK (back -> front), matching the requested correction:
     1. .gallery-blue-backing   (z-index:1)
     2. .gallery-this-month-tape (existing rule, unchanged, z-index:50)
     3. .gallery-banner          (z-index:60)
   The tape's own position/size rule is untouched — only its
   stacking relative to the new front layer changes (it was already
   above the old single banner asset; now the banner front layer
   is deliberately raised above it instead).

   .gallery-banner-composite is a plain position:relative wrapper
   (no z-index of its own, so it does NOT create an isolated
   stacking context) — this lets .gallery-blue-backing (nested
   inside it) and .gallery-this-month-tape (a sibling further down
   in .gallery-canvas) still compare directly by z-index as if they
   were all in one shared stack.

   .gallery-banner remains the normal-flow element that sizes this
   composite (display:block, width:100%, height:auto, unchanged
   sizing behavior) — .gallery-blue-backing is absolutely
   positioned to fill that same box (object-fit:cover;
   object-position:top, so it's anchored to its own top edge,
   which is solid teal — not an arbitrary vertical crop).
   ============================================================ */

/* ============================================================
   GALLERY BANNER WIDTH FIX
   ============================================================
   Gallery_Banner.png (6375x3799) has a 374px fully-transparent
   margin baked into its LEFT edge only (verified consistent
   across the full image height; right edge is flush at x=6374,
   content width = 6000px of the 6375px file). Per instruction,
   the asset itself is not modified — this is corrected purely via
   CSS sizing/position: the whole image is scaled up so its
   CONTENT width (6000px) — not the file's outer bounds — maps to
   the full canvas width, then shifted left so that content starts
   at x:0. The excess (the enlarged transparent margin, now
   pushed further left, plus a hair of rounding on the right) is
   clipped by .gallery-banner-composite's overflow:hidden.

   scale  = canvas-w * (6375/6001)   [6375 = full file width,
                                       6001 = real content width
                                       (6374 - 374 + 1)]
   left   = canvas-w * (-374/6001)   [374 = transparent margin,
                                       pushed left by that same
                                       scale factor]

   This necessarily makes the banner's rendered height taller too
   (auto, from the new width) — composite and .gallery-blue-backing
   (height:100%) resize with it automatically, no separate change
   needed there.
   ============================================================ */

.gallery-banner-composite {
  position: relative;
  overflow: hidden;
  /* ============================================================
     TEAL-GAP FIX (diagnosed separately, implemented here)
     ============================================================
     Previously unset, so this box's height auto-derived from
     .gallery-banner's own full rendered height - which includes a
     fully-transparent margin below the baked-in "This Month" tape,
     running from the tape's own bottom edge (y:4172 in the source
     6375x4339 file - same figure .gallery-this-month-hit-area below
     already uses for its own position) down to the file's bottom
     edge (y:4339). With no explicit height here, that dead margin
     was included in this box's visible area, letting
     .gallery-blue-backing (height:100% of this element) show
     through it as an unintended full-width teal band directly above
     .gallery-teal-section.

     Explicit height, stopping exactly at the tape's own bottom edge,
     using the same canvas-w/6001 scale factor already established
     by every other measurement in this file (see
     .gallery-this-month-hit-area and .gallery-banner above) so this
     stays proportionally correct at any viewport width without a
     breakpoint-specific override. .gallery-banner itself is
     untouched (still renders at its full natural height/position,
     torn edge and tape unaffected) - this only changes how much of
     it this container's overflow:hidden lets through, clipping away
     the dead transparent tail (and the teal it was revealing) below
     the tape. .gallery-teal-section (next sibling) naturally moves
     up to close the resulting gap, per normal document flow - no
     change to .gallery-teal-section's own rules was needed or made. */
  height: calc(var(--gallery-canvas-w) * 4172 / 6001);
}

.gallery-blue-backing {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  display: block;
  z-index: 1;
}

.gallery-banner {
  position: relative;
  display: block;
  width: calc(var(--gallery-canvas-w) * 6375 / 6001);
  left: calc(var(--gallery-canvas-w) * -374 / 6001);
  height: auto;
  z-index: 60;
}

.gallery-teal-section {
  height: calc(var(--gallery-canvas-w) * 1.5 - 84.101px); /* Tracks
                      Canvas.png's own rendered height (6000x9000, i.e.
                      exactly 1.5x this canvas's width — the same
                      formula used everywhere else in this file, not a
                      new flat number) MINUS the composition's existing
                      translateY(-84.101px). Canvas.png's own intrinsic
                      height as an element is unaffected by that
                      transform (translate never changes an element's
                      own width/height), but the transform DOES shift
                      where its bottom edge actually ends up relative to
                      this section — this expression sizes the section
                      to end exactly there, so the #2A9D8F fallback
                      below is never exposed beneath it. The transform
                      itself is untouched — this only accounts for its
                      already-known, existing effect. Was a flat 3711px
                      (Canvas's own height alone, ignoring the shift);
                      is now 3626.899px. Overridden by .is-collapsed
                      below for the collapsed state, which is
                      unchanged. */
  background: #000; /* was #2A9D8F (teal) - that was correct back when
                      this rule's height matched Canvas.png's own true
                      coverage exactly (see the bottom-overlap fix
                      further down, which now extends this rule's
                      height slightly past that point to reach
                      .gallery-bts-tear's centreline). Canvas.png itself
                      doesn't extend into that added sliver - nothing
                      does, since it was never part of the mosaic's
                      real content - so the fallback is what actually
                      renders there now, confirmed visually (a thin
                      teal line appeared right at the torn edge once
                      the height was extended). Black matches the
                      surrounding torn-paper/BTS palette and blends in
                      rather than showing a stray teal line. Collapsed
                      state is unaffected - its own window (187px+) is
                      always fully covered by Canvas.png, so this
                      fallback was already never exposed there either
                      way. */
  position: relative;
  overflow: hidden; /* required for the collapsed sliver below to
                        actually clip content rather than just
                        shrinking the box while content still shows
                        past it — section has no other content of its
                        own currently, so this has no effect on the
                        existing expanded appearance. */
  transition: height 400ms cubic-bezier(0.33, 1, 0.68, 1); /* accordion
                        animation — height is already a plain px value
                        in both the collapsed and expanded rules, so
                        this transitions cleanly between them with no
                        other change required. Duration kept at 400ms;
                        eased with a smoother deceleration curve
                        (easeOutCubic-style, no overshoot/bounce) than
                        the previous plain ease-out, per the animation
                        refinement pass. */
  /* ============================================================
     TAPE-FLANKING TEAL FIX
     ============================================================
     The "This Month" tape graphic (baked into gallery-banner-with-
     tape.png, y:3799-4172 of that file) is narrower than the full
     canvas width, so the transparent pixels either side of it (still
     within .gallery-banner-composite, which is correctly clipped
     exactly at the tape's own bottom edge - unchanged by this rule)
     reveal .gallery-blue-backing as visible teal.

     Rather than touching the composite/backing/tape at all, this
     pulls .gallery-teal-section's own box upward by exactly the
     tape's own height (373px of that file = 153.775px canvas-native,
     the same figure .gallery-this-month-hit-area already uses),
     using a plain negative margin-top - no position/height/z-index
     change needed. .gallery-this-month-asset children are already
     position:absolute;top:0 relative to THIS element, so they move
     up in exact lockstep with it: the crop of Canvas.png (etc.)
     already visible in the window is unchanged, just physically
     extended upward into the tape's row-band.

     Once there, no z-index change is needed either: .gallery-banner
     (z-index:60, the tape/tear artwork) still paints above everything
     in that shared region wherever it's opaque; Canvas.png and
     .gallery-blue-backing share the same z-index:1, so standard CSS
     stacking resolves the tie by DOM order - Canvas.png, being later
     in the DOM, already wins and paints over blue-backing wherever
     the two now overlap. The net effect: the tape's flanking
     transparency now reveals gallery image content instead of teal,
     with the tape and torn edge completely unaffected (still opaque,
     still on top). .gallery-bts-section (next sibling) shifts up by
     this same amount purely as a normal-flow consequence - its own
     rules are untouched. */
  /* Extended from -373 to -436 (in the same file-space/6001 ratio
     units): -373 alone (the tape's own hard alpha boundary, exact)
     left a thin residual band still visible above the tape - measured
     directly on the rendered page (not just source-file alpha) at
     ~10-15px rendered at 1440px width (~17-26px canvas-native),
     because the browser's own downscaling (~4.2x, 6375px source down
     to ~1530px rendered) blends/softens the torn edge's already-jagged
     alpha taper beyond what the raw source pixels alone show. +63
     file-space px (measured taper + small safety margin, converted
     back to this file's coordinate space: 26 canvas-native px *
     6001/2474) covers that fully. */
  margin-top: calc(var(--gallery-canvas-w) * -436 / 6001);
  /* ============================================================
     EXPANDED-STATE BOTTOM OVERLAP (mirrors the .is-collapsed fix)
     ============================================================
     This base/expanded rule only ever received the TOP overlap
     (margin-top above) - it had no equivalent at the bottom, unlike
     .is-collapsed below (which already extends to .gallery-bts-tear's
     centreline). Confirmed by measurement: with no margin-bottom here,
     this rule's own height put its bottom edge exactly at
     .gallery-bts-tear's own top (zero overlap), so the tear's full
     height appeared as an abrupt solid-black rectangle immediately
     after the photos, instead of the same soft photo-into-tear blend
     already working in the collapsed state.
     Same fix, same ratio (621/12000 = half of .gallery-bts-tear's own
     height formula, 621/6000), mirrored onto this rule.

     KNOWN LIMITATION (investigated, not fixed - see chat history):
     .gallery-this-month-asset (every photo layer, including
     Canvas.png) is width:100%;height:auto - each sizes itself from
     its own fixed intrinsic aspect ratio, so none of them actually
     extend any further just because this container is taller. A thin,
     unavoidable dark band is visible exactly at .gallery-bts-tear's
     own soft top edge (its source alpha ramps 3.6%->100% over roughly
     its first 60 of 621 rows) immediately above the white torn edge,
     regardless of the overlap amount used here: reducing the overlap
     to end sooner does not help, because that low-alpha zone sits at
     the very start of the tear (immediately adjacent to Canvas.png's
     real edge either way) and is included in ANY non-zero overlap.
     Both this rule's own #000 fallback and .gallery-bts-section's real
     #000 background are equally dark, so this isn't a fallback-color
     problem either - the band comes from the tear's own dark pixels
     at low alpha, which read as dark regardless of what (if anything)
     is behind them. Genuinely fixing this would require real photo
     content to physically extend into that exact zone (images would
     need to be sized/positioned beyond their natural aspect ratio) or
     a different tear asset - out of scope without further direction. */
  height: calc(var(--gallery-canvas-w) * 1.5 - 84.101px + var(--gallery-canvas-w) * 621 / 12000);
  margin-bottom: calc(var(--gallery-canvas-w) * -621 / 12000);
}

/* ============================================================
   COLLAPSIBLE THIS MONTH / BTS SECTIONS — DOCUMENT FLOW FIX
   ============================================================
   Previous version anchored both tapes with fixed/absolute
   coordinates independent of the sections they control, which
   broke as soon as a section's height needed to change (BTS's tear
   didn't move when This Month expanded, and .gallery-canvas's old
   min-height:8000px kept the page tall even with both collapsed).

   Corrected architecture: both tapes are now normal-flow children
   of the section they control. Changing a section's height now
   naturally pushes everything after it — no element ever needs to
   be manually repositioned.

   Accordion behavior (only one section open at a time) is handled
   in gallery.js, not CSS — same .is-collapsed class toggle as
   before, just now also collapsing the other section first.
   ============================================================ */
.gallery-teal-section.is-collapsed {
  /* Extends the visible composition down to the exact horizontal
     centreline of .gallery-bts-tear (base 187px + half the tear's own
     canvas-native height: var(--gallery-canvas-w)*621/6000, halved =
     621/12000). .gallery-bts-tear is now protected with its own
     z-index:60 (see that rule), so it stays visually intact and on
     top across this whole overlap - this only extends how far the
     underlying imagery reaches, not what's painted on top of it.
     Proportional (canvas-w-based), not a fixed px guess, so the
     centreline alignment holds at any viewport width.

     KNOWN LIMITATION (investigated, not fixed - see chat history):
     a thin, unavoidable dark band is visible immediately above the
     white torn edge, at the tear's own soft top-edge alpha ramp,
     regardless of how much overlap this rule uses - tried reducing it
     and confirmed the band persists unchanged, because that low-alpha
     zone sits at the very start of the tear either way. Not a
     fallback-color issue (this rule's #000 and .gallery-bts-section's
     real #000 are equally dark) - it's the tear's own dark pixels at
     low alpha reading as dark regardless of what's behind them.
     Genuinely fixing this needs real photo content physically
     extending into that exact zone or a different tear asset - out of
     scope without further direction. */
  height: calc(187px + var(--gallery-canvas-w) * 621 / 12000);
  /* Cancels only the added extension (not the original 187px) so
     .gallery-bts-section's own resting position in normal flow is
     unchanged - same overlap technique as the top fix's margin-top,
     mirrored for this edge. */
  margin-bottom: calc(var(--gallery-canvas-w) * -621 / 12000);
}

/* ============================================================
   "THIS MONTH" TAPE LABEL
   ============================================================
   SOURCE ASSET: ThisMonth_Tape.png (1568x782 canvas, real content
   bbox 1433x467 — cropped to that bbox to drop the excess
   transparent padding).

   Now the first normal-flow child of .gallery-teal-section (was:
   absolutely positioned on .gallery-canvas at a global coordinate,
   overlapping the banner's tail by ~15px). That overlap is gone —
   the tape now starts exactly at This Month's own top edge — a
   small, deliberate visual trade-off for having it genuinely move
   with its section. Collapsed height (187px) was already sized as
   tape-height(179.2) + ~8px sliver, so with the tape as the actual
   first child, the arithmetic works out with no other change
   needed: the remaining ~8px below it is the required sliver of
   visible teal, and overflow:hidden on the section (unchanged)
   clips anything beyond that.
   ============================================================ */
.gallery-this-month-hit-area {
  /* ============================================================
     INVISIBLE HIT AREA — This Month is now baked into
     gallery-banner-with-tape.png as a single combined artwork
     (tear + tape), per explicit instruction not to recreate,
     reposition, resize, or layer a separate tape element. This
     button adds no visuals — it's the click/keyboard target,
     positioned to align exactly over where the tape renders
     within that artwork.

     Position measured directly from the source PNG's own alpha
     channel (tape's bounding box within the full 6375x4339 image:
     x 2661-4091, y 3799-4172), converted through the same
     scale/shift math already used for .gallery-banner itself
     (content width 6001 = 6374-374+1, same left margin as before):
       scale      = 2474 / 6001 = 0.4122646...
       left_shift = 374 * scale = 154.187px
       top        = 184 (nav height) + 3799*scale = 1750.193px
       left       = -154.187 + 2661*scale = 942.849px
       width      = (4091-2661)*scale = 589.538px
       height     = (4172-3799)*scale = 153.775px
     ============================================================ */
  position: absolute;
  top: 1750.193px;
  left: 942.849px;
  width: 589.538px;
  height: 153.775px;
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  z-index: 65; /* MUST be higher than .gallery-banner's z-index:60 — the
                   button's screen area overlaps the banner image itself
                   (the tape is now part of that artwork), so without a
                   higher z-index the banner's own opaque pixels there
                   intercept clicks before they reach this button.
                   Purely a hit-testing fix — invisible either way. */
  -webkit-appearance: none;
  appearance: none;
}

/* ============================================================
   B.T.S SECTION (tear-out-of-teal + collapsible black backing)
   ============================================================
   SOURCE ASSET: BTS_Section.png (6009x5904, RGBA) — same crop as
   before (9,58)-(6009,679); see prior notes on the asymmetric
   margin trim, archived original, etc.

   RESTRUCTURED: .gallery-bts-tear is now the first normal-flow
   child of .gallery-bts-section (was: a sibling of .gallery-canvas
   with a hardcoded global top position, so it never moved when
   This Month's height changed, and got orphaned from BTS entirely).
   .gallery-bts-body (new) holds the actual black content area and
   is what the accordion visually grows/shrinks — the tear itself
   keeps its own natural height always (flex-shrink:0), since it's
   also the always-visible click target.

   .gallery-bts-section's own background was originally teal (#2A9D8F,
   matching .gallery-teal-section) rather than black: the tear's image
   has a transparent top (revealing whatever's directly behind it),
   and with the tear living in normal flow immediately after This
   Month, a teal backing kept that reveal visually continuous with
   the section above instead of exposing raw canvas white or an
   abrupt black edge above the torn paper texture. UPDATED: the
   section above is now covered by gallery imagery instead of exposed
   teal (see the margin-top fix on .gallery-teal-section above), so
   that rationale no longer applies - background changed to #000 to
   match .gallery-bts-body instead (see that rule for the current
   reasoning).
   ============================================================ */
.gallery-bts-tear {
  display: block;
  width: 100%;
  height: auto;
  flex-shrink: 0;
  cursor: pointer;
  /* ASSET NOTE: bts-tear.webp was trimmed from 6000x621 to 6000x578
     (top 43 rows removed) - its own top rows had very low, gradually-
     ramping alpha (~7% at row 0, reaching ~255 only by ~row 60), and
     although the underlying color there was already correctly white/
     cream (the torn-paper texture), at that low opacity it was too
     faint to read against whatever's behind it, visually appearing as
     an unwanted dark band immediately above the torn edge. Only the
     top rows were removed (color data elsewhere untouched) - the torn
     edge silhouette, the B.T.S tape, and the black BTS divider below
     it are all visually unchanged, just ~6.9% shorter overall. This
     is a real edit to assets/images/bts-tear.webp, not a CSS change. */
  /* Stacking protection: .gallery-teal-section now extends down to
     overlap this element's own top half (see that rule's height/
     margin-bottom below) so the gallery imagery can occupy that space.
     Without an explicit position+z-index here, this plain static img
     would be painted *under* .gallery-this-month-asset's children
     (position:absolute with explicit z-index) wherever they now
     overlap, hiding this artwork. z-index:60 matches .gallery-banner's
     own value - the same protective mechanism already proven at the
     top boundary - so this stays visually on top and fully intact
     regardless of what extends behind it. No offsets: this does not
     move the element itself. */
  position: relative;
  z-index: 60;
}

.gallery-bts-section {
  display: flex;
  flex-direction: column;
  /* Was #2A9D8F (teal), matching .gallery-teal-section above it - that
     was intentional at the time (see original comment below), to keep
     .gallery-bts-tear's soft transparent top blending with what was
     then a visibly-teal section above. That rationale no longer holds:
     the region above is now covered by gallery imagery (see the
     margin-top fix on .gallery-teal-section above), not exposed teal.
     Changed to #000 to exactly match .gallery-bts-body's own black
     background instead, so the tear's transparent edge now blends
     into the black BTS content beneath it, which is what it's
     actually adjacent to now. */
  background: #000;
  overflow: hidden;
  height: 6318.875px; /* EXPANDED height, explicit now instead of
                          content/flex-derived: 256.046875px (tear) +
                          6062.828125px (.gallery-bts-body's previous
                          min-height) = the exact same total this
                          already rendered at — changed to a plain px
                          value (was content-sized via flex/min-height)
                          purely so it's a transitionable property for
                          the accordion animation below. Nothing about
                          the rendered result changes. */
  transition: height 400ms cubic-bezier(0.33, 1, 0.68, 1); /* accordion animation — same smoother curve as .gallery-teal-section above, kept in sync */
}

.gallery-bts-section.is-collapsed {
  height: 264px; /* was flex:0 0 264px — switched to plain height for
                     the same reason as above (transitions cleanly
                     against the explicit height now set on the base
                     rule; flex-basis vs "auto" can't be transitioned
                     smoothly). Value unchanged: tear's ~256px + ~8px
                     sliver of .gallery-bts-body below it. */
}

.gallery-bts-body {
  background: #000;
  flex: 1; /* still fills whatever space is left inside
               .gallery-bts-section's own (now explicit, animating)
               height — same behavior as before, just recalculated
               every frame as the parent's height transitions. */
  position: relative; /* positioning context for the temporary Coming
                          Soon placeholder below — harmless addition,
                          .gallery-bts-body has no other positioned
                          content to be affected by this. */
}

/* Temporary "Coming Soon" placeholder — remove this whole rule (and
   the <img> in the HTML) once the real BTS content is built. Sized/
   positioned from .gallery-bts-body's own top (not centered in its
   full height, which spans the entire eventual expanded content) so
   it sits correctly within the small peek revealed by the Coming
   Soon click interaction (see gallery.js playBtsComingSoon()), per
   the supplied visual reference. */
.gallery-bts-coming-soon {
  position: absolute;
  top: 28px;
  left: 50%;
  transform: translateX(-50%);
  width: 36%;
  max-width: 900px;
  height: auto;
  pointer-events: none; /* purely visual — clicks still go to the tear above it */
}

/* Redundant with .gallery-bts-section's own explicit height above
   (kept, harmless, describes the same figure) — not removed since
   this task is animation-only. */
.gallery-bts-section:not(.is-collapsed) .gallery-bts-body {
  min-height: 6062.828125px;
}

/* Temporary faster transition used only during the Coming Soon peek
   interaction (small/quick), toggled on/off by gallery.js around the
   peek only — .gallery-bts-section's own normal 400ms transition
   (used for the real, eventual accordion open/close) is completely
   unaffected outside of that brief window. */
.gallery-bts-section.is-peeking {
  transition: height 200ms cubic-bezier(0.33, 1, 0.68, 1);
}

/* ============================================================
   THIS MONTH — LAYERED ASSET COMPOSITION (Phase 1)
   ============================================================
   19 layers, each a full 6000x9000px canvas export (transparent
   except for that layer's own content) — reused directly, not
   cropped/recreated. Every layer is displayed at the section's
   full width/height (2474 x 3711px, matching the canvas's own
   6000:9000 = 2:3 aspect ratio) and stacked via explicit z-index
   matching the supplied layer-stack order exactly (1 = bottom/
   Canvas, 19 = top/DSC06150) — deterministic regardless of DOM
   order, per the brief.

   Individually addressable via the shared base class below (for
   the common positioning/hover rule) plus a per-asset modifier
   class encoding a slugified filename (spaces/underscores ->
   hyphens, lowercased) for Phase 2 targeting — filenames on disk
   are unchanged.
   ============================================================ */
.gallery-this-month-asset {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: auto;
  display: block;
  transition: transform 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94); /* was
                    250ms ease — smoother, more deliberate deceleration
                    (easeOutQuad-style, no overshoot), duration nudged
                    to 280ms per the animation refinement pass. Scale
                    factor (1.07) and everything else about this rule
                    is unchanged. */
  transform: translateY(-84.101px); /* Moves the whole 19-layer
                    composition up as one unit (every layer shares this
                    exact rule, so all 19 shift identically — no wrapper
                    introduced, per the requested "simplest solution").

                    Derived from the banner's ACTUAL alpha data, per the
                    specified methodology (not the banner element's box,
                    not a prior guessed value):
                      1. Tear's horizontal extent (excluding the tape's
                         own alpha) spans source x 374-6374 -> center
                         x = 3374.
                      2. At x=3374, the lowest non-transparent banner
                         pixel (alpha>8) is source row 4135 (this lands
                         within the tape's own opaque region, since the
                         tape sits directly on/over the tear at that
                         horizontal position — expected, per the tear+
                         tape being one attached unit).
                      3. Converted via the banner's real scale
                         (1788.796875/4339 = 0.41226): canvas y =
                         184 + 4135*0.41226 = 1888.696.
                      4. Composition's unshifted top is 1972.797 (teal-
                         section's own top) -> offset = 1888.696 -
                         1972.797 = -84.101px.

                    .gallery-teal-section's own overflow:hidden clips
                    whatever moves above its own top — unchanged,
                    pre-existing behavior, not touched here. */
}

/* Clickable cursor cue — scoped via [data-original] to exactly the 18
   photographic layers that actually open the fullscreen viewer,
   naturally excluding Canvas.png (no data-original attribute, not
   clickable). Only visually communicates clickability; the browser
   already only shows this where the element is actually hit-testable
   (i.e. within its own clip-path, and only while This Month is
   expanded / pointer-events:auto below) — cursor doesn't add any new
   interactive area of its own. */
.gallery-this-month-asset[data-original] {
  cursor: pointer;
}

/* Scoped to genuine hover/fine-pointer environments only (same
   established pattern Home's own styles.css already uses for its own
   hover-driven marquee) — touch devices report hover:none and never
   match this at all, so hover-scale is naturally absent on mobile
   without any JS/UA detection. Desktop mouse users are completely
   unaffected: real desktop browsers correctly match hover:hover and
   pointer:fine. Scale factor, transition, and everything else about
   the rule itself is untouched from the previous animation refinement
   pass. */
@media (hover: hover) and (pointer: fine) {
  .gallery-this-month-asset:hover {
    transform: translateY(-84.101px) scale(1.07); /* Must include the same
                      translateY as the base rule -- :hover replaces
                      (doesn't add to) the base transform, so omitting it
                      here would cause a visible jump on every hover.
                      1.07 = 7%, within the specified 5-10% range. Each
                      layer's interactive area is restricted to
                      (approximately) its own visible artwork via
                      clip-path below, rather than the full 6000x9000
                      canvas — see report for how that was derived. */
  }
}

/* Hover must be fully disabled while This Month is collapsed — not just
   visually suppressed, but the interaction itself. Scoped to the
   .is-collapsed state (already toggled by the existing accordion JS,
   nothing new needed here): every layer's pointer-events are turned off
   entirely while collapsed, regardless of where clip-path shapes fall
   relative to the collapsed 187px sliver. */
.gallery-teal-section.is-collapsed .gallery-this-month-asset {
  pointer-events: none;
}

.gallery-this-month-asset--canvas                  { z-index: 1; }
.gallery-this-month-asset--golf-sunset              { z-index: 2; }
.gallery-this-month-asset--banner-img-10            { z-index: 3; }
.gallery-this-month-asset--stilldropblues-3dl-1      { z-index: 4; }
.gallery-this-month-asset--dscf1005                 { z-index: 5; }
.gallery-this-month-asset--dscf0143                 { z-index: 6; }
.gallery-this-month-asset--dsc058705                { z-index: 7; }
.gallery-this-month-asset--dsc06165                 { z-index: 8; }
.gallery-this-month-asset--clouds-1                 { z-index: 9; }
.gallery-this-month-asset--oscar-og                 { z-index: 10; }
.gallery-this-month-asset--dsc08764-recovered       { z-index: 11; }
.gallery-this-month-asset--dsc08937                 { z-index: 12; }
.gallery-this-month-asset--dsc06079                 { z-index: 13; }
.gallery-this-month-asset--still-kodak-5218-kodak-2383-1 { z-index: 14; }
.gallery-this-month-asset--mblhrolnd                { z-index: 15; }
.gallery-this-month-asset--dsc06063                 { z-index: 16; }
.gallery-this-month-asset--unknown-dubes            { z-index: 17; }
.gallery-this-month-asset--dscf0063                 { z-index: 18; }
.gallery-this-month-asset--dsc06150                 { z-index: 19; }


/* ============================================================
   PER-LAYER HOVER HITBOXES — clip-path from actual alpha data
   ============================================================
   Root cause (confirmed via direct testing, not assumed): every
   layer shares the exact same full-canvas bounding box, so plain
   :hover always resolved to whichever layer has the highest
   z-index at ANY point in the section, regardless of that layer's
   own transparency there — 18 of 19 layers could never receive
   their own hover.

   Two alternatives were tried and rejected first:
     - Canvas-based per-pixel alpha sampling in JS: technically
       correct in principle, but drawImage()+getImageData() throws
       a SecurityError ("canvas tainted by cross-origin data") when
       the page is opened via file:// — confirmed directly. This
       would silently break for anyone testing the site the way
       it's been tested throughout this project, so it was dropped.
     - SVG <image pointer-events="visiblePainted">: also tested
       directly with known transparent/opaque coordinates from the
       actual asset data — Chromium does NOT respect raster alpha
       for this on <image> elements (both a known-transparent and
       known-opaque test point matched), so this doesn't work either.

   Solution actually used: clip-path, generated (not hand-guessed)
   from each asset's own alpha channel via a convex hull of its
   opaque pixels (scipy.spatial.ConvexHull, computed at a downscaled
   resolution for speed, output as resolution-independent percentages
   -- exactly the "generated transparent hitbox geometry based on the
   actual visible alpha region" approach). clip-path restricts BOTH
   rendering and pointer-event hit-testing to the polygon -- verified
   directly: a known-transparent coordinate correctly misses the
   image (falls through to whatever's beneath), a known-opaque one
   correctly hits it. Pure CSS, no canvas/pixel-reading at runtime,
   so no file:// CORS issue.

   This is a convex hull, not a pixel-perfect silhouette -- for
   concave/irregular photo shapes it includes some transparent
   "slack" near the shape's own concavities, but it eliminates the
   vast majority of the previous full-6000x9000-canvas over-reach.
   Canvas.png has no clip-path (it's fully opaque across its own
   entire canvas already, confirmed -- no clipping needed).

   No asset files were modified, cropped, resized, or renamed to
   produce this -- these coordinates are derived, in-memory-at-
   build-time values living only in this stylesheet.
   ============================================================ */
.gallery-this-month-asset--golf-sunset { clip-path: polygon(0.0% 0.0%, 70.0% 0.0%, 70.0% 27.33%, 62.5% 39.67%, 54.5% 39.67%, 0.0% 27.33%); }
.gallery-this-month-asset--banner-img-10 { clip-path: polygon(56.5% 0.0%, 99.5% 0.0%, 99.5% 35.67%, 57.5% 37.67%, 56.5% 37.67%); }
.gallery-this-month-asset--stilldropblues-3dl-1 { clip-path: polygon(21.0% 34.33%, 21.0% 33.33%, 23.0% 25.0%, 23.5% 23.0%, 24.0% 21.33%, 25.0% 20.67%, 40.5% 13.67%, 41.5% 13.33%, 44.0% 13.33%, 45.5% 13.67%, 68.5% 19.33%, 69.0% 19.67%, 69.0% 20.67%, 67.0% 30.0%, 66.0% 33.67%, 65.5% 35.33%, 65.0% 36.0%, 55.0% 43.67%, 53.5% 43.67%, 46.0% 43.0%, 39.5% 42.33%, 32.5% 41.33%); }
.gallery-this-month-asset--dscf1005 { clip-path: polygon(0.0% 9.67%, 33.5% 10.33%, 33.5% 45.33%, 0.0% 45.33%); }
.gallery-this-month-asset--dscf0143 { clip-path: polygon(9.5% 51.67%, 10.0% 35.33%, 10.5% 35.0%, 43.0% 28.0%, 45.5% 28.0%, 72.5% 29.33%, 79.0% 29.67%, 80.0% 30.33%, 80.0% 61.0%, 79.5% 61.33%, 10.0% 61.33%, 9.5% 60.0%); }
.gallery-this-month-asset--dsc058705 { clip-path: polygon(26.5% 46.33%, 25.0% 40.33%, 25.5% 40.0%, 27.0% 39.67%, 29.5% 39.33%, 35.5% 38.67%, 36.0% 38.67%, 37.5% 39.0%, 63.0% 47.0%, 64.0% 47.33%, 65.0% 48.0%, 65.5% 48.67%, 66.0% 50.0%, 66.5% 51.67%, 69.0% 60.67%, 70.0% 64.33%, 70.5% 67.0%, 70.5% 68.33%, 67.5% 69.0%, 59.5% 70.0%, 51.0% 71.0%, 36.0% 72.67%, 33.5% 72.67%, 32.5% 69.33%, 30.5% 62.0%); }
.gallery-this-month-asset--dsc06165 { clip-path: polygon(33.5% 81.33%, 30.0% 81.0%, 23.5% 80.33%, 21.0% 77.33%, 20.5% 76.67%, 19.5% 74.67%, 19.0% 72.67%, 18.5% 69.33%, 18.5% 68.0%, 19.0% 65.33%, 19.5% 64.0%, 20.0% 63.0%, 23.0% 59.67%, 25.0% 58.0%, 30.5% 54.67%, 36.5% 54.67%, 40.5% 55.0%, 51.0% 56.33%, 58.5% 58.33%, 65.0% 60.33%, 82.0% 66.67%, 82.5% 67.33%, 82.5% 67.67%, 81.0% 72.0%, 80.0% 73.67%, 79.5% 74.0%, 78.0% 74.67%, 52.0% 79.67%, 44.5% 80.67%, 36.0% 81.33%); }
/* .gallery-this-month-asset--clouds-1: bottom two points extended from
   99.67%/99.5% to a full 100%/100% (was: 0.0% 99.67% ... 99.5% 99.67%).
   This is the one continuous bottom-spanning mosaic layer (z-index:9,
   x:0%-99.5% at its original bottom edge) - the other three layers
   sharing its old 99.67% maximum (oscar-og, still-kodak, mblhrolnd)
   are smaller pieces layered on top of a subset of this same width and
   don't need to change, since this layer already shows through beneath
   them once extended. The 0.33%/0.5% gap left Canvas.png's flat blue
   backing (the mosaic's structural base layer) exposed along the full
   width at the bottom of the expanded composition, directly above
   .gallery-bts-tear. Verified the source photo (Clouds 1.webp) has
   real image content all the way to its true edge in this region, not
   a transparent/blank margin, so this reveals more real photo, not a
   new gap. Pure clip-path mask change - no asset edited, no
   repositioning, ordering, or z-index change. */
.gallery-this-month-asset--clouds-1 { clip-path: polygon(0.0% 100%, 0.0% 79.67%, 69.5% 43.67%, 71.5% 43.0%, 74.0% 42.33%, 98.5% 42.33%, 99.5% 42.67%, 100% 100%); }
.gallery-this-month-asset--oscar-og { clip-path: polygon(22.5% 99.67%, 22.5% 79.0%, 23.0% 78.67%, 30.0% 76.33%, 39.0% 76.33%, 48.0% 77.67%, 49.0% 78.0%, 62.0% 84.67%, 62.5% 85.0%, 63.0% 85.67%, 63.5% 88.0%, 64.0% 91.0%, 64.0% 92.67%, 57.5% 99.67%); }
.gallery-this-month-asset--dsc08764-recovered { clip-path: polygon(0.0% 75.0%, 0.0% 27.67%, 1.0% 27.33%, 4.5% 28.0%, 6.0% 28.33%, 7.0% 28.67%, 8.0% 29.33%, 31.5% 46.67%, 32.0% 47.33%, 32.5% 48.33%, 33.0% 49.67%, 33.0% 54.67%, 32.0% 58.0%, 31.5% 59.0%, 29.5% 62.33%, 28.0% 64.33%, 19.0% 75.33%, 17.5% 76.67%, 17.0% 77.0%, 15.0% 77.67%, 8.5% 77.67%, 4.5% 77.0%, 3.0% 76.67%, 2.0% 76.33%); }
.gallery-this-month-asset--dsc08937 { clip-path: polygon(0.0% 72.0%, 0.0% 58.33%, 12.5% 47.33%, 13.5% 46.67%, 15.5% 46.0%, 19.5% 46.0%, 21.0% 46.33%, 23.0% 47.67%, 23.5% 49.0%, 26.5% 61.67%, 26.5% 63.33%, 26.0% 68.33%, 24.5% 76.0%, 23.0% 76.0%, 20.5% 75.67%, 7.0% 73.33%, 1.5% 72.33%); }
.gallery-this-month-asset--dsc06079 { clip-path: polygon(0.0% 87.67%, 0.0% 62.67%, 13.5% 62.67%, 18.0% 63.0%, 19.0% 63.33%, 30.0% 67.67%, 30.5% 68.0%, 33.0% 73.67%, 33.5% 77.33%, 33.5% 81.0%, 33.0% 84.33%, 32.5% 85.0%, 23.5% 89.67%, 15.0% 89.67%, 0.5% 88.0%); }
.gallery-this-month-asset--still-kodak-5218-kodak-2383-1 { clip-path: polygon(99.5% 92.0%, 99.5% 99.67%, 73.0% 99.67%, 66.0% 98.0%, 65.0% 97.67%, 64.0% 97.0%, 63.5% 96.33%, 63.5% 95.67%, 67.5% 81.0%, 68.0% 80.0%, 73.5% 71.0%, 74.5% 70.0%, 76.0% 69.33%, 80.5% 69.33%, 82.5% 70.67%); }
.gallery-this-month-asset--mblhrolnd { clip-path: polygon(0.0% 99.67%, 0.0% 89.0%, 9.0% 75.0%, 11.0% 73.67%, 12.0% 73.33%, 13.5% 73.0%, 17.0% 72.67%, 19.0% 72.67%, 22.0% 73.0%, 25.0% 74.0%, 27.0% 75.0%, 28.0% 76.0%, 29.5% 99.0%, 29.5% 99.67%); }
.gallery-this-month-asset--dsc06063 { clip-path: polygon(99.5% 13.67%, 99.5% 44.67%, 98.0% 45.0%, 97.0% 45.0%, 93.0% 44.67%, 91.0% 44.33%, 82.0% 42.67%, 80.0% 42.0%, 79.0% 41.33%, 66.5% 32.67%, 66.0% 31.0%, 66.0% 23.33%, 67.0% 18.0%, 67.5% 17.33%, 68.0% 17.0%, 79.5% 14.33%, 82.0% 14.0%, 85.0% 13.67%, 98.5% 13.33%); }
.gallery-this-month-asset--unknown-dubes { clip-path: polygon(99.5% 34.67%, 99.5% 47.33%, 97.5% 48.67%, 96.0% 49.0%, 92.5% 49.67%, 91.0% 49.67%, 70.5% 47.67%, 69.5% 47.33%, 69.0% 47.0%, 69.0% 45.0%, 69.5% 44.0%, 78.0% 27.33%, 80.0% 26.0%, 81.0% 25.67%, 84.0% 25.67%, 85.5% 26.0%, 87.5% 26.67%, 95.0% 30.0%, 96.0% 30.67%, 97.0% 31.67%, 98.5% 33.33%); }
.gallery-this-month-asset--dscf0063 { clip-path: polygon(27.5% 13.33%, 1.5% 12.0%, 0.0% 11.0%, 0.0% 0.0%, 2.0% 0.0%, 40.0% 3.33%, 40.5% 3.67%, 41.0% 6.67%, 41.0% 7.33%, 38.0% 12.33%, 37.0% 13.0%, 36.0% 13.33%); }
.gallery-this-month-asset--dsc06150 { clip-path: polygon(57.0% 57.67%, 37.5% 56.0%, 34.0% 53.67%, 34.0% 53.0%, 34.5% 51.0%, 35.0% 49.67%, 36.0% 48.0%, 37.0% 47.33%, 43.0% 46.0%, 45.0% 46.0%, 49.0% 46.67%, 50.5% 47.0%, 53.5% 48.0%, 61.5% 51.0%, 62.5% 51.67%, 63.5% 52.67%, 64.5% 54.67%, 64.5% 56.33%, 64.0% 57.0%, 63.0% 57.67%); }

/* ============================================================
   THIS MONTH — FULLSCREEN ORIGINAL-IMAGE VIEWER
   ============================================================
   True viewport-level overlay — deliberately NOT nested inside
   .gallery-canvas (see index.html comment), so it is completely
   unaffected by .gallery-canvas's zoom scaling. position:fixed here
   is relative to the real viewport in both cases, but living outside
   the zoomed subtree avoids any ambiguity/inheritance entirely.
   ============================================================ */
.gallery-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000; /* above everything else on the page, including nav (65) */
  background: rgba(0, 0, 0, 0.75); /* tint, not opaque — page remains
                                        faintly visible through it —
                                        unchanged, same strength as before */
  display: flex; /* always in the layout now (was display:none, toggled
                     to flex only when open) — display itself can't be
                     transitioned, so opacity/pointer-events below do
                     the actual show/hide work instead. Harmless as an
                     always-flex fixed-position overlay: doesn't affect
                     document flow either way, and is invisible +
                     fully non-interactive (see below) while closed. */
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none; /* fully non-interactive while closed — nothing
                            inside (image, arrows, nav zones) can be
                            clicked/hovered; this is what actually keeps
                            "closed" functionally closed, not just
                            invisible. */
  transition: opacity 200ms ease-in; /* closing (is-open removed) —
                                          ease-in: starts slow, exits
                                          quicker, feels like settling
                                          back rather than an abrupt cut */
}
.gallery-lightbox.is-open {
  opacity: 1;
  pointer-events: auto;
  transition: opacity 200ms ease-out; /* opening — ease-out: starts
                                           fast, settles smoothly,
                                           matching the "fast, subtle,
                                           polished" target */
}

.gallery-lightbox-content {
  position: relative;
  display: inline-block; /* shrinks to the image's own rendered size,
                             so nav zones below (scoped to this
                             wrapper) only cover the image itself —
                             everything outside remains genuine
                             clickable backdrop for click-away-to-close.
                             Without this, zones spanning the full
                             viewport half would swallow 100% of the
                             overlay, making click-away impossible. */
  max-width: 90vw;
  max-height: 90vh;
  line-height: 0; /* avoids inline-block's default baseline gap under the image */
}
.gallery-lightbox-content:hover .gallery-lightbox-arrow {
  /* only the specific hovered zone's own :hover rule (below) sets opacity:1 */
}

.gallery-lightbox-image {
  max-width: 90vw;
  max-height: 90vh;
  width: auto;
  height: auto;
  display: block;
  object-fit: contain; /* preserves aspect ratio; never distorts/crops */
  transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1); /* was 300ms
                    ease — smoother, symmetric ease-in-out (Material-
                    style "standard" curve), no overshoot; duration
                    unchanged at 300ms. This CSS value is the resting
                    default only — gallery.js's SLIDE_MS/slide easing
                    (kept in sync, see there) is what actually applies
                    during navigation, since it sets this inline. */
  user-select: none;
  -webkit-user-drag: none;
}

/* Left/right hover+click zones scoped to the image's own bounds
   (parent is sized to hug the image, see .gallery-lightbox-content
   above) — "hover over the left/right side of the displayed image",
   not the whole half of the viewport. */
.gallery-lightbox-nav-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  z-index: 3;
  display: flex;
  align-items: center;
  cursor: pointer;
}
.gallery-lightbox-nav-zone--left { left: 0; justify-content: flex-start; }
.gallery-lightbox-nav-zone--right { right: 0; justify-content: flex-end; }

.gallery-lightbox-arrow {
  width: 90px;
  height: auto;
  margin: 0 24px;
  opacity: 0;
  transition: opacity 200ms ease-out; /* was ease — slightly more
                    deliberate reveal, duration unchanged at 200ms */
  pointer-events: none; /* the zone div handles the click/hover, not the arrow image itself */
}
.gallery-lightbox-nav-zone--left:hover .gallery-lightbox-arrow--left,
.gallery-lightbox-nav-zone--right:hover .gallery-lightbox-arrow--right {
  opacity: 1;
}
.gallery-lightbox-arrow--right {
  transform: scaleX(-1); /* Same single supplied arrow asset, mirrored
                             via pure CSS transform for the opposite
                             direction — not a recreated/substituted
                             icon, just the one authoritative asset
                             used twice. */
}
