/* wiki.css — the public user guide at /wiki.
   Built to docs/DESIGN.md; read that before changing anything here.
   Tokens are §3 verbatim, type roles are §4, nesting limit is §5.

   The faces are NOT re-declared: assets/fonts.css already self-hosts Geist,
   Geist Mono, Instrument Serif and the Fraunces wordmark subset, and a second
   @font-face set would download them twice. Every page links it directly.

   No @keyframes anywhere in this file. A reference guide has nothing to reveal
   on scroll, and DESIGN.md §7 records what a base-rule/keyframe inversion did
   to a hero in Firefox 141. The only motion is a hover/focus colour change. */

.wiki {
  /* §3 — one chromatic accent; everything else is paper, ink and hairline. */
  --paper: #FBFAF8;
  --wash: #F4F3F0;
  --speaker: #F2EFEA;
  --ink: #14161A;
  --ink-soft: #5A6068;
  --ink-faint: #666B73;
  --rule: #E2E0DB;
  --rule-strong: #C9C6BF;
  --signal: #7A1F2B;

  --measure: 66ch;
  --gutter: 24px;
  --max: 1200px;
  --head: 57px;             /* sticky header height; the sidebar hangs off it */

  --mono: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;

  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Geist', sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

/* --ink-faint is 3.1:1 on paper. It is in the token set because DESIGN.md puts
   it there, but it is never used for text in this file — a reference guide is
   read, not skimmed, and captions here take --ink-soft (6.1:1) instead. */

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

@media (prefers-reduced-motion: no-preference) {
  .wiki { scroll-behavior: smooth; }
  .wiki :is(a, button, summary) { transition: color .15s ease, border-color .15s ease; }
}

/* ── Links, focus, the single accent ─────────────────────────────────────
   Claret is interactive-or-current only: links, the page you are on, the
   screen you are on in a breadcrumb, and the focus ring. Nowhere else. */
.wiki a { color: var(--signal); text-underline-offset: 3px; text-decoration-thickness: 1px; }

/* Bold maps to the 600 face that actually ships. The browser default is 700,
   and no 700 face exists, so every <strong> in the guide was being synthesised
   — visibly fatter and fuzzier than the true 600 of the headings beside it,
   and a strong inside an already-bold cell compounded to a faux 900. The
   product's own stylesheets make the same mapping. */
.wiki :is(strong, b) { font-weight: 600; }
/* Geist Mono ships one weight. A bold inside a mono run (the current breadcrumb
   segment, a strong in a code sample) gets full ink instead of a fake weight. */
.wiki :is(code, kbd, .where) :is(strong, b),
.wiki .where strong { font-weight: 500; color: var(--ink); }
.wiki a:hover { text-decoration-thickness: 2px; }
.wiki :is(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--signal); outline-offset: 3px; border-radius: 2px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  background: var(--paper); color: var(--ink); border: 1px solid var(--ink);
  padding: 10px 16px; font-size: 15px; font-weight: 500; text-decoration: none;
}
/* Below the header band, not on top of the wordmark — at top:10px the panel
   covered "RolePlay LMS" with the final S poking out, which reads as a
   rendering fault rather than an affordance. */
.skip:focus { left: 12px; top: calc(var(--head) + 8px); }

/* ── Header ───────────────────────────────────────────────────────────── */
/* The header rule reaches the viewport edge while the header content stays
   inside the 1200px measure. This used to be one element and a centred
   `width: 100vw` pseudo — but 100vw counts the classic vertical scrollbar and
   the layout viewport does not, so on any browser that gives its scrollbar real
   width (most desktops) the rule was ~15px wider than the page and put a
   horizontal scrollbar under every screen in the guide. Headless browsers use
   overlay scrollbars and never showed it. A full-width band carrying the border
   costs one div and cannot drift from the viewport. */
