/* site.css - every other rule, in original cascade order
 *
 * Lifted verbatim from Views/blogPost.cshtml (whose CSS was the superset of
 * Views/Home.cshtml's) during task group 4 of .kiro/specs/site-standardization.
 * Rule order is preserved deliberately: the article carries six separate
 * @media (max-width:760px) blocks and the trailing "mobile pass" overrides the
 * earlier ones, so merging or tidying duplicate media blocks is a regression.
 *
 * Load order matters and is tokens.css then site.css.
 */

body {
  margin:0; background:var(--paper); color:var(--ink-2);
  font-family:var(--serif); font-size:18px; line-height:1.65;
  font-kerning:normal; text-rendering:optimizeLegibility;
}
/* Bottom padding is 56 rather than 96 because a site footer now follows: 56 is the gap
   the home page's copyright rule already sat at, so the rhythm is the one this design
   had, and the article stops trailing off into 96px of nothing. */
.wrap { max-width:65rem; margin:0 auto; padding:0 24px 56px; }

/* Justified setting. At the full 992px measure the line is long enough that justification
   does not open rivers; the phone breakpoint reverts to left, where it would. */
.wrap > p:not(.sub), .apx > p:not(.sub), .lede, .aside p, .lesson p, figcaption, li {
  text-align:justify; -webkit-hyphens:auto; hyphens:auto;
}

/* Running text, code, tables and figures all share one full-width measure, by choice: a
   118-character source line needs the room, and the column edges line up.
   --measure is that choice expressed as a switch, and it is currently `none`, so this
   rule resolves to `max-width:none; margin-inline:auto` and has no effect: every
   selector here is a block with auto width, for which auto inline margins compute to
   zero. Kept rather than deleted because it is the one knob that narrows the column
   without touching anything else - set --measure to e.g. 34rem in tokens.css and the
   running text pulls in while .wrap keeps its 65rem for tables and charts. Deliberate
   decision, task 4.4; do not "clean up" as dead code. */
.wrap > p, .wrap > h2, .wrap > h3, .wrap > .sub, .wrap > ul, .wrap > .aside, .wrap > .lesson,
.apx > p, .apx > h2, .apx > h3, .apx > .sub, .apx > ul, .apx > .aside, .apx > .apx-tag,
header.mast, footer, figcaption {
  max-width:var(--measure); margin-inline:auto;
}

/* --- site header: a folio line, not a navigation bar -------------------------------
   These pages are documents, so the header is built from the same micro-type as
   .eyebrow, .byline and h2 + .sub - mono, uppercase, .12em, --ink-3 - and separated by
   the same 1px rule as everything else. A padded bar with a logo and pill buttons would
   read as a different website glued on top of this one.

   .topbar-in repeats .wrap's measure and gutter so the wordmark and the toggle sit on the
   same left and right edges as the text below them. Every other rule in this design is
   content-width, so this one is too; a full-bleed rule would be the odd voice out.

   Not sticky, deliberately: this is a reading site, and vertical space on a phone is
   worth more than a bar that follows you down the page. */
.topbar-in {
  max-width:65rem; margin:0 auto; padding:15px 24px; position:relative;
  display:flex; align-items:baseline; gap:16px;
}
/* The rule is drawn inset to the text column rather than on the padding box. A border on
   .topbar-in would run the full 65rem and overhang .byline's rule and .lesson's by the
   24px gutter on each side - close enough to look like a mistake, which it would be. Same
   treatment on the footer, so all three rules share one left and right edge. */
.topbar-in::after, .sitefoot-in::before {
  content:""; position:absolute; left:24px; right:24px;
  border-top:1px solid var(--rule);
}
.topbar-in::after { bottom:0; }
.sitefoot-in::before { top:0; }
/* Lowercase, because it is a hostname and mono already says so. Slightly larger and
   darker than the links so it reads as identity rather than as another label. */
