/* ==========================================================================
   Amin Mansouri - personal site
   Hand-written. No preprocessor, no build step, no framework.

   THE RULE THAT IS THE WHOLE IDENTITY, applied without exception:
     SERIF carries every sentence a human wrote.
     MONO  carries only machine facts - dates, DOIs, identifiers, labels.
   A reader can tell at a glance which parts of the page are argument and
   which are record. That is most of the design.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS.  All contrast ratios are computed WCAG 2.1 relative luminance.
      Light is the base. Dark redefines ONLY these same names.
   -------------------------------------------------------------------------- */
:root {
  color-scheme: light dark;

  /* grounds */
  --paper:        #FAF8F4;
  --paper-2:      #F3EFE7;   /* recessed: reply band, advocacy aside */

  /* ink */
  --ink:          #1A1D21;   /* 15.95:1 on --paper / 15.35:1 on --paper-2  AAA */
  --ink-muted:    #55595F;   /*  6.64:1 on --paper /  6.14:1 on --paper-2  AA  */

  /* accents - exactly two, each with one job */
  --accent:       #144E63;   /*  8.61:1 on --paper /  7.96:1 on --paper-2  AAA */
  --accent-ink:   #FAF8F4;   /*  8.61:1 on --accent - label on filled button */
  --mark:         #9A4A21;   /*  5.87:1 on --paper /  5.42:1 on --paper-2  AA
                                derived or live: the modelled chip and the traverse reading edge. */

  /* lines - three weights, each with a stated contrast floor */
  --rule:         #C7BFAF;   /* 1.72:1 - decorative hairlines only */
  --rule-strong:  #A79D8A;   /* 2.53:1 - margin rule, section rules, author dots */
  --edge:         #8F8877;   /* 3.32:1 - MEETS SC 1.4.11. The ONLY token allowed as
                                the sole visible boundary of an interactive control. */

  --focus:        #144E63;
  --select:       #D8E4EA;

  /* spacing - 4px base. Nothing between steps. */
  --s-1: .25rem;  --s-2: .5rem;  --s-3: .75rem; --s-4: 1rem;  --s-5: 1.5rem;
  --s-6: 2rem;    --s-7: 3rem;   --s-8: 4rem;   --s-9: 6rem;

  --measure:    34rem;    /* prose column - 61-63ch at --t-base */
  --margin-col: 17rem;    /* evidence margin - 38ch at --t-sm, deliberately shorter */
  --gap-col:    2.5rem;
  --page:       53.5rem;  /* measure + gap + margin. Nothing is wider. */
  --pad-x:      clamp(1.25rem, 4vw, 3rem);
  --bar-h:      3.25rem;

  /* type */
  --font-prose: "Source Serif 4", "Serif Fallback", Georgia, "Iowan Old Style",
                "Times New Roman", serif;
  --font-meta:  "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
                Consolas, monospace;

  --t-mono-xs: .6875rem;
  --t-mono-sm: .75rem;
  --t-mono-md: .8125rem;
  --t-sm:      .9375rem;
  --t-base:    clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  --t-h3:      clamp(1.0625rem, 1rem + 0.3vw, 1.125rem);
  --t-h2:      clamp(1.375rem, 1.2rem + 0.8vw, 1.75rem);
  --t-lede:    clamp(1.1875rem, 1.05rem + 0.8vw, 1.5rem);
  --t-h1:      clamp(2.125rem, 1.5rem + 2.8vw, 3.25rem);
}

