/* Post-event gallery — one module, the day in hours, and the black
   spent on three things.

   Every tile is the same square. A larger tile was tried six times and
   each meaning it was given had to be explained in words: nobody edits
   this gallery and nobody picks a picture of the hour, so there is
   nothing for a bigger frame to mean. A square costs a landscape photo
   and a portrait one the same quarter to the crop.

   The route palette is not on this page. A gallery item is a code, a
   name, a team and a time — the line was never a fact it has — so the
   plate is black on every tile, and the palette stays in the stripe
   under the nav and again on the footer, where it cannot be read as a
   key to anything.

   An hour is a heavy rule over a heading, not another black bar: the
   black is the nav, the one control and the footer, and nothing else. */

/* ---------------- The title, the one control, what the page holds ---- */

.gal-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 24px;
  align-items: center;
}

/* the status line and the gate take the left, the one control the
   right, level with them */

.gal-go {
  grid-column: 2;
  grid-row: 1 / span 2;
  justify-self: end;
  display: flex;
}

/* the one control on the page, and the only thing on it carrying the
   offset shadow */
.gal-btn {
  padding: 15px 22px;
  font-weight: 800;
  letter-spacing: -0.012em;
  box-shadow: var(--shadow);
}

.gal-line {
  grid-column: 1;
  margin: 0;
  font-size: 1rem;
  line-height: 1.5;
  max-width: 44em;
  font-variant-numeric: tabular-nums lining-nums;
}
.gal-line:empty { display: none; }

/* ---------------- An hour ---------------- */

.gal-hour {
  margin-top: 56px;
  border-top: 6px solid var(--text);
  padding-top: 14px;
}
.gal-hour:first-child { margin-top: 40px; }

.gal-head {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 24px;
}

.gal-hour-time {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 850;
  letter-spacing: -0.03em;
  line-height: 1;
  font-variant-numeric: tabular-nums lining-nums;
}

/* the count is the way into the rest of the hour, so it is the
   control: bold text and an arrow, the lighter treatment on the
   lesser action */
.gal-all {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 0;
  padding: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: -0.012em;
  line-height: 1.25;
  font-variant-numeric: tabular-nums lining-nums;
  cursor: pointer;
}
.gal-all svg {
  display: block;
  transition: transform var(--duration-fast) var(--ease-smooth-out);
}
.gal-hour.is-open .gal-all svg { transform: rotate(180deg); }
.gal-all:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---------------- One module ---------------- */

.gal-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: 24px;
  row-gap: 56px;
}

/* a closed hour shows its first row; the count above it opens the rest */
.gal-hour:not(.is-open) .gal-tile:nth-child(n + 5) { display: none; }

.gal-tile {
  display: block;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.gal-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.gal-tile:hover .gal-name { text-decoration: underline; text-underline-offset: 3px; }

.gal-pic {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: 2px;
  background: var(--border);
}
.gal-pic img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* one corner holds one object: the code, and on a video the play
   glyph with it, so a still and a video differ in exactly one way */
.gal-plate {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 9px;
  background: var(--sign-bg);
  color: var(--sign-ink);
  line-height: 1;
}
.gal-quest {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
}
.gal-play { display: block; }

/* the title is one line, the meta sits under it, the pair is 8px from
   its picture and there is no rule between them */
.gal-caption { display: block; margin-top: 8px; }
.gal-name {
  display: block;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.012em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* in ink, not grey: as the palest type on the page it read as a
   footnote to the picture rather than as what the picture is */
.gal-meta {
  display: block;
  margin-top: 2px;
  font-size: 0.75rem;
  line-height: 1.35;
  font-variant-numeric: tabular-nums lining-nums;
}

@media (max-width: 560px) {
  .gal-top {
    grid-template-columns: minmax(0, 1fr);
  }
  /* the control goes under what the page holds, as low in the header as
     it can go without landing in the middle of the day, and full width
     because that is the largest target the page can give it */
  .gal-go {
    grid-column: 1;
    grid-row: auto;
    justify-self: stretch;
    margin-top: 20px;
  }
  .gal-btn {
    width: 100%;
    justify-content: flex-start;
    padding: 16px 18px;
  }

  .gal-hour { margin-top: 40px; padding-top: 0; }
  .gal-hour:first-child { margin-top: 28px; }
  .gal-head { align-items: center; padding: 14px 0; margin-bottom: 0; }
  /* the whole heading row is the control at this width: same words, same
     treatment, drawn at the size a thumb needs */
  .gal-all::after { content: ''; position: absolute; inset: 0; }

  .gal-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 16px;
    row-gap: 28px;
  }
  /* a 171px column clips almost every name at one line, and
     "Is the Escalator Wor…" says nothing, so it wraps to two */
  .gal-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: normal;
    text-overflow: clip;
  }
}

