/* tyler.gold — Book Stock (decision 001) */

/* ONE TYPEFACE (decision 008, 2026-08-02). Newsreader, by Production Type — drawn to be
   read on a screen at news length. It replaced Fraunces AND EB Garamond together: the
   display role is now carried by size and weight rather than by a second family.

   Two files, 83 KB total, against 109 KB for the two families it replaced. The italic is
   REAL — a drawn alphabet, not a slant — which is the first time that has been true here.
   Both are instanced to wght 400–600 (all the site uses) and pinned at one optical size;
   keeping Newsreader's opsz axis live would have cost 46 KB more than the whole family
   does now, and lightweight was the brief. */
@font-face{
  font-family:"Newsreader";
  src:url("/fonts/newsreader.woff2") format("woff2");
  font-weight:400 600; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"Newsreader";
  src:url("/fonts/newsreader-italic.woff2") format("woff2");
  font-weight:400 600; font-style:italic; font-display:swap;
}

:root{
  color-scheme:light dark;
  --paper:#EFEDE3;
  --ink:#16150F;
  --muted:#6A6455;
  --accent:#7C6420;
  --rule:#D8D3C2;
  --accent-soft:color-mix(in srgb,var(--accent) 12%,transparent);
  --measure:34rem;
  /* Both roles are the same family now. The tokens stay because the ROLES are still
     real — display type is set tighter and heavier than body type — and keeping them
     means a second face can be tried again without touching forty rules. */
  --display:"Newsreader",Georgia,serif;
  --body:"Newsreader",Georgia,serif;
  /* The portrait and every logo sit in ONE left column, so the page has a single hard
     edge running its length. Both read this token — change it and they move together,
     which is the only way the edge cannot drift apart. */
  --gutter:4.5rem;
  /* every hairline-ruled object shares one corner, so they read as one family */
  --plate:3px;
  /* THE BOXES ARE INVISIBLE ON PURPOSE (2026-07-31). Every box that wraps a mark, a
     portrait or the quote keeps its 1px border for layout and paints it transparent,
     so nothing shifts if it is ever turned back on. The horizontal RULES stay — they
     are the page's ruling, not a frame. Do not "fix" a missing border here. */
}

/* NIGHT. True black, like Gold's Guide — the page follows the system and offers no switch
   (Tyler, 2026-09-10). Gold and muted are lifted, not recoloured: the hue holds and
   the step moves until each clears 4.5:1 on the dark ground, the same margin the
   light palette has on cream (accent 5.5:1, muted 5.0:1 — see docs/design/palette.md).
   Every translucent rule and underline on the site is a color-mix of a token, so
   nothing here has to be restated; the five values below are the whole theme. */
@media (prefers-color-scheme:dark){
  :root{
    --paper:#000;
    --ink:#F6C365;
    --muted:#9F7E41;
    --accent:#F6C365;
    --rule:#2C2312;
  }
  /* ONE COLOUR OF TEXT AT NIGHT (Tyler, 2026-09-11 — "it's kind of a lot of colors, maybe
     its all gold text"). Ink and accent are the same gold — Gold's Guide's own, #F6C365 —
     and muted is that gold dimmed to 62% over the black (6.1:1). With no second colour
     to say what is clickable, the underline does; the rules for that are at the END of
     this file, where they can outrank the daytime ones at equal specificity. */
  /* The Rutgers R is the one full-colour mark that glares on gunmetal — scarlet with no
     edge against a dark ground. Four hard ¾px shadows draw a paper keyline round its
     outline, the way the marks drawn in ink get a paper twin. No second file, and the
     R stays the size it is by day (Tyler, 2026-09-11). */
  .row__mk--rutgers img{filter:drop-shadow(.75px 0 0 var(--ink)) drop-shadow(-.75px 0 0 var(--ink))
    drop-shadow(0 .75px 0 var(--ink)) drop-shadow(0 -.75px 0 var(--ink))}
  /* The speaker portraits need nothing. make_portraits.py duotones them between the
     same two inks this block swaps, so on the dark ground the shadows ARE the paper
     and the highlights ARE the text. Inverting them was tried first and produced
     negatives — a duotone maps tone, not colour, and tone must not flip. */
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--body); font-size:19px; line-height:1.55;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
::selection{background:var(--accent-soft)}

a{color:var(--accent);text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--accent) 32%,transparent);}
a:hover{border-bottom-color:var(--accent)}
a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}

.page{max-width:38rem;margin:0 auto;padding:4rem 1.5rem 5rem;
  display:flex;flex-direction:column;gap:2.6rem}
/* <main> is a landmark, not a box. display:contents lifts its children back up
   to be .page's own flex items — wrap the sections for real and every gap
   between them collapses into one. */