/* DARK, declared TWICE on purpose. This is the whole mechanism behind the
   scheme control. The media block is guarded by :not([data-theme="light"]) so
   an explicit "Light" choice can beat a dark-mode OS; the attribute block below
   gives an explicit "Dark" choice something to win with on a light-mode OS.
   Without BOTH, the control is decoration: against a bare @media rule, picking
   Light on a dark OS changes nothing at all.

   The duplication is real, and it is the price of supporting browsers older
   than mid-2024. When those stop mattering, light-dark() collapses this to one
   declaration per token and both blocks go.

   THE TWO BLOCKS MUST STAY IDENTICAL. Edit one, edit the other. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:       #14161A;
    --paper-2:     #1B1E23;

    --ink:         #ECE7DE;  /* 14.71:1 / 13.42:1  AAA */
    --ink-muted:   #A2A8B0;  /*  7.56:1 /  6.90:1  AAA */

    --accent:      #79BDD6;  /*  8.68:1 /  7.92:1  AAA */
    --accent-ink:  #0E1216;  /*  9.01:1 on --accent */
    --mark:        #E0885C;  /*  6.77:1 /  6.18:1  AA
                                (#9A4A21 would fall to 2.9:1 here and fail) */

    --rule:        #3B3F46;  /* 1.71:1 - optically matched to light's 1.72 */
    --rule-strong: #565C66;  /* 2.69:1 */
    --edge:        #646B76;  /* 3.37:1 - MEETS SC 1.4.11 */

    --focus:       #79BDD6;
    --select:      #23343C;
  }
}
:root[data-theme="dark"] {
  --paper:       #14161A;
  --paper-2:     #1B1E23;

  --ink:         #ECE7DE;
  --ink-muted:   #A2A8B0;

  --accent:      #79BDD6;
  --accent-ink:  #0E1216;
  --mark:        #E0885C;

  --rule:        #3B3F46;
  --rule-strong: #565C66;
  --edge:        #646B76;

  --focus:       #79BDD6;
  --select:      #23343C;
}

/* Pin the UA scheme to the resolved theme, or scrollbars, native form controls
   and the radio inputs inside the scheme control itself stay on the OS setting
   while the page around them changes. With JS off neither attribute is ever
   written and the `color-scheme: light dark` on :root stands - today's
   behaviour, unchanged. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark;  }

/* Metric-matched fallback so the serif swap does not reflow.
   VERIFY against a real render before claiming zero CLS; if reflow shows,
   switch Source Serif 4 to font-display:optional rather than tuning blind. */
@font-face {
  font-family: "Serif Fallback";
  src: local("Georgia"), local("Times New Roman");
  size-adjust: 98%;
  ascent-override: 92%;
  descent-override: 26%;
  line-gap-override: 0%;
}

/* --------------------------------------------------------------------------
   2. RESET AND BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  overflow-x: clip;          /* backstop only - never load-bearing */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-prose);
  font-size: var(--t-base);
  line-height: 1.65;
  font-synthesis-weight: none;
  hanging-punctuation: first;   /* Safari only; degrades silently */
  hyphens: none;                /* actively harmful across surnames and DOIs */
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; text-wrap: balance; }
p, li, dd, dt   { text-wrap: pretty; }
p { margin: 0 0 1.15em; }
ul, ol, dl { margin: 0; padding: 0; }
cite { font-style: italic; }

::selection { background: var(--select); color: var(--ink); }

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

/* Visited links are NOT restyled: a reader who has clicked a DOI should not
   see the page change character. */
a { color: var(--accent); }
a:hover { text-decoration-thickness: 2px; }

.mono {
  font-family: var(--font-meta);
  font-variant-numeric: tabular-nums;
}

.vh {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: var(--s-4); top: -3rem; z-index: 100;
  background: var(--accent); color: var(--accent-ink);
  font-family: var(--font-meta); font-size: var(--t-mono-sm);
  padding: var(--s-3) var(--s-4); border-radius: 2px;
  text-decoration: none;
}
.skip:focus { top: var(--s-3); }

/* --------------------------------------------------------------------------
   3. STICKY BAR
   -------------------------------------------------------------------------- */
.bar {
  position: sticky; top: 0; z-index: 10;
  height: var(--bar-h);
  background: var(--paper);
  /* Default is the SAFE state: hairline present. main.js adds .js to <html>,
     which is what enables the transparent-at-top behaviour. With JS off the
     hairline is simply always there - never the reverse. */
  border-bottom: 1px solid var(--rule);
}
@supports (backdrop-filter: blur(10px)) {
  .bar {
    background: color-mix(in srgb, var(--paper) 92%, transparent);
    backdrop-filter: blur(10px);
  }
}
.js .bar { border-bottom-color: transparent; transition: border-color 120ms ease; }
.js .bar.is-scrolled { border-bottom-color: var(--rule); }

.bar-in {
  max-width: var(--page); margin-inline: auto;
  padding-inline: var(--pad-x);
  height: 100%;
  display: flex; align-items: center; gap: var(--s-4);
}
.bar-name {
  font-family: var(--font-meta); font-size: var(--t-mono-sm);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bar-alt { display: none; }
.bar-nav { display: none; margin-left: auto; gap: var(--s-5); }
.bar-nav a {
  font-family: var(--font-meta); font-size: var(--t-mono-sm);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-muted); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 2.75rem;
}
.bar-nav a:hover { color: var(--ink); text-decoration: underline; }
.bar .btn { margin-left: auto; }

