/* The blog: one index and one post layout.
 *
 * Loaded after `tokens.css` and `base.css`, composing their classes rather than
 * redefining them. Every colour, size and space below is a token; if a rule
 * needs a number that is not one, that is a gap in the system and it gets
 * reported rather than patched here.
 *
 * The whole file is two ideas:
 *
 *   1. A prose column at `--measure`, with two things allowed to sit wider than
 *      it — the transcript figure and the ledger. They are evidence, and
 *      evidence squeezed into a reading measure stops being readable.
 *   2. Two components, reused everywhere. `.said` is what was said against what
 *      was written; `.ledger` is a two-column list of pairs. A third component
 *      is how a blog ends up with four ways to show the same comparison.
 *
 * Nothing here needs JavaScript, and nothing here reveals on scroll. The site's
 * `.reveal` is right for a marketing section arriving as you reach it and wrong
 * for an article: a paragraph that is not there until it is scrolled to cannot
 * be found with the browser's own find, and that is the one tool a reader of a
 * long page actually uses.
 */

/* ================================================================== *
 * 1. The reading grid
 *
 * Three tracks. Prose lands in the middle one and keeps the measure; a figure
 * takes all three and gets `--s-2xl` of extra room on each side. The outer
 * tracks are `minmax(0, …)`, so on a 320px phone they collapse to nothing and
 * the figure is simply the width of the text — no breakpoint, and no width at
 * which anything hangs off the side of the page.
 * ================================================================== */

.reading {
  display: grid;
  justify-content: center;
  grid-template-columns:
    [wide-start] minmax(0, var(--s-2xl))
    [text-start] min(var(--measure), 100%) [text-end]
    minmax(0, var(--s-2xl)) [wide-end];
}

.reading > * {
  grid-column: text;
}

.reading > .fig {
  grid-column: wide;
}

/* ================================================================== *
 * 2. The index
 * ================================================================== */

.blog {
  padding-block: var(--s-2xl) var(--s-4xl);
}

.blog__head {
  max-width: var(--measure);
  margin-bottom: var(--s-3xl);
}

.blog__head .h1 {
  margin-top: var(--s-s);
}

.blog__head .lede {
  margin-top: var(--s-m);
}

/* ---- 2a. The lead post ----
 *
 * The most recent post is not the first card in a list of cards. It is set as
 * the top of a front page: rules above and below, the title two steps larger
 * than anything in the archive under it, and one piece of the article itself
 * pulled out beside it. The pull is the same `.said` component the post is
 * built from, which is the whole reason the lead can be different without
 * being a second design.
 */

.lead {
  padding-block: var(--s-l) var(--s-2xl);
  border-block: 1px solid var(--paper-edge);
}

.lead__grid {
  display: grid;
  gap: var(--s-xl);
  align-items: start;
}

/* 62rem is where the standfirst still holds a comfortable measure with the pull
 * beside it. Below that the pull goes underneath, where it is a specimen rather
 * than an illustration and reads exactly as well. */
@media (min-width: 62rem) {
  .lead__grid {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--s-3xl);
  }
}

.lead__title {
  margin-top: var(--s-s);
  font-size: var(--step-3);
  line-height: 1.06;
  letter-spacing: -0.025em;
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
}

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

.lead__title a:hover {
  text-decoration: underline;
  text-decoration-color: var(--ink-faint);
}

.lead__stand {
  margin-top: var(--s-m);
  max-width: var(--measure);
  font-size: var(--step-1);
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--ink-body);
  text-wrap: pretty;
}

.lead__meta {
  margin-top: var(--s-l);
}

/* The figure's own vertical rhythm belongs to a prose column. Here it is a
 * column of the lead's grid and the grid's gap has already spaced it. */
.lead__pull .fig {
  margin-block: 0;
}

/* ---- 2b. The archive ----
 *
 * One `<section>` per year, and the year sits in a rail beside its posts once
 * there is room for one. With a single year it reads as an archive marker,
 * which is what it is; with two it is doing the grouping the reader needs.
 *
 * There is no topic filter, and that is a decision rather than an omission. On
 * a static host a `?topic=` link returns the same page it left, so a filter
 * built out of links is a control that silently does nothing — and the honest
 * alternative, one anchored section per topic, would have to compete with the
 * year grouping for the same list. The topic is printed on every entry instead,
 * where it is information and cannot be broken.
 */

.archive__year + .archive__year {
  margin-top: var(--s-3xl);
}

.archive__grid {
  display: grid;
  gap: var(--s-m);
}

@media (min-width: 52rem) {
  .archive__grid {
    grid-template-columns: minmax(5rem, 8rem) minmax(0, 1fr);
    gap: var(--s-2xl);
  }
}

/* Tabular figures so two years stacked in the rail line up digit for digit.
 *
 * --ink-quiet and not --ink-faint, which is where the eye wants it: a year is
 * a word somebody reads, and --ink-faint is 2.9:1, which does not pass even at
 * this size. The rail recedes by being small and being a number, not by being
 * pale. */
