/* ============================================================
   HOUSE CIRCUIT — EVENT PHOTOS
   Crowd and booth photos placed around the site (home + contact).
   Files are pre-graded to one brightness / saturation by
   tools/optimize_photos.py; .ph adds one on-screen treatment so
   every room, from red basements to daylight patios, reads as the
   same set: a light signal-green colour wash, scanlines and a
   vignette. Framed photos add HUD corner ticks and a mono tag, and
   brighten to full colour on hover.
============================================================ */
.ph {
  --ph-b: 0.95;      /* brightness */
  --ph-tint: 0.12;   /* green wash */
  position: relative;
  overflow: hidden;
  margin: 0;
  background: var(--ink-2);
  isolation: isolate;
}
.ph picture,
.ph img {
  display: block;
  width: 100%;
  height: 100%;
}
.ph img {
  object-fit: cover;
  filter: saturate(0.88) contrast(1.06) brightness(var(--ph-b));
  transition: filter 0.7s var(--ease-out), transform 1.4s var(--ease-out);
}
.ph::before,
.ph::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.ph::before {
  z-index: 1;
  background: var(--signal);
  mix-blend-mode: color;
  opacity: var(--ph-tint);
  transition: opacity 0.7s var(--ease-out);
}
.ph::after {
  z-index: 2;
  background:
    repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.2) 0 1px, transparent 1px 3px),
    radial-gradient(120% 95% at 50% 45%, transparent 55%, rgba(5, 7, 6, 0.6) 100%);
}

/* Framed photos: HUD corner ticks (some add a tag), full colour on hover. */
.mission-photo,
.reel-frame,
.join-tile { border: 1px solid var(--line-2); }
.mission-photo::after,
.reel-frame::after,
.join-tile::after {
  --tick: linear-gradient(var(--signal), var(--signal));
  background:
    var(--tick) left 6px top 6px / 14px 1px no-repeat,
    var(--tick) left 6px top 6px / 1px 14px no-repeat,
    var(--tick) right 6px top 6px / 14px 1px no-repeat,
    var(--tick) right 6px top 6px / 1px 14px no-repeat,
    var(--tick) left 6px bottom 6px / 14px 1px no-repeat,
    var(--tick) left 6px bottom 6px / 1px 14px no-repeat,
    var(--tick) right 6px bottom 6px / 14px 1px no-repeat,
    var(--tick) right 6px bottom 6px / 1px 14px no-repeat,
    repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.2) 0 1px, transparent 1px 3px),
    radial-gradient(120% 95% at 50% 45%, transparent 55%, rgba(5, 7, 6, 0.6) 100%);
}
@media (hover: hover) {
  .reel-frame:hover,
  .join-tile:hover { --ph-b: 1.02; --ph-tint: 0.03; }
  .reel-frame:hover img,
  .join-tile:hover img { transform: scale(1.05); }
}
.join-tile:focus-visible { --ph-b: 1.02; --ph-tint: 0.03; }
.ph-tag {
  position: absolute;
  z-index: 3;
  left: 26px;     /* clear of the corner ticks */
  bottom: 9px;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--signal);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.9);
}

/* ------------------------------------------------------------
   MISSION: three booth shots beside the statement. As each one's
   reveal fires it wipes in, then the room lights up (dim and green
   → full) and the shot drifts into place, alongside the words.
------------------------------------------------------------ */
.mission-copy { display: grid; gap: clamp(20px, 3.4vh, 36px); }
.mission-photos { display: none; }
.mission-photo { --ph-b: 0.42; --ph-tint: 0.4; }
.mission-photo.is-in { --ph-b: 0.98; --ph-tint: 0.14; }
.mission-photo img { transform: scale(1.1) translate3d(0, calc(var(--drift, 24px) * 0.5), 0); }
.mission-photo.is-in img { transform: scale(1.06); }
.motion .mission-photo img {
  transition:
    filter 1.6s ease calc(var(--d, 0s) + 0.5s),
    transform 2.6s var(--ease-out) var(--d, 0s);
}
.motion .mission-photo::before { transition: opacity 1.6s ease calc(var(--d, 0s) + 0.5s); }