@media (min-width: 560px) {
  .bar-alt { display: inline; }
  .bar-nav { display: flex; }
  .bar .btn { margin-left: 0; }
}
/* Landscape phones: do not let the bar eat a third of the screen. */
@media (max-height: 26rem) { .bar { position: static; } }

/* --------------------------------------------------------------------------
   4. BUTTONS
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 2.75rem; padding: var(--s-2) var(--s-4);
  font-family: var(--font-meta); font-size: var(--t-mono-md);
  text-decoration: none; border-radius: 2px;
  border: 1px solid transparent; white-space: nowrap;
}
.btn--primary { background: var(--accent); color: var(--accent-ink); }
.btn--primary:hover { text-decoration: underline; text-decoration-thickness: 2px; }
.btn--ghost { color: var(--ink); border-color: var(--edge); }  /* 3.32:1 - SC 1.4.11 */
.btn--ghost:hover { border-color: var(--ink); }

/* --------------------------------------------------------------------------
   5. LAYOUT - the letter, and its two modes
   -------------------------------------------------------------------------- */
main { display: block; }

.letter {
  position: relative;
  max-width: calc(var(--page) + var(--s-6));
  margin-inline: auto;
  padding-inline: var(--pad-x);
  padding-left: calc(var(--pad-x) + 1.25rem);
}
/* ONE margin rule for the whole letter, not one per block - so it runs
   unbroken instead of segmenting at every gap. */
.letter::before {
  content: ""; position: absolute;
  left: var(--pad-x); top: 0; bottom: 0;
  width: 1px; background: var(--rule-strong);
}

section { padding-block: clamp(3rem, 2rem + 4vw, 5.5rem); scroll-margin-top: 5rem; }
:target { scroll-margin-top: 5rem; }

/* MODE A - .leaf (annotated). Only sections with real receipts to pin. */
.leaf { display: block; }
.leaf > .body { max-width: var(--measure); }   /* AT ALL WIDTHS. This single
    declaration is what stops prose running 78ch at 768px and 92ch at 1024px -
    the worst-set text on the page landing on iPad landscape. */
.leaf > .note {
  max-width: var(--measure);
  border-left: 2px solid var(--rule-strong);
  padding-left: var(--s-4);
  margin-block: var(--s-5);
}

/* MODE B - .block (full width of the letter). Sub-grids live HERE, never
   nested inside the prose column beside dead margin. */
.block { max-width: var(--page); }
.block > .body { max-width: var(--measure); }

@media (min-width: 1080px) {
  .leaf {
    display: grid;
    grid-template-columns: var(--measure) var(--margin-col);
    column-gap: var(--gap-col);
    align-items: start;
  }
  .leaf > .note {
    grid-column: 2;
    border-left: 0; padding-left: 0; margin-block: 0;
    padding-top: .35rem; max-width: none;
  }
}

/* --------------------------------------------------------------------------
   6. TYPE ROLES
   -------------------------------------------------------------------------- */
.kicker {
  font-size: var(--t-mono-sm); text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-muted); margin: 0 0 var(--s-5);
}
h1 { font-size: var(--t-h1); line-height: 1.04; letter-spacing: -.026em; }
.byline {
  font-size: var(--t-mono-md); color: var(--ink-muted);
  margin: var(--s-2) 0 var(--s-6);
}
.lede {
  font-size: var(--t-lede); line-height: 1.35; letter-spacing: -.011em;
  margin-bottom: var(--s-5);
}
.hero { padding-top: clamp(2.5rem, 1.5rem + 4vw, 4.5rem); }

.sec-h {
  font-size: var(--t-h2); line-height: 1.2; letter-spacing: -.015em;
  margin-bottom: var(--s-6); padding-top: var(--s-4);
  border-top: 1px solid var(--rule-strong);
  max-width: var(--page);
}
.sec-n {
  display: block;
  font-size: var(--t-mono-sm); font-weight: 500;
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-muted); margin-bottom: var(--s-2);
}

.note-head {
  font-size: var(--t-mono-sm); font-weight: 500;
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-muted); margin: 0 0 var(--s-2);
}
.note { font-size: var(--t-sm); line-height: 1.55; color: var(--ink-muted); }
.note p:last-child { margin-bottom: 0; }
.note .note-head + p { margin-bottom: var(--s-4); }
.roster { font-family: var(--font-meta); font-size: var(--t-mono-md); }

.actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-6); }

