/* The site

   Ink on warm paper, one oxidised-brass accent, no border radius anywhere. EB
   Garamond for the argument, JetBrains Mono for every number.

   Everything vertical is a multiple of eight, and that gets the page its
   rhythm. It does not get it phase, which is the entire point of the tool, so
   the build runs Quoin against this page and writes the phase corrections to
   baseline.css. If that file is missing the page is merely rhythmic, which is
   where most well-made sites stop.

   Single visual world on purpose: this is a letterpress page and it is the same
   letterpress page in a dark room. Every colour is declared rather than
   inherited, so it holds whatever ground it lands on. */

:root {
  --pitch: 8px;

  --paper:      #EFE9DC;
  --paper-lift: #F7F3EA;
  --paper-sunk: #E5DECE;
  --ink:        #191512;
  --ink-soft:   #4A4034;
  --ink-faint:  #7C7264;
  --rule:       #D3C9B4;
  --rule-hard:  #191512;
  --brass:      #7A4A20;
  --good:       #3D6B37;
  --bad:        #A33418;

  --serif: "EB Garamond", Georgia, "Times New Roman", serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Consolas, monospace;

  /*
     33rem, not 36, and the grid picked it rather than the other way round.

     576px is twelve modules of 48 and no gutter, which is a column start rather
     than a column end, so a paragraph filling it stops halfway across a gutter.
     528 is six columns and five gutters exactly. It is also 67 characters of EB
     Garamond at 18px against 73 at the old width, which is the better of the two
     measures anyway: the grid asked for the change and typography had no
     objection.
  */
  /* The column grid this page is set on, named so the overlay can draw the
     same one the layout uses rather than a picture of one. */
  --gutter: 48px;
  --column: 144px;
  --measure: 33rem;
  --shell: 72rem;
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  /* 18/32: four grid rows of leading, and Garamond needs the room. */
  font-size: 18px;
  line-height: 32px;
  font-kerning: normal;
  font-variant-ligatures: common-ligatures;
  -webkit-font-smoothing: antialiased;
}

/* The grid, drawn over everything, off until asked for. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0;
  transition: opacity 140ms linear;
  background-image: repeating-linear-gradient(
    to bottom, rgba(122, 74, 32, 0.28) 0 1px, transparent 1px var(--pitch));
}
body.grid-on::after { opacity: 1; }

/*
   The other axis, drawn the same way.

   A baseline grid is a vertical rhythm inside a column grid and this page only
   ever showed you the vertical half. The columns are real: 1104px of shell,
   48px gutters, six columns of 144px, and 48 is six rows so the two axes are
   measured in the same unit rather than in two conventions that happen to sit
   next to each other.

   Drawn as the columns themselves rather than as lines, because a column grid
   is bands and a baseline grid is rules, and showing both as rules would make
   two different things look like one.
*/
body::before {
  content: "";
  position: fixed;
  top: 0;
  bottom: 0;
  left: 50%;
  width: min(100% - 48px, var(--shell) - 48px);
  transform: translateX(-50%);
  z-index: 89;
  pointer-events: none;
  opacity: 0;
  transition: opacity 140ms linear;
  background-image: repeating-linear-gradient(
    to right,
    rgba(122, 74, 32, 0.10) 0 var(--column),
    transparent var(--column) calc(var(--column) + var(--gutter)));
}
body.columns-on::before { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

.skip {
  position: absolute;
  left: -9999px;
  background: var(--ink);
  color: var(--paper);
  padding: 8px 16px;
  font-family: var(--mono);
  font-size: 13px;
}
.skip:focus { left: 8px; top: 8px; z-index: 100; }

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

.shell { max-width: var(--shell); margin: 0 auto; padding: 0 24px; }
.column { max-width: var(--measure); }

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

h1 {
  font-size: clamp(40px, 7vw, 72px);
  line-height: 72px;
  font-weight: 400;
  letter-spacing: -0.015em;
  margin: 0 0 24px;
  text-wrap: balance;
  max-width: 20ch;
}
h1 em { font-style: italic; color: var(--brass); }

h2 {
  font-size: 34px;
  line-height: 40px;
  font-weight: 400;
  letter-spacing: -0.01em;
  margin: 0 0 16px;
  text-wrap: balance;
  max-width: 22ch;
}

h3 {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 24px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 32px 0 8px;
  text-wrap: balance;
}

p { margin: 0 0 24px; }
p:last-child { margin-bottom: 0; }

strong { font-weight: 600; }
em { font-style: italic; }

code {
  font-family: var(--mono);
  font-size: 0.82em;
  background: var(--paper-sunk);
  padding: 1px 4px;
  /*
     Zero, so the code does not make its line taller than the line-height says.

     An inline element at a different font-size sits its baseline differently
     inside the same line box: the half-leading is (line-height minus content
     height) over two, and a smaller font has a smaller content height, so its
     baseline lands lower in its own box. Align the two baselines and the union
     of the boxes is more than either line-height.

     One pixel, on this page. It was eighteen of the nineteen paragraphs that
     were off the rhythm, against two of the forty-six that were on it, and
     nothing about the CSS looks wrong. A zero line-height on an inline
     contributes no box of its own, so the parent's strut governs the line and
     the glyphs draw exactly where they did.
  */
  line-height: 0;
}

a { color: var(--brass); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--ink); }

