/* ============================================================
   Frank Ray — "Paper" design system  (PRIMARY)
   The site's only stylesheet. Authored as handoff/paper.css in the design
   project, dropped wholesale over static/assets/paper.css in the website
   repo. No parent theme, no child theme, no second copy.
   The wordmark is "Frank Ray" (see hugo.toml). The retired trading name of
   the closed Ltd company must not appear anywhere that publishes, and that
   includes this file: static/ ships verbatim, so a comment here is served
   text on the live site.

   SCOPE: this file is styling only. Rules about Markdown front matter, Go
   templates or which pages carry what belong in the website repo. A
   documentation block that both sides edit can only
   churn, because this file lands wholesale — one such block was restored
   three times before the boundary was drawn.
   Styling only — no markup or template structure changes.
   Dark alternative: ink.css (do not load both).
   ============================================================ */

/* ---------- 1. Tokens ---------- */
:root {
  --bg:            #FAF8F4;
  --paper:         #FAF8F4;   /* alias, for light-on-ink contexts */
  --ink:           #17150F;   /* masthead band + footer */
  --surface:       #F3EFE7;
  --surface-hover: #EFE9DE;
  --row-hover:     #F5F1EA;
  --rule:          #E4DED3;
  --rule-strong:   #CFC7B8;
  --field:         #FFFFFF;

  --heading:       #17150F;
  --lead:          #3F3A32;
  --body:          #2E2B26;
  --muted:         #55504A;
  --meta:          #6B665C;   /* small caps labels, dates, rail items — AA on paper AND on --surface */
  --faint:         #8C877C;   /* ONLY on --ink. Fails AA on paper (3.37:1) and on --surface (3.12:1) */

  --accent:        #7A5C24;   /* bronze — AA on paper, unlike brass */
  --accent-dark:   #5E4519;
  --accent-soft:   #A08758;   /* decorative marks only, never text */
  --accent-faint:  rgba(122, 92, 36, 0.38);
  --accent-dim:    rgba(122, 92, 36, 0.24);

  /* The "… fallback" families are metric-overridden faces (size-adjust /
     ascent-override over a local system font) that stop the swap from resizing
     text. They are DECLARED IN fonts.css, which the design project never
     overwrites — only these names live here, so a paper.css drop can't remove
     them. If a name resolves to nothing the browser skips to the next entry. */
  --serif: "Source Serif 4", "Source Serif 4 fallback", Georgia, "Times New Roman", serif;
  --sans:  "Source Sans 3", "Source Sans 3 fallback", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono:  "IBM Plex Mono", ui-monospace, "SFMono-Regular", Consolas, monospace;

  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 18px;
  --s-5: 26px; --s-6: 34px; --s-7: 48px; --s-8: 64px; --s-9: 96px;

  --measure: 36em;
  /* One gutter for the whole page: .wrap uses it, and the phone masthead rows
     use it too, so header text never leaves the grid main and the footer are on. */
  --gutter: clamp(22px, 5vw, 72px);
  --shell:   1180px;
}

/* ---------- 2. Page shell ---------- */
/* Border-box everywhere. Without it --shell (1180px) is the CONTENT width, so the
   shell renders 1324px wide and every page sits 72px left of the reference. */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--body);
  font-family: var(--sans);
  font-size: 17.5px;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;

  /* Sticky footer, part 1. Short pages (Contact especially) must still put the
     ink footer at the bottom of the window — never leave paper below it.
     dvh tracks the collapsing browser chrome on iOS; vh is the fallback. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* Sticky footer, part 2. The flex chain must reach the footer. If the theme wraps
   header/main/footer in a single element, that element becomes the column instead;
   applying this to both is harmless when only one exists. */
body > .site,
body > #page,
body > .site-wrapper {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Belt and braces: nothing in this design scrolls sideways. */
html { overflow-x: hidden; }

/* Part 3. main absorbs the slack; the footer never shrinks.
   60px from the nav rule to the H1 cap — measured off reference 02, where the rule
   sits at y=152 and the H1 cap top at y=212. Inline padding comes from .wrap. */
body > main,
body > .site > main,
body > #page > main,
body > .site-wrapper > main,
main.site-main {
  flex: 1 0 auto;
  padding-block: 52px 0;
}

.site-footer { flex-shrink: 0; margin-top: 46px; }

@media (max-width: 767px) {
  body > main,
  body > .site > main,
  body > #page > main,
  body > .site-wrapper > main,
  main.site-main { padding-block: 34px 0; }
  .site-footer { margin-top: 34px; }
}

/* ONE SHELL, ONE LEFT EDGE.
   An earlier revision fitted the shell to each page type so a narrow page would
   centre with equal gutters. It was wrong: the chrome cannot narrow with it (the
   nav wraps below ~980px), so a fitted page reads as INDENTED against a nav that
   stayed put — worse than the empty right it was meant to cure. The shell is one
   width everywhere and content starts on the gutter; where a page has no right
   column, the space to its right is margin. */

/* Match to the parent theme's wrapper if these selectors differ. */
.site, #site-content, .site-inner, .wrap {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* The 660px text column. The WordPress theme constrained the content area; Hugo's
   <main class="site-main"><div class="wrap"> does not, so h2 rules and tables would
   run the full 1036px shell while paragraphs stopped at the measure. Cap the
   article instead of every child. LEFT-ALIGNED TO THE GUTTER, everywhere, with no
   exceptions: the masthead wordmark, the nav row and the footer columns all start
   on that line, and a centred measure abandons it — the page reads as two
   unrelated layouts stacked. The measure narrows from the right. */
article.page { max-width: 660px; }

::selection { background: #EADFC6; color: var(--heading); }

/* ---------- 3. Headings ---------- */
h1, h2, h3, h4, h5, h6 { font-family: var(--serif); color: var(--heading); text-wrap: pretty; }

/* FIXED SIZES PER BREAKPOINT, NOT A CLAMP.
   A clamp ties the heading to viewport width while the space around it stays fixed, so
   the same page rendered in two window widths gives two different type-to-space ratios
   — two identical posts read as differently spaced, which is what surfaced this. It
   also lands on the design's numbers at exactly one width: at 1440px the old
   clamp(32px, 4.2vw, 46px) resolved to 46px correctly, but at 834px it gave 35px where
   the design draws 42px.
   The design states three sizes and three only: 46 / 42 / 32. Stepping them at the
   breakpoints makes every window inside a step render identically, which is the
   property that was missing. */
h1 {
  font-weight: 600;
  font-size: 46px;
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin: 0 0 var(--s-4);
}

/* 29 / 27 / 24 per the design, stepped at the breakpoints (see h1 above for why not a
   clamp). The old clamp(25px, 2.5vw, 29px) hit 29px only above ~1160px and fell to its
   25px floor for the whole tablet range, where the design draws 27px.
   margin-top stays at 64px. The design draws 18–48px depending on page type; 64px is a
   deliberate divergence, reviewed on 10 Aug and kept — it is uniform, it reads well,
   and nothing about the built site argues for changing every section break on every
   page to match a number in a file. Do not "correct" it. */
h2 {
  font-weight: 600;
  font-size: 29px;
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: var(--s-8) 0 var(--s-4);
  padding-top: 30px;
  border-top: 1px solid var(--rule);
}

/* 21px, not 19. A sub-label (§17) is serif 18px/600 — at 19px an H3 was the same
   mark, so a section heading and the first item under it read as a matched pair of
   bold lines rather than a heading and its content. 21px sits clearly above the
   sub-label and clearly below h2's 25px.
   And it owns its own space: 34px above, 12px below. The old 4px bottom was tuned
   for an H3 running straight into a paragraph, which is fine when the paragraph is
   body text and collides when the next thing is another bold serif line. */
h3 { font-size: 21px; font-weight: 600; line-height: 1.35; margin: var(--s-6) 0 var(--s-3); }

/* Existing content wraps some headings in <strong> — neutralise it */
h1 strong, h2 strong, h3 strong { font-weight: inherit; }

/* The page's own <hr> separators are redundant once h2 carries a rule. */
.entry-content hr { border: 0; border-top: 1px solid var(--rule); margin: var(--s-7) 0; }
/* A rule immediately before a heading is WordPress conversion residue: some posts
   carry a 72-dash break before every "##" and some carry none, which is an authoring
   accident, not an intention. It used to CHANGE THE LAYOUT — the hr supplied the line
   at 48px above and below and the heading dropped its own rule, so a post with the
   residue broke evenly and a post without it broke 64/30. Same markup, two geometries,
   decided by whether the converter left dashes behind.
   Hiding it lets the heading draw its own rule in every case, so the break is the same
   whatever the Markdown happens to contain. Scoped to h2 only: an hr before an h3 is
   more likely to be intentional, since h3 draws no rule of its own. */
.entry-content hr:has(+ h2) { display: none; }

/* Two hairlines never stack. A block that already ends on a rule — row group,
   table, list, card stack — makes the following h2 drop its own. The heading
   yields; never open the bottom of a list to suit the next heading. */
/* The line is borrowed, the air is not. A normal h2 opens with 64px above its
   rule and 30px below it; a block that ends on a hairline only gives 18px of row
   padding above, so the heading has to carry the section's air on its own side —
   hence s-8 below the borrowed line, not s-6. */
.entry-content :is(ul, ol, table, dl, .index-list, .card-list, .rows) + h2 {
  border-top: 0;
  padding-top: 0;
  margin-top: var(--s-8);
}

/* ---------- 4. Body copy ---------- */
p, ul, ol, blockquote, figure { max-width: var(--measure); }
p { margin: 0 0 var(--s-4); text-wrap: pretty; }

p.lead {
  font-family: var(--serif);
  /* Stepped at the breakpoints in § 16b, not clamped. Design: 22 / 21 / 19. */
  font-size: 22px;
  line-height: 1.5;
  font-weight: 400;
  color: var(--lead);
  margin-bottom: var(--s-5);
}

strong, b { color: var(--heading); font-weight: 600; }
small { font-size: 13.5px; color: var(--meta); }

/* ---------- 5. Links: quiet in body, bronze only on hover/focus ---------- */
.entry-content a, .page-content a, .widget a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--accent-faint);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color 120ms linear, text-decoration-color 120ms linear;
}
.entry-content a:hover, .page-content a:hover, .widget a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}
.entry-content a:visited, .page-content a:visited {
  color: #4A463F;
  text-decoration-color: var(--accent-dim);
}
a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; text-decoration: none; }