.wiki-band {
  position: sticky; top: 0; z-index: 10;
  background: var(--paper); border-bottom: 1px solid var(--rule);
}
.wiki-head {
  /* Mirrors the main site's .topbar exactly: same measure, same padding, same
     wordmark size, same nav. One header, two surfaces. */
  display: flex; justify-content: space-between; align-items: center;
  gap: 14px;
  width: min(1100px, 92vw); margin: 0 auto; padding: 14px 0;
}
.wiki-mark {
  display: flex; align-items: center; gap: 10px; flex: none;
  font-family: 'Fraunces Wordmark', Georgia, serif;
  /* Matches the main site's .brand: same face, same set-solid "RolePlayLMS",
     with LMS in claret. One wordmark, wherever the product shows its name. */
  font-weight: 700; font-size: 24px; letter-spacing: -.02em;
  color: var(--ink); text-decoration: none;
}
/* The word is one span inside the flex row, exactly like the main site's
   .brand-word. Two things went wrong without it: the anchor rule `.wiki a`
   out-specified the ink and painted the whole name claret, and the bare text
   node and the <em> were separate flex items, so the row's 8px gap opened a
   phantom space inside "RolePlayLMS". */
.wiki-mark-word {
  color: var(--ink);
  /* line-height 1, as .brand-word has it — without it Fraunces' tall default
     line box made this band 10px taller than the site's. */
  line-height: 1;
}
.wiki-mark em { font-style: normal; color: var(--signal); }
.wiki-mark-img {
  width: 1.15em; height: 1.15em; flex: none;
  /* Relative to this stylesheet (wiki/wiki.css), so it resolves wherever the
   site is mounted. Absolute, it 404s on any subdirectory install. */
  background: url('../assets/brand/mark.png') center / contain no-repeat;
}
.wiki-head-nav {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: 6px 22px; font-size: 15px;
}
.wiki-head-nav a {
  color: var(--ink-soft); text-decoration: none;
}
.wiki-head-nav a:hover,
.wiki-head-nav a:focus-visible {
  color: var(--ink); text-decoration: underline; text-underline-offset: 3px;
}
.wiki-head-nav a[aria-current="page"] {
  color: var(--ink); text-decoration: underline;
  text-underline-offset: 6px; text-decoration-color: var(--signal);
}
.wiki-head-nav .wiki-signin { color: var(--signal); font-weight: 600; }

/* ── Shell: contents · guide · on this page ──────────────────────────────
   Three regions, no wrappers inside them. Nesting stays at section > row. */
.wiki-shell {
  display: grid; gap: 0 48px;
  grid-template-columns: 236px minmax(0, 1fr) 172px;
  grid-template-areas: "side main toc";
  max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter) 64px;
}

.eyebrow {
  margin: 0 0 16px;
  font-weight: 500; font-size: 13px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-soft);
  /* Uncontained — never a pill. DESIGN.md §4. */
}

/* ── Sidebar ──────────────────────────────────────────────────────────── */
.wiki-side {
  grid-area: side; position: sticky; top: var(--head); align-self: start;
  /* overflow-y only. The list content measures a pixel wider than the box
     (the rotated caret's bounding box), and `auto` on both axes turned that
     pixel into a permanent horizontal scrollbar under the menu. Nothing in a
     nav list should ever scroll sideways. */
  max-height: calc(100vh - var(--head) - 16px);
  overflow-y: auto; overflow-x: hidden;
  padding: 40px 0 24px; font-size: 15px;
}
.wiki-side ul { list-style: none; margin: 0 0 26px; padding: 0; }
.wiki-side li + li { border-top: 1px solid var(--rule); }
.wiki-side a {
  display: block; padding: 9px 0 9px 13px;
  color: var(--ink-soft); text-decoration: none; line-height: 1.4;
  border-left: 2px solid transparent;
}
.wiki-side a:hover { color: var(--ink); border-left-color: var(--rule-strong); }
.wiki-side a[aria-current="page"] {
  color: var(--signal); font-weight: 500; border-left-color: var(--signal);
}
/* Each part of the guide is a <details>; the one you are reading is open.
   Flat, the list was taller than any normal window inside a capped, silently
   scrolling box — so the link marking the page you were on sat below the fold
   on every desktop. Collapsed, it fits, and the summary keeps the part you are
   in named even when its list is closed. */
.side-part { margin: 0 0 18px; }
.side-h {
  margin: 0 0 2px; padding-bottom: 8px;
  font-weight: 600; font-size: 13px; letter-spacing: .01em; color: var(--ink);
  border-bottom: 1px solid var(--rule-strong);
  cursor: pointer; list-style: none;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.side-h::-webkit-details-marker { display: none; }
/* A caret rather than a triangle: the same hairline vocabulary as everything
   else, and it turns because the element's state turned, not because of a
   script. */
.side-h::after {
  content: ''; flex: none; width: 6px; height: 6px; margin-bottom: 2px;
  border-right: 1px solid var(--ink-soft); border-bottom: 1px solid var(--ink-soft);
  transform: rotate(45deg); transition: transform .15s ease;
}
.side-part[open] > .side-h::after { transform: rotate(-135deg); margin-bottom: -2px; }
.side-h:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .side-h::after { transition: none; } }