.archive__label {
  font-size: var(--step-1);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink-quiet);
  font-variant-numeric: tabular-nums;
  padding-top: var(--s-l);
}

.archive__list {
  border-top: 1px solid var(--paper-edge);
}

.entry {
  padding-block: var(--s-l);
  border-bottom: 1px solid var(--paper-edge);
}

.entry__title {
  font-size: var(--step-1);
  line-height: 1.25;
  letter-spacing: -0.012em;
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
}

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

/* Not a stretched overlay covering the whole row. It would make the standfirst
 * unselectable, and a title at this size is already a large target. */
.entry__title a:hover {
  text-decoration: underline;
  text-decoration-color: var(--ink-faint);
}

.entry__stand {
  margin-top: var(--s-xs);
  max-width: var(--measure);
  color: var(--ink-body);
  text-wrap: pretty;
}

.entry__meta {
  margin-top: var(--s-s);
}

/* ---- 2c. The meta line ----
 *
 * Date, reading time, topic. --ink-quiet is 4.9:1 on paper, so it passes as
 * body text at this size; --ink-faint would not, and it is only on the
 * separators, which nobody has to read.
 */

.meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-2xs) var(--s-xs);
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--ink-quiet);
}

.meta__sep {
  color: var(--ink-faint);
}

.meta time {
  font-variant-numeric: tabular-nums;
}

/* ================================================================== *
 * 3. The post
 * ================================================================== */

.post {
  padding-block: var(--s-2xl) var(--s-3xl);
}

.post__head {
  padding-bottom: var(--s-xl);
  border-bottom: 1px solid var(--paper-edge);
  margin-bottom: var(--s-xl);
}

.post__title {
  margin-top: var(--s-s);
  font-size: var(--step-3);
  line-height: 1.06;
  letter-spacing: -0.025em;
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
}

.post__stand {
  margin-top: var(--s-m);
  font-size: var(--step-1);
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--ink-body);
  text-wrap: pretty;
}

.post__meta {
  margin-top: var(--s-l);
}

/* ---- 3a. Body rhythm ----
 *
 * `row-gap` sets the paragraph rhythm once; the headings and figures add to it
 * rather than replacing it, so a heading always has visibly more air above it
 * than the paragraph it is separating from — which is the only thing that makes
 * a long page skimmable.
 */

.post__body {
  row-gap: var(--s-m);
  line-height: 1.7;
  color: var(--ink-body);
}

.post__body > p {
  text-wrap: pretty;
}

.post__body > h2 {
  margin-top: var(--s-xl);
  font-size: var(--step-2);
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
}

.post__body > h3 {
  margin-top: var(--s-l);
  font-size: var(--step-1);
  line-height: 1.25;
  letter-spacing: -0.012em;
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
}

.post__body strong {
  color: var(--ink);
  font-weight: 600;
}

.post__body a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--ink-faint);
  transition: text-decoration-color var(--t-fast) var(--ease);
}

.post__body a:hover {
  text-decoration-color: var(--ink);
}

/* base.css strips list markers site-wide, which is right for navigation and
 * wrong for a list in an argument. They come back here. */
.post__body > ul li {
  position: relative;
  padding-inline-start: var(--s-l);
}

.post__body > ul li::before {
  content: "\2014";
  position: absolute;
  inset-inline-start: 0;
  color: var(--ink-faint);
}

.post__body > ol {
  list-style: decimal outside;
  padding-inline-start: var(--s-l);
}

.post__body > ol li::marker {
  color: var(--ink-faint);
}

.post__body li + li {
  margin-top: var(--s-xs);
}

/* ---- 3b. The pull quote ----
 *
 * A rule and a size, and nothing else. No oversized quotation glyph: it is
 * decoration standing where emphasis belongs, and it reads as a template.
 */

.post__body > blockquote {
  margin-block: var(--s-l);
  padding-inline-start: var(--s-l);
  border-inline-start: var(--s-3xs) solid var(--paper-edge);
  font-size: var(--step-1);
  line-height: 1.45;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: pretty;
}

/* ---- 3c. Code ---- */

.post__body :not(pre) > code {
  padding: 0 var(--s-2xs);
  background-color: var(--paper-sunk);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-s);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.88em;
}

/* `pre` is `white-space: pre` and cannot wrap. base.css already gives it
 * `overflow-x: auto`, so a long prompt line scrolls inside this box and never
 * takes the page with it. */
.post__body pre {
  padding: var(--s-m) var(--s-l);
  background-color: var(--paper-sunk);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-m);
  color: var(--ink-body);
  font-family: var(--mono);
  font-size: var(--step--1);
  line-height: 1.65;
  tab-size: 2;
}