.brand {
  font-family:var(--mono); font-size:.72rem; font-weight:600; letter-spacing:.02em;
  color:var(--ink); text-decoration:none;
}
.brand:hover { color:var(--accent); }
/* Everything after the wordmark sits in one right-aligned group, so task 14.2 can drop a
   <nav> of links in beside the toggle without the alignment moving. */
.topbar-end { margin-left:auto; display:flex; align-items:baseline; gap:18px; }
.topnav { display:flex; align-items:baseline; gap:18px; }
.topnav a {
  font-family:var(--mono); font-size:.68rem; text-transform:uppercase; letter-spacing:.12em;
  color:var(--ink-3); text-decoration:none;
}
.topnav a:hover { color:var(--accent); }
.topnav a[aria-current="page"] { color:var(--ink); }
.topnav a:focus-visible, .brand:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }

/* Nothing to skip until there was a header. */
.skip { position:absolute; left:-9999px; top:0; }
.skip:focus {
  left:8px; top:8px; z-index:70; padding:8px 12px;
  background:var(--surface); color:var(--ink);
  border:1px solid var(--rule-strong); border-radius:3px;
  font-family:var(--mono); font-size:.7rem; text-transform:uppercase; letter-spacing:.1em;
}

/* masthead */
/* 40 rather than 64: the header above now supplies the top air, and stacking both left
   a hole above the h1. */
header.mast { padding:40px 0 12px; }
.eyebrow {
  font-family:var(--mono); font-size:.7rem; text-transform:uppercase; letter-spacing:.13em;
  color:var(--ink-3); margin:0 0 20px;
}
h1 {
  font-family:var(--serif); font-size:clamp(2rem,5.4vw,3.1rem); line-height:1.08;
  letter-spacing:-.02em; color:var(--ink); margin:0 0 .5rem; text-wrap:balance;
}
.deck {
  font-size:1.16rem; color:var(--ink-3); font-style:italic; margin:0 0 26px;
}
.lede { font-size:1.1rem; color:var(--ink-2); margin:0 0 26px; }
.lede b { color:var(--ink); font-weight:600; }
.byline {
  font-family:var(--mono); font-size:.72rem; text-transform:uppercase; letter-spacing:.11em;
  color:var(--ink-3); border-top:1px solid var(--rule); padding-top:16px;
}
.byline-who, .byline-contact { display:inline; }
/* The date floats so the name and contacts wrap underneath it rather than being squeezed
   into a narrow column; it comes first in the source because a float cannot rise to a line
   that has already been laid out. */
.byline-date { float:right; margin-left:1.6em; white-space:nowrap; }
.bsep { margin:0 .62em; color:var(--ink-3); }
.byline-contact a, .author-links a {
  color:var(--accent); text-decoration:underline; text-underline-offset:3px;
  text-decoration-thickness:1px; white-space:nowrap;
}
.ext { letter-spacing:0; }

/* author card */
/* font-family is stated here on purpose. The card used to be a <footer>, so it picked up
   var(--sans) from the bare `footer` element rule, and .author-bio - which sets a size, a
   colour and a line-height but never a family - inherited it. Making the card an <aside>
   in task group 6 removed that rule and silently flipped the bio to the serif body face.
   Declaring it means the card's appearance no longer depends on which element it happens
   to be. */
.author-card {
  border-top:1px solid var(--rule); margin-top:64px; padding-top:24px;
  font-family:var(--sans);
}
.author-label {
  margin:0 0 12px; font-family:var(--mono); font-size:.68rem; text-transform:uppercase;
  letter-spacing:.12em; color:var(--ink-3);
}
.author-bio {
  margin:0 0 14px; font-size:.96rem; line-height:1.65; color:var(--ink-2);
  text-align:justify; -webkit-hyphens:auto; hyphens:auto;
}
.author-bio strong { color:var(--ink); font-weight:600; }
.author-links {
  margin:0; font-family:var(--mono); font-size:.74rem; text-transform:uppercase;
  letter-spacing:.08em; color:var(--ink-3);
}
.author-disclaimer {
  margin:14px 0 0; font-family:var(--sans); font-size:.76rem; color:var(--ink-3);
}

