/* Camera-world layout.
   The world is authored at reading scale (WORLD_COL = 820 world units wide,
   matching the reader measure). The grid is the zoomed-OUT state; focusing a
   piece returns the camera to zoom 1, so body text is only ever scaled while
   in transit, never while you are reading it. */

:root {
  --bg: #000;
  --ink: #f4f4f4;
  --muted: #9a9a9a;
  --line: rgba(255,255,255,0.08);
  --tile-bg: #0a0a0a;
  --radius: 0;      /* squared off: no rounded corners anywhere */
  --edge: 30px;     /* matches EDGE in world.js so chrome lines up with the grid */
  --chrome-top: 28px;
  --pill-bg: rgba(20,20,20,0.72);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-feature-settings: "cv11", "ss01";
  -webkit-font-smoothing: antialiased;
}

@supports (font-variation-settings: normal) {
  html, body { font-family: "InterVariable", "Inter", sans-serif; }
}

a { color: inherit; text-decoration: none; }

/* Native scrolling is kept: #scroller really scrolls, #spacer supplies the
   range, and #stage sticks to the viewport while the camera reads scrollTop.
   Hijacking the wheel would cost momentum, touch, keyboard and find-in-page. */
#scroller {
  height: 100svh;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.22) transparent;
}

#scroller::-webkit-scrollbar { width: 10px; }
#scroller::-webkit-scrollbar-track { background: transparent; }
#scroller::-webkit-scrollbar-thumb {
  background-color: rgba(255,255,255,0.18);
  border-radius: 999px;
  /* Transparent border plus background-clip insets the thumb visually without
     narrowing the track, so the grab area stays a comfortable 10px. */
  border: 3px solid transparent;
  background-clip: content-box;
  transition: background-color 200ms ease;
}
#scroller::-webkit-scrollbar-thumb:hover { background-color: rgba(255,255,255,0.34); }
#scroller::-webkit-scrollbar-thumb:active { background-color: rgba(255,255,255,0.46); }

#stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
}

#world {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
}

/* --- tiles --- */

.tile {
  position: absolute;
  background: var(--tile-bg);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
  isolation: isolate;
  will-change: opacity;
}

.tile img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Tiles are the image alone — no title, date or scrim overlay. */


/* --- a piece's content, living in world space directly below its tile --- */

.detail {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}

.detail.live { pointer-events: auto; }

/* In the reader the grid is still there, invisible, and later tiles paint over
   an earlier piece's blocks. Nothing in the grid is clickable while reading -
   the mark is the way back - so hand every pointer straight to the blocks. */
#world.reading .tile { pointer-events: none; }

/* Off the screen, still in the document: the piece keeps its name for screen
   readers and the outline even when the cover is already carrying it. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

.detail h1 {
  font-size: 38px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
  margin: 0 0 14px;
}

.detail .headline-date {
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 22px;
}
/* The date closes the heading, so what follows starts under it rather than
   across a blank line. The block's own top margin would win the collapse. */
.detail .headline-date + .block { margin-top: 0; }
/* The run-out below a piece is FOCUS_BOTTOM's to set - the last block's own
   margin would otherwise be added to it. */
.detail > .block:last-child,
.detail > :last-child { margin-bottom: 0; }

.detail .block { margin: 36px 0; }
/* The stand-in cover butts against the bar the way a real one does, and the
   heading follows it at the same distance - DETAIL_GAP in world.js. */
.detail > .block.lead { margin: 0 0 14px; }
.detail .block img,
.detail .block video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0;
}
/* audio is drawn by the site's own player - see audio-player.css */

/* A set of images as one unit. Natural heights, top-aligned: cropping to a
   uniform cell would tidy the grid at the cost of the work in it.
   NOT ".gallery": renderBlocks puts `block <type>` on the wrapper, so that name
   would style the wrapper as a grid too and halve the real one. */
.image-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr));
  gap: 10px;
  align-items: start;
}
.image-grid img,
.image-grid video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0;
}
.detail .block.text {
  font-size: 16px;
  line-height: 1.65;
  color: #e0e0e0;
  white-space: pre-wrap;
}

/* `a { text-decoration: none }` is set globally, so a link in body copy would
   otherwise be invisible. Underline sits off the baseline and only brightens
   on hover, so a paragraph of links does not turn into a fence. */
.detail .block.text a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(255,255,255,0.38);
  transition: text-decoration-color 160ms ease;
  overflow-wrap: anywhere;
}
.detail .block.text a:hover { text-decoration-color: var(--ink); }
.detail .block .caption {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 10px;
}

/* --- chrome --- */

/* A separate row on top. Opaque and full-bleed, so tiles pass under it and
   disappear rather than showing through. It no longer moves with scroll. */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: var(--chrome-top) var(--edge) 18px var(--chrome-top);
  background: var(--bg);
  transition: background-color 220ms ease;
}

/* Reading, on a screen wide enough that the column clears the mark: there is
   nothing behind the bar to hide, so the band goes and the mark is left
   floating over the page. The mosaic gets it straight back - see world.js. */
.topbar.clear { background: transparent; }

/* In a focused piece the mark is the way back, so it takes a cursor and a
   little lift on hover. In the grid it is just the home link. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
}

.brand img {
  display: block;
  width: auto;
  height: 30px;
  opacity: 0.95;
}

.wordmark {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--ink);
}

.header-text {
  display: none;
}

.brand { transition: opacity 200ms ease; }
.brand:hover { opacity: 0.7; }

/* Preview mode marker, written into the mark the way the admin writes
   /ADMIN. It used to be a bar across the bottom of the window, sitting on the
   end of the very piece being judged. Coloured rather than dimmed: the admin
   is somewhere you know you are, preview is a state you can forget. */
.wordmark .sub { color: #8ad7a8; white-space: nowrap; }
.wordmark .sub.bad { color: #e8705f; }