/* ── Main column ──────────────────────────────────────────────────────── */
.wiki-main { grid-area: main; min-width: 0; padding: 40px 0 0; }
.wiki-title { margin: 0 0 40px; padding: 0 0 24px; border-bottom: 1px solid var(--rule); }
.wiki-main h1 {
  margin: 0; font-weight: 600; line-height: 1.06; letter-spacing: -.02em;
  font-size: clamp(30px, 4.4vw, 46px);
}
.standfirst { margin: 14px 0 0; font-size: 20px; line-height: 1.5; color: var(--ink-soft); max-width: 46ch; }

.wiki-main h2 {
  margin: 56px 0 16px; padding-top: 22px; border-top: 1px solid var(--rule);
  font-weight: 600; font-size: 26px; line-height: 1.2; letter-spacing: -.015em;
  scroll-margin-top: calc(var(--head) + 16px);
}
.wiki-main h3 {
  margin: 34px 0 10px; font-weight: 600; font-size: 20px; letter-spacing: -.01em;
  scroll-margin-top: calc(var(--head) + 16px);
}
.wiki-main h4 { margin: 26px 0 8px; font-weight: 600; font-size: 17px; }
.wiki-main p { margin: 0 0 18px; max-width: var(--measure); }
.wiki-main :is(ul, ol) { max-width: var(--measure); padding-left: 22px; margin: 0 0 18px; }
.wiki-main li { margin: 0 0 8px; }
.wiki-main hr { border: 0; border-top: 1px solid var(--rule); margin: 48px 0; }
.wiki-main img { max-width: 100%; height: auto; }

/* Mono is a fact: paths, file types, limits, values, keys, code. */
.wiki-main code {
  font-family: var(--mono); font-weight: 500; font-size: .84em;
  background: var(--wash); border-radius: 3px;
  /* Tight to the punctuation. At 5px the chip's right padding read as a
     space before a following comma or full stop, 13 times in the guide. */
  padding: .1em .3em; margin: 0 -.05em;
}
.wiki-main pre {
  font-family: var(--mono); font-size: 14px; line-height: 1.5;
  background: var(--wash); border: 1px solid var(--rule); border-radius: 4px;
  padding: 16px 18px; margin: 0 0 22px;
  /* Wrapped, not scrolled. A horizontally scrolling block is a scroll region
     with no keyboard access (axe: scrollable-region-focusable), and the code
     here is markdown source, which reads perfectly well wrapped on a phone. */
  white-space: pre-wrap; overflow-wrap: break-word; overflow-x: auto;
}
.wiki-main pre code { background: none; padding: 0; font-size: inherit; }

kbd {
  font-family: var(--mono); font-weight: 500; font-size: 12px;
  padding: 3px 7px; border: 1px solid var(--rule-strong); border-radius: 3px;
  background: var(--paper); color: var(--ink); white-space: nowrap;
}

/* Plain markdown tables, for anything that is not a control table.

   The table scrolls; the page must not. A three-column table has a minimum
   width, and on a narrow phone that width was setting the minimum width of the
   whole document — the last column sat past the right edge, clipped mid-word,
   and the reader had to scroll the entire page to reach it. WCAG 1.4.10 allows
   a data table to need two dimensions, but the scrolling has to be contained,
   so .table-scroll contains it. `::: controls` does not need this: it restacks
   below 620px, which is the better answer where the markup can carry one. */
.table-scroll { overflow: auto; margin: 0 0 24px; }
.wiki-main table { border-collapse: collapse; width: 100%; margin: 0 0 24px; font-size: 15px; }
/* Declared after `.wiki-main table`, not before: both selectors are one class
   and one type, so the tie goes to whichever is written last. Written first,
   this lost, and every plain table carried 24px of dead margin inside its own
   scroll container on top of the container's own 24px. */
.wiki-main .table-scroll > table { margin-bottom: 0; }
.wiki-main :is(th, td) { text-align: left; vertical-align: top; padding: 12px 14px 12px 0; border-top: 1px solid var(--rule); }
.wiki-main th { font-weight: 600; }
/* The last way a page could still scroll sideways: one unbreakable token —
   a path, a query string, an identifier — in a cell or a paragraph, setting a
   min-content width wider than the column. Nothing in the guide does today;
   this makes sure nothing can. */