/* body */
h2 {
  font-family:var(--serif); font-size:1.52rem; line-height:1.2; color:var(--ink);
  letter-spacing:-.01em; margin:52px 0 4px; text-wrap:balance;
}
/* Section deep-link, task 18.3. Invisible at rest so the page reads exactly as it did
   before; the h2 is the hover target rather than the anchor itself, which is only ~10px
   wide. Shown outright where hover does not exist, or it would be unreachable on a phone. */
.secno {
  opacity:0; margin-left:.34em; color:var(--ink-3); text-decoration:none;
  font-family:var(--mono); font-size:.62em; font-weight:400; vertical-align:.14em;
  transition:opacity .12s;
}
h2:hover .secno, .secno:focus-visible { opacity:.5; }
.secno:hover { opacity:.85; }
@media (hover: none) { .secno { opacity:.32; } }

/* the masthead already carries a rule and generous space; the default h2 top
   margin on top of that opened a 91px hole */
header.mast + h2 { margin-top:30px; }
h2 + .sub {
  font-family:var(--mono); font-size:.7rem; text-transform:uppercase; letter-spacing:.12em;
  color:var(--ink-3); margin:0 0 20px;
}
h3 {
  font-family:var(--sans); font-size:1.02rem; font-weight:650; color:var(--ink);
  margin:32px 0 8px; letter-spacing:-.005em;
}
p { margin:0 0 1.15em; }
b, strong { color:var(--ink); font-weight:600; }
em { font-style:italic; }
a { color:var(--accent); text-decoration:underline; text-underline-offset:2px; }
code {
  font-family:var(--mono); font-size:.84em; background:var(--surface-2);
  border:1px solid var(--rule); border-radius:3px; padding:.08em .34em;
  color:var(--ink); word-break:break-word;
}
ul, ol { margin:0 0 1.15em; padding-left:1.3em; }
li { margin:0 0 .5em; }

/* pull-quote / aside */
.aside {
  border-left:3px solid var(--accent); background:var(--surface);
  padding:18px 20px; margin:28px 0; border-radius:0 4px 4px 0;
  font-size:.96rem;
}
.aside .lbl {
  display:block; font-family:var(--mono); font-size:.66rem; text-transform:uppercase;
  letter-spacing:.12em; color:var(--ink-3); margin-bottom:8px;
}
.aside.hot { border-left-color:var(--hot); }
.aside p:last-child { margin-bottom:0; }

/* code blocks */
pre {
  background:var(--surface-2); border:1px solid var(--rule); border-radius:5px;
  padding:15px 17px; overflow-x:auto; margin:22px 0 26px;
  font-family:var(--mono); font-size:.77rem; line-height:1.6; color:var(--ink-2);
  -webkit-overflow-scrolling:touch;
}
/* display formulas are centred and unboxed; they are statements, not source */
/* Display equations. The box hugs its contents rather than spanning the column,
   so the shading frames the formula instead of a band of empty space. Both the
   tint and the hairline are mixed from tokens, so they follow the theme. */
pre.formula {
  width:fit-content; max-width:100%;
  margin:30px auto 34px; padding:15px 30px;
  background:color-mix(in srgb, var(--accent) 6%, var(--surface));
  border:1px solid color-mix(in srgb, var(--accent) 18%, var(--rule));
  border-radius:8px;
  text-align:center; font-size:1rem; color:var(--ink); letter-spacing:.01em;
}

pre .cm { color:var(--ink-3); }
pre .del { color:var(--hot); }
pre .ins { color:var(--cool); }