/* Structural links never underline */
.site-header a, .site-footer a, .main-menu a, .nav a,
.post-list a, .card, a.card, .pagination a, .toc a,
.index-row, a.index-row, .blog-list a, .post-nav a, .book-chapters a { text-decoration: none; }

/* ---------- 6. Lists ---------- */
/* 22px below a list, per the design — not the 34px section step. A list is part of the
   thought that introduced it, and its sub-label sits only 14px above it; at 34px below,
   the list floated closer to what it introduced than to what followed and the whole
   block read lopsided. */
ul, ol { margin: 0 0 22px; padding: 0; list-style: none; }
/* 5px, not 11. List items are short scannable units, and 1.65 line-height already
   puts 28px between baselines — an 11px margin on top of that made a five-item list
   read as five separate paragraphs. The gap still has to exceed nothing: at 5px the
   between-item distance is 33px against 28px within a wrapped item, so a two-line
   item still groups as one thing. Do not go below 4px or that inverts. */
/* 17px, per the design. Until now no font-size was set on a list item ANYWHERE in this
   sheet at any width, so items silently inherited body copy at 17.5px — half a pixel out
   on desktop and tablet, and a pixel and a half out on phone, where the design draws 16px.
   The handbook chapters are largely lists, so this was not a rounding error there. */
ul li, ol li { margin: 0 0 5px; line-height: 1.65; font-size: 17px; }

/* Hanging indent, NOT grid. A grid container turns every child into a grid item,
   so an <li> containing a link, an <em> or a bare text node auto-places those
   fragments into the 16px marker column and the item collapses to one word per
   line. A list item is a run of inline content and must stay in normal flow —
   the marker hangs beside it, absolutely positioned out of that flow. */
ul li { position: relative; padding-left: 26px; }
ul li::before {
  content: "—";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--accent-soft);
  font-size: 14px;
  line-height: 1.9;
}
ul li > ul { margin: 5px 0 0; }

/* Numbered steps: plain serif numerals, no boxes */
ol { counter-reset: step; }
ol li {
  counter-increment: step;
  position: relative;
  padding-left: 44px;
  margin-bottom: 14px;
}
/* Stepped lists (numeral + serif title + description) need the wider gap; a plain
   numbered sequence does not. */
ol li:has(> strong:first-child) { margin-bottom: var(--s-5); }
/* Out in the margin and right-aligned against the text edge, so 1 and 101 hang on
   the same line — in normal flow the numeral butts straight against the item. */
ol li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 30px;
  text-align: right;
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.35;
  color: var(--accent-soft);
}
/* Term lists: a bold term on its own line with the description beneath. OPT-IN
   via {.terms} on the list — the positional version was wrong for the same reason
   the positional run-in was: :first-child counts ELEMENT children, so in
   "The <strong>code reviewer</strong> anchored to…" the strong still matches and
   the item breaks into three lines. No selector can see the preceding text node,
   so the author has to say which lists are term lists. */
.terms > li > strong:first-child,
ol.terms > li > strong:first-child {
  display: block;
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 2px;
}

/* ---------- 7. Blockquote, code ---------- */
blockquote {
  margin: 0 0 var(--s-6);
  padding: 2px 0 2px var(--s-5);
  border-left: 1px solid var(--accent-soft);
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.55;
  font-style: italic;
  color: var(--lead);
}
code, kbd, pre { font-family: var(--mono); font-size: 0.9em; }
code { background: var(--surface); border: 1px solid var(--rule); padding: 1px 5px; }
pre {
  background: var(--surface);
  border: 1px solid var(--rule);
  padding: var(--s-4);
  overflow-x: auto;
  max-width: none;
  line-height: 1.6;
}
pre code { background: none; border: 0; padding: 0; }

/* ---------- 8. Tables ---------- */
table { width: 100%; max-width: none; border-collapse: collapse; margin: 0 0 var(--s-6); }
th {
  text-align: left;
  padding: 0 var(--s-3) 9px 0;
  border-bottom: 1px solid var(--rule-strong);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--meta);
}
/* Top, never middle. Cells are prose of unequal length — a two-line label beside
   a one-line value centres that value against nothing and the row reads as a
   drawing error.
   Alignment between the two columns is done with a shared ABSOLUTE line-height
   (§ table.rows), not with padding. A unitless line-height multiplies by each
   cell's own font-size, so a 17px label and an 18px value get different line
   boxes, different half-leading, and first baselines about a pixel apart; the
   label column then used to carry 3px of extra padding-top to compensate. That
   compensation was tuned when the label was 15px and went stale when it became
   17px, leaving the label sitting ~2px low down every row of a nine-row table.
   An absolute line-height gives both cells the same box from the same top edge,
   so the baselines agree whatever the sizes are and nothing needs re-tuning. */
td {
  padding: 13px var(--s-3) 13px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 16.5px;
  color: var(--heading);
  vertical-align: top;
}
td + td { color: var(--muted); }
/* Figures right-align; prose must not. A label/value table's second column is
   prose ("First Class B.Eng (Hons)") and reads wrong flush right, so alignment is
   opt-in — Markdown emits no classes, so rate tables come in as raw HTML or with
   an attribute list. */
td.figure, th.figure,
table.rates td + td, table.rates th + th { text-align: right; padding-right: 0; }
td.figure, table.rates td + td { font-variant-numeric: tabular-nums; }

/* Two table types, per the design — and only two.
   1: label/value — asymmetric, fixed 200px label column (130px on Contact via
   .rows--tight), no header row, no fill. Goldmark REQUIRES a header row in pipe
   tables, so write that row empty and it is hidden here. */
table.rows thead { display: none; }
/* Ruling (DESIGN-CSS-NEEDED §5): the caps meta label is the CONTACT treatment, not
   the label/value treatment. Fees (03) and About (08) draw dark sentence-case bold
   at body size, so that is the base; .rows--tight carries the caps. */
table.rows td:first-child {
  width: 200px;
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--heading);
  vertical-align: top;
}
/* The shared box both columns align from. 28px reads as 1.56 on the 18px value —
   the tighter setting a two-column table wants — and as 1.65 on the 17px label. */
table.rows td { line-height: 28px; }
table.rows td + td { font-size: 18px; color: var(--heading); }
table.rows--tight td:first-child {
  width: 130px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--meta);
}

/* Label/value tables stack on phone: label above value as a caps line. */
@media (max-width: 767px) {
  table.rows, table.rows tbody, table.rows tr, table.rows td { display: block; width: auto; }
  table.rows tr { padding: 13px 0; border-bottom: 1px solid var(--rule); }
  table.rows td { border: 0; padding: 0; }
  table.rows td:first-child { padding-top: 0; margin-bottom: 3px; }
  table.rows td + td { font-size: 17px; }
}

/* 2: comparison — symmetric 1fr 1fr, shaded header row on --rule-strong hairlines,
   everything ending on the measure (no negative-margin bleed). */
table.compare { table-layout: fixed; max-width: var(--measure); }
table.compare th {
  background: var(--surface);
  padding: 9px 12px;
  border-top: 1px solid var(--rule-strong);
  border-bottom: 1px solid var(--rule-strong);
}
/* Body size, 17.5px. It was 16.5 — invented, like every table size here: the design
   file contains no <td> at all, because every table on the site is markup Hugo
   generates from Markdown and the design drew its comparisons as flex divs. There is
   no reason for a comparison cell to be smaller than the prose around it, and three
   different sizes for table text (16.5 compare / 17.5 body / 18 label-value) was two
   too many. */
table.compare td { padding: 13px 12px; text-align: left; font-size: 17.5px; }
/* The body cells sit at 0 — no fill behind them, so their text belongs exactly where
   every other paragraph's text begins. The shaded header cell takes 2px, an optical
   inset so the caps do not touch the fill's boundary.
   2px on the LABEL, not a bleed on the fill: the fill is the visible element and it
   keeps the shared left edge the masthead, nav and body all share. Moving the band left
   to protect the alignment of an 11px caps label — which is what an earlier version of
   this did — moves the wrong thing. At 0.12em letter-spacing a 2px shift is invisible;
   a 12px band offset is not. */
table.compare td:first-child { padding-left: 0; }
table.compare th:first-child { padding-left: 2px; }
/* Ruling (§6): a briefing table with a meaningful header but a one-word label
   column is still a comparison — it keeps the shaded header and takes the 200px
   label column instead of 1fr 1fr. Add .compare--label to those two tables. */
table.compare--label { table-layout: auto; }
table.compare--label th:first-child, table.compare--label td:first-child {
  width: 200px;
  font-weight: 600;
  color: var(--heading);
}
/* Three-column compare tables (Appendix B) size to content rather than thirds; a
   header cell there carries a <br /> from the export and must not be clipped. */
table.compare th { hyphens: none; }

/* ---------- 9. Buttons: ink-black, accent stays a link colour ---------- */
.button, button, input[type="submit"], .wp-block-button__link {
  display: inline-block;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--bg);
  background: var(--heading);
  border: 1px solid var(--heading);
  border-radius: 0;
  padding: 12px 22px;
  text-decoration: none;
  cursor: pointer;
  transition: background 120ms linear, border-color 120ms linear;
}
.button:hover, button:hover, input[type="submit"]:hover, .wp-block-button__link:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}
.button--secondary, .is-style-outline .wp-block-button__link {
  background: transparent;
  color: var(--heading);
  border-color: var(--rule-strong);
}
.button--secondary:hover, .is-style-outline .wp-block-button__link:hover {
  background: transparent;
  color: var(--accent);
  border-color: var(--accent);
}

