/* The public board.
 *
 * Editorial rather than app-like on purpose: this page is read once, by
 * somebody who has never seen it, usually because a friend sent the link.
 * Generous type, hairlines instead of shadows, and the indigo accent spent on
 * exactly two things, the verdict pills and the primary button.
 *
 * Two layouts. Under 960px it is one column, written for a phone first, with
 * the 560px block below tightening it for a small one. From 960px the things
 * that decide what the list shows (the tiles, the controls, the legend) move
 * into a sticky rail on the left and the list takes the rest, because a
 * 720px phone column in the middle of a laptop screen was a phone page shown
 * on a desk. Same markup, the rail and the results are two wrappers in
 * public.html and nothing else moves.
 *
 * Tokens come from `tokens.css`, the same file the app shell loads, so the
 * two surfaces cannot drift apart. Everything is on a 4px grid. No web
 * fonts: the about page promises no third-party requests, and it is true.
 */

* { box-sizing: border-box; }

body {
  margin: 0 auto;
  max-width: 720px;
  padding: 40px 20px 64px;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

/* --- nav ------------------------------------------------------------------ */

/* Every page reachable by a link somebody sent needs a way onwards from it,
   including the first one they land on, where the browser's own back button
   has nowhere to go. */
.crumb {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 16px;
  padding-bottom: 12px;
  margin-bottom: 24px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.crumb a { color: var(--text-2); text-decoration-color: var(--border-strong); }
.crumb a:hover { color: var(--text); }
.crumb .brand {
  font-weight: 600;
  font-size: 15px;
  color: var(--accent);
  text-decoration: none;
}
/* The auto margin used to sit on the brand, which pushed the school's name
   into the right-hand group with the two links, where it read as a third one
   that would not click. It belongs to the brand it qualifies: name on the
   left, then the gap, then only the things that go somewhere. */
.crumb .here {
  margin-right: auto;
  color: var(--text-3);
  font-size: 12px;
}

/* --- header -------------------------------------------------------------- */

.top { margin-bottom: 32px; }

h1 {
  margin: 0 0 16px;
  font-size: 32px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}
h1 em { font-style: italic; color: var(--accent); }

.lede { margin: 0 0 12px; color: var(--text-2); }
.lede strong { color: var(--text); font-weight: 600; }

/* --- tiles --------------------------------------------------------------- */

.tiles {
  display: grid;
  /* Varied widths: three identical cards is the generic grid. */
  grid-template-columns: 1.1fr 1fr 0.9fr;
  gap: 12px;
  margin-bottom: 24px;
}

.tile {
  display: block;
  width: 100%;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  min-height: 44px;
  transition: border-color .12s, background .12s, transform .08s;
}
.tile:hover { border-color: var(--border-strong); }
.tile:active { transform: translateY(1px); }
/* The one currently being shown. A pressed tile and the controls below it
   always say the same thing. A fill, because a hairline was the only mark and
   three tiles read as identical at a glance. */
.tile[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.tile[aria-pressed="true"] b { color: var(--accent); }
/* The muted caption is 4.3:1 on the accent fill. One step up passes. */
.tile[aria-pressed="true"] small { color: var(--text-2); }
.tile b {
  display: block;
  font-size: 28px;
  font-weight: 600;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.tile span { display: block; font-size: 13px; font-weight: 500; }
.tile small { display: block; color: var(--text-3); font-size: 12px; }

/* --- controls ------------------------------------------------------------ */

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
  padding-bottom: 16px;
  margin-bottom: 24px;
  border-bottom: 1px solid var(--border);
}

/* `min-width: 0` on both. A select's automatic minimum is the width of its
   widest option, and this one is filled from the server after the page has
   painted: adding "Sales & business development" widened the control, pushed
   the two checkboxes onto a second line, and moved everything from the legend
   down by 70px. That single reflow was the whole 0.18 layout shift on this
   page. The row's width is the container's business now, not the contents'. */
.field { display: flex; flex-direction: column; gap: 4px; flex: 1 1 160px; min-width: 0; }
.field select, .field input { width: 100%; min-width: 0; }
.field > span {
  font: 500 11px/1.4 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3);
}
.field small { text-transform: none; letter-spacing: 0; }

input, select, button, textarea {
  font: inherit;
  font-size: 14px;
  color: inherit;
  padding: 8px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
input:focus-visible, select:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* The box stays small because a bigger one looks wrong beside 14px text. The
   label around it is the target, and that is what a thumb has to hit. */
.check {
  display: flex; align-items: center; gap: 8px; font-size: 14px;
  min-height: 32px; padding: 4px 0; cursor: pointer;
}
.check input { padding: 0; width: 18px; height: 18px; accent-color: var(--accent); }

/* --- the call to action, and the mode it leads to ------------------------ */

/* The one place on the page that asks the reader for something. It is the
   only accent-filled block outside the pressed tile, on purpose: a board
   that reports 826 unproven clubs and asks for nothing is a board that
   stays at 826. */
.help-wrap { margin: 0 0 20px; }
.help {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--text);
  text-decoration: none;
  font-size: 13px;
  line-height: 1.35;
}
.help:hover { background: var(--accent); color: var(--accent-text); }
.help:hover b { color: inherit; }
.help b {
  font-size: 20px;
  font-weight: 600;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.help::after {
  content: "";
  margin-left: auto;
  align-self: center;
  width: 7px; height: 7px;
  border: solid currentColor; border-width: 1.5px 1.5px 0 0;
  transform: rotate(45deg);
}
#verify-back a { font-size: 13px; color: var(--text-2); }

/* In verify mode the filters are the mode. Leaving them on screen would be
   four controls that either do nothing or take the reader back out of the
   thing they came to do. Search stays, because finding one club by name is
   the other half of the job. */
.verify .tiles, .verify .tiles-note,
.verify .controls .field:nth-child(4), .verify .controls .check {
  display: none;
}

/* --- club cards ---------------------------------------------------------- */

.club {
  padding: 16px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.club h3 { margin: 0 0 8px; font-size: 17px; font-weight: 600; }

.chips { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 12px; }

.pill, .chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font: 500 12px/1.5 var(--sans);
  white-space: nowrap;
}

/* The verdict is the reason this page exists, and it sat in a row of five
   chips at the same weight as "Consulting", with the two accent-coloured ones
   beside it louder than it was. It reads first now: a full pill, heavier, and
   the row is ordered so nothing sits to its left. */
.pill {
  padding: 2px 10px;
  border-radius: 999px;
  font-weight: 650;
  letter-spacing: .01em;
}

.pill.active  { background: var(--ok-bg);      color: var(--ok); }
.pill.dormant { background: var(--warn-bg);    color: var(--warn); }
.pill.dead    { background: var(--bad-bg);     color: var(--bad); }
.pill.unknown { background: var(--neutral-bg); color: var(--neutral); }

.chip { background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border); }
/* Facts about how to join, not verdicts. They keep the accent in their text,
   because "runs an application" is worth more to a first-year than "Consulting"
   is, but not in a border: a crisp accent outline read louder than the verdict
   pill it sat beside, which inverted the one hierarchy on the card that
   matters. Colour with meaning belongs to the verdict. */
.chip.warn { background: transparent; color: var(--accent); border-color: var(--border-strong); }

.why { margin: 0 0 8px; font-size: 14px; color: var(--text-2); }

/* An unproven claim looks like a note in the margin, never like a verdict. */
.claim {
  margin: 0 0 8px;
  padding-left: 12px;
  border-left: 2px solid var(--border-strong);
  font-size: 14px;
  font-style: italic;
  color: var(--text-2);
}

.tally {
  margin: 0 0 12px;
  font: 400 12px/1.5 var(--mono);
  color: var(--text-3);
}

/* Two lines. The question and its two answers are the primary line. Details
   and the outbound links are the secondary line, muted, each at least 32px
   tall so a thumb has something to hit. It was one row of six things at one
   weight, and the buttons read as text. */
.act { display: grid; gap: 8px; }
.act .primary { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }
.act .secondary { display: flex; flex-wrap: wrap; gap: 0 16px; align-items: center; }

/* The question the two buttons answer. Without it they are two verbs with no
   subject, and people read them as filters. */
.ask {
  font-size: 13px;
  color: var(--text-3);
}

/* One control, two answers. They were a solid primary button and a ghost, so
   the loud one was the one that says the club is fine, which is a thumb on the
   scale in a data set whose only value is that nobody put one there. Equal
   weight, and each takes its own colour only on hover, so a resting card is
   still calm. */
/* Outlined at 4.5:1 so the boundary reads as a control (it was --border-strong,
   1.5:1 against the card, and the pair read as two words), 40px tall for a
   thumb, and a pressed state, which it never had. */
.vote {
  display: inline-flex;
  border: 1px solid var(--text-3);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.vote button {
  cursor: pointer;
  padding: 8px 16px;
  min-height: 40px;
  border: 0;
  border-radius: 0;
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
  font-weight: 550;
  transition: background .12s, color .12s, transform .08s;
}
.vote button + button { border-left: 1px solid var(--text-3); }
.vote-yes:hover, .vote-yes:focus-visible { background: var(--ok-bg);  color: var(--ok); }
.vote-no:hover,  .vote-no:focus-visible  { background: var(--bad-bg); color: var(--bad); }
.vote button:active { transform: translateY(1px); }
.vote-yes:active, .vote-yes.pressed { background: var(--ok);  color: var(--ok-bg); }
.vote-no:active,  .vote-no.pressed  { background: var(--bad); color: var(--bad-bg); }
.vote button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Settled: the two buttons become the one answer that was given. The dialog
   before it is where a mis-tap is caught; there is no undo here because the
   store has no delete, and a button that says undo and does not is worse
   than none. */
.voted {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 40px; padding: 0 12px 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); font-size: 13px; color: var(--text-2);
}
.voted::before {
  content: ""; width: 5px; height: 10px;
  border: solid var(--ok); border-width: 0 2px 2px 0;
  transform: translateY(-1px) rotate(45deg);
}
.voted b { color: var(--text); font-weight: 600; }
.ghost {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text-2);
}
.act .secondary a {
  display: inline-flex; align-items: center; min-height: 32px;
  font-size: 13px;
  color: var(--text-2);
  text-decoration-color: var(--border-strong);
}
.act .secondary a:hover { color: var(--text); text-decoration-color: currentColor; }

/* A link that is not worth following. It sits where the link would have been,
   because the absence is the information. */
.deadlink {
  display: inline-flex; align-items: center; min-height: 32px;
  font-size: 13px;
  font-style: italic;
  color: var(--text-3);
}

/* `margin: 0` matters more than it looks. This is a <p> and it is the only
   child of #list while the fetch is in flight, so its default 16px top margin
   collapsed out through #list and held the whole list 16px lower than where
   the cards would land. Everything then jumped up by 16px the moment they
   arrived, for the last of this page's layout shift. */
.empty { margin: 0; padding: 32px 0; color: var(--text-3); text-align: center; }

/* --- explainer and footer ------------------------------------------------ */

.how {
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.how h2 { margin: 0 0 16px; font-size: 20px; font-weight: 600; }
/* The about page is five sections inside one wrapper, so every heading after
   the first had no space above it and the five ran together as one block. */
.how h2 ~ h2 { margin-top: 32px; }
.how h2 + .lede, .how h2 + dl { margin-top: 0; }
.how dl { margin: 0; display: grid; grid-template-columns: 160px 1fr; gap: 8px 16px; }
.how dt { font-weight: 600; font-size: 14px; }
.how dd { margin: 0; font-size: 14px; color: var(--text-2); }

.foot {
  margin-top: 40px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-3);
  text-align: center;
}
/* Three disclaimers and a button. Left-aligned under a page whose columns
   both end above them, the block read as the start of another section. */
.foot p { margin: 0 auto 4px; max-width: 68ch; }

/* --- report dialog ------------------------------------------------------- */

dialog {
  width: min(420px, calc(100vw - 32px));
  padding: 24px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}
dialog::backdrop { background: rgba(20, 22, 26, 0.4); }
dialog h2 { margin: 0 0 8px; font-size: 18px; font-weight: 600; }
dialog .hint { margin: 0 0 16px; font-size: 14px; color: var(--text-2); }
dialog .field { margin-bottom: 12px; }
dialog input, dialog textarea { width: 100%; resize: vertical; }
.foot button { cursor: pointer; font-size: 13px; }
dialog menu { display: flex; justify-content: flex-end; gap: 8px; margin: 16px 0 0; padding: 0; }
dialog button { cursor: pointer; background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
dialog button.ghost { background: var(--surface); border-color: var(--border-strong); color: var(--text-2); }

.error { margin: 0; font-size: 14px; color: var(--bad); }

.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  max-width: min(480px, calc(100vw - 32px));
  padding: 12px 16px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--text);
  color: var(--bg);
  font-size: 14px;
}