/* tables */
.tw {
  overflow-x:auto; margin:24px 0 30px; border:1px solid var(--rule);
  border-radius:5px; background:var(--surface);
}
table { border-collapse:collapse; width:100%; font-family:var(--sans); font-size:.87rem; }
th, td {
  text-align:left; padding:9px 13px; border-bottom:1px solid var(--rule);
  vertical-align:top; overflow-wrap:break-word;
}
thead th {
  font-family:var(--mono); font-size:.66rem; text-transform:uppercase; letter-spacing:.09em;
  color:var(--ink-3); font-weight:600; background:var(--surface-2);
}
tbody tr:last-child td { border-bottom:none; }
td.num, th.num {
  text-align:right; font-family:var(--mono); font-variant-numeric:tabular-nums; white-space:nowrap;
}
td.name { font-family:var(--mono); font-size:.81rem; overflow-wrap:anywhere; }
/* Header alignment follows the column: right over numbers (th.num above),
   left over wide prose columns (the default), centred only where the column is
   narrow enough that a centred label still reads as belonging to its data. */
th.hc { text-align:center; }
.good { color:var(--cool); }
.bad { color:var(--hot); }
tr.total td { font-weight:700; background:var(--surface-2); }

/* figures */
figure { margin:30px 0; }
figure svg { display:block; width:100%; height:auto; }
figcaption { font-family:var(--sans); font-size:.83rem; color:var(--ink-3); margin-top:12px; }
figcaption b { color:var(--ink-2); }
.fr {
  background:var(--surface); border:1px solid var(--rule); border-radius:5px; padding:18px 18px 12px;
}
.ftitle {
  font-family:var(--mono); font-size:.7rem; text-transform:uppercase; letter-spacing:.1em;
  color:var(--ink-2); font-weight:600; margin-bottom:14px;
}

/* lessons */
.lesson {
  border-top:1px solid var(--rule); padding:20px 0 4px;
  display:grid; grid-template-columns:2.4rem 1fr; gap:0 16px;
}
.lesson .n {
  font-family:var(--mono); font-size:1.05rem; color:var(--accent); font-weight:600; line-height:1.4;
}
.lesson h3 { margin:0 0 6px; }
.lesson p { margin:0 0 .6em; font-size:.97rem; }

/* writing list - same rule-separated row as .lesson, date in the numeral slot */
.post {
  display:grid; grid-template-columns:6.5rem 1fr; gap:0 16px;
  border-top:1px solid var(--rule); padding:18px 0;
  text-decoration:none; color:inherit;
}
.post-date {
  font-family:var(--mono); font-size:.7rem; text-transform:uppercase;
  letter-spacing:.1em; color:var(--ink-3); padding-top:.3rem;
}
.post-title {
  display:block; font-family:var(--sans); font-size:1.02rem; font-weight:650;
  color:var(--ink); letter-spacing:-.005em; margin-bottom:5px;
  text-decoration:underline; text-underline-offset:3px;
  text-decoration-color:var(--rule-strong); text-decoration-thickness:1px;
}
.post:hover .post-title { color:var(--accent); text-decoration-color:var(--accent); }
.post:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.post-deck { display:block; font-size:.95rem; color:var(--ink-3); font-style:italic; }

/* appendix */
.apx { border-top:2px solid var(--rule-strong); margin-top:60px; padding-top:8px; }
.apx-tag {
  font-family:var(--mono); font-size:.68rem; text-transform:uppercase; letter-spacing:.13em;
  color:var(--ink-3);
}
/* --- site footer ---------------------------------------------------------------------
   Replaces the bare `footer` element rule this design used to carry. That rule also
   applied to the author card, because the card was itself a <footer>; the card is now an
   <aside> and every child of it sets its own family, size and colour, so nothing is lost.

   The rule sits on .sitefoot-in rather than .sitefoot so it stays content-width, matching
   .topbar above and every other rule here. Both pages get one now - the article
   previously had no site footer at all. */
.sitefoot { font-family:var(--sans); font-size:.85rem; color:var(--ink-3); }
.sitefoot-in {
  max-width:65rem; margin:0 auto; padding:22px 24px 44px; position:relative;
}
.sitefoot p { margin:0; }