/* ---------- 10. Masthead: ink band + nav row on paper ---------- */
/* Markup (fixed, every page):
     header.site-header > .wrap > p.site-title, p.site-tagline, nav > ul.main-menu
   The band is full-bleed ink; the wordmark and tagline stay inside the 1180px
   shell because .wrap already centres and pads (see §2). The nav row sits on
   paper below the band, under a single hairline.

   How the two backgrounds coexist with one .wrap: the header paints ink across
   its whole height, then the nav paints paper back over the lower part. The nav's
   paper has to reach the viewport edges while its text stays on the shell grid,
   so the bleed is a pseudo-element, not padding. isolation:isolate makes the
   header a stacking context, which is what lets a z-index:-1 child paint ABOVE
   the header's own ink background instead of disappearing behind it. */
.site-header {
  background: var(--ink);
  isolation: isolate;
  padding-block: 0;
  /* The nav's bleed pseudo below reaches past the viewport; without this it adds
     to the document scroll width and the page gains a horizontal scrollbar.
     `clip` (not `hidden`) so no scroll container is created. */
  overflow-x: clip;
}
/* flow-root, not block: the tagline's 5px top margin otherwise collapses out
   through the wrap and leaves a 5px strip of ink below the nav row. */
.site-header > .wrap { padding-block: 0; display: flow-root; }

.site-title, .site-title a {
  font-family: var(--serif);
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--paper);
  text-decoration: none;
}
.site-header .site-title { margin: 0; padding-top: 22px; max-width: none; }
.site-title a:hover { color: #E6C58F; }
.site-title a:focus-visible { outline: 2px solid #E6C58F; outline-offset: 3px; }

/* #A8A29A, not --faint: the band needs a lighter grey than the footer's to hold
   this size. Both pass AA on ink. */
.site-header .site-tagline,
.site-header .site-description {
  font-size: 15px;
  line-height: 1.5;
  color: #A8A29A;
  margin: 5px 0 0;
  padding-bottom: 20px;
  max-width: 46em;
}

/* Nav row: paper, full-bleed background, content on the shell grid.
   17px above the items and 16px below, so the row sits centred between the band's
   lower edge and its closing hairline. */
.site-header nav {
  position: relative;
  background: var(--bg);
  padding-top: 10px;
}
.site-header nav::before {
  content: "";
  position: absolute;
  top: 0;
  /* Belt and braces: the paper runs 24px BELOW the nav row. Any residual ink
     under the row — from a collapsed margin, a stray line box, a theme's
     padding — is covered, and the overspill lands on main's paper, which is the
     same colour. The closing hairline is ::after, so it still paints on top. */
  bottom: -24px;
  left: -100vmax;
  right: -100vmax;
  background: var(--bg);
  z-index: -1;
  pointer-events: none;
}
/* The closing hairline runs to the viewport edges (references 02, R1, R2), so it
   cannot live on .main-menu — that sits inside the padded shell and stops 72px
   short on each side. */
.site-header nav::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: -100vmax;
  right: -100vmax;
  height: 1px;
  background: var(--rule);
  pointer-events: none;
}

/* The phone toggle row exists only below 800px (see the phone block). On desktop
   both the label and its checkbox are display:none and .main-menu is simply
   visible, so no toggle state can ever hide the desktop nav. */
.menu-toggle, .nav-toggle-input { display: none; }

.main-menu, .nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-5);
  list-style: none;
  margin: 0;
  padding: 0 0 14px;   /* 10 top + 30 items + 14 = 54px band edge to hairline */
  max-width: none;
  border-bottom: 0;
}
/* §6 gives every ul li a hanging indent for its em-dash marker; structural lists
   have no marker, so the padding that reserves room for one must go too or the nav
   sits 26px right of the wordmark. */
.main-menu li, .nav ul li { margin: 0; display: block; position: static; padding-left: 0; }
.main-menu li::before, .nav ul li::before, .site-footer li::before { content: none; }
.main-menu a, .nav a { font-size: 14.5px; color: var(--muted); transition: color 120ms linear; }
.main-menu a:hover, .nav a:hover { color: var(--heading); }

/* Bronze underline on the current item ONLY. */
.main-menu .current-menu-item > a,
.main-menu .current_page_item > a {
  color: var(--heading);
  box-shadow: inset 0 -1px 0 var(--accent);
}
/* WordPress and most generators also mark ancestors of the current page. A guide,
   post, category or chapter must not light up its parent nav item — reset them,
   including when an ancestor class lands on the same <li> as nothing else. */
.main-menu .current-menu-ancestor > a,
.main-menu .current-page-ancestor > a,
.main-menu .current-menu-parent > a,
.main-menu .current-page-parent > a,
.main-menu .current-post-ancestor > a {
  color: var(--muted);
  box-shadow: none;
}
.main-menu .current-menu-ancestor.current-menu-item > a,
.main-menu .current-page-ancestor.current_page_item > a {
  color: var(--heading);
  box-shadow: inset 0 -1px 0 var(--accent);
}

/* Measured: the nine items occupy 739px, and the gutter is 5vw each side, so the
   row is measured to wrap at 845px and to still have 47px of slack at 860, so it
   collapses at 859. No width ever shows a wrapped row
   (one item alone on a second line reads as breakage, not as a wrap). Only the
   ink band's type shrinks later, at 767. */
@media (max-width: 859px) {
  /* Toggle row and every open row rule edge to edge, text on the shared gutter
     (identical to what .wrap would give, so nothing shifts). */
  .site-header > .wrap { padding-inline: 0; }
  .site-header .site-title,
  .site-header .site-tagline,
  .site-header .site-description { padding-inline: var(--gutter); }

  .site-header nav { padding-top: 0; }
  .site-header nav::after { content: none; }   /* the last row carries the rule */

  /* 44px toggle row: caps MENU label left, three bars right, hairline beneath.
     Markup is a visually-hidden checkbox + <label class="menu-toggle"> — no
     JavaScript, and nothing that can persist across a resize. */
  .site-header .nav-toggle-input {
    display: block;
    position: absolute;
    width: 1px; height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
  }
  .site-header .nav-toggle-input:focus-visible + .menu-toggle {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
  }
  .site-header .main-menu { display: none; }
  .site-header .nav-toggle-input:checked ~ .main-menu { display: flex; }
  .site-header .menu-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 44px;
    padding: 0 var(--gutter);
    border: 0;
    border-bottom: 1px solid var(--rule);
    background: transparent;
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--meta);
    cursor: pointer;
    list-style: none;
  }
  .site-header .menu-toggle::after {
    content: "";
    width: 20px;
    height: 9px;
    border-top: 1px solid var(--heading);
    border-bottom: 1px solid var(--heading);
    background: linear-gradient(var(--heading), var(--heading)) center / 100% 1px no-repeat;
  }

  .main-menu, .nav ul { flex-direction: column; gap: 0; padding-bottom: 0; }
  .main-menu a, .nav a {
    display: block;
    font-size: 16px;
    color: var(--body);
    padding: 13px var(--gutter);   /* 53px rows, matching R2 */
    border-bottom: 1px solid var(--rule);
  }
  /* Open, the current item is a 2px bronze bar on the left edge, not the desktop
     underline — an underline inside a full-width row reads as a divider. */
  .main-menu .current-menu-item > a,
  .main-menu .current_page_item > a,
  .main-menu .current-menu-ancestor.current-menu-item > a,
  .main-menu .current-page-ancestor.current_page_item > a {
    color: var(--heading);
    box-shadow: inset 2px 0 0 var(--accent);
  }
}

/* Phone: the ink band's type shrinks. Matches BUILD.md "The masthead", and 767
   is the same breakpoint the gutters and the footer use. */
@media (max-width: 767px) {
  .site-title, .site-title a { font-size: 19px; }
  .site-header .site-title { padding-top: 18px; }
  /* 13px, not 16: with the tagline on two lines at 390px this puts the band's
     lower edge at 99px, as in reference R2. */
  .site-header .site-tagline, .site-header .site-description { font-size: 13.5px; padding-bottom: 13px; }
}

/* ---------- 11. Post lists / archives ---------- */
.post-list, .posts { list-style: none; margin: 0; padding: 0; max-width: none; }
.post-list > li, article.summary, .post-summary {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: 22px 0;
  border-top: 1px solid var(--rule);
  margin: 0;
  transition: background 120ms linear;
}
.post-list > li::before { content: none; }
.post-list > li:hover { background: var(--row-hover); }
.post-list > li:last-child, .post-summary:last-child { border-bottom: 1px solid var(--rule); }

.entry-title, .post-title {
  font-family: var(--serif);
  font-size: 23px;
  font-weight: 600;
  line-height: 1.28;
  letter-spacing: 0;
  margin: 0;
  border-top: 0;
  padding-top: 0;
}
.entry-title a { color: var(--heading); }
.entry-title a:hover { color: var(--accent); }
.entry-meta, .post-meta, .posted-on {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--meta);
}
.entry-excerpt, .excerpt { font-size: 16px; line-height: 1.6; color: var(--muted); margin: 0; }

.pagination { display: flex; gap: 10px; margin-top: var(--s-5); }
.pagination .current { background: var(--heading); color: var(--bg); padding: 7px 12px; font-family: var(--mono); font-size: 12px; }
.pagination a { border: 1px solid var(--rule); color: var(--muted); padding: 7px 12px; font-family: var(--mono); font-size: 12px; }
.pagination a:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- 12. Resource / callout cards ---------- */
/* A card set in running prose owns its own space: 34px above and below. With only the
   preceding paragraph's 18px it read as attached to that paragraph rather than as a
   block the reader steps aside to.
   34px is the card's own space and it is not required to survive downstream. Where an h2
   follows, h2's 64px top margin wins the collapse and the card gets 34 above / 64 below.
   That is correct and must not be "balanced": the 64px is the section division, a
   different thing from the card's own breathing room, and forcing symmetry there would
   mean either shrinking a section break or inflating every card.
   Every card on the site is wrapped in a <p> — Goldmark treats <a> as inline HTML, so a
   raw card authored on one line comes out as <p><a class="card">. This rule still works
   through that wrapper: the <p> has no padding or border, so the card's top margin
   collapses out through it rather than adding to it. Do not scope a rule to the wrapper.
   The space goes on the card, not on the paragraph: the card is the interruption, and
   putting padding on paragraphs to solve it would touch every paragraph on the site.
   Scoped to prose — cards in a .card-list grid are spaced by the grid's own gap and
   must not carry margins as well. */