.page>main{display:contents}
.page--wide{max-width:58rem}
/* The homepage is nearly empty, so it holds the full height of the window and
   lets the quote settle at the foot of it rather than leaving dead space. */
.page--home{min-height:100vh;padding:3.4rem 1.5rem 2.4rem;gap:2.2rem}

/* ---------- masthead ---------- */
.mast{display:flex;align-items:flex-start;gap:1.2rem}
.mast__body{display:flex;flex-direction:column;gap:.8rem;min-width:0}
/* A photograph tipped into a book, not an avatar: a 3:4 plate on a hairline, square
   corners. The nudge down aligns its top with the name's cap height rather than its
   line box, which sits higher than the letters do. */
.mast__por{width:var(--gutter);height:calc(var(--gutter)*4/3);object-fit:cover;
  object-position:center 22%;border:1px solid transparent;border-radius:var(--plate);flex:none;
  /* retuned for Newsreader (decision 008) — its cap sits higher in the line box than
     Fraunces' did, so the old .3rem nudge left the plate hanging below the name */
  margin-top:.02rem}
/* Optical alignment. A 3.1rem display face carries a side bearing the small text
   does not, so a box-aligned name reads as indented. The em unit keeps the
   correction proportional if the size ever changes. Tuned against a guide at the
   column edge, magnified 4x — not by eye. */
.mast__name{margin:0 0 0 -.055em;font-family:var(--display);font-size:3.1rem;
  font-weight:600;letter-spacing:-.015em;line-height:1.02}
.mast__contact{display:flex;gap:1.1rem;flex-wrap:wrap;font-size:.84rem;color:var(--muted);
  align-items:center}
.mast__contact a{color:var(--accent);border-bottom-color:color-mix(in srgb,var(--accent) 30%,transparent)}
.mast__contact a:hover{color:var(--accent);border-bottom-color:var(--accent)}
/* The city, first in the row, behind a drawn pin — in the row's gold, like the links,
   with no underline, which is what says it is not one (Tyler, 2026-09-11). */
.mast__place{display:inline-flex;align-items:center;gap:.32em;color:var(--accent)}
.mast__place .ar--pin{width:.78em;height:.78em;margin:0 0 .08em}

/* ---------- registers ---------- */
.reg{display:flex;flex-direction:column;gap:.75rem}
/* a real <h2> since 2026-08-22 (still the same small capitals) — margin:0 matters
   because there is no global heading reset and the UA default would open the gap */
.reg__label{margin:0;font-size:.68rem;text-transform:uppercase;letter-spacing:.18em;
  font-weight:500;color:var(--accent);padding-bottom:.5rem;border-bottom:1px solid var(--rule)}
.reg__rows{display:flex;flex-direction:column;gap:.68rem}

.row{display:grid;grid-template-columns:1fr auto;gap:.15rem 1.1rem;align-items:baseline}
.row__name{font-weight:600;font-size:1.03rem}
.row__name a{color:var(--ink);border-bottom-color:color-mix(in srgb,var(--ink) 22%,transparent)}
.row__name a:hover{color:var(--accent);border-bottom-color:var(--accent)}
.row__when{font-size:.82rem;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
.row__note{grid-column:1/-1;color:var(--muted);font-size:.95rem;line-height:1.5;max-width:var(--measure)}
/* Outbound button under a row. This asked for `all-small-caps` for a year against a
   font with no small caps in it, so every browser drew SHRUNKEN CAPITALS instead —
   too light and too wide beside real lowercase, which is the classic tell. Newsreader
   has no `smcp` either, so the honest fix is to stop asking: real capitals, small, with
   tracking. Do not restore font-variant-caps here without a font that actually has it. */
.row__more{grid-column:1/-1;justify-self:start;margin-top:.55rem;
  text-transform:uppercase;font-size:.64rem;font-weight:500;letter-spacing:.16em;
  color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 42%,transparent);border-radius:4px;
  padding:.3rem .72rem;display:inline-flex;align-items:baseline;gap:.42em;
  /* The box aligns with the column. Pulling it left so the WORDS aligned instead
     made the border hang past every rule on the page, which read as a mistake —
     a bordered object wants its edge on the column. */
  transition:border-color .14s,background .14s}
.row__more:hover{border-color:var(--accent);background:var(--accent-soft)}
/* the outbound arrow, drawn. align-self centres it against the small-caps word,
   whose baseline sits higher than the flex line's */
.ar--out{width:.66em;height:.66em;flex:none;align-self:center;
  transition:transform .14s ease}
.row__more:hover .ar--out{transform:translate(.1em,-.1em)}

