/* ==========================================================================
   Itamar Avitan: direction 2, "Lab notebook"
   Grid: a narrow left gutter holds "when" (dates, kind tags, the paper's
   figure); the column to its right holds "what". A margin rule runs between
   them and works as a time axis: a 2px ink tick marks each section, a 1px
   accent tick crosses the axis at every dated entry. On the front door the
   rule starts at Now: About and the featured paper are not dated and stand
   on plain paper (controller decision C5 item 17, 2026-09-25; the laptop
   block's note on main.opens-plain).

   Four pages now, not one scroll (2026-09-21). The navigation strip at the top
   of every page is the same device one floor up: the page you are on carries a
   2px ink tick on the strip's hairline, exactly as a section carries one on the
   margin rule. Moving between pages is the same gesture as moving between
   sections, and the tick is the only thing that moves. Two tones, on purpose:
   the strip's hairline is a divider and keeps --rule; the margin rule is the
   axis and is drawn in --spine, the card-border tone, because at the hairline
   tone (1.29:1 on the light page) the site's signature was the faintest mark
   on it (deep review 2026-09-25, DS-11).

   One visual language for three jobs:
     outlined box   = venue badge, never clickable: on the paper card, and
                      the paper's first badge again beside the home page's
                      featured Research block (DS-09). A kind or a page name in a
                      log's gutter is not a box: it is a small uppercase mono
                      label in the muted colour of the dates (DS-03: twelve
                      of fourteen boxes were not venues)
     underlined text = link: body sans in the masthead row and in running text,
                       mono for a card's link labels. The underline is drawn
                       at 65% of the link colour and comes up to full on hover;
                       a link that is a title is set in ink (DS-04)
     filled box     = the one primary action in its group (CV, Paper)
   ========================================================================== */

/* ---------- Fonts: self-hosted, SIL Open Font License 1.1 (see fonts/) ---------- */
@font-face { font-family: "Fira Sans"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/fira-sans-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "Fira Sans"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/fira-sans-latin-600-normal.woff2") format("woff2"); }
/* The one italic, for the titles of works (`works` in site.yaml, wrapped in <i class="work"> by nb()): without
   it, and with font-synthesis off below, an <i> set in roman (DS-07). Fetched only by the page that uses one. */
@font-face { font-family: "Fira Sans"; font-style: italic; font-weight: 400; font-display: swap;
  src: url("fonts/fira-sans-latin-400-italic.woff2") format("woff2"); }
@font-face { font-family: "Fira Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/fira-mono-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "Fira Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/fira-mono-latin-500-normal.woff2") format("woff2"); }

/* ---------- Tokens ---------- */
:root {
  --sans: "Fira Sans", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "Fira Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;

  --col: 47.5rem;      /* 760px main column = gutter + gap + text */
  --gutter: 8.5rem;    /* 136px: fits "14–15 Sep 2026" in 13px mono */
  --gap: 2rem;         /* the margin rule runs down the middle of this */
  --pad: 1.25rem;      /* page side padding */
  --card-pad: 1.25rem;

  color-scheme: light;
  --bg: #F4F7F8;            /* cool paper */
  --surface: #FFFFFF;       /* pasted-in sheet */
  --ink: #14212B;           /* blue-black */
  --ink-2: #41525D;         /* secondary text */
  --muted: #52636E;         /* dates, labels */
  --rule: #D3DCE1;          /* hairlines: the strip's divider, the BibTeX box */
  --rule-strong: #B7C4CC;   /* card border */
  --spine: var(--rule-strong);   /* the margin rule and its phone-edge form: the axis, one tone up from a hairline */
  --tag-line: #7D8F9A;      /* neutral tag outline */
  --accent: #0B5F73;        /* petrol ink */
  --accent-strong: #084A5A;
  --accent-tint: #E2EEF1;
  --target-tint: #D8E5E8;   /* the entry a permalink lands on: the accent at 12% over the ground */
  --btn-fill: #0B5F73;      /* the one filled control per group */
  --btn-fill-hover: #084A5A;
  --btn-ink: #FFFFFF;
  /* A figure is printed as it is, in both themes. Nothing scales it, dims it or turns it; the mat below is
     what settles it into the dark page. The two tokens stay because the distinction they carry is real --
     a plot's colour is its data -- and because a later hand reaching for a filter has to change them here,
     in the open, rather than quietly inside a rule. */
  --plot-filter: none;
  --art-filter: none;
  /* The photograph is the one image that may be dimmed, and only in the dark theme: it is neither data nor an
     illustration, so nothing is misread if it is a shade darker, and its white wall was the brightest object
     on the dark first screen -- 43% of its pixels out-shone the name (DS-02; mean luminance 0.72 -> 0.45 with
     the dark value, and no pixel above the name's). The light theme leaves it alone, and so must print (the
     print block of WP-S9 sets it back to none). Reversible: one token, three lines, no file touched. The
     matte -- the wall cut away and the portrait set on the accent tint -- is the owner's call (Q-N item 9);
     if he takes it, replace this filter with --portrait-ground, never run both. */
  --portrait-filter: none;
  /* The mount the figure is pasted onto. It has to be seen, or the figure is one object in the dark theme --
     a print on a mount -- and a different one in the light theme, a picture lying straight on the sheet.
     #E7EDF0 stood here and was 1.18:1 against the white card: present in the file, invisible on the page. The
     page's own hairline tone is 1.39:1 against the card and reads as the mount it is, under the darker border
     that frames it. The dark theme keeps a light mount, which is what stops a pale print reading as a hole
     cut in the sheet; the two themes now agree that a figure is mounted, each in its own register. */
  --mat: #D3DCE1;
  --ico: var(--muted);   /* link marks; set it to var(--ink) for the strict black-or-white of the brand guides */
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0F171C;
    --surface: #162129;
    --ink: #E4EBEF;
    --ink-2: #B5C3CB;
    --muted: #97A8B2;
    --rule: #2C3C46;
    --rule-strong: #3A4B55;
    --tag-line: #6A7E8A;
    --accent: #6DB3C4;        /* about 7.7:1 on the ground; quieter than the h1 */
    --accent-strong: #8FD0DE;
    --accent-tint: #14313A;
    --target-tint: #1A2A30;
    --btn-fill: #1C6678;      /* a filled button must not out-shine the name */
    --btn-fill-hover: #217387;
    --btn-ink: #F2FAFC;
    --plot-filter: none;
    --art-filter: none;
    --portrait-filter: brightness(0.8) contrast(1.06);
    --mat: #BCCBD4;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0F171C;
  --surface: #162129;
  --ink: #E4EBEF;
  --ink-2: #B5C3CB;
  --muted: #97A8B2;
  --rule: #2C3C46;
  --rule-strong: #3A4B55;
  --tag-line: #6A7E8A;
  --accent: #6DB3C4;
  --accent-strong: #8FD0DE;
  --accent-tint: #14313A;
  --target-tint: #1A2A30;
  --btn-fill: #1C6678;
  --btn-fill-hover: #217387;
  --btn-ink: #F2FAFC;
  --plot-filter: none;
  --art-filter: none;
  --portrait-filter: brightness(0.8) contrast(1.06);
  --mat: #BCCBD4;
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 1.0625rem/1.6 var(--sans);   /* 17px, never lighter than 400 */
  font-synthesis: none;
}

h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }
h3 { text-wrap: balance; }
/* At every width, not only from 45rem up as before: on phones the About paragraphs ended on "mind." and
   "2029." alone and the teaching intro on "tutored." (deep review 2026-09-25). A browser without `pretty`
   sets the paragraph as it did. */
p { text-wrap: pretty; }

/* A word too long for its column breaks instead of pushing the page. At 175% text on a 320px screen
   "Commonplace", "electroencephalography" and "Itamar Avitan" are each wider than the measure, and with
   nothing set here each of them scrolled the whole page sideways. break-word, not anywhere: it breaks only
   a word that would otherwise overflow, so ordinary lines are set exactly as they were. */
h1, h2, h3, p, li, blockquote { overflow-wrap: break-word; }

h1, h2, h3 { font-weight: 600; color: var(--ink); }

/* The underline is the cue that says "link" on this site -- accent against ink is only 2.26:1, so colour
   alone could not -- but drawn at full strength on every link a page of them read as a link farm. At 65%
   of the link colour it is 3.13:1 against the light page and 3.94:1 against the dark one, above the 3:1 a
   non-text cue needs (45%, the first proposal, was 2.11:1), and it comes up to full on hover. */
a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 65%, transparent);
  text-underline-offset: 0.2em;
  transition: color 120ms ease, background-color 120ms ease, border-color 120ms ease;
}
a:hover { color: var(--accent-strong); text-decoration-thickness: 2px; text-decoration-color: currentColor; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* The first Tab stop: a link past the strip, the identity and the contact line to the page's content, kept
   above the viewport until it holds focus and painted then, in the mono of the labels on the card colour,
   at the top left where a keyboard reader looks for it (deep review 2026-09-25, PA-06). :focus, not
   :focus-visible: nothing can point at a link that is off the screen, so any focus it takes is a keyboard's.
   <main> takes the focus the link hands it (tabindex -1 in the markup) and draws no ring: the ring says
   "this control", and the whole page is not a control. (0,1,1) beats the :focus-visible ring's (0,1,0). */
.skip {
  position: absolute;
  left: 1rem;
  top: -3rem;
  padding: 0.5rem 0.75rem;
  background: var(--surface);
  color: var(--accent);
  border: 1px solid var(--rule-strong);
  font: 500 0.8125rem/1 var(--mono);
  z-index: 10;
}
.skip:focus { top: 0.75rem; }
main:focus { outline: none; }

/* proper nouns and terms of art never break at their hyphen or space */
.nb { white-space: nowrap; }

/* kept in the markup (the sentence stays whole for readers and copy-paste), not painted */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* in-page links land with some air above them */
[id] { scroll-margin-top: 1.5rem; }

.page {
  max-width: calc(var(--col) + 2 * var(--pad));
  margin-inline: auto;
  padding-inline: var(--pad);
}

/* ---------- The navigation strip ----------
   Ordinary links, in the mono face every label on this site is set in, over one hairline that runs the width
   of the column. The page you are on is the one in ink rather than accent, and it carries a 2px ink tick
   sitting on that hairline -- the section tick of the margin rule, one floor up. --strip-pad is the distance
   from the links down to the rule, and the tick is placed by it, so the two stay together if it changes. */
.topstrip {
  --strip-pad: 0.625rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  min-height: 2rem;
  padding-block: 1rem var(--strip-pad);
  border-bottom: 1px solid var(--rule);
}
/* The row gap is wider than the tick is long. On a phone the strip has the whole line to itself now that
   the theme button stands in the colophon there (the phone block below; deep review 2026-09-25, PA-04) and
   "Home" is left out of it (the same block; the name at the top of every other page is the link home), so
   the strip is one line at every width from 320px up, and the tick lies on the hairline, which is the point
   of it. Should the strip ever wrap again -- a longer page name, or text enlarged past 200% on the
   narrowest phone -- the tick under a link on the first line hangs into the gap under it, and 1.125rem of
   gap against 0.6875rem of overhang keeps it clear of the line below, so it still reads as an underline
   and never lands on another link. */
.sitenav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.125rem;
}
/* No underline in the strip: it is a named navigation landmark, not running text, and three underlined page
   names competed with the tick for "this one is special". The underline returns on hover. The page you are
   on keeps no underline even then, as before: its tick is its mark. */