.entry-content .card, .entry-content a.card { margin: var(--s-6) 0; }
/* No .card-list override. An earlier version zeroed the margin inside .card-list on the
   assumption that the container spaced its children with a gap — it does not; there is no
   layout rule for .card-list anywhere in this sheet, so zeroing would have stacked cards
   flush against each other. Left as ordinary block flow: adjacent cards' 34px margins
   collapse into a single 34px gap, which is what is wanted anyway. */
/* <a class="card" href="…"><strong>Title</strong><span>Description</span></a> */
.card, a.card {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 2px solid var(--accent);
  padding: var(--s-4) 22px;
  max-width: var(--measure);
  margin: 0 0 var(--s-6);
  transition: background 120ms linear, border-color 120ms linear, box-shadow 120ms linear;
}
/* --surface-hover alone is a 1.5% lightness step on --surface: invisible. Three
   things move together instead — a deeper paper, the left rule reading heavier
   (inset shadow, so nothing reflows), and the title going bronze. */
a.card:hover {
  background: #EAE3D6;
  border-color: var(--accent-faint);
  border-left-color: var(--accent-dark);
  box-shadow: inset 2px 0 0 var(--accent-dark);
}
a.card:hover > strong, a.card:hover .card-title { color: var(--accent-dark); }
.card > strong, .card-title {
  transition: color 120ms linear;
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 600;
  color: var(--heading);
  text-transform: none;
  letter-spacing: 0;
}
.card > span, .card-desc { font-size: 15.5px; line-height: 1.6; color: var(--muted); }

/* Groups of index rows (Resources, one per H2). The rule above the first row is
   the group's, not the row's — rows only ever own their bottom hairline, so a
   group can end a section cleanly and the next h2 drops its own rule (§4). */
/* The group's own opening hairline — always drawn, including under a heading. */
.index-list { border-top: 1px solid var(--rule); }
/* A paragraph introducing a group needs the group's own air beneath it, not the
   paragraph gap. At 18px the intro sat as close to the list as the rows sit to each
   other, so it read as another row description rather than as prose above the group
   — Writing's "Below is a selection of recent pieces…" was the case that showed it.
   40px is the design file's number for this gap, not a scale step; margins collapse
   between the two siblings, so this sets the whole distance. */
p + .index-list, p + .contents-list { margin-top: 40px; }
/* A closing line after a group is a paragraph about the list, not another row —
   it needs the section's air above it, not the row gap. */
.index-list + p, .contents-list + p { margin-top: var(--s-6); }
/* A group under a heading KEEPS its opening rule. There was a rule here removing it,
   on the reasoning that "the heading's own rule already sits there — one line, not
   two". That was a false application of "two hairlines never stack": h2's rule sits
   ABOVE the heading, 64px away on the far side of the heading text, so nothing
   stacks and the group simply lost the line that opens it — first row bare, every
   later row divided, group closing on a rule. h3 makes it plainer still: h3 draws no
   rule at all, so on the handbook contents "Part One" removed chapter 01's opening
   line with nothing whatsoever in its place.
   The genuine stacking case is the mirror one below, where a group's CLOSING rule
   and a following heading's opening rule would land on the same pixel. */
/* And the mirror case: the group's last row already closed it with a hairline, so
   the heading that follows must not draw a second one. */
.index-list + h2, .index-list + h3,
.contents-list + h2, .contents-list + h3 { border-top: 0; padding-top: 0; }
.index-list + h2, .contents-list + h2 { margin-top: var(--s-8); }

/* INDEX PAGES PUT THE SECTION RULE BELOW THE HEADING, not above it.
   Two h2 treatments exist in the design and they are not interchangeable:
     - prose pages (Expert Witness, fees, the guides) — h2 draws its own rule ABOVE
       itself, 30px of padding under the line, 40px of margin over it;
     - index pages (Resources, the handbook contents) — h2 draws NO rule, and the
       line under it is the group's own opening hairline, 18px below the heading.
   The difference is not decoration. On a prose page the rule closes the section that
   just ended. On an index page it opens the group that is about to start, which is
   why it belongs under the heading — the heading and its rows are one block, and a
   line above the heading would cut it off from the prose it belongs to.
   48px above, per the design, in BOTH positions: the first h2 after the intro
   paragraph and every later h2 following a group. This block must stay AFTER the
   ".index-list + h2" rule above, which sets 64px for the prose case and would
   otherwise win on equal specificity. */
.entry-content h2:has(+ .index-list),
.entry-content h2:has(+ .contents-list) {
  border-top: 0;
  padding-top: 0;
  margin-top: var(--s-7);
}

/* Index rows (Resources, Writing). No marker — the hover underline is the
   affordance. Do not add bullets, arrows or squares to long lists. */
.index-row {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 18px 0;
  border-bottom: 1px solid var(--rule);
}
.index-row:hover { background: var(--row-hover); }
.index-row .index-title {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--heading);
}
/* One-line description under an index title. Shared by Resources (04) and the
   home route rows — same size as .card-desc so the two never disagree. */
/* No inner measure: the row itself is already capped, and a second cap inside it
   leaves the text stopping short of the row's own hairline and hover tint. */
.index-row .index-desc,
.index-row .route-desc {
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--muted);
  max-width: none;
}

/* Download format chip (DOCX / PDF). Sits inside a serif .card title or an
   .index-title, so every inherited property is restated — it must not pick up the
   title's family, size or weight in either placement. */
.format-chip {
  display: inline-block;
  vertical-align: 2px;
  margin-left: 9px;
  padding: 1px 5px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--meta);
  border: 1px solid var(--rule-strong);
  white-space: nowrap;
}
/* The chip is a fact about the file, not part of the link's hover state. */
a.card:hover .format-chip, .index-row:hover .format-chip { color: var(--meta); }

/* ---------- 12b. Contact cards (screens 02, 03) ---------- */
/* The two-up mailto:/tel: pair. Deliberately NOT .card: no bronze left rule —
   that rule marks a resource you can take away, and these are addresses. */
.contact-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-4);
  max-width: var(--measure);
  margin: 0 0 var(--s-6);
}
.contact-card {
  display: flex;
  flex-direction: column;
  gap: 5px;
  background: var(--surface);
  border: 1px solid var(--rule);
  padding: var(--s-4) 20px;
  text-decoration: none;
  transition: background 120ms linear, border-color 120ms linear;
}
.contact-card:hover { background: #EAE3D6; border-color: var(--accent-faint); }
/* Caps come from CSS — the content writes the label sentence-case, as it does for
   table.rows labels. */
.contact-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--meta);
}
.contact-value {
  font-size: 17px;
  line-height: 1.4;
  color: var(--accent-dark);
  word-break: break-word;
}
.contact-card:hover .contact-value { text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 640px) {
  .contact-cards { grid-template-columns: 1fr; gap: var(--s-3); }
}

/* ---------- 12c. Fees: rate figure and stage cards (screen 03) ---------- */
/* The rate reads as one line: the figure large, the basis on its baseline to the
   right. Split at the space in the content — no words or punctuation changed. */
.rate-figure {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  max-width: var(--measure);
  margin: 0 0 var(--s-6);
}
.rate-amount {
  font-family: var(--serif);
  /* 44px, per the design. The old clamp resolved to 56px at 1440 — a quarter larger
     than drawn, and the biggest single divergence the audit found. Stepped in § 16b. */
  font-size: 44px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}
.rate-basis { font-size: 17px; line-height: 1.5; color: var(--muted); }
@media (max-width: 560px) {
  .rate-figure { gap: 6px; }
  .rate-basis { flex-basis: 100%; }
}

/* Stage cards. The card treatment without the bronze left rule — these are not
   resources you can take away, they are what the work costs at each stage. */
.stage-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  padding: 26px 28px;
  max-width: var(--measure);
  margin: 0 0 var(--s-5);
}
/* §4 gives an h2/h3 in the entry content its section hairline; inside a card the
   heading is the card's own title and takes none of it. */
.stage-card h3 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  margin: 0;
  padding-top: 0;
  border-top: 0;
  font-size: 20px;
}
.stage-figure {
  flex: none;
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--heading);
  white-space: nowrap;
}
.stage-basis {
  margin: 4px 0 var(--s-3);
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--meta);
  max-width: none;
}
.stage-card > p:last-child { margin-bottom: 0; }
/* Phone: the figure drops under the title rather than squeezing it. */
@media (max-width: 560px) {
  .stage-card h3 { display: block; }
  .stage-figure { display: block; margin-top: 6px; }
}

/* ---------- 12d. Numbered stages (Expert Witness, "When to Instruct") ---------- */
/* The 01/02/03 numerals are generated, not written: they are an ordinal drawn by
   the design, so they must not sit in the Markdown where they would be read as
   copy and go stale if a stage is added. */
/* A wrapper that splits an ordinal sequence across several lists — the counter is
   reset once here, so the second list continues rather than restarting. */
.stage-group { counter-reset: stage; }
.stage-group .stage-steps { counter-reset: none; }
/* Lettered variant, for a sequence that ends in appendices. */
.stage-steps--alpha { counter-reset: stage; }
.stage-steps--alpha > li::before { content: counter(stage, upper-alpha); }