/* --- chart components, ported from the internal analysis --- */
.panel { background:var(--surface); border:1px solid var(--rule); border-radius:5px; padding:20px 20px 12px; }
.panels2 { display:grid; grid-template-columns:1fr 1fr; gap:14px; }
.ptitle { display:flex; justify-content:space-between; align-items:baseline; gap:12px; margin-bottom:14px; }
.ptitle .ph { margin:0; font-family:var(--mono); font-size:.74rem; text-transform:uppercase; letter-spacing:.1em; font-weight:600; color:var(--ink-2); }
.ptitle .pk { font-family:var(--mono); font-size:.74rem; color:var(--ink-3); font-variant-numeric:tabular-nums; }
.chart { position:relative; }
.chart svg { display:block; width:100%; height:auto; overflow:visible; }
.tip { position:absolute; pointer-events:none; opacity:0; transition:opacity .1s; background:var(--ink); color:var(--paper); font-family:var(--mono); font-size:.7rem; padding:5px 8px; border-radius:3px; white-space:nowrap; transform:translate(-50%,-140%); z-index:5; font-variant-numeric:tabular-nums; }
.legend { display:flex; flex-wrap:wrap; gap:6px 20px; margin:14px 0 0; font-family:var(--mono); font-size:.72rem; color:var(--ink-2); }
.legend span { display:inline-flex; align-items:center; gap:7px; }
.sw { width:11px; height:11px; border-radius:2px; flex:none; }
.rc-readout { display:flex; flex-wrap:wrap; gap:4px 30px; margin:2px 0 14px; }
.rc-readout div { display:flex; flex-direction:column; gap:1px; }
.rc-readout .rk { font-family:var(--mono); font-size:.62rem; text-transform:uppercase; letter-spacing:.1em; color:var(--ink-3); }
.rc-readout .rv { font-family:var(--mono); font-size:.98rem; font-weight:600; font-variant-numeric:tabular-nums; color:var(--ink); }
.rc-readout .rv.good { color:var(--healthy); }
.rc-range { position:relative; margin-top:6px; touch-action:none; }
.rc-range svg { cursor:ew-resize; display:block; width:100%; height:auto; }
.rc-hint { font-family:var(--mono); font-size:.64rem; color:var(--ink-3); margin:7px 0 0; letter-spacing:.03em; }
.rc-handle { cursor:ew-resize; }
.rc-handle:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.copied { position:fixed; left:50%; bottom:28px; transform:translateX(-50%); background:var(--ink); color:var(--paper); font-family:var(--mono); font-size:.72rem; padding:8px 14px; border-radius:4px; opacity:0; pointer-events:none; transition:opacity .16s; z-index:50; letter-spacing:.02em; }
.copied.show { opacity:1; }


/* References. Two explicit grid columns rather than a column flow: flow balances
   by height but will split a group and leave the second column headless, while a
   row-based grid would force matching row heights and open dead gaps. Independent
   stacks in each column give whole groups, a heading at the top of both, and a
   near-equal split — the groups are sized so each column carries seven entries. */
/* References sits under a 2px rule and a 60px block margin, so its default h2
   top margin stacked into a very deep gap while the group headings crowded it
   from below. Only this h2 is a first child - the appendices lead with a tag. */
.apx > h2:first-child { margin-top:14px; }
.refcols { margin-top:26px; display:grid; grid-template-columns:1fr 1fr; gap:0 40px; align-items:start; }
.refcol { min-width:0; }
.refgroup {
  font-family:var(--mono); font-size:.64rem; text-transform:uppercase; letter-spacing:.12em;
  color:var(--ink-3); margin:0 0 8px; padding-bottom:6px;
  border-bottom:1px solid var(--rule-strong);
}
.refblock + .refblock { margin-top:24px; }
.refs { list-style:none; padding:0; margin:0; }
.refs li {
  text-align:left; font-size:.85rem; line-height:1.45;
  padding:0 0 9px; margin:0 0 9px; border-bottom:1px solid var(--rule);
}
.refs li:last-child { border-bottom:none; padding-bottom:0; margin-bottom:0; }
.refs a { font-weight:600; }
.refs .note { display:block; color:var(--ink-3); font-size:.82rem; margin-top:3px;
               text-align:justify; -webkit-hyphens:auto; hyphens:auto; }