.sitenav a:not(.btn) {
  position: relative;
  display: inline-block;
  padding-block: 0.25rem;
  font: 500 0.8125rem/1.6 var(--mono);
  color: var(--accent);
  text-decoration: none;
}
.sitenav a:not(.btn):hover { text-decoration: underline; text-decoration-color: currentColor; }
.sitenav a[aria-current="page"], .sitenav a[aria-current="page"]:hover {
  color: var(--ink);
  text-decoration: none;
}
.sitenav a[aria-current="page"]::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(-1 * var(--strip-pad) - 1px);
  height: 2px;
  background: var(--ink);
  pointer-events: none;   /* a mark is not a target: it must not take the pointer from the link under it */
}
/* the CV keeps the rule it has always kept: one filled element per group, and this group is the whole site */
.sitenav__cv .btn { padding-block: 0.4375rem; }
.toggle {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4375rem 0.625rem;
  font: 500 0.75rem/1 var(--mono);
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
/* Both buttons -- the strip's and the colophon's -- are written hidden and the script unhides them, so a
   visitor whose browser ran no JavaScript is never shown a control that cannot do anything. The rule above
   sets display from a class, which outranks the browser's own [hidden] rule, so the attribute has to be
   honoured here in so many words: without this line the dead button is painted. The topbar keeps its height
   either way, so nothing moves when the script runs. */
.toggle[hidden] { display: none; }
.toggle:hover { color: var(--ink); border-color: var(--tag-line); }

/* ---------- Masthead ----------
   The portrait column is set in px, not rem, and that is deliberate: the portrait is a photograph, not text.
   WCAG 1.4.4 governs text, and a picture that doubles with the text size eats the name's column -- at 200% a
   5rem portrait is 160px of a 320px screen and the name has nowhere to go. The >= 45rem block below overrides
   both of these with var(--gutter), so the laptop composition is untouched. */
.masthead {
  display: grid;
  grid-template-columns: 80px minmax(0, 1fr);
  column-gap: 16px;
  align-items: center;
  margin-top: 1.75rem;
}
/* the portrait sits where a date would: in the gutter, squared off like a print pasted into the notebook */
.masthead picture {
  grid-column: 1;
  grid-row: 1;
  display: block;
  width: 80px;                /* px for the same reason as the column above: this is a photograph, not text */
}
.masthead picture img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  background: var(--surface);
}
/* The name's cell: the mark above the name, then the name (WP-S17, to the WP-S14 spec; controller decision
   C5 under the owner's delegation of 2026-09-25). The wrapper is the grid item; min-width: 0 so a long name can
   still break inside it rather than push the column. The mark is the colophon's drawing at 50 by 12 -- a
   signature, not a heading -- set 2px in so its first circle's edge lines up with the name's first stroke. */
.masthead__name { grid-column: 2; grid-row: 1; min-width: 0; }
.mark--mast { display: block; margin: 0 0 0.875rem 2px; }
.masthead h1 {
  /* A cap, never a grow: min() takes the smaller of the two, so the name is 2rem everywhere it fits and only
     gives way on a narrow screen at a large text size, where 2rem would otherwise be wider than its column
     and push the page sideways. 15vw is the measured ceiling that still holds two lines with no overflow at
     every width; 13vw is a deliberate margin under it. The >= 45rem block overrides this on the laptop. */
  font-size: min(2rem, 13vw);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.role, .lede, .links-nav { grid-column: 1 / -1; }

/* ---------- The byline: whose site this is, on every page but the home page ----------
   The name and the role line, under the same portrait, small. The bio is said once, at home; this is only the
   label on the folder. The name is the link home (controller decision C5 item 16 under owner ruling 18,
   2026-09-25; it used to be plain text, with "Home" in the strip as the one way back), and on a phone,
   where the strip drops "Home", it is the only one. It is set in ink with no underline, so the identity
   does not read as a control, and takes an ink underline -- not the accent -- when pointed at or focused.
   The portrait is part of the same target: the link's overlay (::before) reaches over the picture and the
   gap between them, the way the profile links widen "X" without widening its box, so a tap on the portrait
   goes home and there is still one link. On a phone the overlay is the byline row itself -- the <p> is the
   positioned box, shrunk to its content so the target ends at the name -- and from 45rem, where that <p>
   is display: contents and has no box, the overlay is placed on .byline over the portrait's own rectangle
   (the block below). One pixel of padding above and below the name, taken back by the margin so nothing
   moves, brings the link's own box to 24px, the rule every navigation link on this site is held to. */
.byline { margin-top: 1.5rem; }
.byline__who {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  max-width: 100%;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.4;
}
.byline__home {
  padding-block: 0.0625rem;
  margin-block: -0.0625rem;
  color: var(--ink);
  text-decoration: none;
}
.byline__home:hover, .byline__home:focus-visible {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: currentColor;
}
.byline__home::before {
  content: "";
  position: absolute;
  inset: 0;
}
.byline__who picture { display: block; flex: none; }
.byline__who img {
  display: block;
  width: 2rem;
  height: 2rem;
  object-fit: cover;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  background: var(--surface);
}
.byline .role { margin-top: 0.25rem; font-size: 0.9375rem; }
/* the portrait, at home and in the byline, takes the dark theme's dimming and nothing else: see --portrait-filter */
.masthead picture img, .byline__who img { filter: var(--portrait-filter); }

/* where: the scannable line between the name and the claim.
   Items never break inside; the "·" separators are drawn in each item's left
   padding, and one that would start a line falls outside the clip and vanishes. */
.role {
  display: flex;
  flex-wrap: wrap;
  margin-top: 0.75rem;
  margin-left: -1.25em;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink-2);
  clip-path: inset(-6px -6px -6px calc(1.25em - 6px));   /* room for the focus ring */
}
/* No nowrap here. "Ben-Gurion University of the Negev" set as one unbreakable box is 344px wide at 125% text
   and pushes a 320px page sideways; the proper noun is kept whole by the nb() span the macro now wraps it in,
   which protects the hyphen without making the whole phrase rigid. */
.role li { position: relative; padding-left: 1.25em; }
/* The empty alternative text after the slash keeps the separator out of the accessible text: without it a
   screen reader read the role line as "· PhD candidate", "· Brains and Machines Lab" (deep review
   2026-09-25, PA-05). The dot is drawn for the eye; the list items are already separate for the ear. */
.role li::before {
  content: "\00B7" / "";
  position: absolute;
  left: 0.625em;
  transform: translateX(-50%);
}

.lede {
  margin-top: 1.25rem;
  font-size: 1.25rem;
  line-height: 1.45;
  text-wrap: balance;
}
/* The identity line's second sentence (owner ruling 17: two sentences, the object of study and then the
   question): one step under the lede, at the size the other pages' intros take, so the front door opens on a
   six-word statement and the question stands under it rather than the two running together as a paragraph.
   `pretty`, not `balance`: balanced, the dash before "and when it does not" opened a line at 320px. */
.lede__more {
  display: block;
  margin-top: 0.5rem;
  font-size: 1.0625rem;
  line-height: 1.5;
  text-wrap: pretty;
}

/* how to reach him: quiet rows of text links in the body face, the address first and the profiles under it;
   the CV button is their only filled element */
.links-nav { margin-top: 1.25rem; }
.links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 1.25rem;
  font-size: 1rem;
  line-height: 1.5;
}
.links__label { color: var(--muted); }
.links a:not(.btn), .links__email, .links__label {
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
}
/* the address falls under its own label rather than dragging the page sideways when the text is enlarged:
   an inline-flex box cannot break between "Email" and the address unless it is allowed to wrap */
.links__email { flex-wrap: wrap; }
/* The front door sets two picked profiles after the address in this same list (`pick`, macros.html.j2).
   Below 33.75rem the three do not share one row, and a plain wrap then set the address and GitHub on the
   first line and "Google Scholar" alone on the second at every common phone width from 390 to 500px, with
   GitHub 2px from the right edge at 390. So under that width the address takes a row of its own and the
   pair wraps under it as a whole, which is the rule the colophon's lists keep (they wrap as groups).
   Measured: the three fit one row from 513px up; the 27px of margin covers a font that renders wider. */