.stage-steps {
  list-style: none;
  counter-reset: stage;
  margin: 0 0 var(--s-6);
  padding: 0;
  max-width: var(--measure);
}
.stage-steps > li {
  counter-increment: stage;
  position: relative;
  padding-left: 46px;
  margin: 0 0 var(--s-6);
  border-left: 0;
}
.stage-steps > li:last-child { margin-bottom: 0; }
.stage-steps > li::before {
  position: absolute;
  left: 0;
  top: 0;
  content: counter(stage, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  line-height: 1;
  padding-top: 7px;
  color: var(--accent);
}
.stage-steps h3 {
  margin: 0 0 8px;
  padding-top: 0;
  border-top: 0;
  font-size: 20px;
}
.stage-steps p:last-child { margin-bottom: 0; }
/* Phone: the numeral stops hanging and sits above the heading on its own line.
   The hanging column works on a wide measure, but at 390 it was costing 34px of a 346px
   measure for a two-character label, and the gap between numeral and title had collapsed
   to almost nothing — "01" was touching "Pre-Litigation".
   Widening the column would have fixed the collision by taking another 10px of measure
   for decoration. Setting the numeral static gives the heading and its paragraphs the
   full width and removes the collision rather than padding around it. */
@media (max-width: 560px) {
  .stage-steps > li { padding-left: 0; }
  .stage-steps > li::before {
    position: static;
    display: block;
    padding-top: 0;
    margin-bottom: 5px;
  }
}

/* ---------- 12e. The before/after requirement pair (screen 05) ---------- */
/* The only left-ruled blocks on the site that are not resource cards: a card is a
   thing you can go and get, and these are quotations being compared. Hence no
   fill, no border box, no hover — a rule, a label, and the line. */
.spec-before, .spec-after {
  border-left: 2px solid var(--rule-strong);
  padding: 10px 0 10px 18px;
  max-width: var(--measure);
  margin: 0 0 var(--s-4);
}
/* Bronze marks the one being argued FOR. The grey/bronze pair is the whole point
   of the section, so the two rules must never be given the same colour. */
.spec-after { border-left-color: var(--accent); }
.spec-label {
  display: block;
  margin-bottom: 5px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--meta);
}
.spec-after .spec-label { color: var(--accent-dark); }
.spec-before p, .spec-after p {
  margin: 0;
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1.45;
  max-width: none;
}
/* The rejected requirement is set in italic and muted; the rewritten one upright
   and in full ink. The reader should be able to tell them apart with the labels
   covered. */
.spec-before p { font-style: italic; color: var(--muted); }
.spec-after p { color: var(--heading); }

/* ---------- 12f. Handbook contents rows (screen 05) ---------- */
/* Chapter numbers here are DATA, not an ordinal: 06 is chapter 06 wherever it is
   listed, and A and B are the book's appendix letters. They come from front
   matter, the same source the book rail (§13f) reads — which is why this list
   does not use the generated numerals of .stage-steps. */
.contents-list { border-top: 1px solid var(--rule); margin-bottom: var(--s-6); }
.index-row.chapter {
  display: grid;
  grid-template-columns: 34px 1fr;
  align-items: baseline;
  gap: 4px 14px;
  padding: 15px 0;
}
/* Every child pinned to column 2 explicitly: auto-placement would drop the
   description back into the 34px numeral column. */
.index-row.chapter > * { grid-column: 2; }
.index-row.chapter .ch-num {
  grid-column: 1;
  grid-row: 1 / -1;
  font-size: 12px;
  color: var(--accent);
}
.index-row.chapter .index-title { font-size: 19px; }
.index-row.chapter .index-desc { font-size: 15.5px; }

/* Label-column tables take a top rule (About's technical practice, Fees' travel
   expenses): the table is a block on the page, not a continuation of the prose. */
table.rows { border-top: 1px solid var(--rule); }
/* A header row in a label/value table is the same meta label as the first column,
   not a shaded compare header. */
table.rows th {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--meta);
  background: none;
  text-align: left;
}

/* Inline pull-quote: a sentence already in the flow, lifted. No rule, no marks —
   scale and colour do the work, so the paragraph can be read either way. */
.entry-content p.pull-quote {
  font-family: var(--serif);
  /* 22px — the same serif voice as the lead, which is what the design draws for a
     lifted sentence. Stepped in § 16b. */
  font-size: 22px;
  line-height: 1.4;
  color: var(--heading);
  margin: var(--s-6) 0;
  max-width: var(--measure);
  text-wrap: pretty;
}

/* A bold run-in label needs air beneath it when it introduces a paragraph rather
   than a list. */
.entry-content p.sub-label + p { margin-top: 0; }
/* An h3 followed straight by a sub-label needs its own air. h3's 12px bottom margin is
   sized for body copy; a 15px sans label that close to a 21px serif heading crowds it,
   and the two read as one stacked pair rather than a heading and the label beneath it.
   26px total, matching the space an h3 gets above a list. */
.entry-content h3 + p.sub-label { margin-top: 14px; }
.entry-content p.run-in { margin-bottom: var(--s-4); }

/* ---------- 13. Eyebrow, contents rail, sidebar credentials ---------- */
.eyebrow {
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--meta);
  margin: 0 0 var(--s-4);
}

.toc { display: flex; flex-direction: column; gap: 10px; }
.toc a { font-size: 13.5px; line-height: 1.4; color: var(--muted); padding-left: 11px; border-left: 1px solid var(--rule); }
.toc a:hover, .toc a.is-current { color: var(--heading); }
.toc a.is-current { border-left-color: var(--accent); }

/* Home only, and inside the sidebar aside — never a full-width band. */
.credentials { display: flex; flex-direction: column; border-top: 1px solid var(--rule); margin-top: 2px; }
.credentials > div { display: flex; flex-direction: column; gap: 3px; padding: 12px 0; border-bottom: 1px solid var(--rule); }
.credentials > div:last-child { border-bottom: 0; }
.credentials dt, .credentials .cred-label {
  font-family: var(--serif); font-size: 16.5px; font-weight: 600; line-height: 1.25; color: var(--heading);
}
.credentials dd, .credentials .cred-desc {
  margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted);
}

.portrait { display: block; width: 100%; aspect-ratio: 4 / 5; object-fit: cover; border: 1px solid var(--rule); }
/* About (08): the portrait floats into the right column and the body text stays
   left on the gutter — the page has no aside, so this is the whole right column. */
/* The float has to escape the measure: the article is capped at 660px, so a float
   inside it eats half the text column. The negative right margin puts the figure
   in the space beside the measure — the right column the page otherwise has no
   element for — and the paragraphs keep their full width. */
.portrait-figure {
  float: right;
  width: 240px;
  margin: 4px 0 var(--s-5) var(--s-7);
  margin-right: calc(-1 * (240px + var(--s-7)));
}
.portrait-figure figcaption {
  font-family: var(--serif);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--heading);
  margin-top: 10px;
}
/* 1059, not 834 and not 767. About's portrait is the site's one legitimate float — it
   sits BEFORE the paragraphs in source order, so there is text for it to flow past. But
   the float only FITS above a width this rule has to name explicitly:
       660px measure + 48px gap + 240px rail = 948px of content,
   plus two gutters of clamp(22px, 5vw, 72px). At a 1060px viewport the gutters are 53px
   each and the content box is 954px — just enough. At 1059px it is 947px and the portrait
   pushes past the right edge of the page.
   Below that the whole DOCUMENT becomes wider than the viewport, which is why this showed
   up as the masthead's ink band stopping short: a full-bleed band sized to 100% ends at
   the viewport edge while the document scrolls past it. The band was the symptom; the
   float was the cause.
   Earlier versions of this rule used 767 and then 834. Both were aimed at breakpoints
   that exist for other reasons; this one is arithmetic, and if the measure, the gap or
   the rail width ever change, this number changes with them. */
@media (max-width: 1059px) {
  .portrait-figure { float: none; width: 100%; max-width: 320px; margin: 0 0 var(--s-5); margin-right: 0; }
}

.book-jacket { display: block; width: 100%; aspect-ratio: 3 / 4; object-fit: contain; border: 1px solid var(--rule); }

/* ---------- 13c. Home (screen 01) ---------- */
/* Two columns under a hairline. Left-aligned to the gutter, never centred: the
   page has a right column, so a centred text block would leave the aside hanging
   off the shell. article.page's 660px cap (§2) does not apply here. */
/* One rule for where a portrait starts: level with the first line of the lead,
   on every page that has one. About and Expert Witness get that for free — their
   aside sits in the body column, which opens on the lead. Home's lead lives in a
   full-width intro band above the columns, so its aside started a whole band
   lower and the photo looked adrift. The intro and the columns are flattened into
   one grid here so the aside can span both rows and rise to meet the lead. */
.home {
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, 660px) 240px;
  column-gap: var(--s-9);
  justify-content: start;
}
.home-intro { grid-column: 1; grid-row: 1; }
.home-columns { display: contents; }
.home-body { grid-column: 1; grid-row: 2; }
.home-aside { grid-column: 2; grid-row: 1 / span 2; }

.home-intro {
  max-width: 660px;
  padding-bottom: var(--s-6);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--s-7);
}
.home-intro h1 {
  /* Stepped at the breakpoints in § 16b, not clamped. */
  font-size: 54px;
  margin-bottom: var(--s-4);
}
.home-intro .lead {
  /* Stepped at the breakpoints in § 16b, not clamped. */
  font-size: 25px;
  margin-bottom: 0;
}

/* 240px, matching the sidebar template's rail (§13e) — the right column is ONE
   width across the site, so the portrait lands on the same left edge on home,
   Expert Witness and About, and the pages read as one design. */
/* .home-columns is display:contents (above): its children are placed on .home's
   grid directly, so it declares no tracks of its own. */
.home-body { max-width: 660px; }

/* Route rows: the index-row pattern (§12) plus a trailing arrow. The arrow is the
   only place home departs from the plain index list — three destinations, not a
   long index, so the row is a signpost rather than a catalogue entry. */