/* ---------- the logo gutter ----------
   A section whose rows carry logos stops being an index and becomes a letterhead: the
   mark sits at real size in its own column with a hairline under every entry, and the
   section label stays at the far left so the rule spans the whole measure.

   THE UNIFYING IDEA IS THE BOX, NOT THE ARTWORK. Six marks that share nothing — a 3.1:1
   wordmark, a hollow triangle, a ring of stars, a solid glyph — will never agree on a
   width, a height or a weight. So each is given an identical square, scaled to sit inside
   it, and centred there. What repeats down the page is the box; the artwork floats in it.
   This is why the earlier attempts kept failing: aligning artwork EDGES made the column
   answer to whichever mark had the most eccentric outline. */
.reg--marked{--box:3rem}
.reg--marked .reg__rows{gap:0}
/* the column gap matches the masthead's, so the entry names start where the name at the
   top of the page does */
.reg--marked .row{grid-template-columns:var(--gutter) 1fr auto;column-gap:1.2rem;
  padding:.9rem 0;align-items:center;border-bottom:1px solid color-mix(in srgb,var(--rule) 80%,transparent)}
.reg--marked .row:last-child{border-bottom:none;padding-bottom:.2rem}
.reg--marked .row__name{grid-column:2;font-size:1.1rem}
/* Both of these live in the top-right cell, and both are pinned to the first row so
   neither can be pushed down and take the description with it. */
.reg--marked .row__when{grid-column:3;grid-row:1}
.reg--marked .row__note{grid-column:2/-1}
/* An entry MAY carry both a date and a link, and they were pinned to the same cell —
   which printed the year and the button on top of each other. When both are present the
   date keeps the top-right slot, the button drops beneath it, and the description gives
   up the column it would otherwise have spanned into. */
.reg--marked .row:has(.row__when):has(.row__more) .row__more{grid-row:2;align-self:start;
  margin-top:.4rem}
.reg--marked .row:has(.row__when):has(.row__more) .row__note{grid-column:2}
/* The outbound button rides in the date slot — top right of the entry, where the eye is
   already going for a year. Its height is pinned to the name's line box: left to size
   itself it came out 31px against the name's 27px, which grew the first row and pushed
   this entry's description lower than every other entry's. */
.reg--marked .row__more{grid-column:3;grid-row:1;justify-self:end;align-self:center;
  margin-top:0;height:1.7rem;padding:0 .62rem;align-items:center}
/* Spans the name and its description only — letting it span the Read more button too
   dragged the mark below the title it belongs to. */
/* The box is drawn, not implied. Its rule is the same weight as the rules between rows,
   so it reads as part of the same ruling rather than as a control. The padding is the
   mark's clear space — a mark touching its own frame reads as cramped, and every brand
   guideline in the world specifies a keep-out margin for exactly this reason. */
.row__mk{grid-column:1;grid-row:1/span 2;align-self:center;display:flex;
  align-items:center;justify-content:center;width:var(--box);height:var(--box);
  padding:.34rem;border:1px solid transparent;border-radius:var(--plate)}
/* Fitted inside the box on both axes, never sized to it — setting an explicit height
   beside a max-width is what squashed the VICE wordmark, because the width got clamped
   while the height held. */
/* When a mark links out, the plate is the target. The global `a` underline is overridden
   by .row__mk's own border shorthand; hover warms the rule rather than moving anything,
   because a logo that shifts under the cursor reads as a glitch. */
a.row__mk{transition:border-color .14s,background .14s}
a.row__mk:hover{border-color:color-mix(in srgb,var(--accent) 55%,transparent);background:var(--accent-soft)}
a.row__mk:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

.row__mk img{display:block;width:auto;height:auto;
  max-width:calc(100% * var(--s,1));max-height:calc(100% * var(--s,1))}

/* --s is a density correction, because an equal box is not an equal apparent size: a solid
   glyph that fills its square reads far larger than a thin ring with air inside it at the
   same measurement. Only the marks that look wrong carry one, and the value for X was
   picked by rendering 1.00 / .90 / .84 / .78 beside its neighbours rather than guessed. */
.row__mk--x{--s:.84}        /* a solid glyph filling its square — the densest mark here */
.row__mk--rutgers{--s:.88}  /* solid slab R in saturated scarlet */

/* ---------- chapter ----------
   Everything from here to the colophon only shows up when a chapter or archive
   page is switched back on (PUBLISH_PAGES / PUBLISH_ARCHIVE in build.py). It is
   dormant, not dead — deleting it would break those pages the day they return. */
.back{font-size:.8rem;letter-spacing:.04em;color:var(--muted);border:0}
.back:hover{color:var(--accent)}

