/* Southpaw Book Club
   ------------------------------------------------------------------
   A Bread and Puppet broadside. Relief printing: lino and woodblock cut
   by hand, inked unevenly, pulled onto cheap unbleached newsprint.

   The principle that drives everything below — and the thing the earlier
   sticker-wall version got backwards — is that in relief printing THE PAPER
   IS THE GROUND. Colour is ink laid on top of it, one pull of the press per
   colour, and you get two or three because that is what you can afford.
   Making the teal a full-bleed background forced every other ink to fight
   it. Here the teal is an ink again, like it is on the club's own sticker.

   Three things are therefore banned outright, because each one is a
   scrapbook device rather than a printmaking one:
     - drop shadows. A print is ink soaked into paper. It is flat.
     - rounded corners. Blocks are cut with a gouge and a knife.
     - masking tape. Nothing is stuck on. It is printed in place.

   Edges are roughened with an SVG turbulence filter rather than drawn true,
   because a carved block never gives you a straight line and the wobble is
   most of what your eye reads as "hand-made".
   ------------------------------------------------------------------ */

:root {
  /* The stock. Unbleached newsprint and a second, browner sheet. */
  --paper: #ece2cc;
  --paper-2: #ded0b0;
  --paper-3: #f4eddd;

  /* Ink is never pure black — it is a soft carbon that soaks in. */
  --ink: #1b1710;
  --ink-soft: #4a4234;

  /* The inks, straight off the club sticker. Flat fills, no gradients. */
  --pink: #da1c54;
  --pink-ink: #a8143f;
  --teal: #5fb4c6;
  --navy: #132937;
  --indigo: #3f468a;
  --mustard: #e8d171;

  --cut: 3px solid var(--ink);
  --cut-fat: 5px solid var(--ink);

  /* Broken coverage, in both directions: bare paper grinning through an
     inked area, and ink sitting unevenly on a pale one. A hand-inked block
     never lays down solid, and that is the single strongest tell that a flat
     area was pulled rather than filled by a computer. Thresholded fractal
     noise, so there is no spacing for the eye to lock onto — the earlier
     version tiled three dot lattices and read as a halftone screen, which is
     photographic reproduction and the opposite of carving. */
  --speck-light:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='340' height='340'%3E%3Cfilter id='s' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.925 0 0 0 0 0.886 0 0 0 0 0.8 2.6 0 0 0 -1.75'/%3E%3C/filter%3E%3Crect width='340' height='340' filter='url(%23s)'/%3E%3C/svg%3E");
  --speck-dark:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='340' height='340'%3E%3Cfilter id='s' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.106 0 0 0 0 0.09 0 0 0 0 0.063 2.6 0 0 0 -1.75'/%3E%3C/filter%3E%3Crect width='340' height='340' filter='url(%23s)'/%3E%3C/svg%3E");

  /* Two wood types, a tired typewriter, and a working book face.
     There is deliberately no "handwriting" face any more: a sketchy outlined
     script reads as chalk on a blackboard, and layering one under a carving
     filter fought the filter instead of helping it. The hand comes from the
     gouge, not from a font pretending to be a pen. */
  --display: "Ultra", Rockwell, "Clarendon", Georgia, serif;
  /* One wood type, used at different sizes and cases. A print shop has the
     type it has; two near-identical heavy slabs would just be two. */
  --carved: var(--display);
  --marker: var(--type);
  --type: "Special Elite", "Courier New", Courier, monospace;
  --body: "EB Garamond", Georgia, "Times New Roman", serif;
}

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