@media (max-width: 33.74rem) {
  .masthead .links--reach .links__email { flex-basis: 100%; }
}
.links a:not(.btn) { position: relative; padding-block: 0.25rem; }

/* Tap target, WCAG 2.2 SC 2.5.8: every profile link must be at least 24 by 24 CSS px to point at. The box is
   32px tall already; "X" sets one letter and is 8.6px wide, so it is widened by an overlay rather than by a
   minimum width, because a wider box would push its neighbours apart and open a hole in the row exactly where
   the shortest label is. The overlay belongs to the link, so it takes the pointer; the row's rhythm is the
   rhythm of the words. It reaches 7.7px past "X" on each side, well inside the 20px gap, so no two targets
   overlap. */
.links a:not(.btn)::after {
  content: "";
  position: absolute;
  inset-block: 0;
  left: 50%;
  width: 1.5rem;
  transform: translateX(-50%);
}

/* the mark before a label says where the link leads; the label is still the link. So a mark takes the colour
   of dates and labels, not of links, and lifts to the link colour when the link is hovered or focused. */
.ico {
  flex: none;
  width: 1rem;               /* 16px: the smallest size ORCID allows for its iD mark */
  height: 1rem;
  fill: currentColor;
  color: var(--ico);
  transition: color 120ms ease;
}
a:hover > .ico,
a:focus-visible > .ico { color: var(--accent-strong); }

/* Optical sizing. The three marks are drawn in the same 24x24 box but fill it very differently, and three
   equal boxes are not three equal weights. Rendered at 16px and sampled at 8x, the ink each lays down covers
   Bluesky 58.7% of its box, mail 45.2%, GitHub 42.7%. So the solid butterfly comes down a pixel, which brings
   the three inside 42-52% rather than 43-59%; the envelope and the GitHub disc keep the full 16px. */
.ico--bluesky { width: 0.9375rem; height: 0.9375rem; }    /* solid, and the widest of the three */
/* Sizing them settles their alignment too, so no mark is nudged by hand. Measured the same way, the ink of
   the GitHub disc runs from 0.25px to 15.62px of its box -- past the band at both ends, the overshoot a
   circle has to have -- while the envelope (3.00 to 12.88) and the butterfly (1.00 to 14.88) sit inside it,
   which is where a flat-topped shape belongs. Their ink centroids agree to within 0.7px. */

/* One rhythm, marks first. Only three of the seven destinations allow their mark to be drawn here, so the
   links that carry one are kept together and set before the ones that cannot: the marks are contiguous, which
   is what stops them reading as four icons that failed to load. What the split must NOT do is open a hole.
   A 3rem step between the groups against a 1.25rem step inside one did exactly that at desktop width: it read
   as a missing item rather than as two groups, since nothing on the page tells a reader why these six
   addresses fall into two kinds -- it is a licensing accident, not a ranking. So the step between the groups
   is the step inside them, and the row is one even run of links. The lists stay apart in the markup because
   they still wrap as whole groups: side by side while both fit, stacking when they do not. */
.links-row { display: flex; flex-wrap: wrap; column-gap: 1.25rem; }
.links-row > .links { flex: none; max-width: 100%; }

.prose p + p { margin-top: 0.875rem; }
/* the statement's bullets are paragraphs too: without this the reduced-motion bullet ended on "motion." alone
   at 390 and from 1024 up (review of WP-S4) */
.prose li { text-wrap: pretty; }

/* ---------- Statement lists: the accessibility page ----------
   Sentences, not log rows. Each one is a thing that was done or a thing that is not claimed, and none of them
   is an event, so none takes the gutter or a tick on the margin rule. They borrow the "Now" list's mark -- the
   small accent dot -- because that is this site's shape for "a list of lines under one heading"; the step
   between two of them is wider than "Now" gives, since each here runs to two or three lines of prose. */
.prose > .statement { margin-top: 0.875rem; }
.statement li { position: relative; padding-left: 1.125rem; }
.statement li + li { margin-top: 0.75rem; }
.statement li::before {
  content: "";
  position: absolute;
  left: 0.125rem;
  top: calc(0.5lh - 0.15625rem);
  width: 0.3125rem;
  height: 0.3125rem;
  border-radius: 50%;
  background: var(--accent);
}
/* Each item opens with its claim in bold ink and carries its evidence after it in the secondary grey, so the
   longest page on the site can be scanned for the one line a reader came for (DS-14). The template cuts the
   lead at the item's first sentence or colon; no word of the statement changes. */
.statement li { color: var(--ink-2); }
.statement .lead { font-weight: 600; color: var(--ink); }

/* ---------- Tags: outlined, mono, never clickable ----------
   The box belongs to the paper card's venue badges (and its "Ongoing"), and to the paper's venue badge set
   once more beside the home page's featured Research block (DS-09). A kind under a talk's date or a page
   name in the invitation rows takes the same class and is unboxed by the log rule further down. */
.tag {
  display: inline-block;
  max-width: 100%;
  padding: 0.25rem 0.4375rem;
  font: 500 0.75rem/1.2 var(--mono);
  letter-spacing: 0.01em;
  color: var(--ink-2);
  border: 1px solid var(--tag-line);
  border-radius: 3px;
}
/* accent = peer-reviewed publication venue; neutral = presentation */
.tag--venue {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-tint);
}

/* ---------- Link labels: underlined mono; the primary one is filled ---------- */
.btn {
  display: inline-block;
  padding: 0.5625rem 0;
  font: 500 0.8125rem/1 var(--mono);
  text-underline-offset: 0.25em;
}
.btn--primary {
  padding: 0.5625rem 0.75rem;
  color: var(--btn-ink);
  text-decoration: none;
  background: var(--btn-fill);
  border: 1px solid var(--btn-fill);
  border-radius: 3px;
}
.btn--primary:hover {
  color: var(--btn-ink);
  background: var(--btn-fill-hover);
  border-color: var(--btn-fill-hover);
}

/* ---------- Sections ---------- */
main { margin-top: 3.25rem; }
section + section { margin-top: 3.25rem; }

h2 {
  font-size: 1.375rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin-bottom: 1.125rem;
}
h3 { font-size: 1.125rem; line-height: 1.35; }
/* A link that is a title stays a title: ink, with the underline in the accent so it still says "link". Two
   project titles side by side used to be set in two colours, because one had an address and one did not.
   Descendant selectors, so a title that gains a wrapping element keeps the rule. */
h3 a, .log--go .what a { color: var(--ink); text-decoration-color: color-mix(in srgb, var(--accent) 65%, transparent); }
h3 a:hover, .log--go .what a:hover { color: var(--accent-strong); text-decoration-color: currentColor; }

/* The page's own title, on every page but the home page, where the name in the masthead is the h1. It is a
   step above a section heading and takes the same tick, because it is the first section of its page. */
main > section > h1 {
  font-size: 1.625rem;
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin-bottom: 1.125rem;
}
/* a page that opens on its own title needs less air above it: the byline has just said whose site this is */
main.opens-with-h1 { margin-top: 2.25rem; }

/* One or two lines of framing under a page title, in the text column. Ink, not the secondary grey: on the
   research page this line is the research statement, and set quieter than the body copy under it the first
   text under each title was the quietest (DS-12). From 45rem up it takes a step towards the home lede (the
   sizes are in the two wider blocks); phones keep body size, where at 19px the statement ran to nine lines at
   390 (eleven at 320) and pushed the card below the fold. The commonplace page is the exception, below. */
.page-intro { margin: -0.25rem 0 1.5rem; color: var(--ink); }
/* the commonplace keeps its intro quiet: on that page the quotations are the large ink text */
#quotes > .page-intro { font-size: inherit; line-height: inherit; color: var(--ink-2); }
/* A page-intro that ends its page (the 404 page) must not push its margin out past main, or the margin rule
   breaks for that height between main's foot and the colophon's first segment. Elsewhere it ends only its
   own section, and the next section's larger top margin sets that gap, so nothing else moves. */
.page-intro:last-child { margin-bottom: 0; }

/* ---------- Now: what he is doing, under one date ----------
   Not events, so no dates of their own and no ticks of their own. The mark before each line is a 5px accent
   dot, the circle of the site's own mark: it used to be an accent hairline, the same colour, height and
   centre as the minor tick that crosses the rule 10px to its left, so the first line read "Sep 2026 -- --"
   (DS-05). A dot says "item" without repeating the tick. */
.now li { position: relative; padding-left: 1.125rem; }
.now li + li { margin-top: 0.625rem; }
.now li::before {
  content: "";
  position: absolute;
  left: 0.125rem;
  top: calc(0.5lh - 0.15625rem);
  width: 0.3125rem;
  height: 0.3125rem;
  border-radius: 50%;
  background: var(--accent);
}

/* ---------- Log rows: "when" + "what" ---------- */
.when {
  display: block;
  margin-bottom: 0.125rem;
  font: 400 0.8125rem/1.6 var(--mono);
  color: var(--muted);
}
.when::first-letter { text-transform: uppercase; }
.log > .row + .row { margin-top: 1.75rem; }
.log--tight > .row + .row { margin-top: 1rem; }

/* A log whose rows carry a role as well as a date: the talks, and the teaching posts, which are laid out the
   same way for the same reason -- the gutter says when and in what capacity, the column says what. */
.kind { line-height: 1; margin-bottom: 0.5rem; }
.log--kind .when { float: left; margin: 0 0.625rem 0 0; line-height: 1.5rem; }
.log--kind .kind { min-height: 1.5rem; }
.log--kind .what { clear: left; }
/* The kind is a label, not a badge: small uppercase mono in the muted colour of the dates, the register of
   the card's run-in labels. Boxed, twelve of the site's fourteen boxes were not venues, the teaching
   gutter was a column of form fields, and "Contributed talk and poster" wrapped inside its box into a
   two-line 192x41px block (DS-03). Unboxed it wraps as two right-aligned lines of text. Muted on the page is
   5.79:1 light and 7.38:1 dark, which the contrast suite checks. */