pre.code { padding:14px 0; }
pre.code .ln {
  display:block; width:max-content; min-width:100%;
  padding:0 18px 0 26px; position:relative;
}
pre.code .ln::before { position:absolute; left:9px; font-weight:700; opacity:.85; }
pre.code .ln-del { background:color-mix(in srgb, var(--hot) 13%, transparent); box-shadow:inset 2px 0 0 var(--hot); }
pre.code .ln-del::before { content:"\2212"; color:var(--hot); }
pre.code .ln-add { background:color-mix(in srgb, var(--cool) 13%, transparent); box-shadow:inset 2px 0 0 var(--cool); }
pre.code .ln-add::before { content:"+"; color:var(--cool); }

pre.code .k  { color:var(--c-key); font-weight:600; }
pre.code .t  { color:var(--c-type); }
pre.code .fn { color:var(--c-fn); }
pre.code .st { color:var(--c-str); }
pre.code .sh { color:var(--c-type); }
pre.code .nu { color:var(--c-num); }
pre.code .cm, pre.code .cd { color:var(--c-com); font-style:italic; }
pre.code .cdt { color:var(--c-com); opacity:.85; font-style:normal; }
pre.code .op { color:var(--c-op); }
/* the claim that was wrong: a squiggle reads as "incorrect", never as "removed" */
pre.code .lie {
  text-decoration:underline wavy var(--hot);
  text-decoration-thickness:1px; text-underline-offset:3px;
  font-style:normal; color:var(--ink-2);
}


/* --- proof punchline, ported --- */
.giveback.proof { border-color:color-mix(in srgb, var(--accent) 34%, var(--rule)); border-left-color:var(--accent); background:color-mix(in srgb, var(--accent) 6%, var(--surface)); }
.giveback { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:26px 34px; margin:0 0 34px; padding:26px 28px; border:1px solid color-mix(in srgb, var(--healthy) 34%, var(--rule)); border-left:4px solid var(--healthy); border-radius:5px; background:color-mix(in srgb, var(--healthy) 7%, var(--surface)); }
.gb-k { display:block; font-family:var(--mono); font-size:.66rem; text-transform:uppercase; letter-spacing:.11em; color:var(--ink-2); margin-bottom:9px; }
.gb-v { display:block; font-family:var(--mono); font-size:2.3rem; font-weight:700; line-height:1; color:var(--healthy); letter-spacing:-.03em; font-variant-numeric:tabular-nums; white-space:nowrap; }
.gb-v .gb-u { font-size:.42em; font-weight:600; letter-spacing:0; }
.gb-v.gb-word { font-size:1.5rem; letter-spacing:-.02em; }
.gb-n { display:block; font-size:.82rem; color:var(--ink-2); margin-top:10px; line-height:1.45; }
.gb-n b { color:var(--ink); font-weight:600; }
@media (max-width:760px) {
  .giveback { grid-template-columns:1fr; gap:20px; padding:20px 18px; }
  .gb-v { font-size:1.7rem; }
}

/* windows table: headings centred over their columns; the spans are uniform width
   now that every one is a full datetime, so the values centre with them */
.win td.num { text-align:center; }
/* Each datetime is one nowrap unit, because the hyphens in a date are themselves wrap
   opportunities and neither non-breaking spaces nor word-break:keep-all suppress those. The
   arrow is tied to the first datetime with a non-breaking space, so where the phone rule below
   lets the pair wrap it breaks in exactly one place and the arrow is never left on a line of
   its own. The nowrap units also give the column a width to be laid out against. */
.win .dt { white-space:nowrap; }

/* The windows table needs two lines for a span before the phone rules further down arrive, so
   that its label column has room to break between words rather than through them. */
@media (max-width:600px) { .win td.num { white-space:normal; } }

/* Labels made of words rather than identifiers break between the words. td.name defaults to
   overflow-wrap:anywhere for the dotted type names in the census table, where a single token is
   wider than a phone column; applied to prose it guillotines "Response time" into Respon/se. */