body {
  margin: 0;
  font-family: var(--body);
  font-size: 1.18rem;
  line-height: 1.55;
  color: var(--ink);
  background-color: var(--paper);
  /* Paper, not pattern. The grain is a fractal-noise field — genuinely
     random, so there is no cell to find — rather than two crossed
     repeating-gradients, which met at a fixed pitch and read as graph paper
     the moment anyone zoomed in. stitchTiles keeps the 320px tile seamless.
     Under it, the blotchy absorbency of stock with rag in it. Still no dot
     grid: halftone dots are photographic reproduction, the opposite of
     carving. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Cfilter id='g' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.106 0 0 0 0 0.09 0 0 0 0 0.063 0.55 0 0 0 -0.24'/%3E%3C/filter%3E%3Crect width='320' height='320' filter='url(%23g)'/%3E%3C/svg%3E"),
    radial-gradient(
      ellipse at 20% 30%,
      rgba(140, 120, 80, 0.09),
      transparent 60%
    ),
    radial-gradient(
      ellipse at 78% 70%,
      rgba(140, 120, 80, 0.07),
      transparent 55%
    );
  overflow-x: hidden;
}

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

a {
  color: var(--pink-ink);
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}

a:hover {
  color: var(--ink);
}

:focus-visible {
  outline: 4px solid var(--pink);
  outline-offset: 3px;
}

.wrap {
  width: min(1120px, 92vw);
  margin-inline: auto;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------------------------------------------------- the carved edge */

/* Applied to blocks and display type. The filter is defined once as inline
   SVG in base.html. Kept off body copy and off anything containing a sticky
   element — a filter makes a containing block and would strand it. */
.carved {
  filter: url(#gouge);
}

/* ---------------------------------------------------- type */

h1,
h2,
h3 {
  font-family: var(--carved);
  font-weight: 400;
  line-height: 1;
  margin: 0 0 0.4em;
  letter-spacing: 0.005em;
  color: var(--ink);
}

/* The big ones are wood type: a poster face, letterspaced tight, set solid.
   The gouge filter roughens the stems so they read as cut rather than set. */
.woodtype {
  font-family: var(--display);
  text-transform: uppercase;
  line-height: 0.92;
  letter-spacing: -0.01em;
  filter: url(#gouge);
}

/* A second pull of the press, slightly out of register. Two inks, offset by
   a couple of millimetres, which is what actually happens when you hand-feed
   a sheet. Kept small — a big offset is a graphic effect, not a misprint.

   Down and LEFT, deliberately. At 2px down-right this was indistinguishable
   from a drop shadow, which is the first thing this stylesheet bans: every
   drop shadow anyone has ever seen falls to the lower right, so the eye
   read the pink as a shadow of the black rather than as a colour that missed
   its register. No press misfeeds towards the light source. */
.misprint {
  color: var(--ink);
  text-shadow: -3px 2px 0 var(--pink);
}

.marker {
  font-family: var(--type);
  font-weight: 400;
  font-size: 0.92em;
  letter-spacing: 0.01em;
}

/* Typewritten and mimeographed: the label under the image. */
.eyebrow {
  display: inline-block;
  font-family: var(--type);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink);
  background: none;
  border-bottom: 3px solid var(--ink);
  padding: 0 0 0.25rem;
  margin: 0 0 1.2rem;
}
.eyebrow a {
  color: inherit;
}

/* A solid block of ink with the words knocked out of it — the way a lino
   block is cut when you want white letters. */
.slab {
  display: inline-block;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--display);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.2rem 0.7rem 0.28rem;
  filter: url(#gouge);
}

.slab--pink { background: var(--pink-ink); color: var(--paper); }
.slab--indigo { background: var(--indigo); color: var(--paper); }
.slab--mustard { background: var(--mustard); color: var(--ink); }
.slab--teal { background: var(--teal); color: var(--ink); }

/* Cut through a card with a knife and sprayed. */
.stencil {
  display: inline-block;
  font-family: var(--type);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.82rem;
  color: var(--ink);
  border: 3px solid var(--ink);
  padding: 0.35rem 0.9rem;
  filter: url(#gouge-fine);
}

/* ---------------------------------------------------- rules and ornament */

/* A carved bar. Thick, uneven, the full measure. */
.rule {
  height: 11px;
  background: var(--ink);
  margin: 2.2rem 0;
  filter: url(#gouge-hard);
}

.rule--thin {
  height: 4px;
}

/* A row of cut marks, the way a broadside breaks between blocks. */
.rule--dashes {
  height: 12px;
  background: repeating-linear-gradient(
    90deg,
    var(--ink) 0 26px,
    transparent 26px 40px
  );
  filter: url(#gouge-hard);
}


/* Incomplete coverage. A hand-inked block never lays down solid — the paper
   grins through in specks, which is the single strongest tell that a black
   area was printed rather than filled by a computer. */
.inky {
  position: relative;
}
.inky::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image: var(--speck-light);
}

/* ---------------------------------------------------- printed blocks */

/* What used to be a sticker is now a compartment ruled off on the sheet.
   No shadow, no radius; the edge is knife-cut and slightly out of true. */
.sticker {
  background: var(--paper-3);
  border: var(--cut-fat);
  border-radius: 0;
  padding: 1.5rem 1.6rem;
  position: relative;
  clip-path: polygon(
    0.4% 0.6%, 26% 0, 61% 1.1%, 100% 0.3%,
    99.4% 34%, 100% 71%, 99.5% 99.2%,
    72% 100%, 38% 98.9%, 0.6% 99.6%,
    0 66%, 0.7% 31%
  );
}

.sticker--navy { background: var(--navy); color: var(--paper); }
.sticker--navy a { color: var(--mustard); }
.sticker--pink { background: var(--pink-ink); color: var(--paper); }
.sticker--pink a { color: var(--mustard); }
.sticker--mustard { background: var(--mustard); color: var(--ink); }
.sticker--indigo { background: var(--indigo); color: var(--paper); }
.sticker--indigo a { color: var(--mustard); }
.sticker--teal { background: var(--teal); color: var(--ink); }

/* The deep-ink compartments — the ethos block on the front page is the
   second-largest flat colour on the site — get the same broken coverage as
   the bands. Without it they were the one place a big area of colour still
   looked poured rather than pulled. The clip-path on .sticker crops this to
   the block's own cut edge. */
.sticker--navy::after,
.sticker--pink::after,
.sticker--indigo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.38;
  background-image: var(--speck-light);
}

/* Nothing is taped on any more. The class survives so old markup doesn't
   leave a stray box, but it prints nothing. */
.tape { display: none; }

/* Hand-lettered on a banner, which is where Bread and Puppet puts words. */
.bubble {
  background: none;
  color: var(--paper);
  border: 0;
  border-radius: 0;
  padding: 0;
  font-family: var(--carved);
  font-size: clamp(1.4rem, 3.4vw, 2.1rem);
  line-height: 1.05;
  text-transform: uppercase;
  position: relative;
  display: inline-block;
  filter: url(#gouge);
}
.bubble::before,
.bubble::after {
  content: none;
}

/* ---------------------------------------------------- topic tags */

.tag {
  display: inline-block;
  font-family: var(--type);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 0.22rem 0.65rem 0.26rem;
  border: 3px solid var(--ink);
  border-radius: 0;
  text-decoration: none;
  white-space: nowrap;
  filter: url(#gouge-fine);
}

.tag--politics { background: var(--pink-ink); color: var(--paper); }
.tag--sociology { background: var(--indigo); color: var(--paper); }
.tag--nature { background: var(--mustard); color: var(--ink); }
.tag--science { background: var(--navy); color: var(--mustard); }
.tag--history { background: var(--paper-3); color: var(--ink); }

a.tag:hover {
  background: var(--ink);
  color: var(--paper);
}

a.tag[aria-current="true"] {
  background: var(--ink);
  color: var(--paper);
}

/* ---------------------------------------------------- buttons */

.btn {
  display: inline-block;
  font-family: var(--display);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: 1.05rem;
  padding: 0.5rem 1.3rem 0.55rem;
  background: var(--ink);
  color: var(--paper);
  border: 3px solid var(--ink);
  border-radius: 0;
  text-decoration: none;
  cursor: pointer;
  filter: url(#gouge-fine);
  transition: background 0.08s linear, color 0.08s linear;
}
/* The deeper pink on anything carrying cream type. The bright one is a
   3.8:1 against this paper either way round, which is under the bar for
   17px type even when it is this heavy; the deeper one makes 5.8:1. The
   bright pink stays where it is decoration — the misprint offset, the focus
   ring, the sun behind the blast. */
.btn:hover {
  background: var(--pink-ink);
  border-color: var(--pink-ink);
  color: var(--paper);
}
.btn--pink {
  background: var(--pink-ink);
  border-color: var(--pink-ink);
  color: var(--paper);
}
.btn--pink:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.btn--ghost {
  background: none;
  color: var(--ink);
}
.btn--ghost:hover {
  background: var(--ink);
  color: var(--paper);
}
.btn--danger {
  background: none;
  color: var(--pink-ink);
  border-color: var(--pink-ink);
}
.btn--danger:hover {
  background: var(--pink-ink);
  color: var(--paper);
  border-color: var(--pink-ink);
}

/* The compartment the sun sits in, ruled top and bottom. Tighter than the
   old 5rem of air on each side — a broadside is one sheet and you paid for
   all of it, so nothing gets a margin that wide. */
.burst-block {
  text-align: center;
  margin: 3rem 0;
}

/* THE BIG ONE — the way into the back catalogue. A cut sun, which is the
   most Bread and Puppet shape there is. */
.blast {
  --blast-bg: var(--ink);
  display: inline-grid;
  place-items: center;
  position: relative;
  width: 340px;
  height: 340px;
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0;
  filter: url(#gouge-hard);
}
.blast__burst,
.blast__burst-shadow {
  position: absolute;
  inset: 0;
  clip-path: polygon(
    50% 0%, 59% 14%, 71% 5%, 74% 20%, 88% 15%, 86% 30%, 100% 30%,
    92% 42%, 100% 50%, 92% 58%, 100% 70%, 86% 70%, 88% 85%, 74% 80%,
    71% 95%, 59% 86%, 50% 100%, 41% 86%, 29% 95%, 26% 80%, 12% 85%,
    14% 70%, 0% 70%, 8% 58%, 0% 50%, 8% 42%, 0% 30%, 14% 30%, 12% 15%,
    26% 20%, 29% 5%, 41% 14%
  );
}
/* Not a shadow — the pink block, printed first, then the black pulled over
   it a few millimetres out. Two runs through the press. */
.blast__burst-shadow {
  background: var(--pink);
  transform: translate(-7px, -8px) rotate(-6deg);
}
.blast__burst {
  background: var(--blast-bg);
}
.blast__label {
  position: relative;
  z-index: 2;
  font-family: var(--carved);
  color: var(--paper);
  text-transform: uppercase;
  font-size: 2.1rem;
  line-height: 1;
  letter-spacing: 0.01em;
  text-align: center;
  max-width: 66%;
}
.blast:hover .blast__burst,
.blast:focus-visible .blast__burst {
  background: var(--pink-ink);
}

/* ---------------------------------------------------- masthead */

/* The whole top of the sheet is one inked block with the title cut out of
   it, a figure standing in it, and the club's own slogan hand-lettered
   underneath. Nothing floats; it is all one pull of the press. */
.masthead {
  position: relative;
  background: var(--ink);
  color: var(--paper);
  padding: 1.6rem 0 1.2rem;
  margin-bottom: 1.8rem;
}
.masthead .wrap {
  position: relative;
  z-index: 1;
}

/* The nameplate, across the head of the sheet and ruled off underneath.
   Letterspaced wide and set smaller than the shout on purpose: this says who
   is printing, the shout says what they want, and if the name competed with
   "READ SOMETHING TRUE" the top of the page would have two things shouting
   and no hierarchy. */
.nameplate {
  font-family: var(--display);
  text-transform: uppercase;
  font-size: clamp(1.15rem, 3.1vw, 2.1rem);
  line-height: 1;
  letter-spacing: 0.06em;
  margin: 0 0 0.9rem;
  padding: 0 0 0.7rem;
  color: var(--paper);
  border-bottom: 5px solid var(--paper);
  filter: url(#gouge);
}

.masthead__top {
  display: flex;
  align-items: center;
  gap: 1.8rem;
  flex-wrap: wrap;
}

.logo {
  display: block;
  width: 168px;
  flex-shrink: 0;
  border: 5px solid var(--paper);
  border-radius: 0;
  /* Printed onto the sheet with the rest of it, not stuck on afterwards. */
  filter: url(#gouge) saturate(0.88) contrast(1.08);
}

.masthead__cry {
  margin: 0;
}

/* Cut out of the black. */
.masthead__shout {
  font-family: var(--display);
  text-transform: uppercase;
  font-size: clamp(2.2rem, 8vw, 5rem);
  line-height: 0.82;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--paper);
  filter: url(#gouge);
}

/* Nav is a printed index across the foot of the masthead. */
.scatter-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.8rem;
  align-items: center;
  margin: 1.4rem 0 0;
  padding: 0.7rem 0 0;
  list-style: none;
  border-top: 5px solid var(--paper);
}
.scatter-nav a {
  display: inline-block;
  font-family: var(--display);
  text-transform: uppercase;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--paper);
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0.1rem 0;
}
.scatter-nav a:hover,
.scatter-nav a[aria-current="page"] {
  color: var(--mustard);
  text-decoration: underline;
  text-decoration-thickness: 4px;
}

/* ---------------------------------------------------- sections */

/* Crammed. A broadside is one sheet and you paid for all of it. */
section {
  margin: 2.4rem 0;
}

/* Every section title is reversed out of a solid bar of ink, full measure.
   This is the layout device that carries the whole page: bands of black with
   the words cut out of them, and the paper doing the rest. */
.section-head {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  flex-wrap: wrap;
  margin-bottom: 1.4rem;
  background: var(--ink);
  color: var(--paper);
  padding: 0.45rem 1rem 0.55rem;
  filter: url(#gouge);
}
.section-head h2 {
  font-size: clamp(1.9rem, 6vw, 3.4rem);
  margin: 0;
  color: var(--paper);
}
/* Already inside a filtered parent — distorting twice muddies it. */
.section-head .btn {
  filter: none;
  background: var(--paper);
  color: var(--ink);
  border-color: var(--paper);
  margin-left: auto;
}
.section-head .btn:hover {
  background: var(--pink-ink);
  border-color: var(--pink-ink);
  color: var(--paper);
}

/* ---------------------------------------------------- currently reading */

.now {
  display: grid;
  grid-template-columns: minmax(200px, 300px) 1fr;
  gap: 2.5rem;
  align-items: start;
}
.now--bare {
  grid-template-columns: minmax(150px, 190px) 1fr;
  gap: 2rem;
}

.now__frame {
  position: relative;
}

.now__meta h2 {
  font-size: clamp(2.2rem, 6vw, 3.8rem);
  margin-bottom: 0.2em;
}
.now__author {
  font-family: var(--type);
  font-size: 1rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0 0 1.2rem;
}
.now__summary {
  background: none;
  border: 0;
  border-left: 9px solid var(--ink);
  border-radius: 0;
  padding: 0.2rem 0 0.2rem 1.3rem;
  max-width: 60ch;
}
.now__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  align-items: center;
  margin-top: 1.4rem;
}

/* ---------------------------------------------------- covers */

.cover {
  border: var(--cut-fat);
  border-radius: 0;
  width: 100%;
  background: var(--paper-3);
  aspect-ratio: 2 / 3;
  object-fit: cover;
  /* Knocked back so a glossy photographic jacket sits in the same world as
     the carved blocks around it. */
  filter: contrast(1.12) saturate(0.75) sepia(0.16);
}

.cover--sm {
  border-width: 3px;
}

/* Cut by hand when there is no cover to pull.

   Most of the club's books have no ISBN, so this stand-in is not the rare
   case — it is most of the back catalogue. Printed in one ink it turned the
   wall into fifteen identical crimson rectangles, which is a failure of the
   premise: a shop with one plate on the press is not what this is meant to
   look like. The ink follows the topic instead, so the wall reads as a run
   with the plates changed between pulls, and the topic is legible from across
   the page before you have read a word.

   The deeper pink, not the bright one: at 12px the author line needs 4.5:1
   and the bright pink only gives 3.8 against newsprint either way round. */
.cover-blank {
  --cover-ink: var(--pink-ink);
  --cover-paper: var(--paper);
  border: var(--cut-fat);
  border-radius: 0;
  background: var(--cover-ink);
  aspect-ratio: 2 / 3;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 1rem 1rem 1.2rem 1.5rem;
  position: relative;
  overflow: hidden;
  color: var(--cover-paper);
}
.cover-blank--politics { --cover-ink: var(--pink-ink); }
.cover-blank--sociology { --cover-ink: var(--indigo); }
.cover-blank--science { --cover-ink: var(--navy); }
.cover-blank--nature { --cover-ink: var(--mustard); --cover-paper: var(--ink); }
/* No plate at all — the bare second stock, with the type struck in black. */
.cover-blank--history { --cover-ink: var(--paper-2); --cover-paper: var(--ink); }

/* The spine. On the light stocks the black bar is the only ink on the
   board, so it carries more of it. */
.cover-blank::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 15px;
  background: var(--ink);
}
/* The same broken coverage as the inked bands. Without it this is the
   largest flat colour on the site and the only area that gives itself away
   as a fill rather than a pull. */
.cover-blank::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.4;
  background-image: var(--speck-light);
}
.cover-blank--nature::after,
.cover-blank--history::after {
  background-image: var(--speck-dark);
}

.cover-blank__title {
  font-family: var(--display);
  font-weight: 400;
  text-transform: uppercase;
  font-size: 1.2rem;
  line-height: 0.98;
  /* Ultra is a very wide face and these boards are narrow. Hyphenate first —
     a word broken at a hyphen reads as tight setting, which is what it is —
     and only snap mid-word for something that cannot fit a line on its own.
     `anywhere` would break far more eagerly than that. Before either of
     these the title was simply sliced off mid-letter by overflow:hidden,
     which reads as a bug rather than as a tight fit. */
  hyphens: auto;
  overflow-wrap: break-word;
}
.cover-blank__author {
  font-family: var(--type);
  font-size: 0.78rem;
  margin-top: 0.3rem;
  overflow-wrap: break-word;
}

/* The thumbnails on the wall are ~96px wide. Ultra needs to come down a long
   way to set more than one word on a board that size. */
.cover-blank.cover--sm {
  padding: 0.45rem 0.45rem 0.5rem 0.75rem;
}
.cover-blank.cover--sm .cover-blank__title {
  font-size: 0.54rem;
  line-height: 1.1;
  letter-spacing: -0.015em;
}
.cover-blank.cover--sm .cover-blank__author {
  font-size: 0.54rem;
  margin-top: 0.2rem;
}
.cover-blank.cover--sm::before {
  width: 9px;
}

/* ---------------------------------------------------- the back catalogue */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  align-items: center;
  margin-bottom: 2rem;
}

.wall {
  columns: 3;
  column-gap: 2rem;
}

.wall > * {
  break-inside: avoid;
  margin-bottom: 2rem;
  display: block;
}

/* Compartments ruled off on the sheet, not cards floating over it.

   The rule and the fill are both on the pseudo-element so the gouge can have
   them without touching the type inside — a filter on the card itself would
   drag the title and the cover through the displacement map too. These are
   the most repeated block on the site, and while they were drawn true they
   were the one thing on the page that gave away a straight edge. */
.book-card {
  --card-ink: transparent;
  position: relative;
  background: none;
  border: 0;
  border-radius: 0;
  padding: 1.1rem;
  text-decoration: none;
  color: var(--ink);
  transition: color 0.1s linear;
}
.book-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--card-ink);
  border: 4px solid var(--ink);
  filter: url(#gouge-fine);
  transition: background 0.1s linear;
}
/* Positioned, so they paint over the block rather than under it. */
.book-card > * {
  position: relative;
}

/* No positional tint. Every block on the wall is the same bare stock, and
   the only colour in a card is its topic — carried by the board and the tag,
   both of which mean something.

   There were two rules here that tinted every 3n+2 and every 5n+3 block, on
   the theory that it read as a planned two-colour run. It didn't. Positional
   selectors don't scatter: with fifteen books in three CSS columns, 3, 8 and
   13 all land in row three, so the "second ink" came out as a stripe across
   the page, and it restriped differently at every book count and every
   breakpoint. It also collided with the topic inks on the boards — a colour
   that means a topic sitting inside a colour that means nothing at all. */

.book-card:hover,
.book-card:focus-visible {
  --card-ink: var(--ink);
  color: var(--paper);
}
.book-card:hover .book-card__date,
.book-card:focus-visible .book-card__date {
  color: var(--paper);
}
.book-card__top {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}
/* A flex item's default min-width is auto, which means it refuses to shrink
   below its own min-content width — one long word in Ultra. On a narrow
   phone that pushed the title clean off the side of the card, hidden only by
   overflow-x on the body. This lets the column shrink; break-word below
   gives the word somewhere to go once it has. */
.book-card__top > * {
  min-width: 0;
}
.book-card__thumb {
  width: 96px;
  flex-shrink: 0;
}
.book-card h3 {
  font-size: 1.5rem;
  line-height: 0.95;
  margin: 0 0 0.2em;
  overflow-wrap: break-word;
}
.book-card__author {
  font-family: var(--type);
  font-size: 0.82rem;
  margin: 0;
}
.book-card__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  margin-top: 1rem;
  font-size: 0.85rem;
}
.book-card__date {
  font-family: var(--type);
  font-size: 0.78rem;
  color: var(--ink-soft);
}

/* The two rules that used to live here forced the stamp and the date to
   plain ink on the teal blocks, where they fell to 3.1:1 and 4.2:1. With the
   positional tints gone every card is bare stock, the stamp makes 5.8:1 and
   the date 7.7:1 everywhere, and the exception isn't needed. */

/* Where the money went. Struck on afterwards with a rubber stamp. */
.gave {
  font-family: var(--type);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: none;
  color: var(--pink-ink);
  border: 3px solid var(--pink-ink);
  border-radius: 0;
  padding: 0.12rem 0.45rem;
  display: inline-block;
  filter: url(#gouge-fine);
}

/* ---------------------------------------------------- book detail */

/* Narrower stock for a book that has nothing written up yet. The cover is a
   fixed 2:3 board roughly 400px tall, so across the full 1120px measure a
   title and an author left an L-shaped hole the height of the cover and the
   width of the page. Cut the sheet down and the two sit together instead. */
.sheet--bare {
  max-width: 44rem;
}

.detail {
  display: grid;
  grid-template-columns: minmax(180px, 270px) 1fr;
  gap: 2.5rem;
  align-items: start;
}
/* Guarded by a min-width, not left unguarded. `.sheet--bare .detail` outranks
   the single-column `.detail` in the max-900 block below on specificity, so
   without this guard the bare book page kept two columns on a phone and the
   title column — which cannot shrink below the min-content width of a word
   like OLIGARCHY in Ultra — pushed ~100px off the side of the sheet. */
@media (min-width: 901px) {
  .sheet--bare .detail {
    grid-template-columns: minmax(160px, 220px) 1fr;
    gap: 2rem;
  }
}
/* No filter anywhere up this subtree — it would break the sticky. */
.detail__side {
  position: sticky;
  top: 2rem;
}
.detail h1 {
  font-size: clamp(2.2rem, 6vw, 3.6rem);
}
.prose p {
  margin: 0 0 1rem;
  max-width: 62ch;
}

/* What people said, hand-lettered in the margin of the sheet. */
.thought {
  background: none;
  border: 0;
  border-left: 9px solid var(--ink);
  border-radius: 0;
  padding: 0.1rem 0 0.1rem 1.2rem;
  margin: 0 0 1.8rem;
}
.thought p {
  margin: 0 0 0.5rem;
  font-size: 1.28rem;
  font-style: italic;
  line-height: 1.4;
}
.thought footer {
  font-family: var(--type);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--pink-ink);
}
/* Every quote's rule is ink. It used to alternate to pink on even quotes,
   which is the same positional decoration as the old card tints: the second
   person to speak is not a different kind of thing from the first, so the
   colour was telling the reader something that isn't true. */

/* ---------------------------------------------------- charity */

/* The block on a book page saying where the money went.

   The link is optional, and the two states are meant to read as different
   kinds of thing. Without one this is a record: the club gave, here's who to,
   here's why. With one it's also an invitation, so it grows a button in the
   block's own second ink and the reader can do the same thing the club did.

   That button is the whole of it. There was a rotated PAID stamp up in the
   corner as well, on the theory that a donation leaves a receipt — but the
   block is already saying it gave money, in a heading, in wood type, and the
   stamp was a second voice saying it again with a wink. Every other mark on
   this site earns its place by carrying information. That one was costume. */
.charity h2 {
  color: var(--mustard);
  font-size: 1.8rem;
}
.charity__name {
  margin: 0 0 0.6rem;
  font-family: var(--marker);
  font-size: 1.15rem;
}
/* Specific enough to beat `.sticker--indigo a`, which paints every link on
   this block mustard — and would put mustard type on a mustard button. */
.charity a.charity__cta {
  margin-top: 1.2rem;
  background: var(--mustard);
  border-color: var(--mustard);
  color: var(--ink);
}
.charity a.charity__cta:hover {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink);
}

/* ---------------------------------------------------- haunts */

.haunts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 2rem;
}
.haunt h3 {
  font-size: 1.8rem;
  margin-bottom: 0.15em;
}
.haunt__where {
  font-family: var(--type);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pink-ink);
  margin: 0 0 0.8rem;
}
.haunt__order {
  border-top: 4px solid var(--ink);
  margin-top: 1rem;
  padding-top: 0.7rem;
  font-family: var(--type);
  font-size: 0.9rem;
  letter-spacing: 0.04em;
}
/* The label is set as a strapline over the order rather than run into it,
   so "what we get" doesn't have to be phrased as a sentence in the admin —
   whatever anybody types in that box reads right under it. */