.ch__head{display:flex;flex-direction:column;gap:.55rem}
.ch__eyebrow{font-size:.68rem;text-transform:uppercase;letter-spacing:.2em;color:var(--accent)}
.ch__title{margin:0;font-family:var(--display);font-size:2.35rem;font-weight:600;
  letter-spacing:-.015em;line-height:1.06;text-wrap:balance}
.ch__stand{margin:0;font-size:1.06rem;line-height:1.62;max-width:var(--measure)}
.ch__stand .dc{float:left;font-family:var(--display);font-size:3.1rem;line-height:.82;
  padding:.16em .1em 0 0;font-weight:600;color:var(--accent)}

.ch__meta{display:flex;gap:1.6rem;flex-wrap:wrap;font-size:.8rem;color:var(--muted);
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:.7rem 0}
.ch__meta b{display:block;font-family:var(--display);font-size:1.3rem;font-weight:600;
  color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.01em}

/* Text is held to a reading measure; blocks (grids, lists, images) run full width.
   Clamping .prose itself would shrink the plate grid on wide chapters. */
.prose{display:flex;flex-direction:column;gap:1.1rem}
.prose > p,.prose > h2,.prose > blockquote,.prose > ul,.prose > ol{max-width:var(--measure)}
.prose p{margin:0;font-size:1.03rem;line-height:1.65}
.prose h2{margin:1.2rem 0 0;font-family:var(--display);font-size:1.35rem;font-weight:600;letter-spacing:-.01em}
.prose blockquote{margin:0;padding-left:1.1rem;border-left:2px solid var(--rule);
  color:var(--muted);font-style:italic}
.prose em{font-style:italic}
/* Archive photographs carry no width/height attributes; keep them contained. */
.prose img{max-width:100%;height:auto;display:block;border:1px solid color-mix(in srgb,var(--ink) 14%,transparent)}

/* ---------- work lists ---------- */
.group{display:flex;flex-direction:column;gap:.7rem}
.group__label{font-size:.68rem;text-transform:uppercase;letter-spacing:.16em;color:var(--accent);
  padding-bottom:.45rem;border-bottom:1px solid var(--rule)}
.items{display:flex;flex-direction:column;gap:.55rem}
.item{display:grid;grid-template-columns:1fr auto;gap:.1rem 1rem;align-items:baseline}
.item__t{font-size:.98rem;line-height:1.38}
.item__t a{color:var(--ink);border-bottom-color:color-mix(in srgb,var(--ink) 16%,transparent)}
.item__t a:hover{color:var(--accent);border-bottom-color:var(--accent)}
.item__n{font-size:.8rem;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}

/* ---------- plates ---------- */
.plates{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem 1.1rem}
.plate figure{margin:0;display:flex;flex-direction:column;gap:.42rem}
/* height:auto is load-bearing — the img's height="720" attribute is a presentational
   hint, and without overriding it the box stays 720px tall and aspect-ratio is ignored. */
.plate img{width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;display:block;
  border:1px solid color-mix(in srgb,var(--ink) 16%,transparent);background:var(--rule)}
.plate figcaption{font-size:.85rem;line-height:1.36}
.plate figcaption a{color:var(--ink);border-bottom-color:color-mix(in srgb,var(--ink) 16%,transparent)}
.plate figcaption a:hover{color:var(--accent);border-bottom-color:var(--accent)}
.plate .cnum{display:block;font-size:.76rem;color:var(--muted);
  font-variant-numeric:tabular-nums;margin-top:.15rem}
.rule-note{font-size:.85rem;color:var(--muted);font-style:italic;text-align:center;
  border-top:1px solid var(--rule);padding-top:.7rem}

/* ---------- colophon ---------- */
.colophon{font-size:.82rem;color:var(--muted);padding-top:.9rem;border-top:1px solid var(--rule);
  display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap}

/* ---------- the quote ----------
   A grace note at the foot of the homepage, chosen at build time (content/quotes.md).
   margin-top:auto pushes it to the bottom of the window on a short page. */
.quote{margin-top:auto;padding:1.7rem 1.5rem;text-align:center;
  border:1px solid transparent;border-radius:var(--plate);
  display:flex;flex-direction:column;align-items:center;gap:.55rem}
.quote__t{margin:0;max-width:30rem;font-size:.98rem;line-height:1.6;
  color:var(--ink);text-wrap:balance}
/* The gilt quotation (decision 002). The marks sit INLINE, not absolutely
   positioned: absolute hugged the words only while a quote fitted on one line,
   and drifted out to the edges of the measure the moment one wrapped.
   line-height:0 keeps a 1.95rem glyph from opening up the line it sits on. */