.routes { margin: var(--s-7) 0; border-top: 1px solid var(--rule); }
.index-row.route {
  display: grid;
  grid-template-columns: 1fr 24px;
  align-items: center;
  gap: 4px var(--s-4);
}
.index-row.route .index-title { grid-column: 1; }
.index-row.route .route-desc  { grid-column: 1; }
.index-row.route .route-arrow {
  grid-column: 2;
  grid-row: 1 / -1;
  justify-self: end;
  font-size: 16px;
  line-height: 1;
  color: var(--accent);
  transition: transform 120ms linear;
}
.index-row.route:hover .index-title { color: var(--accent-dark); }
.index-row.route:hover .route-arrow { transform: translateX(3px); }

/* Aside. 280px is a fixed rail, not a fraction — the portrait is placed at that
   width and the credential rows are set to match it. */
.home-aside {
  width: 240px;
  /* Top-aligned to the H1, deliberately: home's headline wraps to two or three
     lines depending on the window, so any offset trying to meet the lead would
     have to guess at its height and drift. The top edge is a fixed point. */
  align-self: start;
  /* Optically level, not mathematically: the H1's line box carries leading above
     its cap, so a zero offset puts the photo's hard top edge above the letters. */
  margin-top: 12px;
}
.home-aside .portrait { width: 240px; margin-bottom: var(--s-3); }
/* Aside typography is the same wherever an aside appears — home and the sidebar
   template both draw a name over a small caption. Scoping it to .home-aside let
   the Expert Witness caption fall through to body size. */
.home-aside .aside-name,
.sidebar-aside .aside-name,
.sidebar-aside .portrait + p {
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--heading);
  margin: 0 0 2px;
  max-width: none;
}
.home-aside .aside-caption,
.sidebar-aside .aside-caption,
.sidebar-aside .portrait + p + p {
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
  margin: 0 0 var(--s-5);
  max-width: none;
}

/* Tablet: home STACKS, it does not float. About and Expert Witness float their asides
   here and that is right for them — their body copy runs for screens, so the text flows
   past the rail and closes underneath it.
   Home cannot. Its aside is a 240px portrait plus four credential rows, around 620px
   tall; its body is three short paragraphs, around 250px. The text runs out roughly
   370px before the rail does, so a float leaves a permanently empty left column and
   ".routes { clear: right }" then pushes the whole page down past it. That was not a
   narrow-band edge case — it is what floating a tall rail past short text always does.
   Stacked from 834 down, so there is no float band at all on this page. */
@media (max-width: 834px) {
  .home { display: block; }
  .home-columns { display: block; }
  .home-body { max-width: none; }
  .home-aside {
    float: none;
    width: 100%;
    max-width: 320px;
    margin: var(--s-7) 0 0;
  }
  .routes { clear: none; }
}

/* Phone: nothing floats. The aside stacks under the body, full width. */
@media (max-width: 767px) {
  .home-aside {
    float: none;
    width: 100%;
    max-width: 320px;
    margin: var(--s-7) 0 0;
  }
  .home-intro { margin-bottom: var(--s-6); }
}

/* ---------- 13d. Blog + category archive (07a / 07b) ---------- */
/* The one place the column widens past the 660px text measure: these rows are a
   title and a date, not running copy, so the measure argument does not apply and
   760px keeps the date clear of long titles. */
.archive { max-width: 760px; }
.archive > header {
  max-width: 760px;
  margin-bottom: var(--s-6);
}
.archive > header h1 { margin-bottom: 0; }

.blog-list {
  max-width: 760px;
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule);
}
/* §6 turns every ul li into a two-column grid for its em-dash marker. These rows
   carry their own grid and need no marker (same exemption as the footer, §10). */
.blog-list li {
  display: block;
  margin: 0;
  position: static;
  padding-left: 0;
  border-bottom: 1px solid var(--rule);
}
.blog-list li::before { content: none; }
.blog-list a {
  display: grid;
  grid-template-columns: 1fr 96px;
  align-items: baseline;
  gap: var(--s-5);
  padding: 16px 0;
  text-decoration: none;
  color: inherit;
  transition: background 120ms linear;
}
.blog-list a:hover { background: var(--row-hover); }
.blog-title {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--heading);
  text-wrap: pretty;
}
.blog-list a:hover .blog-title { color: var(--accent-dark); }
/* --meta, not --faint: --faint fails AA on paper, and this is the only place the
   year appears. */
.blog-date {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--meta);
  text-align: right;
  white-space: nowrap;
}

@media (max-width: 560px) {
  .blog-list a { grid-template-columns: 1fr; gap: 4px; padding: 14px 0; }
  .blog-date { text-align: left; }
}

/* ---------- 13e. Sidebar template (02 / 03 / 04a / 04b) ---------- */
/* Two columns pinned left at the gutter — never centred, or the rail would hang
   off the shell. The aside's top offset is DERIVED: the layout owns two rows
   (header, then body), the article maps onto them with subgrid, and the aside is
   placed in row 2. So a wrapping H1 pushes the aside down by exactly the amount
   it pushed the lead paragraph — no magic number to keep in sync with type. */
.sidebar-layout {
  display: grid;
  /* 660, not 680: the measure is one number site-wide (§2). A 20px difference here
     also pushed the rail and the portrait 20px right of every other page's. */
  grid-template-columns: minmax(0, 660px) 240px;
  grid-template-rows: auto 1fr;
  justify-content: start;
  gap: 0 var(--s-9);
  align-items: stretch;
}
.sidebar-article {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: 1 / span 2;
  grid-column: 1;
  max-width: 660px;
}
.sidebar-aside {
  grid-column: 2;
  grid-row: 2;
  width: 240px;
}
/* Older engines: no subgrid, so fall back to spanning both rows and accept the
   header's own height as the offset. */
@supports not (grid-template-rows: subgrid) {
  .sidebar-article { display: block; grid-row: 1 / -1; }
  .sidebar-aside { grid-row: 1 / -1; padding-top: calc(1.1em * 2); }
}

/* Only the rail pins. The portrait and enquiry scroll away with the page. */
.sidebar-aside .toc {
  position: sticky;
  top: 24px;
}
.sidebar-aside .portrait { width: 240px; margin: 0 0 var(--s-5); }

/* Fees and the guides index carry the rail alone: no rule above it, and the gap
   is margin so it does not travel down with the pinned box. */
.sidebar-aside > .toc:first-child { margin-top: 0; border-top: 0; }

/* Expert Witness: a hairline separates the rail from the blocks above it. It is
   set as the preceding block's border-bottom rather than the rail's border-top,
   so the rail keeps no top padding to drag along when it pins. */
.sidebar-aside > *:not(.toc) + .toc { margin-top: var(--s-5); }
.sidebar-aside .enquiry {
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--rule);
}

/* One line and the site's only button. */
.sidebar-aside .enquiry p {
  font-size: 15px;
  line-height: 1.55;
  color: var(--muted);
  max-width: none;
  margin: 0 0 var(--s-3);
}
.sidebar-aside .enquiry .button { width: 100%; text-align: center; }

/* Tablet: the aside STACKS. It used to float right here, on the reasoning that the body
   would flow past it. It cannot: the aside comes AFTER the article in source order, so a
   right float starting at that point has nothing left to flow past and ends up marooned
   at the foot of the page with an empty column beside it — a rail of contents links, or a
   portrait and credentials, sitting alone in 400px of paper.
   That was true of every sidebar page (Expert Witness, fees, About, the guides) and of
   home, for the same reason. Source order, not width, is what makes the float useless, so
   there is no band where it works and none where it should be reinstated.
   Stacked from 834 down, matching the phone treatment below. Sticky is released because
   nothing can pin inside the collapsed layout. */
@media (max-width: 834px) {
  .sidebar-layout { display: block; }
  .sidebar-article { display: block; max-width: none; }
  .sidebar-aside {
    float: none;
    width: 100%;
    max-width: 320px;
    margin: var(--s-7) 0 0;
    padding-top: var(--s-5);
    border-top: 1px solid var(--rule);
  }
  .sidebar-aside .portrait { width: 100%; }
  .sidebar-aside .toc { position: static; }
}

@media (max-width: 767px) {
  .sidebar-aside {
    float: none;
    width: 100%;
    max-width: 320px;
    margin: var(--s-7) 0 0;
    padding-top: var(--s-5);
    border-top: 1px solid var(--rule);
  }
  .sidebar-aside .portrait { width: 100%; }
}

/* ---------- 13f. The book rail (handbook chapters) ---------- */
/* The only tinted aside on the site. The tint is painted by a pseudo-element that
   bleeds to the top, bottom and right shell edges while the rail itself stays on
   the 240px column — so the fill never moves the content off the grid. Scoped to
   .handbook: Expert Witness, Fees and the guides index stay untinted. */
.handbook .book-aside {
  position: relative;
  isolation: isolate;
  /* The rail aligns to the H1 cap, not the lead, so it takes the whole column and
     drops by the cap offset instead of sitting in the body row. 11px = the H1's
     line-box-to-cap gap less the book title's own. Recompute if either size moves. */
  grid-row: 1 / -1;
  padding-top: 11px;
}
.handbook .book-aside::before {
  content: "";
  position: absolute;
  z-index: -1;
  /* Exactly main's top padding (52px) and the footer's top margin (46px), both in
     §2. The three numbers are coupled: change one and the tint either laps over the
     nav rule above or leaves a white strip above the ink footer. */
  top: -52px;
  bottom: -46px;
  left: calc(-1 * var(--s-5));
  /* Stops at the shell's right edge, not the viewport's: on a wide screen a
     viewport bleed turns the rail into a tinted half-page. One gutter past the
     column is enough to read as a band. */
  right: calc(-1 * var(--gutter));
  background: var(--surface);
}
.handbook .book-aside .toc { top: var(--s-5); }

.book-rail { position: sticky; top: var(--s-5); }