.win td.name, .cost td.name { overflow-wrap:break-word; }

/* evidence table: the source column holds single long identifiers, which
   overflow-wrap:anywhere would guillotine mid-word */
.ev td.name { overflow-wrap:break-word; min-width:13ch; }
@media (max-width:760px) { .ev td.name { min-width:0; font-size:.72rem; } }


/* embedded console renderings: CloudWatch draws on white, so give the shot its own
   light ground in both themes rather than letting a bright block fight dark mode */
.shot { display:grid; gap:10px; background:#ffffff; border:1px solid var(--rule); border-radius:4px; padding:8px; }
.shot img { display:block; width:100%; height:auto; border-radius:2px; }
@media (max-width:760px) { .shot { padding:5px; gap:6px; } }

/* The toggle now lives in the header, so it is styled as one more link rather than the
   floating pill it used to be - inside a folio line a bordered, filled capsule would be
   the loudest thing on the page. That also retires the phone rule that parked it
   bottom-right on top of the content. */
.themebtn {
  background:none; border:0; padding:0; cursor:pointer;
  font-family:var(--mono); font-size:.68rem; text-transform:uppercase; letter-spacing:.12em;
  color:var(--ink-3);
}
.themebtn:hover { color:var(--accent); }
.themebtn:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }

/* The label names the theme you will get, and it is set in CSS so it is already correct
   at first paint. Setting it from JS meant the button rendered blank until the script
   ran, and since the script waits for the whole document that is a long blank on a
   375 KB article - then the label appearing would shift the rest of the header.
   The four cases cannot overlap: two require the attribute, one forbids it. */
.themebtn::after { content:"Dark"; }
:root[data-theme="dark"] .themebtn::after { content:"Light"; }
:root[data-theme="light"] .themebtn::after { content:"Dark"; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .themebtn::after { content:"Light"; }
}
/* No JS, no working toggle, so no button. The head script adds .js before first paint,
   which is why this does not flash. */
:root:not(.js) .themebtn { display:none; }

@media (max-width:760px){ .panels2 { grid-template-columns:1fr; } }

@media (max-width:760px) {
  body { font-size:17px; }
  .wrap { padding:0 16px 40px; }
  .topbar-in { padding:12px 16px; }
  .sitefoot-in { padding:18px 16px 36px; }
  .topbar-in::after, .sitefoot-in::before { left:16px; right:16px; }
  :root { --measure:none; }
  /* must match the base selector's specificity: `:not(.sub)` counts as a class */
  .wrap > p:not(.sub), .apx > p:not(.sub), .lede, .aside p, .lesson p, figcaption, li { text-align:left; }
  .author-bio { text-align:left; }
  header.mast { padding:28px 0 10px; }
  .lesson { grid-template-columns:1fr; gap:4px 0; }
  .post { grid-template-columns:1fr; gap:4px 0; }
  .post-date { padding-top:0; }
  table { font-size:.82rem; }
  th, td { padding:8px 8px; }
  /* the widest thing in a narrow table is usually a two-word heading; let headings wrap
     rather than push the table into a horizontal scroller. The `.num` class outranks a
     type-only selector, so it has to be named explicitly. */
  thead th, thead th.num { white-space:normal; }
  pre { font-size:.73rem; }
}

@media (max-width:480px) {
  th, td { padding:7px 4px; }
  /* A figure made of several parts -- two numbers and a separator, a number and its unit, a
     pair of datetimes -- may wrap here rather than hold a table open into a scroller. All of
     them fit on one line above this width. overflow-wrap:normal overrides what the cells
     inherit, so a figure is never split through the middle of itself. */
  td.num { white-space:normal; overflow-wrap:normal; }
  /* The three densest tables step their labels down rather than scroll: five numeric columns
     (cost), three prose columns (evidence), and a column sharing the line with a datetime
     pair (windows). */
  .cost thead th { font-size:.56rem; letter-spacing:.03em; }
  .cost td.name { font-size:.66rem; }
  .ev { font-size:.74rem; }
  .ev td.name { font-size:.64rem; }
  .win td.name { font-size:.70rem; }
  thead th { font-size:.61rem; letter-spacing:.05em; }
  table { font-size:.78rem; }
  td.name { font-size:.76rem; }
}