.log .kind .tag {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  font: 500 0.6875rem/1.35 var(--mono);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}
.log--kind h3 { font-size: 1.0625rem; }   /* the paper card keeps the only large title */
.authors { color: var(--ink-2); font-size: 1rem; margin-top: 0.25rem; }
.me { color: var(--ink); font-weight: 600; }
.venue { font-size: 1rem; margin-top: 0.125rem; }
.place { display: block; color: var(--ink-2); }   /* line 1 the event, line 2 the place */
.note { color: var(--ink-2); font-size: 1rem; margin-top: 0.375rem; }
.what > h3 + p:not([class]) { margin-top: 0.375rem; }

/* ---------- The invitations at the foot of the home page ----------
   The one list whose gutter carries an address instead of a date, so it carries the page's name as the quiet
   mono label the kind tags use -- never clickable, and no longer boxed, because a boxed page name read as a
   button that does nothing (DS-03) -- and no tick. The margin rule stays a time axis; a page name is not a
   point on it. The link is set like a title (ink, accent underline: the h3 a rule above), and bold. The
   selector is a descendant on purpose, so a title that gains a wrapping element keeps the rule. The section
   has no heading (WP-S17: two small invitations, not a directory), so it takes no section tick; the tags in
   the gutter and the section's own air above it are what set it apart from the news over it. */
.log--go .kind { margin-bottom: 0.375rem; }
.log--go .what a { font-weight: 600; }

/* ---------- The featured paper on the home page (WP-S17) ----------
   The first research card, in the front door's register: the venue badge in the gutter -- the one outlined box
   outside the card (DS-09) -- and in the text column the paper's short title as a linked h3, one plain
   paragraph that runs question, test, result, scope (the question opened it in bold until the review of
   WP-S17: after the lede and the title it was the third statement of the idea in half a screen, so the
   title carries the weight alone), the four marks of the card's diagram at three-quarters of their size
   with one-word captions, and the links in the mono of the card's labels. On a phone the badge stands above
   the title, as the card's badges do. The links row is the quiet "Paper · Code" line the Research hand-off
   used to carry, two links longer, and it is a list set the way the role line is: the dot between two items
   is drawn in each item's left padding and the list's clip-path cuts it off where an item opens a line, so
   the row never ends a line on a bare dot or opens one with it (until the review of WP-S17 the dots were
   typed into a paragraph, and at 320-410px the line broke after "Video ·"; at 200% text the dot had a line
   of its own). The alternative text after the slash keeps the dot out of what a screen reader says, as on
   the role line. Each link's box is padded to the 24px a target needs (WCAG 2.2 SC 2.5.8): the padding
   makes the row 32px tall against 22px without it -- an inline-block's padding does grow its line -- and
   that 10px is the price of the target; the row is still one quiet line under the strip. */
.feature__venue { line-height: 1; margin-bottom: 0.75rem; }
.feature h3 { font-size: 1.25rem; line-height: 1.3; letter-spacing: -0.008em; text-wrap: balance; }
.feature__text { margin-top: 0.75rem; }
.feature__links {
  --step: 1.8em;          /* the width of " · " in the mono: three advances of 0.6em, so the row spaces as the typed line did */
  --reach: 0.3125rem;     /* what each link's box is padded by, above and below the text */
  display: flex;
  flex-wrap: wrap;
  margin-top: 1rem;
  margin-left: calc(-1 * var(--step));
  font: 500 0.8125rem/1.6 var(--mono);
  clip-path: inset(-6px -6px -6px calc(var(--step) - 6px));   /* the first step, where a line-opening dot lands; room for the focus ring */
}
.feature__links li { position: relative; padding-left: var(--step); }
.feature__links li::before {
  content: "\00B7" / "";
  position: absolute;
  left: calc(var(--step) / 2);
  top: var(--reach);      /* down by the link's padding, so the dot sits on the text's line and not on the box's */
  transform: translateX(-50%);
}
.feature__links a { position: relative; display: inline-block; padding-block: var(--reach); }

/* ---------- The expander: the older end of the news list ----------
   The commonplace had one of these too, while it shared a page with everything else. It has a page of its own
   now, and all four lines stand open on it: there is nothing to save room for. */
.older { margin-top: 1rem; }
.older > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  padding-block: 0.375rem;
  font: 500 0.8125rem/1.6 var(--mono);
  color: var(--accent);
  cursor: pointer;
  list-style: none;
}
.older > summary::-webkit-details-marker { display: none; }
/* The +/- box is a marker, not a word: the empty alternative text after the slash keeps it out of the
   summary's accessible name, which is then "Older news (2)" rather than "plus Older news 2". */
.older > summary::before {
  content: "+" / "";
  display: grid;
  place-items: center;
  width: 1rem;
  height: 1rem;
  font: 500 0.75rem/1 var(--mono);
  color: var(--accent);
  background: var(--bg);
  border: 1px solid var(--tag-line);
  border-radius: 2px;
}
.older[open] > summary::before { content: "\2212" / ""; }
.older > summary:hover span { text-decoration: underline; text-underline-offset: 0.2em; }
.older > .log { margin-top: 0.625rem; }

/* ---------- Paper card ---------- */
/* container-type: on a phone the card answers the container query of its resource rows below (there the
   body is display: contents and has no box to ask; the card's content box is the column the rows have). From
   45rem up the body is a box of its own and is the container instead (the desktop block), as the home
   page's .feature__body is for its strip: asked of the whole card, gutter included, the query said "wide
   enough" at 720-750px with the text at 200%, where the body column is ten rem, and the rows ran 4-19px
   past the viewport in both engines (WP-S18's own sweep). */
.paper {
  padding: 1.25rem 1rem 1.375rem;
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  container-type: inline-size;
}
.paper + .paper { margin-top: 1.5rem; }
.paper__badges { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-bottom: 0.75rem; }
.paper__badges li { display: flex; }
/* The mat. A picture is never inverted, dimmed or desaturated here: an illustration misread is as wrong as a
   plot misread, and the dark theme has no more right to repaint one than the other. What the dark theme gets
   instead is the mount -- a light border of card between the print and the sheet, the way a print is mounted
   before it is pasted in. It is what stops a pale figure reading as a hole cut in a dark page: the brightness
   now has an edge that was put there on purpose, and steps down to the sheet rather than falling off it. */
.paper__plot {
  display: block;
  padding: 0.375rem;
  background: var(--mat);
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  overflow: hidden;
}
.paper__plot picture { display: block; }
.paper__fig img {
  display: block;
  width: 100%;
  height: auto;
}
/* Both are none in every theme, and the hooks are kept so that a filter cannot come back by accident: any
   value put here has to pass the test that only a brightness() scale may ever touch a plot, because scaling
   the three channels together is the one operation that leaves every hue and saturation where it was. */
.paper__fig--plot img { filter: var(--plot-filter); }
.paper__fig--art img { filter: var(--art-filter); }
/* The caption is set in the gutter's own type, but flush left at every width, under the plate's left edge:
   it is two sentences, not a label, and set against the margin rule on a desktop it read as four ragged-left
   lines of mono (final site review 2026-09-26, R1). The badges above the plate still turn with the gutter. */