/* Hero record panel */
.rec { list-style: none; }
.rec li {
  padding-block: var(--s-2);
  border-top: 1px solid var(--rule);
}
.rec li:first-child { border-top: 0; padding-top: 0; }
.rec-v { display: block; color: var(--ink); }
.rec-s {
  display: block; font-size: var(--t-mono-xs);
  text-transform: uppercase; letter-spacing: .09em;
}
.rec-more { margin-top: var(--s-3); }

/* The a/b/c trio */
.trio { list-style: none; margin-top: var(--s-5); }
.trio li { position: relative; margin-bottom: var(--s-3); }
.trio-n {
  font-size: var(--t-mono-sm); color: var(--ink-muted);
  text-transform: uppercase; letter-spacing: .12em;
  margin-right: var(--s-3);
}
@media (min-width: 720px) {
  .trio li { padding-left: 0; }
  .trio-n { position: absolute; left: -1.75rem; margin-right: 0; }
  .trio { padding-left: 0; }
}

/* --------------------------------------------------------------------------
   7. PUBLICATIONS
   -------------------------------------------------------------------------- */
.pubs-wrap { padding-top: 0; }
.grp {
  font-size: var(--t-mono-sm); font-weight: 500;
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-muted);
  margin: var(--s-6) 0 var(--s-5);
}
.pubs { list-style: none; }
.pub {
  max-width: var(--measure);
  padding-bottom: var(--s-6); margin-bottom: var(--s-6);
  border-bottom: 1px solid var(--rule);
}
.pubs > .pub:last-child { border-bottom: 0; margin-bottom: 0; }

.chips { display: flex; flex-wrap: wrap; gap: .375rem; margin: 0 0 var(--s-2); }
.chip {
  font-family: var(--font-meta);
  font-size: var(--t-mono-xs); text-transform: uppercase; letter-spacing: .09em;
  padding: .2rem .5rem; border: 1px solid currentColor; border-radius: 2px;
  white-space: nowrap;
}
.chip--peer  { color: var(--accent); }
.chip--press { color: var(--ink-muted); }
.chip--oral  { color: var(--ink-muted); }
.chip--prog  { color: var(--ink-muted); }
.chip--first { color: var(--mark); }   /* the page's only hue shift */

.pub-title {
  font-size: var(--t-h3); line-height: 1.3;
  margin-bottom: var(--s-2);
}

/* AUTHOR EMPHASIS: value and weight, never colour, never a highlight. */
.authors {
  display: flex; flex-wrap: wrap; gap: 0 .35rem;
  list-style: none; margin: 0 0 .35rem;
  font-size: var(--t-sm); line-height: 1.55; color: var(--ink-muted);
}
.authors > li { white-space: nowrap; }   /* wraps land BETWEEN authors */
.authors > li:not(:last-child)::after {
  /* separator drawn, not typed - no screen reader announces a middot 40 times */
  content: ""; display: inline-block;
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--edge); vertical-align: .32em; margin-left: .35rem;
}
.authors-prose {
  font-size: var(--t-sm); line-height: 1.55; color: var(--ink-muted);
  margin: 0 0 .35rem;
}
.me { color: var(--ink); font-weight: 600; }

.position {
  font-size: var(--t-mono-xs); text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-muted); margin: 0 0 var(--s-2);
}
.venue { font-size: var(--t-sm); margin: 0 0 var(--s-1); }
.num { font-size: var(--t-mono-md); color: var(--ink-muted); }

.doi { margin: 0 0 var(--s-3); }
.doi a {
  font-family: var(--font-meta); font-size: var(--t-mono-md);
  color: var(--accent);
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  display: inline-block; max-width: 100%;
  overflow-wrap: anywhere;              /* SCOPED here and .contact-value only */
  padding-block: .35rem;                /* .35 x 2 + line = 44px tap target */
}
.doi .doi-prefix { color: var(--ink-muted); }

.locator {
  font-size: var(--t-mono-md); color: var(--ink-muted);
  margin: 0 0 var(--s-3);
}
.finding { font-style: italic; font-size: var(--t-sm); margin: 0; }
.mypart { font-size: var(--t-sm); color: var(--ink-muted); margin: var(--s-2) 0 0; }
.mypart .mono {
  font-size: var(--t-mono-xs); text-transform: uppercase; letter-spacing: .09em;
  margin-right: var(--s-2);
}

/* --------------------------------------------------------------------------
   8. LEDGER, RAIL, TIMELINE  (all MODE B - full block width)
   -------------------------------------------------------------------------- */