/* ---------------- Slideshow ----------------
   The same grammar at the size of a projector: the picture matted in
   paper, its code, name and team on a black sign under it, and the
   controls on a sign bar across the foot. The room is the site's own
   black rather than a colour of its own.

   No stripe in here. It is the site's mark on the nav and on the footer
   and nowhere between, and this layer has neither. */
html.ss-open, html.ss-open body { overflow: hidden; }

.ss-overlay {
  position: fixed;
  inset: 0;
  z-index: 1600;
  /* the room's own margins, named because the picture well is measured
     against them: a well sized in vw alone was wider than the stage it
     sits in, and a phone lost the right edge of the frame */
  --ss-side: 24px;
  --ss-mat: 22px;
  --ss-drop: 248px;
  background: var(--sign-bg);
  color: var(--sign-ink);
  display: grid;
  grid-template-rows: 1fr auto;
}

/* The one column is pinned to the stage's width. Left to size itself it
   took the frame's max-content width, so at a large text size the plate
   pushed the column past the screen and the frame's `max-width: 100%`
   — which is a per cent of that column — capped nothing. */
.ss-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  min-height: 0;
  padding: var(--ss-side) var(--ss-side) 12px;
  cursor: pointer;
}

.ss-frame {
  display: grid;
  grid-template-rows: 1fr auto;
  min-width: 0;
  max-width: min(1400px, 100%);
  max-height: 100%;
  background: var(--card-bg);
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  animation: ss-in var(--duration-slow) var(--ease-smooth-out);
}
@keyframes ss-in {
  from { opacity: 0; transform: scale(0.985); }
}

/* the mat: paper margin around the picture, wider at the bottom the
   way a framed print is */
.ss-mat {
  padding: var(--ss-mat) var(--ss-mat) calc(var(--ss-mat) - 4px);
  display: grid;
  place-items: center;
  min-height: 0;
}
/* the picture well is a constant size, so the frame does not jump
   between a portrait and a landscape shot; whatever is in it is
   fitted whole and the rest falls away into the room. Its width is
   what the stage has left after the mat and the room's margins, so the
   frame cannot be wider than the screen it is drawn on. */
.ss-mat img,
.ss-mat video {
  display: block;
  width: min(1180px, calc(100vw - 2 * var(--ss-side) - 2 * var(--ss-mat) - 2px));
  height: calc(100vh - var(--ss-drop));
  object-fit: contain;
  background: var(--sign-bg);
  border: 1px solid var(--border);
  border-radius: 2px;
}

/* the plate: the tile's caption at the size of the room. The code on
   the left the way it sits on a tile, the team on the right, the way a
   sign carries a route and a destination. */
.ss-plate {
  display: flex;
  align-items: baseline;
  gap: 16px;
  min-width: 0;
  padding: 11px 16px 12px;
  background: var(--sign-bg);
  color: var(--sign-ink);
}
.ss-plate-line {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex: 0 1 auto;
  min-width: 0;
}
.ss-code {
  flex: none;
  padding: 0;
  background: none;
  color: var(--sign-ink);
  font-family: var(--mono);
  font-size: var(--t-small);
  font-weight: 700;
}
.ss-quest-name {
  font-size: var(--t-lede);
  font-weight: 700;
  letter-spacing: -0.012em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* both halves of the plate give way rather than push the frame wider
   than the screen it is drawn on */
.ss-team {
  margin-left: auto;
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--sign-muted);
  font-size: var(--t-small);
  font-weight: 700;
}

