/* ─────────────────────────────────────────────────────────────────────────
   any — site.css

   The site is a sheet. That is not a metaphor chosen for the site: it is
   LIGHT / PAPER's own ground, so the white here is the same white the work
   is printed on, and a paper piece is set directly onto the page with no
   frame at all. LIGHT / SIGNAL's ground is #07060a, so its pieces read as
   apertures cut into the sheet. The two series carry the whole contrast
   between them and the page adds none of its own.

   Two typographic voices, no third:
     mono   — every piece of apparatus: nav, indices, wall labels, captions.
              Deliberately the same voice as the works' own HUD.
     serif  — the name, the titles, the prose. Wall label and catalogue essay.

   Ornament is crop and registration marks, drawn in CSS. They are LIGHT /
   PAPER's literal subject, and they keep the apparatus visible, which is
   the parent statement's condition too.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  --sheet:  #ffffff;
  --stock:  #faf9f6;   /* the warm off-white of a press stock, for insets   */
  --ink:    #14120f;
  --ink-2:  #6b6459;
  --ink-3:  #a8a196;
  --rule:   #e4e0d8;
  --void:   #07060a;   /* LIGHT / SIGNAL's ground, exactly                  */
  --accent: #6b4a86;   /* the parent grid's hover violet, used sparingly    */

  --rail: 200px;
  --gut: 28px;
  --pad: 40px;

  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
           Georgia, "Times New Roman", serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--sheet);
  color: var(--ink);
  font: 400 16px/1.6 var(--serif);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, canvas, iframe { display: block; max-width: 100%; }

a { color: inherit; }