@media (min-width: 1024px) and (min-height: 600px) {
  .mission-grid {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: clamp(40px, 5vw, 96px);
  }
  .mission-photos {
    display: block;
    position: relative;
    height: min(60svh, 33vw, 600px);   /* leaves the statement its width */
    aspect-ratio: 0.8;
  }
  .mission-photo {
    position: absolute;
    height: 62%;
    aspect-ratio: 2 / 3;
  }
  .mission-photo .ph-tag { top: 9px; bottom: auto; }   /* the overlap hides bottoms */
  .mission-photo:nth-child(1) { left: 0; top: 0; --drift: 30px; }
  .mission-photo:nth-child(2) { left: 24%; top: 19%; z-index: 1; --drift: -22px; }
  .mission-photo:nth-child(3) { right: 0; top: 38%; z-index: 2; --drift: 40px; }
}
/* Tall tablets / phones: a row of three under the pillars. */
@media (max-width: 1023px) and (min-height: 820px) {
  .mission-photos {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    max-width: 560px;
    margin-top: clamp(4px, 1.5vh, 16px);
  }
  .mission-photo { aspect-ratio: 3 / 4; }
}
@media (max-width: 599px) {
  .mission-photo .ph-tag { display: none; }
}

/* ------------------------------------------------------------
   THE NAME: each entry has its photo behind it, fading in
   from the right (the booth for "house", the floor for "circuit").
------------------------------------------------------------ */
.entry { position: relative; overflow: hidden; isolation: isolate; }
.entry > :not(.entry-photo) { position: relative; z-index: 1; }
.entry-photo {
  --ph-b: 0.62;
  position: absolute;
  z-index: 0;
  inset: 0 0 0 32%;
  opacity: 0.8;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 55%);
          mask-image: linear-gradient(90deg, transparent 0%, #000 55%);
}
.entry-head dfn,
.entry-def { text-shadow: 0 1px 14px rgba(5, 7, 6, 0.85); }