.lead-line { margin-bottom: var(--s-6); }

.ledger { display: grid; row-gap: var(--s-5); }
.ledger dt {
  font-size: var(--t-mono-sm); text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-muted); margin-bottom: var(--s-1);
}
.ledger dd { margin-inline-start: 0; max-width: var(--measure); }
@media (min-width: 900px) {
  .ledger {
    grid-template-columns: 12rem minmax(0, 1fr);
    column-gap: var(--s-6); row-gap: var(--s-5);
  }
  .ledger dt { margin-bottom: 0; padding-top: .3rem; }
}

.rail { list-style: none; margin: var(--s-6) 0; }
.rail li {
  position: relative;
  border-left: 1px solid var(--rule-strong);
  padding-left: var(--s-4); padding-block: var(--s-2);
}
.rail li::before {
  content: ""; position: absolute; left: 0; top: 1rem;
  width: .75rem; height: 1px; background: var(--ink-muted);
}
.rail-t {
  display: block;
  font-size: var(--t-mono-sm); text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink); margin-bottom: var(--s-1);
}
.rail-d { display: block; font-size: var(--t-sm); color: var(--ink-muted); }
@media (min-width: 900px) {
  .rail {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0; border-top: 1px solid var(--rule-strong);
  }
  .rail li {
    border-left: 0; padding-left: 0;
    padding-top: var(--s-4); padding-right: var(--s-5);
  }
  .rail li::before { top: 0; left: 0; width: 1px; height: .75rem; }
}

.aside-note { color: var(--ink-muted); font-size: var(--t-sm); }

.timeline { list-style: none; }
.timeline li {
  display: grid; gap: var(--s-1);
  padding-block: var(--s-4);
  border-top: 1px solid var(--rule);
}
.timeline li:first-child { border-top: 0; padding-top: 0; }
.tl-what { font-weight: 600; }
.tl-what .chip { margin-left: var(--s-2); font-weight: 400; vertical-align: .1em; }
.tl-when { font-size: var(--t-mono-md); color: var(--ink-muted); }
.tl-where { font-size: var(--t-sm); color: var(--ink-muted); }
@media (min-width: 720px) {
  .timeline li {
    grid-template-columns: minmax(0, 1fr) 10rem;
    column-gap: var(--s-5);
  }
  .tl-what  { grid-column: 1; grid-row: 1; }
  .tl-where { grid-column: 1; grid-row: 2; }
  .tl-when  { grid-column: 2; grid-row: 1 / span 2; text-align: right; }
}

.skills { font-size: var(--t-sm); margin-bottom: var(--s-2); }
.skills-k {
  display: block;
  font-size: var(--t-mono-xs); text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-muted); margin-bottom: var(--s-1);
}
.timeline + .skills { margin-top: var(--s-6); }

/* Advocacy / press slot */
.record-box {
  border: 1px solid var(--rule); border-radius: 2px;
  background: var(--paper-2);
  padding: var(--s-4); margin-block: var(--s-5);
  max-width: var(--measure);
}
.recs { list-style: none; }
.recs li { padding-block: var(--s-2); }
.rec-t { display: block; }
.rec-l { display: block; font-size: var(--t-mono-md); }

/* --------------------------------------------------------------------------
   9. REPLY BAND AND FOOTER
   -------------------------------------------------------------------------- */
.reply {
  background: var(--paper-2);
  border-top: 1px solid var(--rule-strong);
  padding-block: clamp(2.5rem, 1.5rem + 4vw, 4rem);
  margin-top: var(--s-8);
}
.reply-in {
  max-width: var(--page); margin-inline: auto; padding-inline: var(--pad-x);
}
.reply .sec-h { border-top: 0; padding-top: 0; }
.reply .body { max-width: var(--measure); }

.contact { display: grid; gap: var(--s-3); margin-top: var(--s-6); }
.contact dt {
  font-size: var(--t-mono-xs); text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-muted);
}
.contact dd { margin-inline-start: 0; }
.contact-value { overflow-wrap: anywhere; }
.contact-email a { font-size: var(--t-lede); }
@media (min-width: 560px) {
  .contact { grid-template-columns: 10rem minmax(0, 1fr); gap: var(--s-4) var(--s-5); }
  .contact dt { padding-top: .35rem; }
}