.haunt__order-label {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 0.15rem;
}

/* A spot that has closed, set as a death notice.

   The browner stock and a struck name were not enough on their own: in a grid
   of nine near-identical blocks the difference only showed once you were
   already reading the card, which is exactly when you no longer need telling.
   So the signal is a mourning band across the head of the block — the oldest
   device in the trade for this, and the one thing on the page you can read
   from across the room.

   The other half of it is subtraction. Colour on this site means something
   live: the pink neighbourhood line, the ink of a topic. A closed spot gives
   all of that up and prints in one ink, so the wall separates into places you
   can still eat and places you can't before a word is read.

   Not greyed out, though. The club ate there, the blurb is still true, and
   the body text stays at full strength — this is a memorial, not a deletion. */
.haunt--closed {
  background-color: var(--paper-2);
  /* Room for the band, which is positioned over the top of the block. */
  padding-top: 3.5rem;
}
.haunt--closed::before {
  content: "Closed";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--type);
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 0.5rem 1.6rem 0.55rem;
}
.haunt--closed h3 {
  text-decoration: line-through;
  text-decoration-thickness: 4px;
  color: var(--ink-soft);
}
/* The neighbourhood line loses the pink with everything else. */
.haunt--closed .haunt__where {
  color: var(--ink-soft);
}
.haunt__rip {
  border-top: 4px solid var(--ink);
  margin-top: 1rem;
  padding-top: 0.7rem;
  font-family: var(--type);
  font-size: 0.9rem;
  letter-spacing: 0.04em;
}
.haunt__rip-mark {
  display: inline-block;
  background: var(--ink);
  color: var(--paper);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  padding: 0.1rem 0.4rem 0.14rem;
  margin-right: 0.4rem;
}