/* Links in prose get a hairline, not a colour. The colour belongs to the art. */
.prose a,
a.u {
  text-decoration: none;
  border-bottom: 1px solid var(--ink-3);
  transition: border-color .15s;
}
.prose a:hover,
a.u:hover { border-color: var(--ink); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.skip {
  position: absolute; left: -9999px;
  background: var(--ink); color: var(--sheet);
  padding: 10px 16px; z-index: 100;
}
.skip:focus { left: 12px; top: 12px; }

/* ── mono voice ─────────────────────────────────────────────────────────── */

.m,
nav a, .label, .idx, .meta, .wall dt, .wall dd, .spec th, .spec td,
.caption, .rail-foot, .strip-meta, .tag, .strike-note, .cv dd i {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.label { color: var(--ink-3); }
.idx   { color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* ── the rail ───────────────────────────────────────────────────────────
   A fixed spine down the left. It holds the wordmark, the nav and the
   colophon, and its right edge is the ledger's only permanent rule.      */

.rail {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--rail);
  padding: var(--pad) 0 24px 24px;
  border-right: 1px solid var(--rule);
  background: var(--sheet);
  display: flex;
  flex-direction: column;
  gap: 34px;
  z-index: 20;
}

/* The mark is a brushed ink drawing — black on transparent, so it sits on the
   sheet the same way a LIGHT / PAPER piece does, with no frame and no plate.
   It already carries its own circle, which is why the rail no longer draws a
   registration mark under it: two circles competed. */
.wordmark {
  display: block;
  width: 116px;
  margin-left: -6px;   /* the circle's optical left edge, not its bounding box */
  text-decoration: none;
}
.wordmark img { width: 100%; height: auto; }

nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
nav a {
  text-decoration: none;
  color: var(--ink-2);
  transition: color .15s;
  display: inline-block;
}
nav a:hover { color: var(--ink); }
nav a[aria-current="page"] { color: var(--ink); }
nav a[aria-current="page"]::before {
  content: "→ ";
  margin-left: -1.4em;
}

.rail-foot { margin-top: auto; color: var(--ink-3); padding-right: 24px; }
.rail-foot a { text-decoration: none; }
.rail-foot a:hover { color: var(--ink); }

/* ── the field ──────────────────────────────────────────────────────────── */

.field {
  margin-left: var(--rail);
  padding: var(--pad) var(--pad) 120px;
}

/* Prose is set on a measure, and never on the full field width. */
.prose { max-width: 62ch; }
.prose p { margin: 0 0 1.15em; }
.prose p:last-child { margin-bottom: 0; }
.prose h2 {
  font-size: 11px;
  font-family: var(--mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 400;
  margin: 3em 0 1.1em;
}
.prose strong { font-weight: 600; }
.prose em { font-style: italic; }

.lede {
  font-size: 21px;
  line-height: 1.45;
  max-width: 34ch;
}

hr.rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 0;
}

/* ── the plate ──────────────────────────────────────────────────────────
   A work's surface. `.plate` is the sheet-ground form used by LIGHT /
   PAPER: no frame, the piece simply sits on the page. `.plate.void` is the
   aperture form used by LIGHT / SIGNAL: the ground goes to #07060a and the
   piece is a hole cut in the sheet.                                       */

.plate { position: relative; background: var(--stock); }
.plate.void { background: var(--void); }
.plate > iframe,
.plate > canvas { width: 100%; height: 100%; border: 0; }

/* Crop marks: four L's, set outside the plate's corners. Hairlines only. */
.crop { position: relative; }
.crop::before, .crop::after {
  content: "";
  position: absolute;
  width: 16px; height: 16px;
  pointer-events: none;
}
.crop::before {
  top: -7px; left: -7px;
  border-top: 1px solid var(--ink-3);
  border-left: 1px solid var(--ink-3);
}
.crop::after {
  bottom: -7px; right: -7px;
  border-bottom: 1px solid var(--ink-3);
  border-right: 1px solid var(--ink-3);
}

/* ── index: the ledger ──────────────────────────────────────────────────
   Not a card grid. Works alternate flush-left and flush-right against a
   12-column ledger at different scales, and the right-hand one bleeds off
   the viewport edge.                                                      */

.ledger { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--gut); }

.entry { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: end; }
.entry + .entry { margin-top: 130px; }

/* Four columns, not three: at three the card set a ~28ch measure and the
   description broke to four words a line. */
.entry .plate-wrap { grid-column: 1 / span 7; }
.entry .card       { grid-column: 9 / span 4; padding-bottom: 6px; }

/* The second entry mirrors, and runs to the field's right edge. */
.entry.mirror .plate-wrap {
  grid-column: 5 / span 8;
  margin-right: calc(var(--pad) * -1);
}
.entry.mirror .card { grid-column: 1 / span 4; }

.entry .plate { aspect-ratio: 3 / 2; }

.card h2 {
  font-family: var(--serif);
  font-size: 27px;
  line-height: 1.12;
  letter-spacing: -.015em;
  font-weight: 400;
  margin: 14px 0 10px;
}
.card h2 a { text-decoration: none; }
.card p { margin: 0 0 14px; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.card .meta { color: var(--ink-3); display: flex; flex-direction: column; gap: 3px; }

.enter {
  display: inline-block;
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
}
.enter:hover { color: var(--accent); border-color: var(--accent); }

/* ── work page ──────────────────────────────────────────────────────────
   The piece IS the header. Nothing is set above it. The wall label sits
   under it, as a label does.                                             */

.hero { margin: 0 calc(var(--pad) * -1); }
.hero .plate { aspect-ratio: 16 / 9; min-height: 420px; }

.strike-note {
  display: flex; justify-content: space-between; gap: 20px;
  padding: 9px var(--pad) 0;
  color: var(--ink-3);
}

/* Wall label: a two-column definition ledger, hairline separated. */
.wall {
  margin: 54px 0 0;
  display: grid;
  grid-template-columns: 132px 1fr;
  max-width: 620px;
}
.wall dt { color: var(--ink-3); padding: 11px 0; border-top: 1px solid var(--rule); }
.wall dd {
  margin: 0; padding: 11px 0; border-top: 1px solid var(--rule);
  color: var(--ink); text-transform: none; letter-spacing: .03em;
}
.wall dd:last-of-type, .wall dt:last-of-type { border-bottom: 1px solid var(--rule); }

.title-line {
  font-family: var(--serif);
  font-size: clamp(34px, 5.4vw, 62px);
  line-height: 1.02;
  letter-spacing: -.025em;
  font-weight: 400;
  margin: 40px 0 0;
}
.title-line .year { color: var(--ink-3); font-size: .38em; letter-spacing: 0; vertical-align: .55em; margin-left: .5em; }

/* Method spec table — the generative-art convention: state the sets. */
.spec { width: 100%; max-width: 720px; border-collapse: collapse; margin: 22px 0 0; }
.spec th, .spec td { text-align: left; padding: 11px 16px 11px 0; border-top: 1px solid var(--rule); vertical-align: top; }
.spec th { color: var(--ink-3); font-weight: 400; width: 132px; white-space: nowrap; }
/* These cells carry real paragraphs, not one-word values, so they get prose
   leading -- 11px mono at 1.5 is a wall. */
.spec td { text-transform: none; letter-spacing: .03em; line-height: 1.75; color: var(--ink-2); }
.spec td b { color: var(--ink); font-weight: 400; }
.spec tr:last-child th, .spec tr:last-child td { border-bottom: 1px solid var(--rule); }

/* ── contact strip ──────────────────────────────────────────────────────
   Rendered by one offscreen engine blitting into 2D canvases, exactly as
   grid.html does it. Browsers cap live WebGL contexts near 16 and silently
   drop the oldest, so a strip of live canvases would blank its own head.  */

.strip {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: 26px 20px;
  margin: 22px 0 0;
}
.strip a { text-decoration: none; display: block; }
.strip canvas {
  width: 100%; height: auto; aspect-ratio: 3 / 2;
  background: var(--stock);
  transition: opacity .2s;
}
.strip.void canvas { background: var(--void); }
.strip .pending canvas { opacity: .18; }
.strip-meta { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding-top: 7px; color: var(--ink-3); }
/* Clipped, not wrapped: `interference · ultraviolet` broke to two lines and
   pulled its cell's caption out of line with the rest of the row. */
.strip-meta b {
  font-weight: 400; color: var(--ink-2);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.strip-meta .idx { flex: none; }
.strip a:hover .strip-meta b { color: var(--accent); }

/* ── explore ────────────────────────────────────────────────────────────── */

.controls {
  display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center;
  padding: 14px 0; margin: 0 0 26px;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; z-index: 10;
  background: var(--sheet);
}
.controls label { font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.controls input[type="text"] {
  font: 11px/1.5 var(--mono);
  letter-spacing: .06em;
  padding: 6px 9px; width: 22ch;
  background: var(--stock);
  border: 1px solid var(--rule);
  color: var(--ink);
  border-radius: 0;
}
.controls input[type="text"]:focus { outline: none; border-color: var(--ink-2); }
.controls button {
  font: 11px/1.5 var(--mono);
  letter-spacing: .08em; text-transform: uppercase;
  padding: 6px 14px;
  background: var(--sheet);
  border: 1px solid var(--ink-2);
  color: var(--ink);
  border-radius: 0;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.controls button:hover:not(:disabled) { background: var(--ink); color: var(--sheet); }
.controls button:disabled { opacity: .35; cursor: default; }
.controls .status { margin-left: auto; font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }

/* ── info ───────────────────────────────────────────────────────────────── */

.cv { max-width: 720px; margin: 0; }
.cv dl { display: grid; grid-template-columns: 92px 1fr; margin: 0; }
.cv dt { font-family: var(--mono); font-size: 11px; letter-spacing: .08em; color: var(--ink-3); padding: 11px 0; border-top: 1px solid var(--rule); font-variant-numeric: tabular-nums; }
.cv dd { margin: 0; padding: 11px 0; border-top: 1px solid var(--rule); font-size: 15px; }
.cv dd i { font-style: normal; color: var(--ink-3); display: block; font-family: var(--mono); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; padding-top: 2px; }

/* An unfilled CV line is marked, not faked. */
.tbd { color: var(--ink-3); font-style: italic; }
.tbd::before {
  content: "TK";
  font-family: var(--mono); font-size: 9px; letter-spacing: .1em;
  border: 1px solid var(--ink-3); border-radius: 2px;
  padding: 1px 4px; margin-right: 9px;
  font-style: normal; vertical-align: 1px;
}

.contact-line { font-family: var(--serif); font-size: 21px; }

/* ── section heads ──────────────────────────────────────────────────────── */

.sec { margin-top: 96px; }
.sec > .label {
  display: block;
  padding-bottom: 11px;
  margin-bottom: 26px;
  border-bottom: 1px solid var(--rule);
}

footer.field-foot {
  margin: 120px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 14px;
  color: var(--ink-3);
}

/* ── responsive ─────────────────────────────────────────────────────────
   The rail lies down into a top bar. The ledger stops alternating, because
   at one column an alternation is just an inconsistency.                  */

@media (max-width: 900px) {
  :root { --pad: 20px; }

  .rail {
    position: static; width: auto; height: auto;
    flex-direction: row; align-items: center; flex-wrap: wrap;
    gap: 10px 22px;
    padding: 18px var(--pad);
    border-right: 0; border-bottom: 1px solid var(--rule);
  }
  /* Small enough to share the bar, large enough that the y's descender and the
     circle still resolve as a drawn mark rather than a smudge. */
  .wordmark { width: 54px; margin-left: -3px; }
  nav ul { flex-direction: row; flex-wrap: wrap; gap: 4px 18px; }
  nav a[aria-current="page"]::before { content: ""; margin: 0; }
  nav a[aria-current="page"] { border-bottom: 1px solid var(--ink); }
  .rail-foot { display: none; }

  .field { margin-left: 0; padding-bottom: 80px; }

  .entry .plate-wrap,
  .entry .card,
  .entry.mirror .plate-wrap,
  .entry.mirror .card { grid-column: 1 / -1; }
  .entry.mirror .plate-wrap { margin-right: 0; }
  .entry + .entry { margin-top: 84px; }
  .entry .card { padding-bottom: 0; }

  .hero .plate { aspect-ratio: 4 / 3; min-height: 0; }
  .wall { grid-template-columns: 104px 1fr; }
  .cv dl { grid-template-columns: 74px 1fr; }
  .sec { margin-top: 68px; }
  .controls { position: static; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* The works are white-ground and black-ground objects with authored palettes.
   Forcing a dark UI around them would recolour the sheet that LIGHT / PAPER
   is printed on, so this page commits to its light ground in both schemes. */