.qm{font-family:var(--display);font-size:1.95rem;line-height:0;
  color:var(--accent);vertical-align:-.3em}
.qm:first-child{margin-right:.04em}
.qm:last-child{margin-left:.04em}
/* the span is always rendered so the rotation script has somewhere to write —
   collapse it when a quote carries no attribution, so the gap doesn't show */
.quote__a{font-size:.78rem;letter-spacing:.02em;color:var(--muted)}
.quote__a:empty{display:none}
/* There is one gold. A lighter tint was tried for the gilt marks and dropped: any
   gold pale enough to read as "shiny" lands at ~2.6:1 on this cream, against 4.8:1
   for --accent, so it could never carry text. See docs/design/palette.md. */

/* The whole quote is one link (build.py wraps it), not just the attribution:
   one affordance instead of two, and a target you cannot miss. Text inside an
   <a> stays selectable, so a quote can still be dragged and copied.
   The affordance is PERSISTENT — a hairline under the attribution — because a
   link that only appears on hover does not exist on a phone. */
.quote__link{display:flex;flex-direction:column;align-items:center;gap:.55rem;
  color:inherit;border:0;text-decoration:none}
/* [href] because a quote without a source still renders as an <a> so the rotation script
   has somewhere to put one — but until it has a target it must not claim to be a link. */
.quote__link[href] .quote__a{border-bottom:1px solid color-mix(in srgb,var(--muted) 32%,transparent);padding-bottom:2px;
  transition:color .14s,border-color .14s}
.quote__link[href]:hover .quote__a{color:var(--accent);border-bottom-color:var(--accent)}
.quote__link:focus-visible{outline:2px solid var(--accent);outline-offset:8px;border-radius:3px}


/* ---------- Selected Quotes (/quotes) ----------
   The homepage letterhead with the publication mark swapped for a face. A speaker
   quoted more than once takes the full width; the eighteen quoted once run two
   across — a portrait, a name, a life span and a single sentence is a lot of
   furniture for one line, and at full width eighteen of them is most of the page.

   The portraits are duotoned into the page's own two inks by tools/make_portraits.py,
   so twenty pictures gathered from four centuries read as one printed set rather
   than as a scrapbook. */
/* The sort control ships NO JAVASCRIPT: two radios in front of the gallery, and the
   whole page reorders on a :checked selector driving `order` on the grid items. The
   per-speaker rules are generated into the page's own <style> by build.py — this
   file holds no data. A–Z is the DOM order, so it is what a browser too old for any
   of this still gets.
   The inputs are moved off the page rather than display:none'd — display:none takes
   them out of the tab order and the control stops working on a keyboard. */
.sorted{display:flex;flex-direction:column}
.qsort{position:absolute;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
.sortbar{display:flex;align-items:baseline;gap:1.1rem;font-size:.68rem;font-weight:500;
  text-transform:uppercase;letter-spacing:.18em;
  padding-bottom:.5rem;border-bottom:1px solid var(--rule)}
/* "Sort" is the only word here that is not a choice, so it does not look like one:
   italic, normal case and no tracking against two tracked capital labels. Since
   decision 008 this is a REAL drawn italic — a different alphabet, not a slant. */
.sortbar__l{font-family:var(--display);font-style:italic;font-weight:400;
  font-size:.95rem;text-transform:none;letter-spacing:0;color:var(--accent)}
.sortbar__o{color:var(--muted);cursor:pointer;padding-bottom:2px;
  border-bottom:1px solid transparent;transition:color .14s,border-color .14s}
.sortbar__o:hover{color:var(--accent)}
#qs-az:checked~.sortbar [for=qs-az],
#qs-yr:checked~.sortbar [for=qs-yr]{color:var(--ink);border-bottom-color:var(--accent)}
/* the focus ring has to land on the label, because the input it belongs to is a
   1px square parked off the page */
#qs-az:focus-visible~.sortbar [for=qs-az],
#qs-yr:focus-visible~.sortbar [for=qs-yr]{outline:2px solid var(--accent);
  outline-offset:4px;border-radius:2px}

.gal{display:grid;grid-template-columns:1fr 1fr;column-gap:1.5rem}
.spk{display:grid;grid-template-columns:var(--gutter) 1fr;column-gap:1.2rem;
  padding:1.1rem 0;border-bottom:1px solid color-mix(in srgb,var(--rule) 80%,transparent);align-items:start}
.spk--multi{grid-column:1/-1}
/* NOT :last-child — the cells reorder, so the last one in the DOM is not the last one
   on the page. build.py marks the final row of each sort order. */