@media (max-width: 560px) {
  body { padding: 24px 16px 48px; }
  h1 { font-size: 26px; }
  /* Stacking these put a screen and a half of preamble above the first club.
     Three small numbers in a row say the same thing in one band. */
  /* Three fixed columns put a 20px number and a label into 96px at 375. Let
     them fall to two when that is what fits. */
  .tiles { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; }
  .tile { padding: 8px; }
  .tile b { font-size: 20px; }
  .tile span { font-size: 12px; }
  /* These captions are the only thing that says what the three numbers mean,
     and hiding them on a phone left a stranger with three bare figures on the
     one device where they have the least patience to work it out. */
  .tile small { display: block; font-size: 11px; line-height: 1.35; }
  /* iOS Safari zooms the whole page in when a focused input is under 16px,
     and it does not zoom back out: you tap Search, the page jumps, and every
     control you wanted next is off screen. This is the one page built for a
     phone, so 16px is the floor there. */
  input, select, textarea { font-size: 16px; }

  .how dl { grid-template-columns: 1fr; }
  .how dt { margin-top: 8px; }
  /* Five stacked controls come to 302px on a 320 phone, which is most of a
     screen between the numbers and the first club. Search keeps the full
     width because it is the one people type in; the two menus and the two
     checkboxes pair off. */
  .controls {
    display: grid;
    /* `1fr` is `minmax(auto, 1fr)`, and that `auto` floor is the track's
       min-content width. "Sales & business development" is 297px as one
       unbreakable option, so two of those columns came to 559px inside a
       320px phone and dragged the whole document with them. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 10px 12px;
    padding-bottom: 12px;
    margin-bottom: 16px;
  }
  .controls > .field:first-child { grid-column: 1 / -1; }
  .controls > .check { margin: 0; }
  /* One line, not two blocks: a count and a way to say it is wrong belong
     next to each other, and each was taking its own band. */
  .count { display: inline; margin: 0; }
  .wrong { display: inline; margin: 0 0 0 6px; }
  .count-row { margin: 0 0 14px; }
  .act a { margin-left: 0; }

  /* The two answers split the card's full width, so each thumb target is
     about 170px wide rather than 100 and the pair is not two small words in
     a corner. */
  .act .primary { flex-direction: column; align-items: stretch; }
  .vote { display: flex; }
  /* Half of a 320px card is 138px, and "Report as folded" needs 125 of it
     at this size, so the side padding is what gives. */
  .vote button { flex: 1; padding: 8px 6px; white-space: nowrap; }
  /* A sheet from the bottom, where the thumb already is, rather than a box
     floating in the middle with the keyboard about to cover it. Still the
     native dialog, so Esc, focus and the backdrop are unchanged. */
  dialog {
    width: 100%; max-width: none;
    margin: auto 0 0;
    border-radius: 12px 12px 0 0;
    border-bottom: 0;
    padding-bottom: max(24px, env(safe-area-inset-bottom));
  }
  .toast { bottom: max(24px, env(safe-area-inset-bottom)); }
}

/* --- the laptop layout ---------------------------------------------------- */

@media (min-width: 960px) {
  body.board {
    max-width: 1140px;
    padding: 32px 32px 64px;
    display: grid;
    /* `minmax(0, 1fr)`, not `1fr`: a card's evidence line can carry an
       unbroken URL, and the auto minimum would let it widen the column. */
    grid-template-columns: 296px minmax(0, 1fr);
    column-gap: 48px;
    align-items: start;
  }
  .board > .crumb, .board > .top, .board > .foot { grid-column: 1 / -1; }
  .board .lede { max-width: 62ch; }
  .results { min-width: 0; }

  /* Sticky so the filters stay in reach two hundred cards down. Scrolls
     inside itself when the legend is open on a short screen, rather than
     running off the bottom with the last control unreachable.

     The sticky box is the inner div and the grid item around it is stretched
     to the row, because sticky on the grid item itself was not held to the
     end of its own grid area: on a four-result search the rail carried on
     down and printed itself over the footer, 58px of "Not affiliated with,
     endorsed by, or run by any university" under the legend. Inside a
     stretched block the bottom of the block is the floor and there is
     nothing to get wrong. */
  .rail { align-self: stretch; }
  .rail-in {
    position: sticky;
    top: 24px;
    max-height: calc(100vh - 48px);
    overflow-y: auto;
  }
  /* One tile per row, the number beside its label rather than above it, so
     the three read as a list of filters and not a dashboard. */
  .tiles { grid-template-columns: 1fr; gap: 8px; margin-bottom: 12px; }
  .tile {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 12px;
    align-items: baseline;
  }
  .tile b { grid-row: 1 / 3; font-size: 24px; min-width: 2.2ch; }
  .tile small { grid-column: 2; }
  .controls { flex-direction: column; align-items: stretch; }
  .field { flex: none; }

  /* With the width to spare, the card's two rows become one line: the
     question and its two answers on the left, the ways out on the right. */
  /* The question and its buttons are sized first and never wrap. The links
     take what is left and wrap when a dead-link note is long, since a
     wrapped link costs nothing and a vote pair split over two lines reads
     as two controls. */
  .act { grid-template-columns: max-content minmax(0, 1fr); align-items: center; }
  .act .primary { flex-wrap: nowrap; }
  .act .secondary { justify-content: flex-end; }
}

[aria-busy="true"] { opacity: .55; transition: opacity .12s; }

/* Club evidence quotes a post or a page, and those carry URLs. */
.why, .claim, .tally { overflow-wrap: anywhere; }

/* The list goes from one line of "Loading" to two hundred cards, and the
   explainer under it was shoved down the page the moment it did. Holding the
   space means the page you start reading is the page you keep reading. */
#list { min-height: 70vh; }

/* --- the detail panel ----------------------------------------------------- */

/* A card carries one line of evidence because two hundred cards cannot carry
   six. The rest is one click away rather than on another page, because the
   question people are answering is "is this one worth it", and that is
   answered by comparing cards. */
/* Secondary now, so it borrows nothing from the vote control: no fill, no
   border at rest, a chevron that says it opens something. */
.more {
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  min-height: 32px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-2);
  font-size: 13px;
  font-weight: 500;
}
.more:hover { border-color: var(--border-strong); color: var(--text); }
.more::after {
  content: ""; width: 7px; height: 7px;
  border: solid currentColor; border-width: 0 1.5px 1.5px 0;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .12s;
}
.more[aria-expanded="true"]::after { transform: translateY(1px) rotate(225deg); }