.paper__fig figcaption {
  margin-top: 0.375rem;
  font: 400 0.75rem/1.4 var(--mono);
  color: var(--muted);
  /* A shorter last line where the engine has it (Chromium, WebKit); Firefox 151 has no `pretty`, so what
     keeps "wrong winner." together in every engine is the no-break space in the caption itself (site.yaml,
     figure_options.recovery_matrix), the same tie as "Fig. 1D" (WP-S3 reviews 1 and 2). */
  text-wrap: pretty;
}
.paper h3 {
  font-size: 1.25rem;
  line-height: 1.3;
  letter-spacing: -0.008em;
  text-wrap: balance;
}
.paper .authors { margin-top: 0.5rem; }
.tldr { margin-top: 0.875rem; }
.runin {
  margin-right: 0.375rem;
  font: 500 0.75rem/1 var(--mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
}
.buttons { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 1.125rem; margin-top: 1.125rem; }
.buttons li { display: flex; }
/* The card's links grouped by what a reader does with them (controller decision C4 under owner ruling 18,
   2026-09-26; external review 3 §23): three rows, Read / Reproduce / Watch, each a small mono label and its
   buttons -- the route through the paper's resources read top to bottom, where one string of five links
   read as none in particular. The label takes the run-in's face and size in the muted grey of the gutter
   labels, so the accent stays with the links and the argument's own labels below; the buttons keep their one
   style. Each row is a grid of label and list when the card is wide enough for the widest label beside the
   widest button (the query below: "Reproduce" and "NeurIPS 2025 talk" need about 14rem at the phone's 13px
   mono), and the list wraps inside its cell; narrower than that -- a 320px phone with the reader's text at
   150% or more, or the ten-rem body column of a 720px window at 200% -- the label stands above its buttons,
   so nothing ever runs past the card. A container query, not a media query, because the failing case is the
   text size, which a media query cannot see; the container is the body column from 45rem up and the card
   on a phone (see the note over .paper). The label column is one column for the three rows: see below. */
.buttons--grouped { display: grid; }   /* the rows' own padding is their air; a gap cost the page 8px it did not have */
/* li.buttons__group, not .buttons__group: `.buttons li { display: flex }` above outranks a lone class, and
   until the review of WP-S18 (2026-09-26) each row was that flex line -- the label beside its list because
   a flex row puts it there, the grid below never in effect, the label column never sized. */
li.buttons__group { display: grid; gap: 0 0.75rem; align-items: baseline; }
.buttons__group .buttons { margin-top: 0; min-width: 0; }
.buttons__use {
  padding-block: 0.5625rem;
  font: 500 0.75rem/1 var(--mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}
/* The three rows share one label column, so their first links stand on one left edge (review of WP-S18,
   2026-09-26: as three separate grids, each with its own max-content column, "Paper", "Code" and "NeurIPS
   2025 video" started at three x positions at every width from 320 to 1440, a ragged edge that read as
   unintended). The outer list holds the two columns and each row lays its label and list into them by
   subgrid (Chromium 117, Safari 16, Firefox 71). An engine without subgrid keeps each row's own two
   columns, the first declaration below, and gives the label the widest label's width as its minimum:
   4.33rem is "Reproduce" at 0.75rem Fira Mono with its letter-spacing (69.13px at a 16px root, measured
   in Chromium and WebKit) and a hair over, so the edge is one there too, and scales with the text. */
@container (min-width: 16rem) {
  .buttons--grouped { grid-template-columns: max-content minmax(0, 1fr); column-gap: 0.75rem; }
  li.buttons__group { grid-column: 1 / -1; grid-template-columns: max-content minmax(0, 1fr); grid-template-columns: subgrid; }
}
@supports not (grid-template-columns: subgrid) {
  @container (min-width: 16rem) { .buttons__use { min-width: 4.33rem; } }
}
/* The diagram under the card's Test block (deep review 2026-09-25, WP-S3; under Test since WP-S18). A strip of four marks,
   each captioned by one stage with a visible counter: four columns of 8.5rem in the card body at laptop width
   (4 x 136 + 3 x 24 = 616px in a 672px body), two rows of two on a phone, one column once the reader's text
   is large enough that a column would not fit. The auto-fit form with min(..., 100%) is the one grid that
   passed the 200%-text overflow suite; repeat(4, 1fr) fails it at 768px. The marks take the muted colour of
   the gutter labels, so the one accent object in each is the only coloured thing in the strip. */
.recovery-diagram {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.75rem 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(8.5rem, 100%), 1fr));
  counter-reset: step;
}
.recovery-diagram li { display: grid; align-content: start; gap: 0.375rem; counter-increment: step; }
.recovery-diagram svg { display: block; width: 100%; max-width: 8.5rem; height: auto; color: var(--muted); }
.recovery-diagram p { font-size: 1rem; line-height: 1.45; }
.recovery-diagram p::before { content: counter(step) ". "; font: 500 0.8125rem var(--mono); color: var(--accent); }
/* Between the phone and the laptop the card body is 536px, where auto-fit sets three columns and strands the
   fourth stage alone on a second row; two rows of two keep the strip's order readable there. */
