/* fl718-nyc-2021-2022.css — NYC 2021-2022 desktop styles
   Version: 1.0.0
   Last updated: 2026-09-26 */

    /* ============================================================
       ALL CSS SCOPED TO: body.fl718-nyc-2021-2022-page
       Every rule below uses this body class as its scope prefix.
       Never write an unscoped rule — the site shares one stylesheet
       cascade and unscoped rules bleed into other pages.
       ============================================================ */

    /* ------------------------------------------------------------
       BASE
       ------------------------------------------------------------ */
    body.fl718-nyc-2021-2022-page {
      margin: 0;
      padding: 0;
      /* overflow-x: clip — NOT hidden. hidden creates a new scroll
         container that breaks position:sticky and ScrollTrigger pins
         site-wide. clip clips visually without that side effect.
         Never overflow-x:hidden on body or html on this project. */
      overflow-x: clip;
      background-color: #efeeec;
      color: #211f1c;
      -webkit-font-smoothing: antialiased;
    }

    /* Box-sizing via :where() — zero specificity, never fights another rule */
    :where(body.fl718-nyc-2021-2022-page) *,
    :where(body.fl718-nyc-2021-2022-page) *::before,
    :where(body.fl718-nyc-2021-2022-page) *::after {
      box-sizing: border-box;
    }

    body.fl718-nyc-2021-2022-page img {
      max-width: 100%;
      display: block;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-visually-hidden {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      border: 0;
    }

    /* ============================================================
       HERO
       DEPARTURE FROM THE SITE'S USUAL HERO CROP (Seamus, 2026-09-22):
       shown FULL AND UNCROPPED via object-fit:contain, not the site's
       usual object-fit:cover. The real FL718 Hero export
       (000056420021-hero.jpg, 2560x1440, 16:9) was re-cropped wider in
       Lightroom specifically to minimize letterboxing at this aspect —
       it replaced the original -grid.jpg placeholder (2000x1545, ~4:3),
       which is what made the letterboxing visible in the first place.
       object-fit:contain is kept rather than cover so the whole frame
       stays visible even if the browser viewport's own ratio doesn't
       exactly match 16:9. This is a deliberate choice for this page,
       not a bug — do not "fix" it back to cover without checking with
       Seamus first.

       Background is the pre-load edge colour: #26241f, near-black and
       warm-neutral toward concrete rather than LA's cool night-set
       black — this set is a daylight/shadow set, not a night set. It
       doubles as the letterbox colour now that the photo is contained
       rather than covering the box.
       ============================================================ */

    body.fl718-nyc-2021-2022-page .fl718-ny21-hero {
      position: relative;
      width: 100%;
      /* height, not min-height — the hero is CAPPED at the viewport,
         not just a minimum. Paired with object-fit:contain on the
         image, this is what actually keeps the whole uncropped photo
         inside the visible viewport with no scroll needed (Seamus,
         2026-09-22). A min-height here would let the box grow taller
         than 100vh and push part of the photo below the fold. */
      height: 100vh;
      /* overflow: clip — NOT hidden, same reason as body. */
      overflow: clip;
      background-color: #26241f;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__image {
      width: 100%;
      height: 100%;
      /* object-fit: contain — shows the FULL photograph, no crop.
         Letterboxes left/right against the hero bg colour rather than
         filling the box edge-to-edge. Deliberate per-page departure
         from the site's usual object-fit:cover hero crop — see the
         note above before changing this back. */
      object-fit: contain;
      object-position: center center;
      display: block;
      /* Starting state — GSAP owns the reveal. Paired with the
         no-JS and reduced-motion fallbacks at the bottom of this
         sheet: a CSS opacity:0 start state and its JS reveal tween
         are a matched pair; ship both or neither. */
      opacity: 0;
      transform-origin: center center;
    }

    /* Gradient lift — upper-left, so the title has purchase without a
       visible bar. Warm-neutral dark, matching the page's concrete
       register — never a colour tint of its own; the only warmth on
       this page belongs inside the photograph. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__gradient {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 72%;
      background:
        linear-gradient(to bottom, rgba(16, 14, 11, 0.62) 0%, transparent 100%),
        radial-gradient(ellipse at 0% 0%, rgba(18, 16, 13, 0.52) 0%, transparent 66%);
      z-index: 5;
      pointer-events: none;
      /* Starting state for "Signal Drop" (Script 2) — arrives with the
         photo's final hold, not present before. Paired with the no-JS
         and reduced-motion fallbacks below: ship both or neither. */
      opacity: 0;
    }

    /* Title block — upper-left, following the LA precedent for hero
       text placement clear of the horizon. PLACEMENT UNVERIFIED against
       the real hero crop (brick corner composition) — re-check once the
       -hero export lands, per QA_NOTES. */
    /* Title-block now holds ONLY the byline — the title and the year
       both split out to their own absolutely-positioned elements
       (.fl718-ny21-hero__title, .fl718-ny21-hero__subtitle-block) on
       2026-09-22, per Seamus. The byline itself moved a second time,
       same session: off the lower-left and onto the open stretch of
       red wall below the signal-box shadow, upper-right-ish but lower
       than the title/year stack, "like it's on the wall." Percentage-
       based left/top track THIS photo's composition — re-check if the
       hero photo ever changes. This is a deliberate three-way split
       for this page, not the site's usual single stacked title-block. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__title-block {
      position: absolute;
      top: 50%;
      left: 73%;
      right: clamp(60px, 11vw, 140px);
      z-index: 10;
      pointer-events: none;
    }

    /* "NEW YORK CITY" — split out from the title-block (see note above)
       and positioned independently over the red wall, upper-right,
       clear of the building's window/signal-box detail. Percentage-
       based left/top track the photo's own composition since the hero
       image scales with the viewport under object-fit:contain; this
       is deliberately positioned against THIS photo, not a generic
       corner anchor — re-check placement if the hero photo ever
       changes. Condensed, uppercase, signage-register Oswald —
       deliberately NOT the site's quiet lowercase literary-serif move
       (LA, Peru, China); this is the harder, municipal register the
       editorial notes ask for. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__title {
      position: absolute;
      top: clamp(12px, 4vh, 40px);
      left: 44%;
      right: clamp(24px, 5vw, 64px);
      z-index: 10;
      pointer-events: none;
      display: block;
      font-family: 'Oswald', 'Arial Narrow', sans-serif;
      font-size: clamp(40px, 5.4vw, 78px);
      font-weight: 600;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      color: rgba(244, 242, 236, 0.97);
      line-height: 0.96;
      margin: 0;
      opacity: 0;
      text-shadow: 0 2px 24px rgba(8, 7, 5, 0.58), 0 1px 6px rgba(8, 7, 5, 0.38);
    }

    /* Positioned to sit directly under the title (see .fl718-ny21-hero__title
       above) — same left offset, top anchored below the title's own
       top + its rendered line height. Moved out of the title-block
       2026-09-22 per Seamus, so it stacks with the title on the right
       rather than with the byline on the left. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__subtitle-block {
      position: absolute;
      top: calc(clamp(12px, 4vh, 40px) + clamp(40px, 5.4vw, 78px) * 0.96 + clamp(10px, 1.6vh, 18px));
      left: 44%;
      right: clamp(24px, 5vw, 64px);
      z-index: 10;
      pointer-events: none;
      display: flex;
      align-items: center;
      gap: 14px;
      opacity: 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__subtitle-rule {
      display: block;
      width: 1px;
      height: 16px;
      background: rgba(238, 236, 230, 0.24);
      flex-shrink: 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__year {
      display: block;
      font-family: 'DM Sans', system-ui, sans-serif;
      font-size: clamp(9px, 0.88vw, 12px);
      font-weight: 300;
      font-style: italic;
      letter-spacing: 0.26em;
      color: rgba(238, 236, 230, 0.88);
      text-shadow: 0 1px 3px rgba(8, 7, 5, 0.78), 0 1px 10px rgba(8, 7, 5, 0.70);
    }

    /* The byline. Title face at a lighter weight, not the metadata sans —
       a sentence in Seamus's voice, not a data field. Best-guess draft
       per editorial notes, not final. Held to a short measure. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-hero__byline {
      margin: 0;
      max-width: 100%;
      font-family: 'Oswald', 'Arial Narrow', sans-serif;
      font-weight: 400;
      font-size: clamp(15px, 1.34vw, 21px);
      line-height: 1.5;
      letter-spacing: 0.01em;
      color: rgba(240, 238, 232, 0.97);
      text-shadow: 0 1px 3px rgba(8, 7, 5, 0.80), 0 1px 14px rgba(8, 7, 5, 0.78);
      opacity: 0;
    }

    /* Reduced motion — hero shows its END STATE immediately.
       Reduced motion means skip the animation and KEEP the end state,
       never hide the content. */
    @media (prefers-reduced-motion: reduce) {
      body.fl718-nyc-2021-2022-page .fl718-ny21-hero__image {
        opacity: 1 !important;
        transform: none !important;
        filter: none !important;
      }
      body.fl718-nyc-2021-2022-page .fl718-ny21-hero__gradient,
      body.fl718-nyc-2021-2022-page .fl718-ny21-hero__title,
      body.fl718-nyc-2021-2022-page .fl718-ny21-hero__subtitle-block,
      body.fl718-nyc-2021-2022-page .fl718-ny21-hero__byline {
        opacity: 1 !important;
        transform: none !important;
      }
    }

    /* ============================================================
       GALLERY GRID — CSS-columns masonry
       CSS columns, NOT CSS Grid. All 72 frames are landscape (measured,
       not guessed), which is the masonry family's case.

       3 columns desktop -> 2 at 768px. This is the DESKTOP sheet; a
       mobile template would get its own single-column sheet with no
       width query at all (not built in this desktop scaffold).

       WARNING — column-count fills COLUMN-FIRST. Once a real sequence
       exists (this scaffold ships manifest order, a known placeholder),
       it must be re-checked against RENDERED columns at 3-col, not
       source order — see Monument Valley / White Sands precedent.
       ============================================================ */

    body.fl718-nyc-2021-2022-page .fl718-ny21-grid {
      columns: 3;
      column-gap: 8px;
      padding: 8px;
      padding-top: 14vh;
      padding-bottom: 12vh;
    }

    @media (max-width: 768px) {
      body.fl718-nyc-2021-2022-page .fl718-ny21-grid {
        columns: 2;
        padding-top: 10vh;
      }
    }

    /* ------------------------------------------------------------
       GRID ITEMS
       break-inside: avoid — stops masonry breaking an image mid-column.
       margin: 0 0 8px — <figure> carries a UA margin that escapes a
       :where() reset, so it is zeroed explicitly here.
       opacity: 0 — GSAP owns the reveal; paired with the fallbacks
       at the bottom of this sheet.
       NO CAPTIONS IN THE GRID. The grid is a pure visual field;
       all metadata lives in the lightbox only.
       ------------------------------------------------------------ */

    body.fl718-nyc-2021-2022-page .fl718-ny21-item {
      break-inside: avoid;
      margin: 0 0 8px 0;
      /* overflow:visible (not clip) — "Perimeter Frame Snap" hover
         (below) casts an outward box-shadow into the grid gutter, which
         a clip would cut off. Safe: the <img> itself is width:100%/
         height:auto/display:block and can never overflow its own box
         regardless of this property. */
      overflow: visible;
      cursor: pointer;
      position: relative;
      display: block;
      opacity: 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-item:focus {
      outline: none;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-item:focus-visible {
      outline: 2px solid rgba(214, 208, 198, 0.9);
      outline-offset: 3px;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-item img {
      width: 100%;
      height: auto;
      display: block;
    }

    /* ── HOVER: "Perimeter Frame Snap" — LOCKED 2026-09-22.
       Chosen via a visual-concept-generator pass, two rounds. Round 1
       (Cast Shadow/Gate, Chain-Link Fracture, Signal Cut/Blackout,
       Corner Shadow Wedge) put a shadow/mesh/darkening layer ON TOP of
       the photo's own pixels; Seamus called all three "too much" /
       "blocks the photo" / "darkens into the photo too much" (the
       fourth, Signal Cut, was too subtle to register at all). Round 2
       fixed this by moving the effect OUTSIDE the image entirely.

       MECHANISM: four independent 3px hairlines (one per edge) plus two
       small L-shaped corner brackets snap flush against the photo's own
       four edges from the OUTSIDE of the image box — like a steel sash
       or security-gate track clamping onto a frame that was already
       there. Two diagonal halves close together (top+left from the
       top-left corner, bottom+right from the bottom-right corner, a
       tiny stagger) so the frame reads as hardware engaging from two
       directions, echoing the grid's own "Steel Settle" entrance and
       the site's fire-escape/security-gate material vocabulary. A hard,
       tight cast shadow rides the item's own box-shadow — never a layer
       over the <img> — falling into the grid gutter around the card,
       so it still reads as HARD and SHADOW-ADJACENT per the editorial
       notes ("harder, more shadow-based than LA's warm 'light finds
       it'") without ever obscuring the photograph. Fires on
       focus/blur too.

       .fl718-ny21-item__veil is retired (display:none) — kept only as an
       empty aria-hidden div in each figure's markup so 72 figures don't
       need editing. The edge/corner divs are injected by Script 4 (one
       set per item); GSAP owns their transform/opacity/box-shadow.

       Full narrative: Session 256+ in LOCATION_PAGES_SESSION_LOG.md.
       Prototyped in nyc-2021-2022-concepts/hover-effects/round-2/
       perimeter-frame-snap.html before landing here. ── */
    body.fl718-nyc-2021-2022-page .fl718-ny21-item__veil {
      display: none;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-edge {
      position: absolute;
      background: rgba(230, 226, 218, 0.94);
      pointer-events: none;
      z-index: 2;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-edge--top {
      top: 0; left: 0; right: 0; height: 3px;
      transform-origin: left top;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-edge--bottom {
      bottom: 0; left: 0; right: 0; height: 3px;
      transform-origin: right bottom;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-edge--left {
      top: 0; bottom: 0; left: 0; width: 3px;
      transform-origin: left top;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-edge--right {
      top: 0; bottom: 0; right: 0; width: 3px;
      transform-origin: right bottom;
    }

    /* Corner brackets — small L-shaped hardware marks, drawn with two
       border strokes on a real div (not ::before, so GSAP can tween it
       directly). Sit exactly at the corner, legs running along the
       existing frame edges, never intruding onto the photo. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-corner {
      position: absolute;
      width: 14px;
      height: 14px;
      pointer-events: none;
      z-index: 3;
      opacity: 0;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-corner--tl {
      top: 0; left: 0;
      border-top: 3px solid rgba(230, 226, 218, 0.98);
      border-left: 3px solid rgba(230, 226, 218, 0.98);
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-frame-corner--br {
      bottom: 0; right: 0;
      border-bottom: 3px solid rgba(230, 226, 218, 0.98);
      border-right: 3px solid rgba(230, 226, 218, 0.98);
    }

    @media (prefers-reduced-motion: reduce) {
      body.fl718-nyc-2021-2022-page .fl718-ny21-frame-edge,
      body.fl718-nyc-2021-2022-page .fl718-ny21-frame-corner {
        display: none !important;
      }
    }

    /* ============================================================
       LIGHTBOX
       Layers:
         9000  .fl718-ny21-lb-dark   — backdrop
         9100  .fl718-ny21-lb-stage  — photograph, centred
         9200  .fl718-ny21-lb-ui     — close, nav, counter

       CAPTION CONTRACT: the ONLY thing that produces a caption is
       data-medium. analog / analog-color show the film stock name from
       data-film; digital shows nothing. On THIS page, every film frame
       currently omits data-film (real stock names unknown — see the
       header note), so every lightbox caption is empty until backfilled.

       ANIMATION: the photograph itself is a PLAIN CROSSFADE, never a
       filter-phase "develop" gesture like LA's. The signature gesture
       on this page is the "Big Gate" hardware (see the gate-edge/
       gate-corner rules below) — an unrelated mechanism from the
       photo's own crossfade, so a filter tween on the image itself is
       still not warranted without a real brief.
       ============================================================ */

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-dark {
      position: fixed;
      inset: 0;
      background: rgba(10, 9, 7, 0.92);
      z-index: 9000;
      pointer-events: none;
      opacity: 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-stage {
      position: fixed;
      inset: 0;
      z-index: 9100;
      display: flex;
      align-items: center;
      justify-content: center;
      pointer-events: none;
      opacity: 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-stage--active {
      pointer-events: auto;
    }

    /* Backdrop is a SIBLING of the image wrap, not a child — it captures
       clicks outside the photograph so tap-outside-to-close works clear
       of the arrows. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-backdrop {
      position: fixed;
      inset: 0;
      cursor: pointer;
      z-index: 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-image-wrap {
      position: relative;
      z-index: 1;
      max-width: min(82vw, 1200px);
      max-height: 88vh;
      box-shadow: 0 12px 70px rgba(4, 3, 2, 0.72);
    }

    /* ── LIGHTBOX GESTURE: "Big Gate" — LOCKED 2026-09-23, REVISED
       same day ─────────────────────────────────────────────────
       Same hardware language as the grid's "Perimeter Frame Snap"
       hover (Script 4), scaled up: 7px hairlines vs 3px, 34px corner
       brackets vs 14px. Same structure (two diagonal halves closing,
       corners landing a beat later), same ease families
       (back.out(1.8) / back.out(2.2)), ~40% slower. Reads as the
       identical clamp mechanism operating at a bigger scale — a
       storefront gate, not a display case — never a different modal
       system. The photo itself does a plain, deliberately
       unremarkable crossfade; all the arrival meaning sits in the
       hardware.

       NOT A HELD FRAME — the gate is an arrival/departure gesture
       only, never a permanent border, and never pauses once landed.
       It snaps shut and retracts fully away IMMEDIATELY (no hold) on
       open, leaving the photograph completely clean for the whole
       time it's being viewed; on close it snaps back on and retracts
       immediately as the photo fades. First implementation left it
       clamped for the entire viewing session and Seamus flagged it as
       reading like an unwanted permanent white border; a second pass
       added a brief hold after the snap, which Seamus then also asked
       removed — the retract should begin the instant the corners
       land, no pause either time. Both fixed same day. Full
       sequencing lives in Script 5's ny21LbReveal()/ny21LbClose().

       Chosen from 5 concepts via visual-concept-generator
       (Session 258); concepts kept in
       nyc-2021-2022-concepts/lightbox-gestures/. Fires on OPEN/CLOSE
       only — navigate (arrow keys / prev/next) stays a plain
       crossfade with no gate at all, matching the site's existing
       precedent that a signature lightbox gesture marks
       arrival/departure, not browsing between frames once already
       inside (see Taos mobile: "the lamp does not move during
       navigate — only the print under
       it changes"). */
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-edge {
      position: absolute;
      background: rgba(230, 226, 218, 0.98);
      box-shadow: 0 0 18px rgba(230, 226, 218, 0.25);
      pointer-events: none;
      z-index: 3;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-edge--top {
      top: 0; left: 0; right: 0; height: 7px; transform-origin: left top;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-edge--bottom {
      bottom: 0; left: 0; right: 0; height: 7px; transform-origin: right bottom;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-edge--left {
      top: 0; bottom: 0; left: 0; width: 7px; transform-origin: left top;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-edge--right {
      top: 0; bottom: 0; right: 0; width: 7px; transform-origin: right bottom;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-corner {
      position: absolute;
      width: 34px;
      height: 34px;
      pointer-events: none;
      z-index: 4;
      opacity: 0;
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-corner--tl {
      top: 0; left: 0;
      border-top: 7px solid rgba(230, 226, 218, 0.98);
      border-left: 7px solid rgba(230, 226, 218, 0.98);
    }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-corner--br {
      bottom: 0; right: 0;
      border-bottom: 7px solid rgba(230, 226, 218, 0.98);
      border-right: 7px solid rgba(230, 226, 218, 0.98);
    }
    @media (prefers-reduced-motion: reduce) {
      body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-edge,
      body.fl718-nyc-2021-2022-page .fl718-ny21-lb-gate-corner {
        display: none !important;
      }
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-image {
      display: block;
      max-width: min(82vw, 1200px);
      max-height: 88vh;
      object-fit: contain;
      opacity: 0;
    }

    /* Caption — analog frames only, film stock name only. Currently
       always empty on this page (see caption contract note above). */
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-caption {
      position: absolute;
      bottom: -1.8rem;
      left: 0;
      right: 0;
      text-align: center;
      font-family: 'DM Sans', system-ui, sans-serif;
      font-size: 0.68rem;
      font-weight: 300;
      font-style: italic;
      color: rgba(230, 228, 222, 0.55);
      letter-spacing: 0.06em;
      margin: 0;
      opacity: 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-ui {
      position: fixed;
      inset: 0;
      z-index: 9200;
      pointer-events: none;
      opacity: 0;
    }

    /* The UI sheet never takes pointer-events:auto as a whole — only
       its individual controls do. A full-sheet pointer-events:auto
       swallows the backdrop's close click. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-ui--active .fl718-ny21-lb-close-btn,
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-ui--active .fl718-ny21-lb-nav {
      pointer-events: auto;
    }

    /* 44px minimum touch target on every control. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-close-btn {
      position: absolute;
      top: clamp(1rem, 2.5vw, 1.8rem);
      right: clamp(1rem, 2.5vw, 1.8rem);
      width: 44px;
      height: 44px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: rgba(20, 18, 16, 0.42);
      border: 1px solid rgba(255, 255, 255, 0.12);
      border-radius: 50%;
      cursor: pointer;
      color: rgba(255, 255, 255, 0.8);
      transition: background 0.2s ease;
      /* GeneratePress styles every <button> on the site, and
         button:focus at (0,1,1) beats a bare class selector. These
         explicit background/border/color declarations are what keep
         the control from inheriting GP's grey pill. Do not remove
         them when porting; check :focus and :hover after deploy. */
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-close-btn:hover {
      background: rgba(66, 62, 56, 0.42);
      color: #fff;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-close-btn svg {
      width: 16px;
      height: 16px;
      stroke: currentColor;
      fill: none;
      stroke-width: 1.5;
      stroke-linecap: round;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-counter {
      position: absolute;
      top: clamp(1rem, 2.5vw, 1.8rem);
      left: 50%;
      transform: translateX(-50%);
      font-family: 'DM Sans', system-ui, sans-serif;
      font-size: 0.65rem;
      font-weight: 300;
      letter-spacing: 0.2em;
      color: rgba(255, 255, 255, 0.38);
      white-space: nowrap;
      pointer-events: none;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-nav {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      width: 60px;
      height: 56px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: none;
      border: none;
      cursor: pointer;
      color: rgba(255, 255, 255, 0.72);
      transition: color 0.2s ease;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-nav:hover { color: #fff; }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-nav svg {
      width: 26px;
      height: 26px;
      stroke: currentColor;
      fill: none;
      stroke-width: 1.75;
      stroke-linecap: round;
      stroke-linejoin: round;
      filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.6));
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-prev { left: clamp(0.8rem, 2vw, 1.6rem); }
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-next { right: clamp(0.8rem, 2vw, 1.6rem); }

    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-close-btn:focus-visible,
    body.fl718-nyc-2021-2022-page .fl718-ny21-lb-nav:focus-visible {
      outline: 2px solid rgba(214, 208, 198, 0.85);
      outline-offset: 2px;
    }

    /* Reduced motion — lightbox appears at its end state, fade only,
       no scale, no translate. Every rule here carries the open-state
       qualifier (--active / the JS is-open guard) rather than applying
       "always", per the lightbox dismissal contract. */
    @media (prefers-reduced-motion: reduce) {
      body.fl718-nyc-2021-2022-page .fl718-ny21-lb-stage--active .fl718-ny21-lb-image {
        opacity: 1 !important;
        filter: none !important;
        transform: none !important;
      }
    }

    /* ============================================================
       AFTER-CONTENT — International Static Burst pattern
       Dateline -> rule -> eyebrow -> sibling city strip (JS-rendered)
       -> bottom rule -> taxonomy nav (2-col CSS grid).

       MANDATORY on every location page, desktop and mobile.

       In WordPress this is ONE SHARED COMPONENT, not this markup:
         set_query_var( 'fl718_after', [ 'slug' => 'nyc-2021-2022',
           'eyebrow' => 'From the Field', 'year' => '2021-2022' ] );
         get_template_part( 'template-parts/after-content' );
       Everything variable — cards, hero photographs, links, region,
       coordinates, the taxonomy row — is DERIVED from the Location
       taxonomy. There is no city list in the component. The static
       markup and the JS strip builder below exist only so the
       prototype renders standalone at file://; they are replaced by
       the get_template_part() call at deploy and are NOT the contract.

       The rules below style only this page's own container
       (.fl718-ny21-after*). NOT ONE .fl718-ws-city* SELECTOR IS
       REDECLARED HERE — those live in ../fl718-ws-city-system.css.
       A page that redeclares one silently wins the cascade and
       reverts the shared fix for this page only.
       ============================================================ */

    body.fl718-nyc-2021-2022-page .fl718-ny21-after {
      max-width: 960px;
      margin: 0 auto;
      padding: 80px 40px 140px;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__dateline {
      display: flex;
      align-items: baseline;
      flex-wrap: wrap;
      gap: 0;
      margin-bottom: 40px;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__city,
    body.fl718-nyc-2021-2022-page .fl718-ny21-after__sep,
    body.fl718-nyc-2021-2022-page .fl718-ny21-after__coords,
    body.fl718-nyc-2021-2022-page .fl718-ny21-after__year {
      font-family: 'Courier Prime', monospace;
      font-size: 13px;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__city {
      font-weight: 700;
      letter-spacing: 0.28em;
      text-transform: uppercase;
      color: #3a3835;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__sep {
      font-weight: 400;
      color: #6e6a63;
      margin: 0 20px;
      user-select: none;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__coords,
    body.fl718-nyc-2021-2022-page .fl718-ny21-after__year {
      font-weight: 400;
      letter-spacing: 0.08em;
      color: #6e6a63;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__rule {
      width: 100%;
      height: 1px;
      background: #d8d5d0;
      margin-bottom: 36px;
      transform-origin: left center;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__eyebrow {
      font-family: 'DM Sans', sans-serif;
      font-size: 10px;
      font-weight: 500;
      letter-spacing: 0.26em;
      text-transform: uppercase;
      color: #6e6a63;
      margin-bottom: 24px;
    }

    /* Strip container is page-scoped. The CARDS inside it are styled
       entirely by fl718-ws-city-system.css. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-after__strip {
      display: flex;
      gap: 14px;
      margin-bottom: 36px;
      overflow-x: clip;
    }

    /* Static Burst link-out: full-viewport wipe bar. First-paint-flash
       fix (documented on LA, 2026-09-05) carried forward: visibility
       is what actually suppresses the pre-transform frame on a cold
       load, not the transform alone. */
    body.fl718-nyc-2021-2022-page .fl718-ny21-wipe-bar {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      background: #111;
      transform: translateX(-100%);
      visibility: hidden;
      pointer-events: none;
      z-index: 9999;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-burst-char {
      position: fixed;
      font-family: 'Courier Prime', monospace;
      font-size: 9px;
      letter-spacing: 0.05em;
      color: rgba(255, 255, 255, 0.9);
      text-shadow: 0 0 4px rgba(0, 0, 0, 0.8);
      pointer-events: none;
      z-index: 200;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__bottom-rule {
      width: 100%;
      height: 1px;
      background: #d8d5d0;
      margin-bottom: 28px;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__taxonomy {
      display: grid;
      grid-template-columns: 2fr 1fr;
      gap: 8px 24px;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__tax-row {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 0 6px;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__tax-label {
      font-family: 'DM Sans', sans-serif;
      font-size: 10px;
      font-weight: 500;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      color: #6e6a63;
      margin-right: 10px;
      white-space: nowrap;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__tax-link {
      font-family: 'DM Sans', sans-serif;
      font-size: 12px;
      font-weight: 300;
      letter-spacing: 0.14em;
      text-transform: uppercase;
      color: #6e6a63;
      text-decoration: none;
      transition: color 0.2s ease;
      white-space: nowrap;
      padding: 13px 0;
    }

    body.fl718-nyc-2021-2022-page .fl718-ny21-after__tax-link:hover { color: #3a3835; }

    /* Visible middot between tags — display:none collapses the gap to
       a bare word-space and runs the tags together (LA fix, 2026-09-06). */
    body.fl718-nyc-2021-2022-page .fl718-ny21-after__tax-sep {
      display: inline-block;
      color: #6e6a63;
      user-select: none;
    }

    /* After-content animation start states — only when motion is allowed,
       so a reduced-motion visitor never sees a hidden element. */
    @media (prefers-reduced-motion: no-preference) {
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__dateline    { opacity: 0; }
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__rule        { transform: scaleX(0); }
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__eyebrow     { opacity: 0; }
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__bottom-rule { opacity: 0; }
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__taxonomy    { opacity: 0; }
    }

    /* ============================================================
       REDUCED-MOTION + NO-JS FALLBACKS
       Anything that starts at opacity:0 MUST be visible if JS fails
       or reduced motion is active. Reduced motion means skip the
       animation and keep the END STATE — never hide the content.
       Where an animation uses x/y/scale, the fallback must also
       reset transform, not only opacity.
       ============================================================ */

    @media (prefers-reduced-motion: reduce) {
      body.fl718-nyc-2021-2022-page .fl718-ny21-item {
        opacity: 1 !important;
        transform: none !important;
        filter: none !important;
      }
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__dateline,
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__rule,
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__eyebrow,
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__bottom-rule,
      body.fl718-nyc-2021-2022-page .fl718-ny21-after__taxonomy {
        opacity: 1 !important;
        transform: none !important;
      }
    }

    /* No-JS: show everything at its end state. */
    body.fl718-nyc-2021-2022-page:not(.fl718-js-loaded) .fl718-ny21-item {
      opacity: 1;
      transform: none;
      filter: none;
    }
    body.fl718-nyc-2021-2022-page:not(.fl718-js-loaded) .fl718-ny21-hero__image,
    body.fl718-nyc-2021-2022-page:not(.fl718-js-loaded) .fl718-ny21-hero__gradient,
    body.fl718-nyc-2021-2022-page:not(.fl718-js-loaded) .fl718-ny21-hero__title,
    body.fl718-nyc-2021-2022-page:not(.fl718-js-loaded) .fl718-ny21-hero__subtitle-block,
    body.fl718-nyc-2021-2022-page:not(.fl718-js-loaded) .fl718-ny21-hero__byline {
      opacity: 1;
      transform: none;
      filter: none;
    }

