/* the Periodic (web) — layout and register.
 *
 * The geometry is A4 and the risky part; the faces are A0.3/A6. The
 * remaining A6 work is the finer typographic detail (old-style figures,
 * the band and slug devices from grid.tex), not the type itself.
 *
 * The rule this file exists to enforce: NOTHING SCALES AN IMAGE. Every
 * width and height arrives from the server as an explicit pixel value
 * computed in whole units. No percentages, no `max-width: 100%`, no
 * `object-fit`, no `width: auto` on a dithered <img> — each of those
 * would put a 1-bit pattern on a fractional box and average its dots to
 * grey. The field does not reflow; it snaps between unit steps and lets
 * the outer margins take the slack.
 */

:root {
  --paper: #e5e1d5;
  --ink: #1b1813;
  --red: #8c2f1f;
  --hair: #c9c3b4;

  /* The margin the measure is capped against in page view. */
  --gap: 16px;

  /* Device pixel ratio, for plate view, where the measure is
     PLATE_PX/--dpr and one dither pixel must land on exactly one device
     pixel. Read from resolution media queries rather than JS so there is
     no first-paint reflow. A screen at a fractional ratio (1.5, 2.5)
     lands on the nearest whole step and resamples slightly; nothing on
     the market is exactly 300dpi anyway, and page view is unaffected. */
  --dpr: 1;

  /* --u and --measure are set per-response in an inline <style>: they
     depend on the view, not on the viewport. */
}

@media (min-resolution: 1.5dppx) {
  :root {
    --dpr: 2;
  }
}

@media (min-resolution: 2.5dppx) {
  :root {
    --dpr: 3;
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'EB Garamond', Georgia, 'Times New Roman', serif;
  /* Old-style figures, as the print system sets them. */
  font-variant-numeric: oldstyle-nums;
  /* The one horizontal rule: the field never scrolls sideways. If a row
     ever overflows the measure this clips it, and the smoke test that
     asserts documentElement.scrollWidth === clientWidth catches it. */
  overflow-x: hidden;
}

.tech {
  /* The technical register: labels, folios, figure numbers, vote
     controls. Jost* stands in for the print system's Futura. */
  font-family: 'Jost', 'Futura', 'Century Gothic', system-ui, sans-serif;
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--red);
}

/* ── chrome ──────────────────────────────────────────────────────── */

.head {
  margin: 0 auto;
  padding: 24px 0 8px;
}

.head h1 {
  /* The masthead. Bodoni Moda at 900 italic stands in for the cover's
     lead Bodoni Ultra Italic — the heaviest free face at this cut, and
     still lighter than the metal. */
  font-family: 'Bodoni Moda', 'Bodoni 72', Didot, serif;
  font-size: 34px;
  font-style: italic;
  font-weight: 900;
  letter-spacing: -0.01em;
  margin: 0 0 4px;
}

.head p {
  margin: 0 0 10px;
}

/* \gticks — one tick per unit, all 58. Absolutely positioned at exact
   unit multiples, so a misaligned ruler is a visible symptom of a
   miscomputed measure rather than a silent one. */
.ticks {
  position: relative;
  height: max(6px, calc(var(--u) / 2));
  border-bottom: 1px solid var(--hair);
  margin-bottom: 18px;
}

.ticks i {
  position: absolute;
  bottom: 0;
  width: 1px;
  height: 4px;
  background: var(--hair);
}

.ticks i:nth-child(10n + 1) {
  height: 100%;
  background: var(--red);
}

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

.field {
  margin: 0 auto;
}

.row {
  display: flex;
  /* gap is emitted inline as exactly 2 × unit — the grid's gutter. */
  margin-bottom: calc(var(--u) * 2);
}

.cell {
  /* THE CLIP. A cell is a fixed box and its image is taller than it; the
     overflow is the crop. This is the line that lets ONE PLATE PER SPAN
     serve every row height that span appears in. */
  overflow: hidden;
  position: relative;
  flex: 0 0 auto;
  display: block;
}

.cell.img img {
  display: block;
  max-width: none;

  /* PAGE VIEW SCALES, AND THAT IS THE POINT. The plate is 1312px across
     the measure; a screen has 420-1260 device pixels there. Letting the
     browser downscale the full plate reads better at page size than
     anything else on the table — measurably better than a 1-bit dither
     recomputed at screen size, which puts a 300dpi dot at 1.56x too
     coarse for the picture it describes. `auto` is deliberate: with
     `pixelated` the same downscale becomes nearest-neighbour and drops
     one dot row in three. */
  image-rendering: auto;
  /* Drops the dither's pure white onto the newsprint ground, so the
     pattern sits on paper rather than in a white box. Exact for white,
     and it needs no change to the PNGs. */
  mix-blend-mode: multiply;
}

/* PLATE VIEW IS 1:1. The measure is PLATE_PX/--dpr CSS px, so one dither
   pixel is exactly one device pixel and no resampling happens at all.
   `pixelated` is the belt to that braces: it stops a rounding error of a
   fraction of a pixel from being smoothed into grey. This is where the
   integer-zoom rule the whole design rests on is actually honoured —
   page view answers "how does this read", this answers "what is this
   dot doing". */
[data-view='plate'] .cell.img img {
  image-rendering: pixelated;
}

/* A4 placeholder: a labelled block standing in for a render that does
   not exist yet, so the layout is checkable before the bulk job runs. */
.cell.ph {
  border: 1px solid var(--hair);
  background: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 6px,
    rgba(27, 24, 19, 0.05) 6px,
    rgba(27, 24, 19, 0.05) 12px
  );
  display: flex;
  align-items: center;
  justify-content: center;
}

.cell.txt {
  color: inherit;
  text-decoration: none;
  border-top: 1px solid var(--ink);
  padding-top: 6px;
}

.txt-inner {
  font-size: 15px;
  line-height: 1.45;
  /* Prose and captions are the reading face; headings would be Cormorant,
     which enters with the section devices in A6. */
  font-family: 'EB Garamond', Georgia, serif;
}

.cell.title .txt-inner {
  /* Title candidates are set as the masthead is — they are competing to
     BE one. */
  font-family: 'Bodoni Moda', 'Bodoni 72', Didot, serif;
  font-size: calc(var(--u) * 1.6);
  line-height: 1.05;
  font-style: italic;
  font-weight: 900;
}

.cell.short .txt-inner {
  font-size: 14px;
}

#sentinel {
  height: 1px;
}