.book-rail-head {
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--s-4);
}
/* 16.5px is a ceiling, not a preference: the title must hold one line in 240px. */
.book-title {
  display: block;
  font-family: var(--serif);
  font-size: 16.5px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--heading);
  text-decoration: none;
  white-space: nowrap;
}
.book-title:hover { color: var(--accent-dark); }
/* Set to the chapter titles exactly — the head reads as part of the list, not a
   heading over it. */
.book-strapline {
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--meta);
  max-width: none;
  margin: 4px 0 0;
}

.book-chapters {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
  display: grid;
  gap: 9px;
}
/* §6 gives list items an em-dash marker; the chapter numbers replace it. */
.book-chapters > li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 8px;
  margin: 0;
  padding: 0;
  position: static;
  border-left: 0;
}
.book-chapters > li::before { content: none; }
.ch-num {
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.5;
  letter-spacing: 0.04em;
  color: var(--faint);
}
.book-chapters > li > a {
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--meta);
  text-decoration: none;
  text-wrap: pretty;
}
.book-chapters > li > a:hover { color: var(--heading); }
.book-chapters > li.is-current > a { color: var(--heading); font-weight: 600; }
.book-chapters > li.is-current .ch-num { color: var(--accent); }
/* Appendices are lettered, not numbered — a hairline marks where 01–09 end. */
.book-chapters > li.appendix:first-of-type {
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
}

@media (max-width: 834px) {
  .handbook .book-aside {
    padding-top: var(--s-4);
    padding-left: var(--s-4);
    padding-right: var(--s-4);
    padding-bottom: var(--s-4);
  }
  .handbook .book-aside::before { inset: 0; }
}
@media (max-width: 767px) {
  .handbook .book-aside::before { inset: 0; }
  .book-rail { position: static; }
}
@media (max-width: 767px) {
  .handbook .book-aside { max-width: none; }
  .book-title { white-space: normal; }
}
@media print {
  .handbook .book-aside { display: none; }
}

/* ---------- 13b. Single post ---------- */
/* Narrower measure than pages: the article is centred in its own column. */
.single .entry-content, .single-post .entry-content, article.post .entry-content {
  max-width: 660px;
}
.single .entry-header, article.post > header {
  max-width: 660px;
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--s-6);
}
/* Stepped at the breakpoints in § 16b, not clamped. */
.single .entry-header h1 { font-size: 44px; margin-bottom: var(--s-4); }
/* Byline row: mono date, then author. Strip the theme's "By" / "In" filler if present. */
.single .entry-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--meta);
}
.single .entry-meta .author, .single .entry-meta .byline {
  font-family: var(--sans);
  font-size: 14px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
}
.single .entry-meta a { text-decoration: none; color: inherit; }
.single .entry-meta a:hover { color: var(--accent); }
/* The category is mono caps sitting beside a mono caps date, so without an
   underline it is indistinguishable from it at rest. It takes the body link
   treatment — inherited colour, faint bronze underline, bronze on hover — while
   staying in the byline's mono caps. BUILD.md "Every link needs a rest state". */
.single .entry-meta .post-categories a,
.single .entry-meta .cat-links a {
  text-decoration: underline;
  text-decoration-color: var(--accent-faint);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color 120ms linear, text-decoration-color 120ms linear;
}
.single .entry-meta .post-categories a:hover,
.single .entry-meta .cat-links a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

/* Standfirst: a post's lead is {.lead} like everywhere else (§4) — the old
   positional promotion is gone. This only tightens the space beneath it, and must
   not re-declare the size, or the post standfirst stops scaling with every other
   lead on the site (it was once a fixed 22px against §4's clamp). */
.single .entry-content > p.lead { margin-bottom: var(--s-4); }
/* Closing line, if tagged */
.single .entry-content > p.closing {
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.5;
  color: var(--lead);
  margin-top: var(--s-6);
}

/* Run-in bold paragraphs ("You say no to bad work." …) become serif sub-labels.
   OPT-IN via class — never on position. `p > strong:first-child` looks like it
   means "the paragraph opens with bold", but :first-child counts ELEMENTS, not
   text: in "…should render in **Source Serif 4** at a larger size" the <strong> is
   still the first element child, so mid-sentence bold was promoted to a serif
   block and broke the line. Markdown emits no classes — mark the paragraph with
   an attribute list: {.run-in} */
/* Ruling (§7): yes — a bold-only paragraph introducing a list or table is the same
   sub-label, so it takes the same rule via a second class ({.sub-label}), never a
   positional selector. It sits closer to what it introduces than a run-in does. */
.entry-content p.sub-label { margin-bottom: var(--s-2); }
/* A sub-label is a bold-only paragraph introducing a list or table — nothing
   follows it on the line, so promoting it to its own block is safe and right.
   SANS, not serif, and 15px, not 19px. It was serif 19px against a serif 21px h3:
   two pixels apart in the same face, which gave the reader no way to tell which
   outranked the other — on the incident post the three weight labels read as
   headings of equal rank to the h3 above them, so a section with one heading and
   three labelled groups looked like six headings in a row.
   The rule this settles, site-wide: SERIF IS STRUCTURE, SANS BOLD IS A LABEL.
   Sans bold is already how every other label on the site is drawn — table
   headers, contact labels, eyebrows — so the sub-label joins an idiom rather
   than inventing one, and no size collision can recur however h3 is tuned. */
.entry-content p.sub-label > strong {
  display: block;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0;
  color: var(--heading);
  /* 6px, not 2: a 15px label needs a little more air beneath it than a 19px one
     did, or it sits on the first list row. */
  margin-bottom: 6px;
}
/* A run-in is NOT promoted. It stays inline, in the body face, at body size.
   Promoting it looked like a heading and behaved like a trap: the bold moves to
   its own line but the punctuation joining it to the sentence does not, so
   "**Self-knowledge**: You need to…" leaves a lone colon at the head of the next
   line. CSS cannot reach inside a text node to fix that, and three authoring
   passes over the same file did not fix it either. Inline, the punctuation cannot
   strand and the sentence reads as the sentence it is.
   No serif here: an inline serif bold inside sans body copy reads as a font
   error, not as emphasis. Weight and colour carry it. */
.entry-content p.run-in > strong:first-child {
  font-weight: 700;
  color: var(--heading);
}

/* Two-term comparisons ("Job mindset:" / "Craft mindset:") set as a definition
   table. Wrap the pair in <dl class="compare"> where the copy allows. */
dl.compare { max-width: var(--measure); margin: 0 0 var(--s-6); border-top: 1px solid var(--rule); }
dl.compare > div { display: grid; grid-template-columns: 168px 1fr; gap: 20px; padding: 16px 0; border-bottom: 1px solid var(--rule); }
dl.compare dt { font-family: var(--serif); font-size: 18px; font-weight: 600; color: var(--heading); }
dl.compare dd { margin: 0; font-size: 17px; line-height: 1.65; color: var(--body); }
@media (max-width: 560px) {
  dl.compare > div { grid-template-columns: 1fr; gap: 4px; }
}

/* Author block */
.author-box {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 20px;
  align-items: start;
  max-width: 660px;
  margin: var(--s-7) auto 0;
  padding: var(--s-5) 0;
  border-top: 1px solid var(--rule-strong);
  border-bottom: 1px solid var(--rule);
}
.author-box img { width: 96px; aspect-ratio: 4 / 5; object-fit: cover; border: 1px solid var(--rule); }
.author-box .name { font-family: var(--serif); font-size: 18px; font-weight: 600; color: var(--heading); }
.author-box p { font-size: 16px; line-height: 1.6; margin: var(--s-1) 0 0; max-width: none; }
@media (max-width: 560px) { .author-box { grid-template-columns: 1fr; } }

/* Previous / next */
/* NO TOP RULE — space alone. A deliberate divergence: the design draws a #CFC7B8
   hairline here, and it was built that way on 10 Aug and then removed the same day.
   Reviewed and rejected because on a post the nav is the only thing after the article,
   so the rule is a second signal for a division that whitespace already makes, and
   --rule-strong is the heaviest line on the page — more weight than the end of the
   writing needs when nothing competes with it.
   56px, not the 40px used while the rule was there: the line was doing the separating,
   and once it goes the space has to do that work by itself. The vertical divider
   NO vertical divider between previous and next either, and none on phone. The whole
   block is separated by space: 72px above it, a 40px column gap between the two, and
   44px at the foot. Every line here was tried and removed. Do not reinstate any of
   them to match the design file. The 72px collapses with the last paragraph's own
   18px, so this sets the whole distance. */
.post-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  max-width: 660px;
  margin-top: 72px;
  padding: 0 0 44px;
}
.post-nav a { display: flex; flex-direction: column; gap: 6px; }
.post-nav .label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--meta);
}
.post-nav .title { font-family: var(--serif); font-size: 17px; font-weight: 600; line-height: 1.35; color: var(--heading); }
.post-nav .next { text-align: right; }
.post-nav a:hover .title { color: var(--accent); }
@media (max-width: 560px) {
  /* Stacked, and separated by the grid gap alone — no rule between them, for the same
     reason there is none above the block. */
  .post-nav { grid-template-columns: 1fr; gap: var(--s-6); }
  .post-nav .next { text-align: left; }
}


/* ---------- 14. Forms ---------- */
label {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 5px;
}
input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
input[type="search"], input[type="password"], textarea, select {
  width: 100%;
  max-width: var(--measure);
  background: var(--field);
  border: 1px solid var(--rule-strong);
  border-radius: 0;
  color: var(--heading);
  font-family: var(--sans);
  font-size: 16px;
  padding: 11px 13px;
  margin-bottom: var(--s-3);
}
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); }
::placeholder { color: var(--faint); }

/* ---------- 15. Footer (ink, every page) ---------- */
.site-footer {
  background: var(--ink);
  border-top: 0;
  padding: 40px 0 34px;
  flex-shrink: 0;
}
.site-footer .footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) 1fr 1fr;
  gap: 56px;
  align-items: start;
}
/* The footer CTA heading is an h2, so §3 hands it a rule and 30px of padding.
   It must not — the footer opens on its own edge, not a hairline. */