/* --- mobile pass --- */
@media (max-width:760px) {
  /* chart panels: the desktop padding wastes a third of a phone's width */
  .panel { padding:14px 12px 10px; }
  .panels2 { grid-template-columns:1fr; gap:12px; }
  .ptitle { flex-wrap:wrap; gap:4px 10px; }
  .ptitle h4, .ptitle .pk { font-size:.68rem; }
  .legend { gap:6px 14px; font-size:.7rem; }
  .chart svg { overflow:visible; }

  /* range controls need thumb-sized targets, not mouse-sized ones */
  .rc-range { padding:9px 0; }
  .rc-readout { gap:4px 18px; }
  .rc-readout .rv { font-size:.92rem; }
  .rc-readout .rk { font-size:.62rem; }
  .rc-hint { font-size:.68rem; line-height:1.45; }

  /* Code wraps rather than scrolling sideways. A horizontal scroller nested in a
     vertically scrolling page is the worst thing you can hand a thumb, and the
     row padding gives continuations a hanging indent for free. */
  pre.code { overflow-x:visible; padding:12px 0; }
  pre.code .ln {
    width:auto; min-width:0;
    white-space:pre-wrap; overflow-wrap:break-word; word-break:break-word;
    padding:1px 12px 1px 24px;
  }
  pre.code .ln::before { top:1px; }

  /* formulas break at the 'versus' gap instead of overflowing */
  pre.formula { width:auto; white-space:pre-wrap; font-size:.92rem; margin:24px 0 28px; padding:13px 16px; }

  /* one stack: two columns would be unreadable at this measure */
  .refcols { grid-template-columns:1fr; }
  .refcol + .refcol .refblock:first-child { margin-top:24px; }
  .refs li { font-size:.86rem; padding-bottom:11px; margin-bottom:11px; }
  .refs .note { text-align:left; }
  .refblock + .refblock .refgroup { margin-top:24px; }
}

@media (max-width:480px) {
  pre.code { font-size:.72rem; line-height:1.55; }
  pre.formula { font-size:.85rem; }
  pre.code .ln { padding-left:22px; }
  pre.code .ln::before { left:7px; }
  .panel { padding:12px 10px 8px; }
  h1 { font-size:1.72rem; }
  h2 { font-size:1.24rem; }
  /* the float would leave the first line too little room, so the date takes a line of its own */
  .byline-date { float:none; display:block; text-align:right; margin:0 0 5px; }
}

@media print {
  :root {
    --paper:#fff; --surface:#fff; --surface-2:#f4f4f2; --ink:#000; --ink-2:#222; --ink-3:#555;
    --rule:#ccc; --rule-strong:#999; --accent:#134a86; --hot:#8f3714; --cool:#0a5740;
  }
  @page { margin:16mm 14mm; }
  body { font-size:10.5pt; }
  .wrap { max-width:none; padding:0; }
  .topbar-in, .sitefoot-in { max-width:none; padding-left:0; padding-right:0; }
  .topbar-in::after, .sitefoot-in::before { left:0; right:0; }
  .themebtn { display:none; }
  figure, .tw, pre, .aside, .lesson, .refs li { break-inside:avoid; }
  /* the charts freeze at full range on paper; the drag affordances and the live
     "in view" readouts would then either be blank or contradict the captions,
     which already carry the correct statistics */
  .rc-range, .rc-hint, .rc-readout, .tip, .copied, .scr, .secno { display:none !important; }
  .refs a::after { content:" ↗ " attr(href); font-family:var(--mono); font-size:.8em; color:var(--ink-3); word-break:break-all; }
  h2, h3 { break-after:avoid; }
}
@media (prefers-reduced-motion:reduce) { * { transition:none !important; } }