.wiki-main :is(th, td), .wiki-main p { overflow-wrap: anywhere; }
.wiki-main thead th { border-top: 0; border-bottom: 1px solid var(--rule-strong); padding-top: 0; }

/* ═══ SIGNATURE ══════════════════════════════════════════════════════════
   The figure key. One number identifies one control in three places: pinned
   on the screenshot, leading its callout, and leading its row in the control
   table. The number is the binding, not decoration — which is why it is a
   hairline square in mono (a printed figure key) and not a coloured circle,
   and why it is ink rather than claret: a key is not interactive. */
.pin, .pin-flat, .shot-keys > li::before {
  font-family: var(--mono); font-weight: 500; font-size: 12px; line-height: 1;
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--ink); border-radius: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 21px; height: 21px; padding: 0 4px;
}
/* On the image, the same chip needs to read as something laid ON the
   screenshot rather than part of the interface underneath it. A shadow is out
   (docs/DESIGN.md: depth is hairlines), so it gets a paper halo — a second
   hairline in the page's own background colour, which separates the chip from
   whatever it happens to be sitting on without inventing a new material. The
   key list below the figure needs none of this: it is already on paper. */
.pin {
  position: absolute;
  /* Clamped, not placed raw. A pin is a fixed 21px chip at a percentage
     position, so on a phone — where a 646px figure renders at 310px — a pin
     measured against the right-hand edge of a control ends up half outside the
     frame, and .shot-frame clips it. Clamping pins it to the inside edge
     instead: a pixel or two off where it was measured, and always whole.
     15px is half the widest chip (two digits) plus the halo. */
  left: clamp(15px, var(--px), calc(100% - 15px));
  top: clamp(14px, var(--py), calc(100% - 14px));
  transform: translate(-50%, -50%);
  outline: 3px solid var(--paper);
  /* Proportional to the figure, with a floor so two digits stay legible. */
  min-width: max(17px, 3.1cqw); height: max(17px, 3.1cqw);
  font-size: max(10px, 1.8cqw); padding: 0 3px;
}
.pin-flat { position: relative; top: -1px; margin-right: 7px; }

.shot { margin: 0 0 32px; }
.shot-frame {
  /* The pin sizes itself against the figure, not the page. A figure is 648px
     wide on a laptop and 312px on a phone, so a fixed 21px chip covers 3.2% of
     it in one place and 6.7% in the other — while everything it is pointing at
     halves. That is why pins that sat in clear space at desktop were landing on
     a microphone button and a panel label on a phone. */
  container-type: inline-size;
  position: relative; display: block; overflow: hidden;
  border: 1px solid var(--rule-strong); border-radius: 4px; background: var(--wash);
}
/* pandoc wraps loose inline content in a <p>, so the image arrives inside one.
   It must not inherit the body measure or the screenshot would render at 66ch. */
.shot-frame p { margin: 0 !important; max-width: none !important; }
.shot-frame img { display: block; width: 100%; height: auto; }
.shot-keys { list-style: none; margin: 0 !important; padding: 0 !important; max-width: var(--measure) !important; }
.shot-keys > li {
  position: relative; margin: 0; padding: 13px 0 13px 34px;
  border-top: 1px solid var(--rule); font-size: 16px;
}
.shot-keys > li::before { content: attr(data-n); position: absolute; left: 0; top: 12px; }
.shot figcaption {
  margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--rule);
  font-size: 15px; color: var(--ink-soft); max-width: var(--measure);
}

/* ── Control table ───────────────────────────────────────────────────────
   Fixed three-column contract, so the stacked phone layout can label its
   cells from CSS. Semantics are kept by the explicit ARIA roles the build
   script writes, because display:block strips a table's implicit ones. */
.controls { margin: 0 0 30px !important; }
.controls caption { text-align: left; font-size: 15px; color: var(--ink-soft); padding-bottom: 10px; }
.controls thead th {
  font-weight: 500; font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft); padding-bottom: 10px;
}
.controls .ctl-name { width: 25%; font-weight: 600; padding-right: 20px; }
.controls .ctl-who { width: 21%; }
.controls .ctl-who { color: var(--ink-soft); }
.controls tbody td:not(.ctl-who) { padding-right: 24px; }
.controls tbody :is(th, td) { border-top: 1px solid var(--rule); }