/* the controls, on the sign black. They stand back while the show runs
   and come up on a hover or a pause. */
.ss-bar {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  padding: 12px 12px calc(12px + env(safe-area-inset-bottom, 0px));
  background: var(--sign-bg);
  opacity: 0.25;
  transition: opacity var(--duration-fast) var(--ease-smooth-out);
}
.ss-overlay:hover .ss-bar,
.ss-overlay.is-paused .ss-bar { opacity: 1; }

.ss-btn {
  border: 2px solid var(--sign-muted);
  border-radius: 2px;
  background: transparent;
  color: var(--sign-ink);
  font: inherit;
  font-weight: 700;
  padding: 8px 14px;
  min-height: 42px;
  cursor: pointer;
  transition:
    background-color var(--duration-quick) var(--ease-smooth-out),
    color var(--duration-quick) var(--ease-smooth-out),
    border-color var(--duration-quick) var(--ease-smooth-out);
}
.ss-btn:hover {
  background: var(--sign-ink);
  border-color: var(--sign-ink);
  color: var(--sign-bg);
}
.ss-btn:active { transform: translate(1px, 1px); }
.ss-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Play and pause are different widths as glyphs, so a button sized to
   whichever one it was showing changed width every time it was
   pressed and shoved the rest of the bar sideways with it. It is a
   fixed box with the glyph centred instead. The arrows beside it get
   the same width, since they are single glyphs too and a row of
   matching squares reads better than three sizes. */
.ss-btn.ss-square {
  width: 46px;
  padding-left: 0;
  padding-right: 0;
  display: inline-grid;
  place-items: center;
}

.ss-count {
  color: var(--sign-muted);
  font-family: var(--mono);
  font-size: var(--t-small);
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  padding: 0 10px;
}

/* the settings are paper over the room, because paper is what the site
   reads and operates on */
.ss-panel {
  position: absolute;
  right: 12px;
  bottom: 76px;
  width: min(330px, calc(100vw - 24px));
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  box-shadow: var(--shadow);
  padding: 16px;
  display: grid;
  gap: 14px;
}
.ss-panel-title {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.ss-field { display: grid; gap: 6px; }
.ss-field-top {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: var(--t-small);
}
.ss-field-top strong { font-variant-numeric: tabular-nums lining-nums; }
.ss-field input[type="range"] { width: 100%; accent-color: var(--accent); }
.ss-select {
  width: 100%;
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  padding: 9px 10px;
}
.ss-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ss-check { margin: 0; }

@media (max-width: 700px) {
  .ss-overlay { --ss-side: 12px; --ss-mat: 12px; --ss-drop: 240px; }
  .ss-stage { padding-bottom: 6px; }
  .ss-plate { flex-wrap: wrap; gap: 4px 14px; padding: 10px 12px 11px; }
  .ss-team { margin-left: 0; }
  /* The six controls do not fit one phone row, and left to wrap they
     dropped Close onto a line of its own. The count goes above them
     instead: where you are, then the controls, and both rows full. */
  .ss-bar { opacity: 1; flex-wrap: wrap; gap: 8px; }
  .ss-count { order: -1; flex-basis: 100%; text-align: center; padding: 0 0 2px; }
  .ss-btn { padding: 8px 11px; }
  .ss-btn.ss-square { width: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .ss-frame { animation: none; }
  .gal-all svg { transition: none; }
}

/* The row of event photographs under the gate. The gap is the page's
   own rhythm; the row itself is laid out in assets/photo-strip.css. */
#gal-shots { margin: 22px 0 0; }