.kicker {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 16px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 0 0 24px;
}

.standfirst {
  font-size: 22px;
  line-height: 32px;
  color: var(--ink-soft);
  max-width: 44ch;
  margin: 0 0 40px;
}

.pull {
  font-size: 22px;
  line-height: 32px;
  border-left: 3px solid var(--brass);
  padding-left: 24px;
  margin: 32px 0;
  color: var(--ink);
}

.dim { color: var(--ink-faint); font-family: var(--mono); font-size: 11px; }

/* ---------- borders are layout ---------- */

/*
   Every rule on this page is a hairline in the vertical flow, and a hairline is
   a pixel. Six section borders plus seventeen table rows is twenty-three pixels
   of accumulated offset, and the page below them drifts by exactly that.

   This is the failure the README already documents on craighawkes.dev, where
   twenty-one 1px hairlines were one of three causes of ninety distinct drift
   values. It is also the reason the first build of this site reported itself
   seated and measured 69% on a fresh load: the corrections were computed for a
   layout one pixel taller than the one that shipped.

   So every bordered box below subtracts its border from its own padding. The
   rule stays, the box stays a whole number of grid rows, and nothing downstream
   moves. Quantise what CSS can quantise; leave the tool to do phase.
*/

.hero {
  /* 64 + content + 53 + 3px border = a whole number of rows */
  padding: 64px 0 53px;
  border-bottom: 3px solid var(--rule-hard);
}

/* ---------- the specimen demo ---------- */

/* A 1px rule on all four sides is 2px of height, so the box needs 6px of its
   own to reach the next row. Split evenly, because the panel is a frame around
   something rather than a block of text, and it should stay centred in it. */
.demo {
  border: 1px solid var(--rule-hard);
  padding: 3px 0;
  background: var(--paper-lift);
}

.demo-bar {
  display: flex;
  flex-wrap: wrap;
  /* 8px of row gap, so wrapping costs a whole number of rows rather than
     whatever the buttons happen to be tall. */
  gap: 8px 24px;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px 11px;
  border-bottom: 1px solid var(--rule-hard);
  background: var(--paper-sunk);
}
.demo-readout {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 24px;
  color: var(--ink-soft);
}
.demo-readout .dot {
  width: 8px; height: 8px; flex: none;
  background: var(--ink-faint);
}
.demo-readout .dot[data-state="bad"] { background: var(--bad); }
.demo-readout .dot[data-state="good"] { background: var(--good); }
#demoScore b { color: var(--ink); font-weight: 700; }

.demo-buttons { display: flex; gap: 8px; }
.demo-buttons button {
  font-family: var(--mono);
  font-size: 13px;
  /* 22 + 4 + 4 + two 1px borders = 32 */
  line-height: 22px;
  padding: 4px 16px;
  border: 1px solid var(--rule-hard);
  background: var(--paper-lift);
  color: var(--ink);
  cursor: pointer;
}
.demo-buttons button:hover { background: var(--paper); }
.demo-buttons button[aria-pressed="true"] { background: var(--brass); border-color: var(--brass); color: var(--paper-lift); }
.demo-buttons .primary { background: var(--ink); border-color: var(--ink); color: var(--paper-lift); }
.demo-buttons .primary:hover { background: var(--brass); border-color: var(--brass); }