.spk--last{border-bottom:none}
/* the other sort order's empty twins, waiting their turn */
.fy{display:none}
.plate{display:block;width:var(--gutter);height:calc(var(--gutter)*4/3);
  border:1px solid transparent;border-radius:var(--plate);overflow:hidden;
  background:color-mix(in srgb,var(--rule) 35%,transparent)}
.plate img{display:block;width:100%;height:100%;object-fit:cover}
/* the initials plate is the same box, so a missing photograph never breaks the
   one hard left edge the whole page is hung on */
.plate--none{display:flex;align-items:center;justify-content:center;
  font-family:var(--display);font-size:.92rem;font-weight:600;letter-spacing:.04em;
  color:var(--accent)}
.spk__body{min-width:0}
.spk__name{margin:0 0 .55rem;font-family:var(--display);font-size:1.18rem;font-weight:600;
  line-height:1.2;display:flex;align-items:baseline;gap:.55rem;flex-wrap:wrap}
.spk__meta{display:inline-flex;align-items:baseline;gap:.5rem;white-space:nowrap}
.spk__life{font-family:var(--body);font-size:.75rem;font-weight:400;color:var(--muted);
  font-variant-numeric:tabular-nums}
.spk__n{font-family:var(--body);font-size:.68rem;color:var(--accent);
  border:1px solid color-mix(in srgb,var(--accent) 42%,transparent);border-radius:999px;padding:.05rem .42rem;
  font-variant-numeric:tabular-nums}
.spk__qs{display:flex;flex-direction:column;gap:.6rem}
/* the rail is what keeps seven Steve Jobs quotes reading as seven quotes rather
   than as one paragraph */
.spk__q{display:block;padding-left:.85rem;border-left:1px solid var(--rule);
  border-bottom:0;color:inherit;transition:border-color .14s}
a.spk__q:hover{border-left-color:var(--accent)}
/* A bold quote — `**bold**` in content/quotes.md — is bigger and heavier, nothing
   else: the face's heaviest cut, a step up in size, and the same leading in both
   cell widths (Tyler, 2026-09-10 — "no stars, just bigger and bolder"). */
.spk__q--bold .spk__qt,.spk--one .spk__q--bold .spk__qt{font-size:1.12rem;font-weight:600;
  line-height:1.4}
a.spk__q:hover .spk__qt{color:var(--accent)}
.spk__qt{display:block;font-size:.97rem;line-height:1.5;color:var(--ink);
  transition:color .14s}
.spk__qw{display:block;font-size:.75rem;color:var(--muted);font-style:italic;margin-top:.14rem}
/* one-quote speakers: a tighter plate and no rail — there is nothing to separate */
.spk--one{grid-template-columns:2.4rem 1fr;column-gap:.85rem;padding:.85rem 0}
.spk--one .plate{width:2.4rem;height:2.4rem;margin-top:.15rem}
.spk--one .plate img{object-position:center 14%}
.spk--one .plate--none{font-size:.66rem}
.spk--one .spk__name{font-size:.98rem;margin-bottom:.3rem;gap:.4rem}
.spk--one .spk__q{padding-left:0;border-left:0}
.spk--one .spk__qt{font-size:.92rem;line-height:1.46}
/* the empty twin: it exists only to carry a rule across the other half of the row */
.spk--fill{padding:0}
.spk--fill .plate{display:none}

.credits{margin-top:2.6rem;padding-top:1.2rem;border-top:1px solid var(--rule);
  font-size:.78rem;color:var(--muted);line-height:1.55}
.credits h2{margin:0 0 .5rem;font-family:var(--body);font-size:.68rem;text-transform:uppercase;
  letter-spacing:.18em;font-weight:500;color:var(--accent)}
.credits ul{margin:0 0 .6rem;padding:0;list-style:none;columns:2;column-gap:2rem}
.credits li{margin:0 0 .18rem;break-inside:avoid}
.credits p{margin:0}

/* the quote panel now sits inside a labelled register like everything else */
/* THE QUOTE IS A BONUS, NOT A FOURTH SECTION (decision 009). It had the same label as
   Projects, Work and Education — capitals, gold, and a rule across the full measure —
   and read as equal to them. The label is gone, the rule with it, and the block sits
   lower with real space over it. Do not put a register label back on this. */
.reg--quote{margin-top:auto;padding-top:2.6rem}
.reg--quote .quote{margin-top:0}
/* The card no longer links anywhere; its two destinations are named underneath. Kept
   CLOSE to the card on purpose — they belong to the quote, not to the page. */
.qblock{display:flex;flex-direction:column;gap:.4rem}
/* the card's own 1.7rem bottom padding was doing the spacing, which put the links a
   third of the way to the next section — they sit under the attribution instead */