footer { border-top: 1px solid var(--rule-strong); }
.foot-in {
  max-width: var(--page); margin-inline: auto;
  padding-inline: var(--pad-x); padding-block: var(--s-7);
}
.foot-meta, .foot-note {
  font-size: var(--t-mono-sm); line-height: 1.8;
  color: var(--ink-muted); overflow-wrap: anywhere;
}
.foot-note { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   9b. THE SCHEME CONTROL

   It lives in the footer beside "Hold motion", because those are the page's
   two controls and they belong together. The sticky bar is 3.25rem of a single
   flex row that already ellipsises the name at 360px; three more mono chips in
   there would either overflow it or be hidden exactly on the phones where the
   OS scheme flips at sunset.

   THE MOTION RULE, applied honestly. A colour scheme is a boolean. Its physics
   is a relay: contacts closed to contacts open, no interpolation. So it steps.
   transition: none, deliberately, and there is no reduced-motion branch here
   because there is nothing to reduce - the two states are byte-identical. The
   tempting 200ms crossfade would be the only cubic-bezier on the site, and it
   would also be the only moment when the page's contrast is unknown: mid-fade
   between #FAF8F4 and #1A1D21, body text drops under 4.5:1 for about six
   frames. Stepping cannot do that.
   -------------------------------------------------------------------------- */
.themer { display: none; border: 0; margin: var(--s-4) 0 0; padding: 0; }
/* The control appears only where it can work. [data-theme] is written by the
   inline head script BEFORE first paint, so the browser lays the page out once
   - never once without the control and again with it. */
:root[data-theme] .themer { display: flex; gap: 2px; align-items: center; }
.themer legend { padding: 0; }
.themer input {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.themer label {
  display: inline-flex; align-items: center; min-height: 2.25rem;
  padding: 0 .7rem;
  font: 500 var(--t-mono-sm)/1 var(--font-meta); letter-spacing: .04em;
  color: var(--ink-muted); background: none;
  border: 1px solid transparent; border-radius: 2px;
  cursor: pointer; transition: none;          /* a relay does not ease */
}
.themer label:hover { color: var(--ink); }
/* Driven by the root attribute, which is set pre-paint, so the control itself
   never flashes the wrong state either. */
:root[data-theme-pref="system"] .themer label[for="th-system"],
:root[data-theme-pref="light"]  .themer label[for="th-light"],
:root[data-theme-pref="dark"]   .themer label[for="th-dark"] {
  color: var(--ink); background: var(--paper-2); border-color: var(--edge);
}
.themer input:focus-visible + label { outline: 2px solid var(--focus); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   10. MOTION, PRINT, FORCED COLORS
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
@media (prefers-reduced-motion: reduce) {
  .bar, .js .bar { transition: none; }
}

@media print {
  /* LAST tokens in the sheet. :root[data-theme] is (0,2,0), which ties the
     dark attribute block and beats it on source order - so printing from a
     dark-mode OS, or with Dark explicitly chosen, still prints on white. */
  :root, :root[data-theme] {
    --paper: #fff; --paper-2: #fff; --ink: #000; --ink-muted: #444;
    --accent: #000; --accent-ink: #fff; --mark: #000;
    --rule: #bbb; --rule-strong: #888; --edge: #666;
    color-scheme: light;
  }
  .bar, .skip, .themer { display: none !important; }
  * { background: #fff !important; color: #000 !important; }
  .letter::before { display: none; }
  .leaf { display: block; }
  .body, .note, .pub { max-width: none; }
  /* SCOPED. An unscoped rule would stamp (#evidence) and (mailto:...) across a
     page that is explicitly meant to be printed and forwarded. */
  .pubs a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; }
  .reply { border-top: 1px solid #000; }
}

@media (forced-colors: active) {
  .chip, .btn { border: 1px solid ButtonBorder; color: ButtonText; background: ButtonFace; }
  .authors > li:not(:last-child)::after {
    background: CanvasText; forced-color-adjust: none;
  }
  .letter::before, .rail li::before { background: CanvasText; forced-color-adjust: none; }

  /* Forced colors flattens every border and background to system colours, so
     the selected chip would otherwise be indistinguishable from the other two.
     Underline is a channel that survives. */
  .themer label { border-color: ButtonBorder; color: ButtonText; }
  :root[data-theme-pref="system"] .themer label[for="th-system"],
  :root[data-theme-pref="light"]  .themer label[for="th-light"],
  :root[data-theme-pref="dark"]   .themer label[for="th-dark"] {
    border-color: Highlight; color: Highlight; text-decoration: underline;
  }
}