.detail {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.detail h4 {
  margin: 14px 0 6px;
  font: 500 11px/1.4 var(--mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-3);
}
.detail h4:first-child { margin-top: 0; }
.blurb {
  margin: 0 0 4px;
  font-size: 14px;
  color: var(--text-2);
  overflow-wrap: anywhere;
}

/* Date first, because the date is the whole claim. */
.ledger { margin: 0; padding: 0; list-style: none; }
.ledger li {
  display: grid;
  grid-template-columns: 92px 1fr auto;
  gap: 4px 10px;
  padding: 5px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.ledger li:last-child { border-bottom: 0; }
.ledger time {
  font: 400 12px/1.5 var(--mono);
  color: var(--text-3);
  white-space: nowrap;
}
.ledger span { color: var(--text-2); overflow-wrap: anywhere; }
.ledger a { font-size: 13px; color: var(--text-3); white-space: nowrap; }
/* A claim two people have not yet agreed on is not the same kind of thing as a
   trace, and it should not look like one. */
.ledger li.is-claim span { font-style: italic; }
.ledger li.is-claim time::after { content: " ·"; }

.links a { margin-right: 12px; font-size: 14px; }
.cats { margin: 10px 0 0; font-size: 12px; color: var(--text-3); }

@media (max-width: 560px) {
  .ledger li { grid-template-columns: 1fr; gap: 2px; }
  .ledger a { justify-self: start; }
}

/* --- the legend, the count, and the way to say this is wrong -------------- */

/* Was a section under two hundred and fifty cards, which is a definition
   nobody reaches. Closed by default so it costs one line above the list. */
.how {
  margin: 0 0 20px;
  padding: 12px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.how > summary {
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  list-style: none;
}
.how > summary::-webkit-details-marker { display: none; }
.how > summary::before { content: "+ "; color: var(--text-3); }
.how[open] > summary::before { content: "\2212 "; }
.how[open] > summary { margin-bottom: 14px; }
.how dl { margin-top: 12px; }

/* The default view drops nine hundred clubs and used to say nothing at all. */
/* One line reserved. The span is empty until the fetch answers, and the row
   went from nothing to 26px the moment it did. Under the old stack that moved
   a list that was mostly below the fold; beside the rail it moved every card
   on screen, and was the whole of the page's layout shift. */
.count-row { min-height: 1.6em; }
.count {
  margin: 0 0 14px;
  font-size: 13px;
  color: var(--text-3);
}

.wrong { margin: 0 0 20px; }
.wrong button { font-size: 13px; }
.foot .wrong { margin-top: 12px; }

/* Off screen, in the accessibility tree. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* A card takes focus after "show more". Only a keyboard sees the ring. */
.club:focus { outline: none; }
.club:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* --- the flowchart ------------------------------------------------------- */

/* It is 900px wide and cannot reflow, so on a phone the entire right-hand
   column, which is every verdict the page exists to explain, is off screen
   with nothing saying so. Saying it in a sentence is cheaper and clearer than
   redrawing the diagram, and it links to the same thing in words. */
.swipe {
  margin: 0 0 8px;
  font-size: 13px;
  color: var(--text-3);
}
.reel:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (min-width: 1000px) {
  /* At this width the whole diagram fits, so the instruction is noise. */
  .swipe { display: none; }
}

/* The one instruction that has to stay above the fold, because a tile that
   looks like a statistic is not obviously a control. */
.tiles-note {
  margin: 8px 0 20px;
  font-size: var(--fs-sm);
  color: var(--text-3);
}

.more-row { margin: 20px 0 0; text-align: center; }
.more-row button {
  padding: 8px 20px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.more-row button:hover { border-color: var(--accent); color: var(--accent); }
.more-row button:disabled { color: var(--text-3); cursor: default; }

/* Forced colours flatten the accent border and inset shadow that were the only
   marks on the pressed tile, so all three read as identical and nothing said
   which filter the list was showing. */
@media (forced-colors: active) {
  .tile[aria-pressed="true"] {
    outline: 3px solid Highlight;
    outline-offset: -3px;
  }
  .chip.warn { border-style: dashed; }
}