/* ------------------------------------------------------------
   TICKETS: the floor behind the Posh panel.
------------------------------------------------------------ */
.stub { overflow: hidden; isolation: isolate; }
.stub-main { position: relative; z-index: 1; }
.stub-photo {
  --ph-b: 0.58;
  position: absolute;
  z-index: 0;
  inset: 0;
  opacity: 0.85;
  -webkit-mask-image: linear-gradient(90deg, transparent 8%, #000 72%);
          mask-image: linear-gradient(90deg, transparent 8%, #000 72%);
}
@media (max-width: 959px) {
  .stub-photo {
    --ph-b: 0.45;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 85%);
            mask-image: linear-gradient(180deg, #000 0%, transparent 85%);
  }
}
.stub-title,
.stub-copy { text-shadow: 0 1px 16px rgba(5, 7, 6, 0.9); }

/* ------------------------------------------------------------
   THE REEL — crowd photos drifting past like a film strip between
   the venues and tickets (tilted a touch, sprocket holes top and
   bottom). It never stops: hovering a frame only brightens it.
------------------------------------------------------------ */
.reel {
  position: relative;
  z-index: 1;
  overflow: hidden;
  padding-block: clamp(24px, 5vh, 56px) clamp(48px, 10vh, 112px);   /* transparent: the board runs under the reel */
}
.reel-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  max-width: var(--maxw);
  margin: 0 auto clamp(14px, 2.4vh, 24px);
  padding-inline: var(--gutter);
}
.reel-bar .label { color: var(--text-2); }
.reel-link { transition: color var(--t-fast); }
.reel-link:hover { color: var(--signal); }
.reel-window {
  transform: rotate(-1.6deg);
  margin-inline: -3vw;
  /* Film gate: frames fade in and out at the edges (and clear the stop map). */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
}
@media (min-width: 1100px) {
  .reel-window {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, transparent 60px, #000 220px, #000 90%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, transparent 60px, #000 220px, #000 90%, transparent 100%);
  }
}
.reel-track {
  --frame-h: clamp(200px, 32svh, 420px);   /* big enough to really see the room */
  display: flex;
  width: max-content;
  padding-block: 16px;
  background:
    repeating-linear-gradient(90deg, var(--line-2) 0 10px, transparent 10px 22px) left top 4px / 100% 6px no-repeat,
    repeating-linear-gradient(90deg, var(--line-2) 0 10px, transparent 10px 22px) left bottom 4px / 100% 6px no-repeat;
}
.reel-frame {
  --ph-b: 1;
  --ph-tint: 0.08;
  flex: none;
  height: var(--frame-h);
  aspect-ratio: 3 / 2;
  margin-right: 12px;
}
@media (max-width: 699px) {
  .reel-track { --frame-h: clamp(180px, 30svh, 280px); }   /* about one frame per screen width */
}
/* It slides by a transform set each frame (photo strips, site.js), not
   a CSS animation: see the venues band below. */
.motion [data-marquee] { will-change: transform; }
/* No motion: a still strip you can scroll sideways. */
html:not(.motion) .reel-window { transform: none; margin-inline: 0; overflow-x: auto; }
html:not(.motion) [data-loop-copy] { display: none; }   /* the second pass only serves the loop */
@media (min-width: 1100px) {
  .reel-bar { padding-left: max(var(--gutter), 88px); }
}
@media (min-width: 1800px) and (min-height: 1100px) {
  .reel-bar { padding-left: max(var(--gutter), 100px); }
  .reel-track { --frame-h: clamp(200px, 32svh, 520px); }
}

/* ------------------------------------------------------------
   PHOTO BANDS — full-bleed photos between the home stops, nearly a
   screen tall, so the rooms are really seen. A lighter treatment than
   the framed shots (a faint wash, fine scanlines), soft fades into the
   board above and below, and a big caption. Reveal (one way): the
   frame opens like a letterbox and the photo settles. Phones: a
   portrait photo fills the screen (ph.art). The venues band is a
   gallery sliding across the screen.
------------------------------------------------------------ */
.band {
  position: relative;
  z-index: 1;
  height: clamp(420px, 82svh, 980px);
  margin: 0;
  overflow: hidden;
  isolation: isolate;
}
.band-photo {
  --ph-b: 1;
  --ph-tint: 0.07;
  position: absolute;
  inset: 0;
}
.band-photo img { object-position: 50% 45%; }
.band--late .band-photo img { object-position: 38% 35%; }
.band-photo::after,
.band-shot::after {
  background:
    repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.12) 0 1px, transparent 1px 3px),
    radial-gradient(130% 100% at 50% 45%, transparent 60%, rgba(5, 7, 6, 0.45) 100%);
}
/* Fades into the board above and below, and a floor for the caption. */
.band::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg, var(--ink) 0%, rgba(5, 7, 6, 0) 14%, rgba(5, 7, 6, 0) 50%, rgba(5, 7, 6, 0.8) 86%, var(--ink) 100%);
}
.band-caption {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: clamp(32px, 8svh, 88px);
  display: grid;
  justify-items: start;
  gap: clamp(10px, 1.6vh, 18px);
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
  pointer-events: none;   /* swipes and clicks go through to the photos */
}
.band-caption .label { color: var(--text); text-shadow: 0 1px 12px rgba(0, 0, 0, 0.8); }
.band-quote {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 900;
  font-size: clamp(40px, min(8vw, 11svh), 150px);
  line-height: 0.9;
  text-transform: uppercase;
  color: var(--text);
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.6);
}
@media (min-width: 1100px) {
  .band-caption { padding-left: max(var(--gutter), 88px); }   /* clear of the stop map */
}

/* The venues: full-height photos sliding right to left (two identical
   passes; site.js moves the track one pass along every
   110s). Like the reel and the tape it never stops for the pointer (only
   off screen, or while a keyboard user is in it); each photo opens the
   lightbox. Kept light for phones, where a strip this wide is big: no
   colour wash blend or filter per photo (the band treatment is only
   scanlines), and no CSS animation (phones keep an animated layer's
   whole path painted, which ran them out of memory). */
.band-window { position: absolute; inset: 0; }
.band-track {
  display: flex;
  width: max-content;
  height: 100%;
}
.band-pass { display: flex; height: 100%; }
.band-slide { height: 100%; margin-right: 10px; }
.band-slide--tall { aspect-ratio: 2 / 3; }
.band-slide--wide { aspect-ratio: 3 / 2; }
.band-shot {
  --ph-b: 1;
  --ph-tint: 0.07;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  color: inherit;
  border: 1px solid var(--line-2);
  cursor: zoom-in;
}
.band-shot::before { content: none; }
.band-shot img { filter: none; transition: none; }
.band-shot::after { transition: opacity var(--t-fast); }
@media (hover: hover) {
  .band-shot:hover::after { opacity: 0.35; }
}
.band-shot:focus-visible { outline: 2px solid var(--signal); outline-offset: -4px; }
.band-shot:focus-visible::after { opacity: 0.35; }
/* No motion: one pass you can scroll sideways. */
html:not(.motion) .band-window { overflow-x: auto; }
html:not(.motion) .band-pass[aria-hidden] { display: none; }