/* ---------------------------------------------------- reading next */

/* Picked and booked, not started. A short ruled list rather than cards: it
   is a running order, and three covers here would compete with the one book
   that is actually on the table above it. */
.upnext {
  margin-top: 3rem;
}
.upnext__list {
  list-style: none;
  margin: 0.8rem 0 0;
  padding: 0;
  border-top: 3px solid var(--ink);
}
.upnext__list li {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  padding: 0.75rem 0;
  border-bottom: 2.5px dashed var(--ink);
}
.upnext__list a {
  font-family: var(--carved);
  font-size: 1.25rem;
  text-decoration: none;
  color: var(--ink);
}
.upnext__list a:hover {
  color: var(--pink-ink);
}
.upnext__author,
.upnext__when {
  font-family: var(--type);
  font-size: 0.85rem;
  color: var(--ink-soft);
}
/* Pushed to the end of the line on anything wide enough to have an end. */
.upnext__when {
  margin-left: auto;
}

/* ---------------------------------------------------- footer */

.foot {
  background: var(--ink);
  color: var(--paper);
  margin-top: 4rem;
  padding: 2.6rem 0 2rem;
  border-top: 0;
}
.foot a {
  color: var(--mustard);
}
.foot__grid {
  display: flex;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  align-items: flex-start;
}
.foot h2 {
  color: var(--paper);
  font-size: 2.4rem;
}
.foot__mark {
  width: 110px;
  border: 4px solid var(--paper);
  border-radius: 0;
  filter: saturate(0.9);
}