@media (min-width: 45rem) and (max-width: 63.99rem) {
  .recovery-diagram { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* The same four marks on the home page's featured paper (WP-S17), smaller and captioned by one word each: two
   rows of two on a phone, one row of four from 45rem up when the text column is at least 28rem wide (the
   desktop block; a container query, so that text set at 200% keeps the two rows). The marks are capped at 7rem (the
   card's are 8.5rem) so the strip reads as a figure under the paragraph rather than a second card, and their
   strokes, 1.5 units of 120, still print at over a pixel. The captions are labels, not sentences: the
   gutter's mono at the dates' size, the counter in the accent before each, no full stop after it. These rules
   follow the card's so that, at equal specificity, they win. */
.recovery-diagram--small { margin-top: 1rem; gap: 0.75rem 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.recovery-diagram--small svg { max-width: 7rem; }
.recovery-diagram--small p { font: 400 0.8125rem/1.5 var(--mono); color: var(--muted); }
.recovery-diagram--small p::before { content: counter(step) " "; font-weight: 500; color: var(--accent); }
/* the questions keep their markers: they are a list a reader counts, not a row of links */
.open { margin: 0.25rem 0 0; padding-left: 1.1rem; list-style: disc; }
.open li { margin-top: 0.25rem; }
/* the citation behind an expander set like a link in the mono of the labels, down to the underline (65% of
   its colour, 1px, full on hover: the a rule), or it was the one heavy underline on the card; the entry
   itself wraps rather than scrolls, so an open box on a 320px phone adds no sideways scroll */
.cite { margin-top: 0.5rem; }
.cite > summary {
  display: inline-block;
  padding-block: 0.5625rem;
  font: 500 0.8125rem/1 var(--mono);
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 65%, transparent);
  text-underline-offset: 0.25em;
  cursor: pointer;
  list-style: none;
}
.cite > summary:hover { text-decoration-color: currentColor; }
.cite > summary::-webkit-details-marker { display: none; }
.cite pre {
  margin-top: 0.5rem;
  padding: 0.75rem;
  font: 400 0.75rem/1.5 var(--mono);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 3px;
}

/* ---------- Reading: the commonplace, one line at a time ----------
   The line first, then its source, then one note (a reading room: external review 3 §24; controller decision
   C2 under owner ruling 18, 2026-09-25). The entries are not dated in a gutter -- the year is in the source
   line -- so they are not log rows: on a laptop the list stands in the text column by its inset, with no date
   beside it and no tick of its own; on a phone it draws no rule of its own, and the quotation takes the whole
   measure. Body face, and on a phone body size: a quotation is not a heading and must not read as one -- the
   paper's title is the only large title on the site. The quotation marks are part of the text in site.yaml,
   so a reader who copies a line gets them too; text-indent hangs the opening one into the margin, which keeps
   the quoted words on the same left edge as every other column of prose on the page. */
.quote blockquote { margin: 0; font-size: 1.0625rem; line-height: 1.55; }
.quote blockquote p { text-indent: -0.42em; text-wrap: pretty; }   /* no one-word last line: the source and the note already ask for the same */

/* Then the source, then the context. Each is a step down in size and a step lighter in colour, and the step
   away from the block above it is wider than the space its own lines leave between themselves, so the change
   of voice is visible before it is read: 10px over 7.5px for the source, 8px over 6.3px for the context.
   The context note used to set at the size of the source, which made it a step lighter but not a step
   smaller, and left the two of them taller than the quotation they stand under. At 14px on tighter leading
   it still reads as prose, takes its third place in the order, and stops outweighing the words it places. */
.quote__by {
  margin-top: 0.625rem;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: pretty;
}
/* the dash is drawn, not read: the empty alternative text keeps it out of the source line's accessible
   text, as the role line's dots are kept out of the role line's (PA-05) */
.quote__by::before { content: "\2014\00A0" / ""; }
.quote__note {
  margin-top: 0.5rem;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--muted);
  text-wrap: pretty;
}
/* The permalink: a small "§" at the end of the source line, in the mono face the site's dates and badges
   use and their muted colour, lifting to the link colour when pointed at or focused. Always painted -- a keyboard or a finger
   cannot hover. The padding is what makes a one-glyph link a 24px target (WCAG 2.2 SC 2.5.8): the box is
   padded all round rather than widened by the overlay the profile row uses, because here nothing stands to
   its right to keep a rhythm with. Measured: the "§" is 7.8px wide at 13px, so 0.5rem a side left a 23.8px
   box; 0.5625rem a side makes it 25.8. Inline padding, so the source line's line height does not grow. */
.quote__link {
  margin-left: 0.5rem;
  padding: 0.5rem 0.5625rem;
  font: 500 0.8125rem/1 var(--mono);
  color: var(--muted);
  text-decoration: none;
}
.quote__link:hover, .quote__link:focus-visible { color: var(--accent); text-decoration: underline; }
/* The entry a permalink lands on stands on a panel of the accent tint. The panel is the whole entry, so the
   quotation with its hanging mark, the source and the note all sit on it and nothing has to keep clear of it.
   A ring around the text alone (the plan's CSS) could not: its left stroke ran through the opening mark that
   hangs 0.42em into the margin (review of WP-S4, 2026-09-25). The box-shadow spread is the panel's padding
   without a layout change, so the page does not jump when it lands: 0.625rem stays inside the entry's own air
   (entries are 1.75rem apart here), clears the hanging mark on a phone (0.42em of 17px is 7.1px) and, at
   320px, keeps 10px of the page's padding on the right. On a laptop the entry's left edge is the text's and
   the mark hangs 9.2px at 22px, so the spread steps up there (the laptop block below). The colour is a token,
   not a color-mix(), so the contrast test can read it back as an opaque rgb(); every text on the panel keeps
   4.5:1 in both themes. tests/test_browser.py measures all of this. */
.entry:target { background: var(--target-tint); box-shadow: 0 0 0 0.625rem var(--target-tint); border-radius: 2px; }
/* and the step between two entries is larger again than any step inside one */
.reading > .entry + .entry { margin-top: 1.75rem; }
/* The work's title is the link to a free text of the work where site.yaml gives one (the three Doyle lines,
   Project Gutenberg): set like a title link elsewhere on the site -- the text's own colour with the accent
   under it, the accent itself when pointed at or focused -- so the source line stays quieter than the
   quotation above it and the three links do not become the loudest thing on the page. */
.quote__source { color: inherit; text-decoration-color: color-mix(in srgb, var(--accent) 65%, transparent); }
.quote__source:hover, .quote__source:focus-visible { color: var(--accent-strong); text-decoration-color: currentColor; }

/* ---------- Footer ---------- */
.colophon { padding-block: 3.25rem 3rem; }
/* On every page but the home page the address and the profiles stand here, above the date: the masthead says
   them at home, the colophon says them everywhere else, and no page says them twice. */
.colophon .links-nav { margin-bottom: 1.75rem; }
.colophon .row { font: 400 0.8125rem/1.6 var(--mono); color: var(--muted); }
.colophon .when { display: inline; margin: 0; }
.colophon .what { color: var(--ink-2); }
/* The pages about the site itself, in the same mono register as "Last updated" and under it, so the row reads
   as part of the colophon's small print rather than as a second navigation. It takes no tick: the margin rule
   ends on "Last updated", and a tick below it would claim another section that is not there.
   The links get the tap-target overlay the profile row gets (WCAG 2.2 SC 2.5.8): "Accessibility" is wide
   enough already, but the box is only 21px tall at this size, and a later label here could be one short word. */
.colophon-nav { margin-top: 0.625rem; font: 400 0.8125rem/1.6 var(--mono); }
.colophon-nav ul { display: flex; flex-wrap: wrap; gap: 0 1.25rem; }
.colophon-nav a { position: relative; display: inline-flex; align-items: center; padding-block: 0.25rem; }
.colophon-nav a::after {
  content: "";
  position: absolute;
  inset-block: 0;
  left: 50%;
  width: 1.5rem;
  min-width: 100%;
  transform: translateX(-50%);
}
/* the page you are on, when it is one of these: ink rather than accent, the strip's rule one floor down */
.colophon-nav a[aria-current="page"] { color: var(--ink); text-decoration-color: var(--rule-strong); }
/* The row's last item is the theme button a phone shows in place of the strip's (deep review 2026-09-25,
   PA-04). From 45rem up the strip's button is the one shown and this item does not exist for layout; the
   phone block turns the two around. */
.colophon-nav__theme { display: none; }
/* The mark: two of a kind and the odd one out, the task behind the paper above -- and, since 2026-09-25, the
   line that says so beside it, in the colophon's own mono register, because the mark had stood on every page
   unexplained (DI-01). One and a half times its old size (63x15; at 42x10 the accent square was a speck,
   DS-10). The row is a flex line so the caption centres on the mark and wraps under itself on a phone. */
.mark { display: block; margin-top: 1.5rem; fill: var(--ink); }
.mark rect { fill: var(--accent); }
.mark-row { display: flex; align-items: center; gap: 0.75rem; margin-top: 1.5rem; }
.mark-row .mark { margin-top: 0; flex: none; }
.mark-note { font: 400 0.8125rem/1.4 var(--mono); color: var(--muted); }

/* ==========================================================================
   Phone: the rule moves to the left edge and keeps its ticks
   ========================================================================== */
@media (max-width: 44.99rem) {
  /* The strip carries only the way around the site. The theme button used to stand beside the navigation
     as a 44px square holding its mark alone, and the five items wrapped around it at every phone width --
     two lines from 320 to 430px, five lines at 200% text, where the strip was 70% of the screen (deep
     review 2026-09-25, PA-04). On a phone it stands in the colophon instead, labelled in full, beside the
     link about the site (the rules further down), and the navigation has the line to itself: one line and
     60px tall (spread across it on a phone; the block after this one). The system setting is followed until
     a visitor chooses, so the one control a phone visitor rarely needs is no longer the first thing on the
     page. "Home" leaves the strip on a phone as well (controller decision C5 item 16 under owner ruling
     18, 2026-09-25): with it the strip still wrapped at 320-352px, the CV chip alone on a second line, and
     ran to four lines at 200% text on a 390px phone; without it the four items are one line from 320px up
     and, at 200% text, two lines from 350px (one item a line at 320-344, where each is wider than half the
     screen). The name at the top of every other page is the link home there (the
     byline, above), as it is at every width; on the home page itself nothing needs to lead home. The
     markup keeps all five links on every page -- this is paint, and a laptop still shows "Home". A basis
     of 0 on the nav lets it take the whole line and wrap inside itself, which is where any wrapping
     belongs. */
  .topstrip > .toggle { display: none; }
  .sitenav__home { display: none; }
  .sitenav { flex: 1 1 0; min-width: 0; }
  /* The colophon's button: the row's own mono register at the row's own size, a button's box (28.8px tall,
     above the 24px a target needs) on the row's text line, and its label painted -- it is the one place
     the label is read by eye. The [hidden] rule keeps the no-JavaScript case: the button is written hidden
     and the script unhides it, as the strip's is. */
  .colophon-nav ul { align-items: center; }
  .colophon-nav__theme { display: list-item; }
  .colophon-nav .toggle--foot { margin: 0; padding: 0.25rem 0.5rem; font: 400 0.8125rem/1.6 var(--mono); max-width: 100%; text-align: left; }

  /* tap targets: a finger asks for more height than a pointer does. The width is already settled for every
     viewport by the overlay on .links a, so nothing here has to widen a box. */
  .links a:not(.btn) { padding-block: 0.5rem; }
  .sitenav a:not(.btn) { padding-block: 0.375rem; }
  .sitenav__cv .btn { padding-block: 0.5rem; }
  .older > summary { padding-block: 0.625rem; }
  .btn { padding-block: 0.875rem; }

  .log { border-left: 1px solid var(--spine); padding-left: 0.875rem; }
  .log .when { position: relative; }
  .log .when::before {
    content: "";
    position: absolute;
    left: calc(-0.875rem - 5px);      /* crosses the rule, as on desktop */
    top: calc(0.5lh - 1px);
    width: 0.75rem;
    height: 1px;
    background: var(--accent);
  }

  /* the rule runs on through the expander, whose box sits on it */
  .older { margin-top: 0; padding-top: 1rem; border-left: 1px solid var(--spine); }
  .older > summary { margin-left: calc(-0.5rem - 0.5px); gap: 0.40625rem; }
  .older > .log { border-left: 0; }

  /* The kind follows its date on one line here ("14–15 Sep 2026 · FLASH TALK"). The middle dot between them is
     hung, not typed: the date keeps a 1.25rem margin on its right, and the label opens with an inline block of
     that width pulled back by its own width, the dot centred in it. Beside the date the block fills the gap.
     When a long date sends the label down a line ("2023/24, 2024/25, 2025/26 and 2026/27" over TEACHING
     ASSISTANT at every phone width; the CCN kind at 320) the block lands outside the gutter's left edge and
     overflow-x: clip cuts it off, so the label opens its line with a letter, not a dot. Clip, not hidden:
     hidden would open a new formatting context and push the whole label out from beside the floated date.
     The label's line box matches the date's; 13px and 11px text in two 1.5rem lines still put the two
     baselines 1px apart, and vertical-align takes that up. tests/test_browser.py checks the pair on every
     kind row on phones: the label shares its date's line, or it opens on a letter at the gutter's edge with
     its box set to clip and, read from the pixels, no dot painted in the gutter beside that line. */
  .log--kind .when { margin-right: 1.25rem; }
  .log--kind .kind { line-height: 1.5rem; overflow-x: clip; }
  .log--kind .kind .tag { vertical-align: 1px; }
  .log--kind .kind .tag::before {
    content: "\00B7" / "";
    display: inline-block;
    width: 1.25rem;
    margin-left: -1.25rem;
    text-align: center;
  }

  /* full-bleed sheet: the card's text stays on the page's left edge */
  .paper {
    margin-inline: calc(-1 * var(--pad));
    padding-inline: var(--pad);
    border-inline: 0;
    border-radius: 0;
  }
  /* The card in one column, in a citation's order: badges, title, byline, the venue, the links, the figure as
     a plate with its caption at the foot, then the summary -- what it is, who wrote it, where it appeared,
     where to get it, the plate, what it found. The links come before the summary on every width because they
     are why most readers arrive; under the summary they sat 54px below the fold on a 1280x800 laptop and 1.6
     screens down on a phone. Floated beside the title the figure cut the measure to about two dozen
     characters and broke the one line that matters most on the page into four; moved above the title it
     opened the card with a picture and left a third of that row empty beside it. Below the links it has the
     column to itself and the title gets the full measure back. 13rem is the width at which the running
     figures still read at arm's length without the plate becoming the loudest thing in the card. */
  .paper { display: grid; grid-template-columns: minmax(0, 1fr); }
  .paper__aside, .paper__body { display: contents; }
  .paper__badges { order: 1; }
  .paper h3 { order: 2; }
  .paper .authors { order: 3; }
  .paper .paper__venue { order: 3; }
  .paper .buttons { order: 4; }
  .paper__fig { order: 5; float: none; width: 13rem; max-width: 100%; margin: 1.125rem 0 0; }
  .paper .tldr { order: 6; }
  /* the argument's blocks and the strip share one slot, so DOM order keeps Question -> Setup -> Test -> the
     diagram -> Result -> Scope -> the open questions; the citation closes the card */
  .paper .recovery-diagram, .paper .open { order: 6; }
  .paper .cite { order: 7; }
}

/* The items spread across the line only where the line is tight -- a phone. From 30rem (480px) the
   laptop's 18px gap fits on one line, and a split-screen laptop window (640px is half of 1280) keeps the
   strip's own rhythm rather than a stretched tab bar the site uses nowhere else (WP-S9 review). */
@media (max-width: 29.99rem) {
  .sitenav ul { justify-content: space-between; column-gap: 0.5rem; }
}

/* ==========================================================================
   Desktop: the gutter, the margin rule and its ticks
   ========================================================================== */
@media (min-width: 45rem) {
  :root { --pad: 2rem; }

  .topstrip { padding-top: 1.25rem; }

  .byline { margin-top: 2.25rem; }
  /* The byline joins the grid: the masthead in miniature. It was a flex chip -- thumbnail and name side by
     side inside the text column, the gutter beside it empty -- the one block above the fold that ignored the
     gutter-and-rule grid the masthead and every log keep (DS-08). Now the portrait stands in the gutter,
     right edge on the gutter's edge like the masthead's plate, spanning the two rows beside it, and the name
     and the role line take the text column, the name's foot on the row seam. The <p> around portrait and
     name becomes display: contents so its two children are grid items of their own; a paragraph role is all
     it gives up. 56px, from the 400px source, is sharp. Phones keep the chip.
     The link home (the name) is one of those grid items. Its overlay, which lets a tap on the portrait go
     home, cannot be placed from the <p> here -- display: contents leaves it no box -- so the byline is the
     positioned box, and the overlay is set on the portrait's own rectangle: 3.5rem square, its right edge
     on the gutter's edge, centred on the byline as the picture is (it spans both rows and the grid centres
     it), plus the gap, so the target runs unbroken from the picture's left edge into the name. The link's
     own box hugs the name (justify-self): stretched across the column, as a grid item is by default, its
     focus ring ran to the column's right edge and a click on the empty paper beside the name went home. */
  .byline.inset {
    position: relative;
    margin-left: 0;
    display: grid;
    grid-template-columns: var(--gutter) minmax(0, 1fr);
    column-gap: var(--gap);
    align-items: center;
  }
  .byline__who { display: contents; }
  .byline__who picture { grid-column: 1; grid-row: 1 / span 2; justify-self: end; }
  .byline__who img { width: 3.5rem; height: 3.5rem; }
  .byline__home { grid-column: 2; grid-row: 1; align-self: end; justify-self: start; font-size: 1.125rem; font-weight: 600; line-height: 1.3; }
  .byline__home::before {
    inset: auto;
    top: 50%;
    left: calc(var(--gutter) - 3.5rem);
    width: calc(3.5rem + var(--gap));
    height: 3.5rem;
    transform: translateY(-50%);
  }
  .byline .role { grid-column: 2; grid-row: 2; align-self: start; }

  .masthead {
    grid-template-columns: var(--gutter) minmax(0, 1fr);
    column-gap: var(--gap);
    align-items: start;
    margin-top: 2.5rem;
  }
  /* The portrait fills the gutter exactly, so its left edge sits on the page's edge with the first word of
     the navigation strip above it and its right edge on the margin rule, like a plate pasted into the margin.
     At 7.5rem inside an 8.5rem gutter it was right-aligned to the rule but started 16px inside the page edge,
     which read at the top left as a wobble against the nav. It spans the rows beside it so none stretches. */
  .masthead picture { grid-row: 1 / span 4; justify-self: end; width: var(--gutter); }
  .masthead h1 { font-size: 2.75rem; margin-top: -0.12em; }
  .role, .lede, .links-nav { grid-column: 2; }
  .role { margin-top: 0.375rem; }
  .lede { font-size: 1.375rem; margin-top: 1rem; }
  .lede__more { font-size: 1.1875rem; }   /* the page-intro's size at this width: the question, one step under the lede */

  main { position: relative; margin-top: 4.5rem; --spine-top: 0.9375rem; --section-gap: 4.5rem; }
  section + section { margin-top: var(--section-gap); }
  /* A page headed by its own h1 starts the rule lower, because the rule starts on the first tick and the tick
     sits at the middle of that heading's first line: half of 2rem at 1.2 rather than half of 1.5rem at 1.25. */
  main.opens-with-h1 { margin-top: 3.25rem; --spine-top: 1.2rem; }

  /* the margin rule: starts on the first section tick, ends on "Last updated" */
  main::before {
    content: "";
    position: absolute;
    z-index: 1;
    top: var(--spine-top);
    bottom: 0;
    left: calc(var(--gutter) + var(--gap) / 2);
    width: 1px;
    background: var(--spine);
  }
  /* The front door opens on plain paper (controller decision C5 item 17 under owner ruling 18, 2026-09-25:
     the rule is kept where the content is dated and dropped where it is not; external review 2 §7 asked for
     About to read as prose and the featured paper as a visual explanation). main draws no rule there; each
     ruled section -- Now, News, the invitations -- draws its own stretch instead, reaching up through the
     gap above it so the stretches join, and the colophon's two segments carry on from main's foot as on
     every page. The first ruled section under a plain one starts its stretch on its own tick, where main's
     rule would have started. The plain sections keep their inset and lose the tick: a tick without an axis
     read as a stray dash beside "About" (looked at, both themes, 1280 and 1440). Decided by render against
     the full rule: the half rule reads as the timeline beginning at Now, which is what a phone already
     shows, one log at a time. The gap is section + section's margin, named once above. */
  main.opens-plain::before { content: none; }
  main.opens-plain > section:not(.ruled) > h2.inset::before { content: none; }
  section.ruled { position: relative; }
  section.ruled::before {
    content: "";
    position: absolute;
    z-index: 1;
    top: calc(-1 * var(--section-gap));
    bottom: 0;
    left: calc(var(--gutter) + var(--gap) / 2);
    width: 1px;
    background: var(--spine);
  }
  section:not(.ruled) + section.ruled::before { top: var(--spine-top); }

  /* the framing line under a page title: one step up from the body, still under the home lede */
  .page-intro { font-size: 1.1875rem; line-height: 1.5; }

  .inset { margin-left: calc(var(--gutter) + var(--gap)); }
  .colophon .links-nav, .colophon-nav { margin-left: calc(var(--gutter) + var(--gap)); }

  /* major tick: 2px ink, one per section -- and one for the page's own title, which opens its first section */
  h1.inset, h2.inset { position: relative; }
  h2.inset { font-size: 1.5rem; }
  main > section > h1 { font-size: 2rem; }
  h1.inset::before, h2.inset::before {
    content: "";
    position: absolute;
    z-index: 2;
    left: calc(var(--gap) / -2 - 0.5rem);
    top: calc(0.5lh - 1px);
    width: 1rem;
    height: 2px;
    background: var(--ink);
  }

  .row {
    display: grid;
    grid-template-columns: var(--gutter) minmax(0, 1fr);
    column-gap: var(--gap);
    align-items: baseline;
  }
  .row > .when {
    grid-column: 1;
    grid-row: 1;
    position: relative;
    float: none;
    margin: 0;
    line-height: 1.6;
    text-align: right;
  }
  .row > .what { grid-column: 2; grid-row: 1; }

  /* minor tick: 1px accent, crossing the axis at every dated entry */
  .row > .when::after {
    content: "";
    position: absolute;
    z-index: 2;
    right: calc(var(--gap) / -2 - 4px);
    top: 0.75em;
    top: calc(0.5lh - 1px);
    width: 0.75rem;
    height: 1px;
    background: var(--accent);
  }

  /* talks and teaching: the kind tag lives in the gutter under its date, as in the paper card */
  .log--kind > .row { grid-template-rows: auto 1fr; }
  .row > .kind {
    grid-column: 1;
    grid-row: 2;
    justify-self: end;
    min-height: 0;
    margin: 0.25rem 0 0;
    text-align: right;
  }
  .log--kind > .row > .what { grid-row: 1 / span 2; clear: none; }

  /* the invitation rows have no date above the tag, so the tag takes the first row of the grid itself */
  .log--go > .row > .kind { grid-row: 1; margin-top: 0.125rem; }

  /* The featured paper on the grid: the badge in the gutter against the rule, on the title's first line, the
     rest in the text column; the strip one row of four when the column is wide enough for four captions. */
  .feature {
    display: grid;
    grid-template-columns: var(--gutter) minmax(0, 1fr);
    column-gap: var(--gap);
    align-items: start;
  }
  .feature__venue { grid-column: 1; justify-self: end; margin: 0.1875rem 0 0; }
  .feature__body { grid-column: 2; container-type: inline-size; }
  /* The row of four is asked of the text column, not the viewport: at the default text size the column is
     30.5rem at 720px and 42rem on a laptop, so this is every width of the block above; with the reader's text
     at 200% it is 8rem at 720px and 21rem at 1280, where four columns put "ranking" past the viewport at
     720-730px and broke every caption under its counter (review of WP-S17, 2026-09-26), so the strip keeps
     the phone's two rows of two there. A rem in a media query is the browser's default size; a rem in a
     container query is the page root's, so it follows the root set larger. */
  @container (min-width: 28rem) {
    .recovery-diagram--small { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  }

  /* expander sits on the rule */
  .older > summary {
    position: relative;
    margin-left: calc(var(--gutter) + var(--gap));
  }
  .older > summary::before {
    position: absolute;
    z-index: 2;
    left: calc(var(--gap) / -2 - 0.5rem + 0.5px);
    top: 50%;
    transform: translateY(-50%);
  }

  /* the card hangs out by its own padding so its text stays on the grid */
  .paper {
    display: grid;
    grid-template-columns: var(--gutter) minmax(0, 1fr);
    column-gap: var(--gap);
    align-items: start;
    margin-inline: calc(-1 * var(--card-pad) - 1px);
    padding: 1.5rem var(--card-pad) 1.625rem;
  }
  .paper__aside { grid-column: 1; }
  .paper__badges {
    flex-direction: column;
    align-items: flex-end;
    margin: 0.1875rem 0 0;
  }
  .paper__fig { margin: 0.875rem 0 0; }
  .paper__body { grid-column: 2; container-type: inline-size; }   /* the resource rows ask the body, not the card: see .paper */

  /* The quotations are the reason the commonplace page exists, so on anything wider than a phone they take
     one step up from the prose they are set among: 20px against the 17px of the note under them and of the
     text everywhere else. Still well below the page's own title -- a quotation is not a heading -- but no
     longer the same size as its own footnote, which left the loudest thing on the page the word
     "Commonplace". The phone stays as it was: at 400px the measure cannot afford the step. */
  .quote blockquote { font-size: 1.25rem; line-height: 1.5; }
  /* The reading room on a laptop: the entries stand in the text column, with no date beside them and no tick
     of their own, and the margin rule runs past them from the title's tick to "Last updated" as the page's
     quiet spine (decided by render in both themes against a page with no rule at all: without it the title's
     tick and the colophon's segment stood on nothing, and the column lost the left edge every other page
     has). The opening mark, hung 0.42em into the margin, keeps about 7px of air from the rule at 22px. The
     list stands 2.25rem under the intro (it collapses with the intro's own 1.5rem to 36px) and the entries
     2.25rem apart, wider than any step inside one. The source and the note take a shorter measure than the
     quotation -- 36rem against the column's 42rem -- so the apparatus reads as subordinate to the line it
     places (external review 3 §24). The landing panel's spread steps up to 0.875rem: the entry's left edge
     is the text's here, and 0.625rem left the mark 0.8px inside the panel's edge. */
  .reading { margin-top: 2.25rem; }
  .reading > .entry + .entry { margin-top: 2.25rem; }
  .quote__by, .quote__note { max-width: 36rem; }
  .entry:target { box-shadow: 0 0 0 0.875rem var(--target-tint); }

  /* the rule ends at the last tick: "Last updated" */
  .colophon { padding-block: 4.5rem 4rem; }
  /* The rule runs unbroken from main's foot down to that last tick. The colophon is two blocks -- the links
     and the row -- so it takes two segments, one each; a single segment reaching back 4.5rem assumed the row
     was the first thing here, which it stopped being when the links moved in, and the rule then broke over
     the links and restarted in mid-air. The numbers below are .colophon's own padding-top and .links-nav's
     own margins: the segment has to agree with all three, and that agreement is what drifted apart before. */
  .colophon .links-nav { position: relative; }
  .colophon .links-nav::before {
    content: "";
    position: absolute;
    left: calc(var(--gap) / -2);          /* .links-nav is inset by gutter+gap, so this lands on the rule's column */
    top: calc(-1 * (4.5rem + 1.25rem));   /* .colophon padding-top + .links-nav margin-top -> main's foot */
    bottom: -1.75rem;                     /* .colophon .links-nav margin-bottom -> the row's top */
    width: 1px;
    background: var(--spine);
  }
  .colophon .row { position: relative; }
  .colophon .row::before {
    content: "";
    position: absolute;
    left: calc(var(--gutter) + var(--gap) / 2);
    top: 0;
    height: 0.5lh;                        /* was: top: -4.5rem; height: calc(4.5rem + 0.5lh) */
    width: 1px;
    background: var(--spine);
  }
  .colophon .when { display: block; }
}

/* ==========================================================================
   Laptop: the page grows, and the type grows with it
   --------------------------------------------------------------------------
   Above 45rem the composition was finished: --col was fixed at 47.5rem, so an
   824px block sat in the middle of every screen wider than that and the only
   thing an extra 600px of laptop did was push the same column further from
   both edges -- 308px of empty paper on each side at 1440, 38% of the screen,
   with nothing designed for it. This step grows the page and the type
   together, so the measure stays near the same number of characters and the
   gutter gets wide enough to carry a date, a tag and the portrait at a size
   that belongs to the screen. It must come after the 45rem block: same
   specificity, so source order is what decides.
   ========================================================================== */
@media (min-width: 64rem) {
  :root {
    --col: 56rem;        /* 896px: 192 gutter + 32 gap + 672 of text */
    --gutter: 12rem;     /* the margin is the design here, and it now has to hold a 192px plate */
    --pad: 2.5rem;
  }

  body { font-size: 1.125rem; }          /* 18px against 672px: about 74 characters, as before the step */

  .masthead h1 { font-size: 3.25rem; }
  .lede { font-size: 1.5rem; }
  .lede__more, .page-intro { font-size: 1.25rem; }     /* the step under the lede's 1.5rem; the commonplace intro is exempt */
  main > section > h1 { font-size: 2.25rem; }
  h2.inset { font-size: 1.625rem; }
  h3 { font-size: 1.25rem; }
  .paper h3 { font-size: 1.375rem; }
  .log--kind h3 { font-size: 1.125rem; }
  .quote blockquote { font-size: 1.375rem; }
  .quote__by { font-size: 1.0625rem; }   /* the three steps of the commonplace keep their order: 22 / 17 / 16 */
  .quote__note { font-size: 1rem; }

  /* The mono labels come up with the body, or the gutter reads as dust beside it. The navigation strip takes
     the same 14px step as the gutter dates it is meant to match (13px beside an 18px body was the one mono
     label left behind; external review 2026-09-25, AS-19), and the toggle follows one step under it. The tick
     that marks the current page still lands on the hairline: it is placed from its own link's box by the
     strip's padding, and the link is the tallest thing in the strip at either size, so its foot is the
     strip's foot (tests/test_browser.py measures it at 1280). 15px is not taken: it would put the strip
     above the dates. */
  .sitenav a:not(.btn) { font-size: 0.875rem; }
  .toggle { font-size: 0.8125rem; }
  /* the featured paper's links, the captions under its four marks and the mark's caption are mono labels too,
     and take the same step: at 13px under an 18px line, and under the 14px "Last updated" row, each would be
     the one label left behind */
  .when, .colophon .row, .colophon-nav, .feature__links, .recovery-diagram--small p, .mark-note { font-size: 0.875rem; }
  .buttons .btn, .older > summary { font-size: 0.875rem; }
  .tag { font-size: 0.8125rem; }
  .log .kind .tag { font-size: 0.75rem; }
  .authors, .venue, .note, .role, .links { font-size: 1.0625rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  html { scroll-behavior: auto; }
}

/* ==========================================================================
   Print: the light palette on white, one scale step down, the screen's
   furniture gone, and every address a link leads to printed after it
   (deep review 2026-09-25, PA-01). The older news prints open: the script in
   base.html.j2 opens it on beforeprint, since a closed details' content is
   hidden by the browser itself and no rule here can reach it.
   ========================================================================== */
@media print {
  /* Paper is always the light palette, whatever the screen was showing. The second selector is the
     system-dark block's own selector (0,2,0) and wins by coming later; the third is the toggle's. A bare
     `:root` would lose to the system-dark block on specificity, and a dark-theme page then printed its
     name and lede in a grey of 2.91:1 on white. The portrait's dark-theme dimming is switched off with the
     palette, and the tints go: a print dialog drops backgrounds by default, and an outlined badge or a
     bordered plate reads the same with or without them. */
  :root, :root:not([data-theme="light"]), :root[data-theme="dark"] {
    color-scheme: light;
    --bg: #fff; --surface: #fff; --ink: #000; --ink-2: #222; --muted: #444;
    --rule: #bbb; --rule-strong: #999; --tag-line: #666;
    --accent: #0B5F73; --accent-strong: #084A5A; --accent-tint: transparent; --mat: transparent;
    --target-tint: transparent;
    --portrait-filter: none;
  }
  /* One scale step down for the whole sheet: the root, not body, so the rem-set lines (authors, venue,
     role) shrink with the text around them. Media queries still read the browser default. */
  html { font-size: 87.5%; }
  body { background: #fff; }
  /* Screen furniture: the skip link, the strip, the colophon's row about the site with the phone's theme
     button, the mark and its caption, and the marks that lead nowhere on paper -- a quotation's "§"
     permalink and the closed "Cite (BibTeX)" expander. The margin rule and its ticks are backgrounds, which
     the print dialog drops by default; left in, they printed as white notches in the card's border and the
     strip's hairline. */
  .skip, .topstrip, .colophon-nav, .mark, .mark-row, .quote__link, details.cite,
  main::before, section.ruled::before, .colophon .links-nav::before, .colophon .row::before,
  h1.inset::before, h2.inset::before, .row > .when::after { display: none !important; }
  /* The four marks under the featured paper stay on the screen: with them and the addresses after the
     links, the home page printed on three A4 sheets at Chrome's default margins, the third carrying only
     "Last updated", and at 15mm margins the strip split between its two rows (review of WP-S17). Without
     them the page is two sheets, and the research page prints the full diagram with its captions. The link
     row keeps whole: its addresses take two or three lines on paper. */
  .recovery-diagram--small { display: none; }
  .feature__links { break-inside: avoid; }
  /* The filled button prints as a plain link: its white-on-fill text is what the dialog greys out. */
  .btn--primary { color: var(--accent); background: none; border: 0; padding-inline: 0; text-decoration: underline; }
  /* On paper a link is only as good as its address: the card's and the rows' buttons, a venue, a title that
     is a link, and the home page's Paper, Code and Talk under the featured paper. Not the links inside sentences --
     an address in the middle of a line of prose is noise, and the ones that matter are also on the card. An
     address breaks only when it must (overflow-wrap, not word-break: break-all, which split short ones
     after "ht" or mid-word); the short ones then sit whole on a line of their own. */
  .buttons a[href^="http"]::after, .venue a[href^="http"]::after, h3 a[href^="http"]::after,
  .feature__links a[href^="http"]::after {
    content: " <" attr(href) ">"; font: 400 0.6875rem/1.4 var(--mono); color: #444;
    word-break: normal; overflow-wrap: anywhere;
  }
  /* The card's title is the Paper link (WP-S2), and the Paper button ten lines under it printed the same
     address again; once is enough, after the button. The rows' titles (the practicum) keep theirs. */
  .paper h3 a[href^="http"]::after { content: none; }
  main, section + section { margin-top: 2.25rem; }
  .colophon { padding-block: 2.25rem 0; }
  .colophon .links-nav { margin-bottom: 1rem; }
  /* The paper card is taller than a sheet since its depth blocks landed (WP-S3), so it breaks across sheets
     whatever is asked of it; asked not to, it was pushed whole onto the second sheet and left the first
     three-quarters empty. Its pieces keep whole instead -- the aside, each paragraph, each stage of the
     diagram with its mark, the open questions -- and a list stays with the label over it. A row of a log and
     a quotation never break inside. */
  .paper__aside, .paper .tldr, .recovery-diagram li, .paper .open, .log > .row, .quote { break-inside: avoid; }
  .buttons__group { break-inside: avoid; }
  .paper .recovery-diagram, .paper .open { break-before: avoid; }
  h2, h3 { break-after: avoid; }
}