#specimen {
  display: block;
  width: 100%;
  height: 640px;
  border: 0;
  background: var(--paper-lift);
}

.demo-foot {
  margin: 0;
  padding: 11px 16px 12px;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 24px;
  color: var(--ink-faint);
}

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

/* 56 + content + 55 + 1px border = 112 */
section { padding: 56px 0 55px; border-bottom: 1px solid var(--rule); }
.survey, .get { background: var(--paper-lift); }
.solve { background: var(--paper); }
.formula {
  font-family: var(--mono);
  font-size: 15px;
  line-height: 32px;
  padding: 0 0 0 24px;
  border-left: 3px solid var(--brass);
  margin: 24px 0;
}
.formula code { background: none; padding: 0; font-size: inherit; }
.findings { background: var(--ink); color: var(--paper-lift); }

.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 24px 40px;
  margin: 32px 0;
  padding-top: 7px;
  border-top: 1px solid var(--rule);
}
.split h3 { margin-top: 8px; }
.split p { margin-bottom: 0; }

/* ---------- tables ---------- */

.tablewrap { overflow-x: auto; margin: 32px 0; }
.tablewrap.tight { margin: 24px 0; }

table {
  width: 100%;
  /*
     Separate, not collapse, and it is the grid that decides it.

     Under `border-collapse: collapse` a border is centred on the edge between
     two cells, half inside each, so a cell with 24px of line, 7px of padding and
     a 1px rule renders 32.5px rather than 32. The box height stops being the sum
     of its parts, which means no arithmetic about it is safe and no tool can
     check it. Separate borders with no spacing look the same here, because only
     border-bottom is set, and they add up.
  */
  border-collapse: separate;
  border-spacing: 0;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 32px;
  font-variant-numeric: tabular-nums;
  min-width: 34rem;
}
caption {
  text-align: left;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 24px;
  color: var(--ink-faint);
  padding-bottom: 8px;
}
thead th {
  text-align: right;
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border-bottom: 2px solid var(--rule-hard);
  /* 16 + 3 + 3 + 2px border = 24.

     It was 22 + 2, which is also 24, and the row was right while none of its
     parts were: a 22px leading is not a whole number of rows and neither is a
     2px border, so the tool could only say the box was correct by accident.
     Moving six pixels out of the leading and into symmetric padding leaves the
     text in exactly the same place, to the pixel, and puts every part of the
     box on the grid rather than only their total. */
  padding: 3px 16px 3px 0;
  line-height: 16px;
}
thead th:first-child { text-align: left; }
/* 24 + 3.5 + 3.5 + 1px border = 32, so seventeen rows are 544 rather than 561.

   It was 31 + 1, which is also 32. The row was a whole number of rows and not
   one part of it was, so it held by arithmetic that no tool could confirm and
   no edit could safely touch. The seven pixels are in the padding now, split
   evenly, which leaves the text where it was: centred 15.5px down either way. */