.qblock .quote{padding-bottom:.35rem}
.qfoot{display:flex;align-items:center;justify-content:center;gap:.5rem;
  font-size:.74rem;line-height:1.4}
.qsep{color:var(--rule)}
/* Deliberately faint (Tyler, 2026-08-02: "much lighter"). ~2.5:1 against the paper,
   which is under the readable threshold — so the underline carries the affordance
   rather than the colour, and hover/focus go to full accent. */
/* `hidden` is only a UA-stylesheet rule, and ANY author rule that sets display beats it —
   so .qtxt's own display would un-hide it. Without this line a quote with no source
   prints a dead "Source" link. */
.qtxt[hidden],.qsep[hidden]{display:none}
.qtxt{color:color-mix(in srgb,var(--muted) 62%,transparent);display:inline-flex;align-items:baseline;gap:.35em;
  border-bottom:1px solid color-mix(in srgb,var(--muted) 26%,transparent);padding-bottom:1px;
  transition:color .14s,border-color .14s}
.qtxt:hover{color:var(--accent);border-bottom-color:var(--accent)}
.qtxt:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}
.qtxt .ar,.qtxt .ar--out{width:.62em;height:.62em;flex:none;align-self:center}
.qtxt:hover .ar{transform:translateX(.15em)}
.qtxt:hover .ar--out{transform:translate(.1em,-.1em)}
/* The rule belongs under the WORDS, not under the arrow — an underlined arrow reads
   as a mistake. So the link carries no border and the text span carries it instead. */
.reg__label a{color:inherit;border-bottom:0;display:inline-flex;align-items:center;
  gap:.5em}
.reg__t{border-bottom:1px solid color-mix(in srgb,var(--accent) 32%,transparent);padding-bottom:.15em;
  transition:border-color .14s}
.reg__label a:hover .reg__t{border-bottom-color:var(--accent)}
/* Sized in em so it tracks the label rather than needing its own breakpoint. The
   letter-spacing is cancelled: .18em of tracking after the last letter would push the
   arrow away from the word it belongs to. */
.ar{width:.62rem;height:.62rem;flex:none;margin-left:-.12em;
  transition:transform .16s ease}
/* Back, at the top left above the title. NO BOX (Tyler, 2026-08-02): it was the site's
   bordered button and the border made a piece of navigation the loudest object on the
   page's first line. It rides high — the negative margin pulls it up out of the page's
   4rem top padding — and it is faint enough to find only when looked for. The arrow
   leads rather than trails, because it points the way it goes. */
.backbtn{align-self:flex-start;display:inline-flex;align-items:center;gap:.45em;
  margin-top:-1.9rem;font-size:.64rem;text-transform:uppercase;font-weight:500;
  letter-spacing:.16em;color:color-mix(in srgb,var(--accent) 50%,transparent);border:0;transition:color .14s}
.backbtn:hover{color:var(--accent)}
.backbtn:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:2px}
.backbtn .ar--back{width:.66em;height:.66em;flex:none;align-self:center}
.backbtn:hover .ar--back{transform:translateX(-.15em)}

/* the back link at the foot of a chapter, and the arrow leads the words */
.back{display:inline-flex;align-items:center;gap:.45em;border-bottom:0}
.back span{border-bottom:1px solid color-mix(in srgb,var(--accent) 32%,transparent);transition:border-color .14s}
.back:hover span{border-bottom-color:var(--accent)}
.ar--back{width:.72em;height:.72em;margin-left:0;transition:transform .16s ease}
.back:hover .ar--back{transform:translateX(-.15em)}
.reg__label a:hover .ar{transform:translateX(.15em)}

/* ---------- the 404 ----------
   Decision 012. The 404 is the quotes page's layout with the roster removed: one
   speaker, one sentence, the face in the same gutter every mark and portrait on this
   site sits in. The quotes it draws from live ONLY here (content/404-quotes.md) —
   asking for a page that isn't there is how a reader finds them.

   The plate is emitted even for a quote with no portrait, because the rotation script
   may swap in one that has a face. When it is hidden the gutter goes with it, or the
   sentence would start at an indent nothing explains. */
/* The 404 is a short page on a tall screen, and left at the top of one it read as a
   page that had been cut off rather than composed. It holds the window and centres in
   it — min-height, never height, so a long quote on a phone grows the page instead of
   centring itself out of reach. Same mechanism as .page--home's footer quote. */
.page--nfq{gap:1.7rem;min-height:100vh;justify-content:center;
  padding-top:3rem;padding-bottom:3rem}