/* ── Note and warning ────────────────────────────────────────────────────
   A warning is a glyph and a word, never a colour (DESIGN.md §3, WCAG 1.4.1),
   and there is no coloured left rule on either — that is anti-pattern 9.
   The only left rule in this stylesheet marks speech. */
.note {
  margin: 0 0 26px; padding: 18px 20px; max-width: var(--measure);
  background: var(--paper); border: 1px solid var(--rule); border-radius: 4px;
  /* Paper, not wash: --wash is the code-block ground, and a note sitting on it
     read as a code sample two screens down the specimen page. */
}
.note--warning { border-color: var(--rule-strong); }
.note-h {
  margin: 0 0 4px !important;
  font-weight: 500; font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink);
}
/* The author's heading, set as the sentence it is. Only the one-word kicker
   above it stays uppercase. */
.note-t { margin: 0 0 8px !important; font-weight: 600; font-size: inherit; }
.note-glyph { font-size: 14px; letter-spacing: 0; }
.note > :last-child { margin-bottom: 0 !important; }
.note p { max-width: none; }

/* ── Role marker ─────────────────────────────────────────────────────────
   Deliberately not a note: it qualifies who a paragraph is true for, so it
   is a rule across the column rather than a panel beside it. */
.only {
  margin: 0 0 26px; padding: 16px 0; max-width: var(--measure);
  border-top: 1px solid var(--rule-strong); border-bottom: 1px solid var(--rule-strong);
}
.only-h {
  margin: 0 0 8px !important; font-size: 15px; color: var(--ink-soft);
}
.only-h b { font-weight: 600; color: var(--ink); }
.only > :last-child { margin-bottom: 0 !important; }
.only p { max-width: none; }

/* ── Where this screen lives ─────────────────────────────────────────────
   Most teachers meet this product inside their LMS, so "which product am I
   in" is a real question and the path answers it before the prose starts. */
.where { margin: 0 0 26px; }
.where ol {
  list-style: none; display: flex; flex-wrap: wrap; align-items: center;
  gap: 0 4px; margin: 0 !important; padding: 10px 0 !important; max-width: none !important;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  font-family: var(--mono); font-size: 13px; font-weight: 500; color: var(--ink-soft);
}
.where li { margin: 0; padding: 2px 4px; }
/* On the trailing edge, not the leading one. Generated on the following
   item, a wrapped breadcrumb began its second line with a stray chevron,
   which reads as a typo; at the end of a line it reads as continuation. */
.where li:not(:last-child)::after { content: '\203A'; margin-left: 9px; color: var(--rule-strong); }
.where li[aria-current] { color: var(--signal); }
/* The current segment is claret whether it is a screen name or a key. */
.where li[aria-current] kbd { color: var(--signal); border-color: var(--signal); }

/* ── A person speaking ───────────────────────────────────────────────────
   The serif is only ever this. If it is not a line somebody actually said,
   it is Geist. DESIGN.md §2 — the whole type system depends on it. */
.said { margin: 0 0 28px; max-width: 46ch; }
.said blockquote {
  margin: 0; padding: 18px 22px;
  background: var(--speaker); border-left: 2px solid var(--rule-strong);
}
.said blockquote p {
  margin: 0 !important; max-width: none;
  font-family: 'Instrument Serif', Georgia, serif; font-weight: 400;
  font-size: clamp(21px, 2.4vw, 26px); line-height: 1.32; letter-spacing: -.01em;
}
.said figcaption { margin-top: 10px; font-size: 14px; color: var(--ink-soft); }

/* ── Directory index list ─────────────────────────────────────────────── */
.dir-list { list-style: none; margin: 0 !important; padding: 0 !important; max-width: var(--measure) !important; }
.dir-list li { margin: 0; padding: 18px 0; border-top: 1px solid var(--rule); }
/* The page title already draws a rule under itself, 40px above. Two hairlines
   with nothing between them read as an empty first row. */
.dir-list li:first-child { border-top: 0; padding-top: 0; }

/* The generated folder stub (wiki/img/). Small, but it is a page a reader can
   land on from an image URL, and it carries the screenshots' provenance. */
/* A ruled block immediately before a ruled heading draws two hairlines with
   nothing between them, which reads as an empty section the reader then goes
   looking for content in. Whichever comes second drops its rule. */