tbody th {
  text-align: left;
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 400;
  line-height: 24px;
  padding: 3.5px 16px 3.5px 0;
  border-bottom: 1px solid var(--rule);
}
td {
  text-align: right;
  line-height: 24px;
  padding: 3.5px 16px 3.5px 0;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
/*
   The bar is drawn, not laid out.

   As an inline-block with `vertical-align: middle` it grew the line box of
   every cell it sat in: rows measured 35px against a 32px line, so every table
   put three pixels into the flow per row and the page below moved. Absolute
   positioning takes it out of the line entirely, and the cell keeps its height.
*/
td { position: relative; }
td i {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 6px;
  background: var(--brass);
  opacity: 0.45;
  min-width: 2px;
  pointer-events: none;
}
.ok { color: var(--good); font-weight: 700; }
.bad { color: var(--bad); font-weight: 700; }
/* 16 + 3.5 + 3.5 + 1px border = 24, the same total the 23 + 1 came to and the
   same centre, with every part of it on the grid instead of only the sum. */
table.compact tbody th, table.compact td {
  line-height: 16px;
  padding: 3.5px 16px 3.5px 0;
}
table.compact tbody th { font-size: 15px; }

/* ---------- findings, on ink ---------- */

.findings h2, .findings h3 { color: var(--paper-lift); }
.findings p { color: #C9BFB0; }
.findings code { background: rgba(247, 243, 234, 0.10); color: var(--paper-lift); }

/*
   48, not 40, and it is the horizontal half of the same argument.

   The shell is 1104px of content. Divided by a 40px gutter it comes to 341.33px
   at three columns and 150.67 at six, so every division after the first sits on
   a fraction and nothing downstream can recover it. A 48px gutter divides it
   whole at two, three, four and six: 528, 336, 240, 144.

   It is also six rows, which is the point. The vertical rhythm and the
   horizontal module were two separate conventions in this stylesheet and there
   was no reason for them to be.
*/
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: 48px;
  margin-top: 40px;
}
.cards article { border-top: 2px solid var(--brass); padding-top: 14px; }
.cardkick {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #C08B54 !important;
  margin: 0 0 8px;
  line-height: 16px;
}
.cards h3 {
  font-family: var(--serif);
  font-size: 22px;
  line-height: 32px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--paper-lift);
  margin: 0 0 16px;
}
.cards p { font-size: 16px; line-height: 24px; }
.cardnote { font-size: 14px !important; line-height: 24px; color: #9A9084 !important; }

.figures {
  margin: 16px 0;
  /* 7 + 7 + two 1px borders = 16 */
  padding: 7px 0;
  border-top: 1px solid rgba(247, 243, 234, 0.14);
  border-bottom: 1px solid rgba(247, 243, 234, 0.14);
}
/*
   These rows rewrapped between one viewport and the next, which changed their
   height and moved everything under them. Held on one line, with the label
   allowed to shrink, so the block is the same number of rows at every width.
*/
.figures div {
  display: flex;
  flex-wrap: nowrap;
  align-items: baseline;
  gap: 8px;
  line-height: 24px;
}
.figures dt {
  font-family: var(--mono);
  font-size: 11px;
  color: #9A9084;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.figures dd { flex: none; }
.figures dd {
  margin: 0;
  font-family: var(--mono);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--paper-lift);
}
.figures dd.dim { font-size: 11px; color: #7F776C; }
.findings .ok { color: #7FBF74; }
.findings .bad { color: #E07A5F; }

/* ---------- ways in ---------- */

.ways {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 48px;
  margin: 32px 0 40px;
}
.ways article { border-top: 2px solid var(--rule-hard); padding-top: 14px; }
.ways h3 { margin-top: 0; }
.ways p { font-size: 16px; line-height: 24px; margin-bottom: 0; }
pre {
  margin: 0 0 16px;
  padding: 12px 16px;
  background: var(--ink);
  color: var(--paper-lift);
  overflow-x: auto;
}
pre code {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 24px;
  background: none;
  padding: 0;
  color: inherit;
  white-space: pre;
}

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

footer { padding: 56px 0 64px; background: var(--paper); }
.footgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 48px;
  padding-top: 5px;
  border-top: 3px solid var(--rule-hard);
}
.footkick {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 8px;
  line-height: 24px;
}
.live {
  font-family: var(--mono);
  font-size: 24px;
  line-height: 32px;
  color: var(--brass);
  margin: 0 0 8px;
  font-variant-numeric: tabular-nums;
}
.footnote { font-size: 14px; line-height: 24px; color: var(--ink-faint); margin: 0 0 8px; }
footer ul { margin: 0; padding: 0; list-style: none; }
footer li { font-size: 16px; line-height: 32px; }
footer ul.plain li {
  font-size: 14px;
  line-height: 24px;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.link {
  font: inherit;
  font-size: 14px;
  background: none;
  border: 0;
  padding: 0;
  color: var(--brass);
  border-bottom: 1px solid currentColor;
  cursor: pointer;
}
.link:hover { color: var(--ink); }
.colophon {
  margin: 40px 0 0;
  padding-top: 7px;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 24px;
  color: var(--ink-faint);
}

/* ---------- narrow ---------- */

@media (max-width: 40rem) {
  body { font-size: 17px; line-height: 32px; }
  .hero { padding: 40px 0 32px; }
  h1 { line-height: 48px; }
  #specimen { height: 520px; }
  .standfirst { font-size: 19px; }
}