.site-footer h2, .site-footer .footer-cta-title {
  font-family: var(--serif); font-size: 22px; line-height: 1.3; font-weight: 600;
  letter-spacing: -0.015em; color: var(--paper); margin: 0;
  border-top: 0; padding-top: 0;
}
.site-footer .footer-cta-line { font-size: 15.5px; line-height: 1.6; color: #BDB7AE; margin: 8px 0 0; }
.site-footer .footer-contact { display: flex; flex-direction: column; gap: 3px; margin-top: 12px; }
.site-footer .footer-contact a {
  font-size: 16px; color: #E8E3DA;
  text-decoration: underline; text-decoration-color: rgba(200, 169, 106, 0.5); text-underline-offset: 4px;
}
.site-footer .footer-contact a:hover { color: #E6C58F; text-decoration-color: #E6C58F; }
.site-footer .footer-col { display: flex; flex-direction: column; gap: 9px; }
.site-footer .footer-col .eyebrow { color: var(--accent-soft); margin-bottom: 2px; }
.site-footer nav ul, .site-footer .menu {
  display: flex; flex-direction: column; gap: 9px; list-style: none; margin: 0; padding: 0;
  max-width: none;
}
/* §6 makes every ul li a two-column grid for its em-dash marker. The footer has no
   markers (see §10), so the link would land in the 16px marker column and wrap to
   one word per line. Footer and nav items are plain blocks. */
.site-footer li, .site-footer nav ul li, .site-footer .menu li {
  display: block;
  margin: 0;
  position: static;
  padding-left: 0;
  line-height: 1.4;
}
.site-footer a { font-size: 14.5px; color: #DDD8D0; text-decoration: none; }
/* Colour alone can't carry this: #DDD8D0 -> brass is a hue shift at nearly the
   same lightness, so at 14.5px on ink it reads as no change at all. Brighter,
   plus an underline — the underline is what actually confirms the target. */
.site-footer a:hover {
  color: #F0DDB4;
  text-decoration: underline;
  text-decoration-color: rgba(230, 197, 143, 0.55);
  text-underline-offset: 4px;
}
/* §5 caps paragraph width at --measure (36em). On the 13px legal line that is
   468px, which cropped its hairline to the width of column 1. */
.site-footer p, .site-footer .footer-legal, .site-footer .footer-cta-line { max-width: none; }
.site-footer .footer-legal {
  font-size: 13px; color: var(--faint);   /* on ink — passes comfortably */
  margin-top: 32px; padding-top: 18px; border-top: 1px solid #33302A;
}
@media (max-width: 1023px) {
  .site-footer .footer-grid { grid-template-columns: 1fr 1fr; gap: 34px 40px; }
  .site-footer .footer-grid > :first-child { grid-column: 1 / -1; }
}
@media (max-width: 767px) {
  .site-footer { padding: 30px 0 26px; }
  /* Same step the masthead takes at this breakpoint (22 -> 19, 15.5 -> 13.5):
     both ink blocks are chrome, so they shrink together. */
  .site-footer h2, .site-footer .footer-cta-title { font-size: 19px; }
  .site-footer .footer-cta-line { font-size: 13.5px; }
  .site-footer .footer-grid { grid-template-columns: 1fr; gap: 26px; }
  .site-footer .footer-legal { margin-top: 24px; }
}

/* ---------- 16. Kill the dated theme chrome ---------- */
* { box-shadow: none; text-shadow: none; }
.site-header, .site-footer, .card, .button, input, textarea, select,
.widget, .post-list > li { border-radius: 0; }
img { max-width: 100%; height: auto; }

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

/* ---------- 16b. Responsive type steps ---------- */
/* The heading sizes the design states, stepped at the breakpoints rather than
   interpolated. See § 3 for why not a clamp: a clamp makes the same page render at a
   different type-to-space ratio in every window width, so two identical posts read as
   differently spaced.
   This block sits at the END of the stylesheet deliberately. ".home-intro h1" and
   ".single .entry-header h1" are declared far above with the same specificity as their
   entries here, so source order is what makes these win. Moving this block earlier
   silently breaks the home and post headings only — the generic h1 and h2 would keep
   working, which is the kind of partial failure that is easy to miss.
   834 and 560 because the design draws 834 and 390; max-width includes the bound, so
   834 gets the tablet step and 390 the phone step.
   Home (54px) and post (44px) headings have no tablet or phone drawing in the design —
   only Expert Witness, the handbook chapter, blog and contact are drawn at 834/390. So
   they step by the same ABSOLUTE amounts the generic h1 does (-4, then -14), which
   keeps the scale's intervals intact instead of inventing a second ratio. The same
   applies to home's lead and the rate figure; the body lead and pull-quote ARE drawn
   at all three widths (22 / 21 / 19) and use those. */
@media (max-width: 834px) {
  h1 { font-size: 42px; }
  h2 { font-size: 27px; }
  /* h3 steps here for the first time. It had no narrow-width rule at all, so a flat 21px
     ran from a 27-inch monitor to a 390px phone while every other heading stepped down.
     19 / 18 are the design's drawn values; desktop stays at 21 (reviewed and kept). The
     2px drop at this breakpoint is in step with h1's -4 and h2's -2 at the same point.
     Keeping desktop's +2 offset all the way down would have been preserving a number
     nobody argued for — the reason h3 became 21px vanished when sub-labels turned sans. */
  h3 { font-size: 19px; }
  p.lead, .entry-content p.pull-quote { font-size: 21px; }
  .home-intro h1 { font-size: 50px; }
  .home-intro .lead { font-size: 24px; }
  .single .entry-header h1 { font-size: 40px; }
  .rate-amount { font-size: 40px; }
}
@media (max-width: 560px) {
  /* Body copy steps down on phone, per the design: 16.5px paragraphs, 16px list items.
     At 390px the gutter leaves a 346px measure, and 17.5px there carries about three
     fewer characters a line than drawn — lines break early, paragraphs grow taller, and
     every page scrolls longer than it should. Smaller type at a narrower measure keeps
     the words-per-line roughly constant, which is the whole point of the step.
     On body, not on p: the size has to reach every text element that inherits, not just
     paragraphs. p.lead and the headings re-declare their own sizes below and are
     unaffected. */
  body { font-size: 16.5px; }
  ul li, ol li { font-size: 16px; }
  h1 { font-size: 32px; }
  h3 { font-size: 18px; }
  /* 24px of padding under the rule, not 30: the design tightens it on phone, where
     30px of dead space above a 24px heading is a quarter of the screen's first fold. */
  h2 { font-size: 24px; padding-top: 24px; }
  p.lead, .entry-content p.pull-quote { font-size: 19px; }
  .home-intro h1 { font-size: 40px; }
  .home-intro .lead { font-size: 22px; }
  .single .entry-header h1 { font-size: 30px; }
  .rate-amount { font-size: 40px; }
}

/* ---------- 12g. Post lead image (mood photograph) ---------- */
/* Four posts carried an Unsplash mood image on WordPress. Reinstated at full measure,
   below the header's closing hairline, ABOVE the body — the placement chosen from
   three prototypes ("Post lead image.dc.html", option 2a).
   Full measure, not an inset. An inset float narrows the measure for the whole opening,
   and the measure is what the rest of this stylesheet protects; a margin figure in the
   right column would make posts the one page type that fills the margin every other
   page leaves empty, and at 300px reduced the photograph to a thumbnail too small to
   be worth including.
   16/9 with object-fit: cover. The four sources are 1.5-1.65 landscape, so each loses
   a little top and bottom rather than being letterboxed. The 1px rule is the same frame
   the portrait uses (§13b) — a photograph on this site is always framed.
   NO caption and NO credit: these are mood images, not exhibits, and the files are
   self-hosted rather than served from Unsplash, so no attribution is owed. Do not add
   a figcaption; there is nothing to say about them that the post does not. */
.post-lead-image {
  margin: 0 0 var(--s-6);
  max-width: var(--measure);
}
.post-lead-image img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border: 1px solid var(--rule);
}

/* ---------- 17. Print — solicitors print these pages ---------- */
@media print {
  @page { margin: 18mm 16mm; }
  html, body { background: #fff; color: #000; font-size: 11.5pt; line-height: 1.5; }
  .site-header nav, .main-menu, .menu-toggle, .site-footer nav,
  .toc, .pagination, .search-form, form, .button { display: none; }
  /* The ink band must not print as a black slab. */
  .site-header { background: none; isolation: auto; border-bottom: 0.5pt solid #999; padding-bottom: 6pt; }
  .site-title, .site-title a { color: #000; }
  .site-header .site-tagline, .site-header .site-description { color: #333; padding-bottom: 0; }
  .site, #site-content, .site-inner, .wrap { max-width: none; padding: 0; }
  h1 { font-size: 22pt; }
  h2 { font-size: 15pt; margin-top: 18pt; border-top: 0.5pt solid #999; page-break-after: avoid; }
  h3 { font-size: 12pt; page-break-after: avoid; }
  p, li, td { color: #000; max-width: none; }
  a { color: #000; text-decoration: none; }
  .entry-content a::after, .page-content a::after {
    content: " (" attr(href) ")";
    font-family: var(--mono);
    font-size: 8.5pt;
    color: #555;
    word-break: break-all;
  }
  .card { background: none; border: 0.5pt solid #999; border-left-width: 1.5pt; }
  /* A mood photograph is decoration; solicitors printing a post do not need it, and
     it would take a third of the first page. */
  .post-nav, .author-box img, .post-lead-image { display: none; }
  .single .entry-content, .single .entry-header, .author-box { max-width: none; margin-inline: 0; }
  table, blockquote, .card, li { page-break-inside: avoid; }
  .site-footer::after {
    content: "bettersoftware.uk · info@bettersoftware.uk";
    display: block;
    font-size: 9pt;
    color: #555;
    margin-top: 6pt;
  }
}