/* Reveal: the letterbox opens and the photo settles (once). */
.motion [data-reveal="band"] {
  opacity: 1;
  transform: none;
  clip-path: inset(14% 0 14% 0);
  transition: clip-path 1.4s var(--ease-out) var(--d, 0s);
}
.motion [data-reveal="band"].is-in { clip-path: inset(0 0 0 0); }
.motion [data-reveal="band"] img {
  transform: scale(1.14);
  transition: transform 2.4s var(--ease-out) var(--d, 0s), filter 0.7s var(--ease-out);
}
.motion [data-reveal="band"].is-in img { transform: scale(1.02); }

/* Phones: the portrait photo fills the screen; the venues slide past
   one or two at a time, at full height. */
@media (max-width: 699px) {
  .band { height: clamp(460px, 80svh, 760px); }
  .band-quote { font-size: clamp(40px, 12.5vw, 64px); }
  .band-slide { margin-right: 8px; }
}
@media (min-width: 1800px) and (min-height: 1100px) {
  .band-caption { padding-left: max(var(--gutter), 100px); }
}

/* ------------------------------------------------------------
   JOIN: a small gallery of the floor beside the sign-up. A mosaic
   (one big crowd shot, two tall stage shots, three smaller frames)
   on desktop, a 3×2 grid on tablets and tall phones, one row on
   other phones (and no head row on short ones). Each
   tile opens the lightbox (home.js); "Full gallery" goes on.
------------------------------------------------------------ */
.join-gallery { display: grid; gap: 12px; min-width: 0; }
.join-gallery-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}
.join-gallery-head .label { color: var(--text-2); }
.join-mosaic {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.join-cell { min-width: 0; }
.join-tile {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  padding: 0;
  color: inherit;
  cursor: zoom-in;
}
.join-tile:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }
@media (max-width: 959px) and (max-height: 740px),
       (max-width: 699px) and (max-height: 799px) {
  .join-cell:nth-child(n + 4) { display: none; }
}
@media (max-width: 699px) and (max-height: 700px) {
  .join-gallery-head { display: none; }
  .join-tile { aspect-ratio: 16 / 10; }
}
@media (max-width: 359px), (max-width: 699px) and (max-height: 600px) {
  .join-tile { aspect-ratio: 2 / 1; }
}
@media (min-width: 960px) {
  .join-mosaic {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-rows: repeat(3, minmax(0, 1fr));
    grid-template-areas:
      "a a b c"
      "a a b d"
      "e f f d";
    gap: 10px;
    height: clamp(300px, min(54svh, 36vw), 620px);
  }
  .join-cell:nth-child(1) { grid-area: a; }
  .join-cell:nth-child(2) { grid-area: b; }
  .join-cell:nth-child(3) { grid-area: c; }
  .join-cell:nth-child(4) { grid-area: d; }
  .join-cell:nth-child(5) { grid-area: e; }
  .join-cell:nth-child(6) { grid-area: f; }
  .join-tile { height: 100%; aspect-ratio: auto; }
}
@media (min-width: 1800px) and (min-height: 1100px) {
  .join-mosaic { height: clamp(300px, min(54svh, 36vw), 820px); gap: 14px; }
}

/* ------------------------------------------------------------
   CONTACT — the reel under the page heading: the same sliding film
   strip, a little lower, with no head row.
------------------------------------------------------------ */
.contact-reel { margin-top: clamp(20px, 3vh, 40px); padding-block: 0 8px; }
.contact-reel .reel-track { --frame-h: clamp(150px, 24svh, 300px); }

/* Browsers without small-viewport units: the svh sizes in vh. */
@supports not (height: 1svh) {
  .reel-track { --frame-h: clamp(200px, 32vh, 420px); }
  .contact-reel .reel-track { --frame-h: clamp(150px, 24vh, 300px); }
  .band { height: clamp(420px, 82vh, 980px); }
  @media (min-width: 1024px) and (min-height: 600px) {
    .mission-photos { height: min(60vh, 33vw, 600px); }
  }
  @media (min-width: 960px) {
    .join-mosaic { height: clamp(300px, min(54vh, 36vw), 620px); }
  }
}