:is(.where, .note, .only, .shot):has(+ :is(h2, h3)) + :is(h2, h3),
.wiki-main :is(h2, h3):first-child { border-top: 0; padding-top: 0; }

.wiki-page { max-width: var(--measure); margin: 0 auto; padding: 48px var(--gutter); }
.wiki-page h1 { font-size: 30px; font-weight: 600; letter-spacing: -.02em; margin: 0 0 16px; }
.wiki-page p { margin: 0 0 14px; }
.dir-list a { font-weight: 500; font-size: 18px; text-decoration: none; }
.dir-list a:hover { text-decoration: underline; text-underline-offset: 4px; }
.dir-list span { display: block; margin-top: 4px; color: var(--ink-soft); font-size: 15px; }

/* ── Previous / next ──────────────────────────────────────────────────── */
.wiki-seq {
  display: flex; flex-wrap: wrap; gap: 16px 24px; justify-content: space-between;
  margin-top: 64px; padding-top: 22px; border-top: 1px solid var(--rule);
}
.wiki-seq a {
  flex: 1 1 12rem; max-width: 22rem; text-decoration: none;
  font-weight: 500; font-size: 17px; line-height: 1.35;
}
.wiki-seq a:hover { text-decoration: underline; text-underline-offset: 4px; }
.seq-next { text-align: right; }
/* The front page is the only one with a next and no previous. Without this
   its box sits at the left of the column with its text right-aligned, which
   lands the link dead centre and reads as a stray. */
.wiki-seq > .seq-next:only-child { margin-left: auto; }
.seq-l {
  display: block; margin-bottom: 5px;
  font-family: var(--mono); font-weight: 500; font-size: 12px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-soft);
}

/* ── On this page ─────────────────────────────────────────────────────── */
.wiki-toc {
  grid-area: toc; position: sticky; top: var(--head); align-self: start;
  padding: 44px 0 0; font-size: 14px;
}
.wiki-toc .eyebrow { margin-bottom: 10px; font-size: 12px; }
.wiki-toc ul { list-style: none; margin: 0; padding: 0; }
.wiki-toc li { margin: 0; }
.wiki-toc a {
  display: block; padding: 7px 0 7px 12px; line-height: 1.35;
  color: var(--ink-soft); text-decoration: none; border-left: 1px solid var(--rule);
}
.wiki-toc a:hover { color: var(--signal); border-left-color: var(--signal); }

/* ── Footer ───────────────────────────────────────────────────────────── */
.wiki-foot {
  max-width: var(--max); margin: 0 auto; padding: 28px var(--gutter) 72px;
  border-top: 1px solid var(--rule); color: var(--ink-soft); font-size: 15px;
}
.wiki-foot p { margin: 0 0 6px; }

/* The "all pages" jump. Below 860px the sidebar sits under the article and this
   is a plain visible link to it. Above 860px the sidebar is on the left, where
   nobody needs a link — but the article comes first in the DOM there (so the
   narrow layout reads and tabs in the order it looks), which leaves a keyboard
   user tabbing the whole article before reaching it. So the jump stays in the
   tab order and out of sight until focused, exactly like the skip link. */
.wiki-jump {
  position: absolute; left: -9999px; top: 0; z-index: 20; margin: 0;
  background: var(--paper); border: 1px solid var(--ink);
  padding: 10px 16px; font-size: 15px;
}
.wiki-jump:focus-within { left: 12px; top: calc(var(--head) + 8px); }