/* The club's name at the foot, set as large as the measure will carry. It is
   ranged to fill the width rather than given a fixed size, because a
   nameplate at the bottom of a broadside is cut to the sheet, not to a type
   scale. Ruled off above so it reads as a signature under the notice rather
   than as another heading in it. */
.signoff {
  font-family: var(--display);
  text-transform: uppercase;
  /* Sized so it breaks to two lines and each fills the measure — SOUTHPAW
     over BOOK CLUB. Measured across 360–1920px: two lines throughout, 96–99%
     of the measure, no overflow at any width. The 10rem ceiling matters
     because .wrap stops growing at 1120px while vw doesn't, so without it the
     name runs off the sheet on a wide monitor; a hair larger and it breaks to
     three lines instead. */
  font-size: clamp(1.9rem, 12.8vw, 10rem);
  line-height: 0.9;
  letter-spacing: -0.015em;
  color: var(--paper);
  margin: 2.6rem 0 0;
  padding-top: 1.8rem;
  border-top: 5px solid var(--paper);
  filter: url(#gouge);
}

/* ---------------------------------------------------- empty states */

/* Same treatment as the book cards: the rule on a pseudo-element so the gouge
   can have it without dragging the type inside through the displacement map.
   This is a full compartment like they are, and it was the last one on the
   public side still drawn with a true edge. */
.empty {
  position: relative;
  border: 0;
  border-radius: 0;
  padding: 2rem;
  text-align: center;
  background: none;
}
.empty::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 5px solid var(--ink);
  filter: url(#gouge-fine);
}
.empty > * {
  position: relative;
}
.empty p {
  font-family: var(--display);
  text-transform: uppercase;
  font-size: 1.3rem;
  margin: 0 0 1rem;
}

/* ---------------------------------------------------- responsive */

@media (max-width: 900px) {
  .wall {
    columns: 2;
  }
  .now,
  .detail {
    grid-template-columns: 1fr;
  }
  .detail__side {
    position: static;
    max-width: 220px;
  }
  .now__frame {
    max-width: 240px;
  }
}

@media (max-width: 640px) {
  body {
    font-size: 1.1rem;
  }
  .wall {
    columns: 1;
  }
  /* A single-column card on a 360px phone has about 180px left for the title
     once the board and the gutter are paid for, which is narrower than one
     word of Ultra at 1.5rem. Give the board less and the title less, so it
     sets normally instead of falling back on break-word. */
  .book-card__thumb {
    width: 78px;
  }
  .book-card h3 {
    font-size: 1.25rem;
  }
  /* The board came down with the card, so its type has to come down too.
     Measured across the seeded catalogue at 360px: 0.42rem is the largest
     size at which no title has to break a word. It is very small, but the
     real title is set beside it at 1.25rem — this is the board, not the
     label. */
  .cover-blank.cover--sm .cover-blank__title {
    font-size: 0.42rem;
  }
  .cover-blank.cover--sm .cover-blank__author {
    font-size: 0.42rem;
  }
  .logo {
    width: 150px;
  }
  .blast {
    width: 220px;
    height: 220px;
  }
  .blast__label {
    font-size: 1.3rem;
  }
  .scatter-nav {
    gap: 0 1.1rem;
  }
  .scatter-nav a {
    font-size: 0.95rem;
  }
  /* The turbulence filters are the expensive part of this page and a phone
     is where that bites. Drop the per-element ones — including the card
     rules, which are one filter per book and so the heaviest of them on a
     long catalogue. The big blocks keep theirs so the page still reads as
     carved. */
  .tag,
  .gave,
  .btn,
  .slab,
  .book-card::before {
    filter: none;
  }
}

/* The filters are static — nothing here animates — so reduced motion only
   needs to catch transitions. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition-duration: 0.001ms !important;
  }
}


/* ---------------------------------------------------- topic marks */

/* Licensed silhouettes (see CREDITS.md), cut by the same gouge as the rules
   so they sit in the same print rather than on top of it. */
.topicmark {
  display: block;
  flex-shrink: 0;
  filter: url(#gouge-hard);
}

/* Alongside the topic filters, small enough to label rather than shout. */
.filters .topicmark {
  filter: url(#gouge-fine);
}

.topic-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

/* The one on the book page is the figure of the sheet: full size, ink, and
   it sets the topic before you have read a word. */
.detail__mark {
  margin: 1.6rem 0 0;
  display: flex;
  align-items: center;
  gap: 0.8rem;
}
.detail__mark figcaption {
  font-family: var(--type);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ---------------------------------------------------- colophon */

/* Set at the foot of the sheet under a row of cut marks: the record of the
   book in small type, the way a printed broadside signs itself off. It is
   also what stops a book with no write-up from trailing away into blank
   stock halfway down the page. */
.colophon {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2.6rem;
  margin: 0 0 1rem;
  font-family: var(--type);
}
.colophon dt {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.colophon dd {
  margin: 0.15rem 0 0;
  font-size: 0.95rem;
}

/* In the ethos block the five run as a row of marks over their names. */
.topics {
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem 2rem;
  margin-top: 1.6rem;
}
.topics figure {
  margin: 0;
  text-align: center;
  width: 5.5rem;
}
.topics figcaption {
  font-family: var(--type);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-top: 0.35rem;
}