.nfq{display:grid;grid-template-columns:var(--gutter) 1fr;column-gap:1.2rem;
  align-items:start;padding-bottom:1.4rem;border-bottom:1px solid var(--rule)}
.nfq:has(.nfq__por[hidden]){grid-template-columns:1fr}
/* the same 3:4 plate on a hairline as the masthead portrait and every speaker on
   /quotes — nudged down so its top meets the quote's cap height, not its line box */
.nfq__por{width:var(--gutter);height:calc(var(--gutter)*4/3);object-fit:cover;
  border:1px solid transparent;border-radius:var(--plate);margin-top:.42rem}
.nfq__body{display:flex;flex-direction:column;gap:.7rem;min-width:0;align-items:flex-start}
.nfq__t{margin:0;font-family:var(--display);font-size:1.72rem;font-weight:500;
  line-height:1.22;letter-spacing:-.012em;text-wrap:balance;max-width:var(--measure)}
/* the gilt marks stay gold (decision 002) and scale with the quote — the home page's
   ratio is 1.95rem of mark to .98rem of text, and this holds it at 1.72rem */
.nfq__t .qm{font-size:3.4rem;vertical-align:-.32em}
.nfq__a{font-size:.86rem;color:var(--muted)}
/* .qtxt carries no size of its own — on the home page it inherits .74rem from .qfoot,
   but here it sat in the page's own 19px body and came out larger than the attribution
   above it. It is a footnote to the quote, so it is sized like one. The arrow is .62em
   and follows on its own. */
.nfq__src{font-size:.72rem}
.nfq__foot{display:flex}
/* It says the one thing it has to say, once, in the same voice as every other label on
   the site, and it says it FIRST — a reader who mistyped should learn that before they
   are handed a quote, not after. A muted sentence here read as an apology. */
.nfq__note{margin:0;font-size:.68rem;text-transform:uppercase;letter-spacing:.2em;
  color:var(--accent)}
/* One door. .row__more is built for a grid cell on the home page; here it is a button,
   and the arrow leads rather than follows because the word is Back. */
.nfq__home{grid-column:auto;grid-row:auto;justify-self:auto;margin-top:0;height:auto;
  padding:.34rem .74rem;align-items:center;gap:.5em}
.nfq__home .ar--back{width:.72em;height:.72em;flex:none;transition:transform .16s ease}
.nfq__home:hover .ar--back{transform:translateX(-.15em)}

@media (max-width:640px){
  body{font-size:18px}
  .page{padding:2.6rem 1.15rem 3.5rem;gap:2.1rem}
  .page--home{padding:3rem 1.15rem 2.2rem;gap:2rem}
  .mast__name{font-size:2.3rem}
  .quote{padding:1.4rem 1.1rem}
  .quote__t{font-size:.95rem}
  .ch__title{font-size:1.8rem}
  /* rows keep their two columns on a phone — a name and a date fit side by side.
     Only the long work lists on chapter pages need to stack. */
  .row{gap:.2rem .8rem}
  /* One token still, so the portrait and the marks stay on the same axis. The marks
     shrink with the column, but not below the size where Barstool's star ring and the
     Gold's Guide bar stop being drawings and turn to mud. */
  :root{--gutter:3.6rem}
  .reg--marked{--box:2.6rem}
  .reg--marked .row{column-gap:1rem}
  .mast{gap:1rem}
  .item{grid-template-columns:1fr}
  .item__n{grid-row:2}
  .plates{grid-template-columns:repeat(2,1fr);gap:1rem .8rem}
  .ch__meta{gap:1.1rem}
  /* the 404's quote is the largest type on a phone; hold it under the measure */
  .nfq__t{font-size:1.42rem}
  .nfq__t .qm{font-size:2.8rem}
  /* two-up cannot survive a phone: the measure would be about 24 characters.
     Below this the compression is the only part of the gene that carries over. */
  .gal{grid-template-columns:1fr}
  /* one column, so there is no hole to fill and the filler would print as a
     blank banded row of its own */
  .spk--fill{display:none}
  .credits ul{columns:1}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* ---------- night, part two ---------- */
/* Same media query as the token block at the top; these live last because they override
   daytime rules of equal specificity, and the cascade is source order. Every link carries
   a solid gold underline, and the one button on the page is filled — with one colour of
   text, that is all that says what is clickable. */
@media (prefers-color-scheme:dark){
  a,.mast__contact a,.row__name a{border-bottom-color:color-mix(in srgb,var(--accent) 55%,transparent)}
  .row__more{background:var(--accent);color:var(--paper);border-color:var(--accent)}
  .row__more:hover{background:color-mix(in srgb,var(--accent) 86%,var(--paper))}
}