/* ================================================================== *
 * 4. Figures
 *
 * One wrapper for everything that is evidence rather than sentence: a `pre`, a
 * `.said`, a `.ledger`. The caption sits under it, the way a caption does in
 * print, and it is the one place on the page allowed to be quieter than body
 * text because it is describing something the reader is already looking at.
 * ================================================================== */

.fig {
  margin-block: var(--s-xl);
}

.fig > pre {
  margin: 0;
}

.fig__cap {
  margin-top: var(--s-s);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-quiet);
}

/* ================================================================== *
 * 5. `.said` — what was said against what was written
 *
 * The single most useful thing on this blog, so it is built once and reused in
 * every post. Stacked, not side by side, and that is deliberate: two sentences
 * are compared by reading one and then the other, and a two-column version
 * would have to break to one column on a phone anyway — at which point the site
 * has two layouts for one component and only one of them was ever looked at.
 *
 * The typeface carries the argument. What was said is machine output and is set
 * in mono on sunk paper; what was written is prose and is set in the reading
 * face on raised paper. A reader who skips every word of the labels still sees
 * which one is finished.
 * ================================================================== */

.said {
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-m);
  background-color: var(--paper-raised);
  /* So the first and last take's corners follow the box's. */
  overflow: hidden;
}

.said__take {
  padding: var(--s-m) var(--s-l);
}

.said__take + .said__take {
  border-top: 1px solid var(--paper-edge);
}

.said__take--raw {
  background-color: var(--paper-sunk);
}

.said__label {
  display: block;
  margin-bottom: var(--s-xs);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-quiet);
}

/* The one place the accent is spent on this blog. It marks the take that is
 * finished — a state of the text, which is what the accent means everywhere
 * else in this system. It is never on a heading, a rule or a link. */
.said__take--out .said__label {
  color: var(--accent-ink);
}

.said__text {
  margin: 0;
  color: var(--ink-body);
  text-wrap: pretty;
}

/* Wrapping, not scrolling. A transcript is ordinary words with no structure to
 * preserve, so a broken line costs nothing and a horizontal scrollbar inside a
 * comparison costs the comparison. `pre` is for the things that cannot wrap. */
.said__take--raw .said__text {
  font-family: var(--mono);
  font-size: 0.92em;
  line-height: 1.6;
}

.said__take--out .said__text {
  color: var(--ink);
}

/* ================================================================== *
 * 6. `.ledger` — a list of pairs
 *
 * Registers and their instructions, destinations and their defaults, three
 * transcripts and the three rewrites that used to be accepted. All the same
 * shape: a short left side and a longer right side, hairline-ruled like a
 * table in a newspaper.
 *
 * A `<dl>` and not a `<table>`, because none of these has a header row that
 * would mean anything — and because the stacked layout below 46rem keeps each
 * pair adjacent in source order, which is the thing a stacked table loses.
 * ================================================================== */

.ledger {
  border-top: 1px solid var(--ink-faint);
  border-bottom: 1px solid var(--ink-faint);
}

.ledger__row {
  display: grid;
  gap: var(--s-2xs);
  padding-block: var(--s-s);
}

.ledger__row + .ledger__row {
  border-top: 1px solid var(--paper-edge);
}

@media (min-width: 46rem) {
  .ledger__row {
    grid-template-columns: minmax(8rem, 13rem) minmax(0, 1fr);
    gap: var(--s-l);
    align-items: baseline;
  }
}

.ledger dt {
  color: var(--ink);
  font-weight: 600;
}

.ledger dd {
  margin: 0;
  color: var(--ink-body);
  text-wrap: pretty;
}

/* Both sides are machine text: a transcript beside the rewrite it produced. */
.ledger--mono dt,
.ledger--mono dd {
  font-family: var(--mono);
  font-size: 0.92em;
  line-height: 1.6;
  font-weight: 400;
}

.ledger--mono dt {
  color: var(--ink-quiet);
}

.ledger--mono dd {
  color: var(--ink);
}

/* ================================================================== *
 * 7. The foot of a post
 *
 * Two links. No share buttons, no related-posts strip, no next-and-previous
 * pager — a reader who finished the article wants either another one or the
 * thing it was about, and both of those are here.
 * ================================================================== */

.post__foot {
  margin-top: var(--s-3xl);
  padding-top: var(--s-l);
  border-top: 1px solid var(--paper-edge);
}

.post__foot p {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2xs) var(--s-s);
  font-size: var(--step--1);
  color: var(--ink-quiet);
}

.post__foot a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--ink-faint);
  transition: text-decoration-color var(--t-fast) var(--ease);
}

.post__foot a:hover {
  text-decoration-color: var(--ink);
}

/* ================================================================== *
 * 8. Print
 *
 * These are arguments, and somebody will print one to argue with it.
 * ================================================================== */

@media print {
  .masthead,
  .site-footer,
  .skip-link,
  .post__foot {
    display: none !important;
  }

  .post,
  .blog {
    padding-block: 0;
  }

  .fig,
  .said,
  .ledger__row {
    break-inside: avoid;
  }
}