/* ── Responsive ───────────────────────────────────────────────────────── */
@media (max-width: 1120px) {
  .wiki-shell { grid-template-columns: 220px minmax(0, 1fr); grid-template-areas: "side main"; gap: 0 40px; }
  .wiki-toc { display: none; }   /* the headings are right there in the column */
}
@media (max-width: 860px) {
  .wiki-shell { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main" "side"; gap: 0; }
  .wiki-side {
    position: static; max-height: none; overflow: visible;
    margin-top: 56px; padding-top: 24px; border-top: 1px solid var(--rule-strong);
  }
  .wiki-main { padding-top: 28px; }
  .wiki-jump { position: static; margin: 18px 0 0; font-size: 15px;
               background: none; border: 0; padding: 0; }
  /* Two lines: the wordmark and what this is, then the two links. That is
     ~90px of a 640px phone viewport, so it stops being sticky here — and
     --head goes with it, which keeps `scroll-margin-top` on the headings
     honest when someone follows an anchor. */
  .wiki { --head: 0px; }
  .wiki-band { position: static; }
  /* Same wrap the main site's band does below 720px: wordmark row, then the
     nav on its own line. */
  .wiki-head { flex-wrap: wrap; gap: 8px 16px; padding: 12px var(--gutter); }
  .wiki-head-nav { flex-basis: 100%; gap: 4px 16px; font-size: 14px; }
}
@media (max-width: 620px) {
  .wiki { font-size: 16px; }
  .wiki-main h2 { font-size: 23px; margin-top: 44px; }
  .standfirst { font-size: 18px; }
  .said blockquote { padding: 15px 16px; }
  .note { padding: 15px 16px; }

  /* The control table stacks. The build script writes role="table"/"row"/
     "cell" on it precisely so display:block does not take the semantics with
     it, and the column labels below replace the header row it hides. */
  .controls thead { position: absolute; left: -9999px; }
  .controls, .controls caption, .controls tbody, .controls tr, .controls :is(th, td) { display: block; width: auto; }
  /* Beats the percentage column widths set for the wide layout, which are a
     class selector and would otherwise squeeze each stacked cell to 21%. */
  .controls .ctl-name, .controls .ctl-who { width: auto; }
  .controls tr { padding: 16px 0; border-top: 1px solid var(--rule); }
  .controls tbody :is(th, td) { border-top: 0; padding: 0; }
  .controls .ctl-name { font-size: 17px; margin-bottom: 4px; }
  .controls td:not(.ctl-who) { margin-bottom: 6px; }
  .controls .ctl-who::before {
    content: 'Seen by '; font-family: var(--mono); font-size: 11px;
    letter-spacing: .08em; text-transform: uppercase;
  }
  /* Plain tables stack too, the same way and for the same reason. Each cell
     carries its column heading in data-label, written by the build. */
  .table-scroll > table thead { position: absolute; left: -9999px; }
  .table-scroll > table,
  .table-scroll > table tbody,
  .table-scroll > table tr,
  .table-scroll > table :is(th, td) { display: block; width: auto; }
  .table-scroll > table tr { padding: 16px 0; border-top: 1px solid var(--rule); }
  .table-scroll > table tbody :is(th, td) { border-top: 0; padding: 4px 0 0; }
  .table-scroll > table tbody :is(th, td)::before {
    content: attr(data-label); display: block;
    font-family: var(--mono); font-size: 11px; letter-spacing: .08em;
    text-transform: uppercase; color: var(--ink-soft); margin-bottom: 2px;
  }
  .table-scroll > table tbody th { font-size: 17px; }
  .table-scroll > table tbody th::before { content: none; }

  .shot-keys > li { padding-left: 30px; font-size: 15px; }
  .wiki-seq a { flex-basis: 100%; max-width: none; }
  .seq-next { text-align: left; }
}
@media (max-width: 400px) {
  .wiki-head-nav { gap: 14px; }
  .wiki-head-nav a { font-size: 14px; }
  .wiki-mark { font-size: 17px; }
}

/* ── Print — a teacher will hand this to a colleague ─────────────────── */
@page { margin: 18mm; }
@media print {
  .wiki-band, .wiki-side, .wiki-toc, .wiki-seq, .skip, .wiki-jump { display: none; }
  /* A guide meant to be handed to a colleague. Without break control a figure
     landed on one page and its numbered key on the next, headings were orphaned
     at the foot of a sheet, and a tall screenshot was sliced in two. */
  .wiki-main :is(h1, h2, h3) { break-after: avoid; }
  .shot, .note, .only, .said, tr { break-inside: avoid; }
  /* An overflow container clips on paper — there is no scrollbar to reveal the
     rest, so a wide table would be silently truncated. */
  .table-scroll { overflow: visible; }
  .wiki-main table { font-size: 9pt; }
  /* The pin's halo and chip are painted, and browsers drop backgrounds when
     printing, which would leave bare numerals over the screenshot. */
  .pin { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  /* A link with no destination is a dead reference on paper. */
  .wiki-main a[href^="http"]::after,
  .wiki-main a[href$=".html"]::after {
    content: ' (' attr(href) ')'; font-size: .85em; color: var(--ink-soft);
  }
  .wiki-shell { display: block; max-width: none; padding: 0; }
  .wiki { font-size: 11pt; }
  .wiki a { color: var(--ink); }
}
