/* The Reserve List — shared components.
 *
 * The idioms that genuinely recur across pages. Each one replaces several
 * near-identical copies in the source files; the note on each says which.
 *
 * Rule for adding to this file (CSS Pass C): promote a component across ALL
 * pages at once, never one page at a time. Promoting .tile on the hub while
 * listing.php keeps its own copy is exactly how two .tiles slowly diverge
 * again, which is the situation this file exists to end.
 */

/* ==========================================================================
   The corner-bracket panel
   --------------------------------------------------------------------------
   The site's signature: a panel with four 11px brackets clipped to its corners.
   It appeared under four different class names — .member and .cons in
   index_2.html, .card in listing.html and signup.html, and again in most drill
   pages — with byte-identical rules each time.

   Two pseudo-elements give the top corners; the bottom two need real elements,
   which is why the markup carries <i class="p-bl"></i><i class="p-br"></i>.
   ========================================================================== */

.panel {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line-dim);
  border-radius: 3px;
  padding: 15px 18px;
}

.panel::before,
.panel::after,
.panel > .p-bl,
.panel > .p-br {
  content: "";
  position: absolute;
  width: 11px;
  height: 11px;
  border-color: var(--line);
  border-style: solid;
}

.panel::before      { top: -1px;    left: -1px;  border-width: 2px 0 0 2px; }
.panel::after       { top: -1px;    right: -1px; border-width: 2px 2px 0 0; }
.panel > .p-bl      { bottom: -1px; left: -1px;  border-width: 0 0 2px 2px; }
.panel > .p-br      { bottom: -1px; right: -1px; border-width: 0 2px 2px 0; }

.panel.plain::before,
.panel.plain::after { display: none; }

/* ==========================================================================
   Sections
   ========================================================================== */

.sec      { margin-bottom: 34px; }
.sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 4px; }
.sec-n    { font-family: var(--disp); font-weight: 700; font-size: 11px; color: var(--drill); letter-spacing: .1em; }
.sec-t    { font-family: var(--disp); font-weight: 700; font-size: 19px; }

/* A section heading that links to its own index page. Underlined rather than
   coloured, so it still reads as a heading first and a link second. */
.sec-t a { color: inherit; text-decoration: none; border-bottom: 1px solid var(--line-dim); }
.sec-t a:hover { border-bottom-color: var(--line); }
.sec-d    { font-size: 11.5px; color: var(--ink-dim); margin: 0 0 14px; line-height: 1.55; }

.sect-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: .14em;
  color: var(--ink-dim); margin: 0 0 8px;
}

/* ==========================================================================
   Buttons
   --------------------------------------------------------------------------
   Replaces .cta (signup), .joinbtn (hub member card) and .m-cta (hub listing
   link), which were three near-identical rules.
   ========================================================================== */

.btn {
  display: inline-block;
  font-family: var(--disp);
  font-weight: 700;
  font-size: 13px;
  padding: 11px 22px;
  border-radius: 6px;
  border: 2px solid var(--line-dim);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: transform .1s, filter .15s, border-color .15s, background .15s;
}
.btn:hover:not(:disabled) { transform: scale(1.02); filter: brightness(1.2); }
.btn:disabled { opacity: .4; cursor: not-allowed; }

.btn-go   { border-color: var(--ok);   background: rgba(111, 231, 179, .10); color: var(--ok); }
.btn-line { border-color: var(--line); background: rgba(94, 200, 216, .10);  color: var(--line); }

/* The quiet variant: .m-cta in the original. */
.btn-ghost {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 11px;
  padding: 8px 14px;
  border-width: 1px;
  border-radius: 5px;
  color: var(--line);
}
.btn-ghost:hover { background: rgba(94, 200, 216, .10); transform: none; }

/* ==========================================================================
   Tiles and mode cards
   ========================================================================== */

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(226px, 1fr)); gap: 10px; }

.tile {
  display: block; text-decoration: none; color: inherit;
  background: var(--panel);
  border: 1px solid var(--line-dim);
  border-left: 3px solid var(--ok);
  border-radius: 4px;
  padding: 12px 14px;
  transition: border-color .15s, transform .1s, background .15s;
}
.tile:hover { border-color: var(--line); transform: translateY(-2px); background: #13314f; }
.tile-n { font-family: var(--disp); font-weight: 700; font-size: 14px; margin-bottom: 3px; }
.tile-d { font-size: 10.5px; color: var(--ink-dim); line-height: 1.45; }
.tile-tag {
  display: inline-block; font-size: 8.5px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-dim); border: 1px solid var(--line-dim); border-radius: 8px;
  padding: 1px 7px; margin-top: 7px;
}

.mode-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 820px) { .mode-grid { grid-template-columns: 1fr; } }

.mode {
  display: block; text-decoration: none; color: inherit;
  background: var(--panel); border: 1px solid var(--line-dim);
  border-radius: 4px; padding: 20px 18px;
  transition: transform .15s, border-color .15s;
}
.mode:hover { transform: translateY(-2px); }
.mode-tag { font-size: 10px; letter-spacing: .12em; text-transform: uppercase; margin-bottom: 9px; }
.mode h3 { font-family: var(--disp); font-weight: 700; font-size: 17px; margin: 0 0 8px; line-height: 1.2; }
.mode p  { font-size: 11px; color: var(--ink-dim); line-height: 1.55; margin: 0; }

.mode.endless { border-color: rgba(94, 200, 216, .5); }
.mode.endless:hover { border-color: var(--ok); }
.mode.endless .mode-tag { color: var(--ok); }
.mode.path { border-color: rgba(255, 159, 90, .4); }
.mode.path:hover { border-color: var(--drill); }
.mode.path .mode-tag { color: var(--drill); }
.mode.exam:hover { border-color: var(--bad); }
.mode.exam .mode-tag { color: var(--bad); }

/* ==========================================================================
   EN TRAVAUX
   --------------------------------------------------------------------------
   Two skewed roadworks bars and a trilingual tag, for anything not built yet.
   Byte-identical in signup.html and six hub tiles.

   The red is #D8232A and the cream #F2ECDD — Belgian roadworks livery, which is
   the joke. Left as literals rather than tokenised: they are a specific
   reference, not a role in the palette.
   ========================================================================== */

.soon-card { position: relative; cursor: not-allowed; overflow: hidden; }
.soon-card:hover { transform: none; border-color: var(--line-dim); background: var(--panel); }
.soon-card .inner { opacity: .38; }

.tile.soon { opacity: .38; cursor: default; }
.tile.soon:hover { transform: none; border-color: var(--line-dim); background: var(--panel); }

.barrier { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
.barrier .bar {
  position: absolute; height: 20px; width: 150%; left: -25%; top: 46%;
  background: repeating-linear-gradient(45deg, #D8232A 0 14px, #F2ECDD 14px 28px);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .5);
}
.barrier .bar.b1 { transform: translateY(-50%) rotate(21deg); }
.barrier .bar.b2 { transform: translateY(-50%) rotate(-16deg) translateX(4px); }

.barrier-tag {
  position: absolute; top: 9px; right: 9px; z-index: 4;
  background: #D8232A; color: #fff;
  font-family: var(--mono); font-size: 8px; letter-spacing: .04em;
  padding: 3px 7px; border-radius: 2px;
  font-weight: 600; line-height: 1.55; text-align: right;
}

/* ==========================================================================
   Notices and forms
   ========================================================================== */

.notice {
  background: rgba(94, 200, 216, .06);
  border-left: 2px solid var(--line);
  padding: 11px 14px; margin: 0 0 14px;
  font-size: 11.5px; color: var(--ink-dim); line-height: 1.6;
}
.notice b { color: var(--ink); }
.notice.bad { border-left-color: var(--bad); }
.notice.crit { border-left-color: var(--crit); }
.notice.ok { border-left-color: var(--ok); }

.field { margin-bottom: 14px; text-align: left; }
.field label {
  display: block; font-size: 10px; text-transform: uppercase;
  letter-spacing: .12em; color: var(--ink-dim); margin-bottom: 5px;
}
.field input {
  width: 100%; font-family: var(--mono); font-size: 13px;
  background: var(--dark); color: var(--ink);
  border: 1px solid var(--line-dim); border-radius: 4px;
  padding: 10px 12px;
}
.field input:focus { border-color: var(--line); outline: none; }
.field .err { display: block; font-size: 10.5px; color: var(--crit); margin-top: 5px; min-height: 13px; }
.field.invalid input { border-color: var(--crit); }

.field-check { display: flex; gap: 9px; align-items: flex-start; margin-bottom: 16px; text-align: left; }
.field-check input { margin-top: 3px; accent-color: var(--line); }
.field-check label { font-size: 11px; color: var(--ink-dim); line-height: 1.55; }

/* --- The corner avatar ------------------------------------------------------
 *
 * Fixed top-right on every page, at 34px, linking to your statistics. Drawn by
 * assets/js/core/badge.js from the stored config; see core/avatar.js for why
 * there is no image to serve.
 *
 * Top-RIGHT specifically because top-left is taken: full pages put the
 * breadcrumb there and bare pages put .rl-back there. A fixed element over
 * either of them would cover the only way out of the page.
 *
 * The label is hidden below 720px. A game panel on a phone needs its width more
 * than the corner needs a caption, and the face alone still reads as "you".
 * ------------------------------------------------------------------------- */
.rl-badge {
  position: fixed;
  top: 10px;
  right: 12px;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 11px 5px 5px;
  border: 1px solid var(--line-dim);
  border-radius: 999px;
  background: rgba(15, 39, 64, .88);
  backdrop-filter: blur(3px);
  text-decoration: none;
  color: var(--ink-dim);
  font-size: 10px;
  letter-spacing: .05em;
  line-height: 1;
  transition: border-color .15s, color .15s;
}
.rl-badge:hover { border-color: var(--line); color: var(--ink); }

.rl-badge-face {
  display: block;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  overflow: hidden;
  flex: 0 0 auto;
  background: var(--panel-2);
  /* The ring is the placeholder. If badge.js never runs — no JavaScript, a
     thrown renderer, storage blocked — this is what is left, and an empty disc
     reads as a deliberate silhouette rather than as something broken. */
  box-shadow: inset 0 0 0 1px var(--line-dim);
}
.rl-badge-face svg { display: block; width: 100%; height: 100%; }

.rl-badge-lab { max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 720px) {
  .rl-badge { padding: 4px; gap: 0; }
  .rl-badge-lab { display: none; }
}

/* Print and reduced-motion have nothing to do with each other, but a fixed
   floating badge is wrong in both: it lands on top of the text in print. */
@media print { .rl-badge { display: none; } }

/* --- Disclosures on the explainers -----------------------------------------
 *
 * Every explainer is interactive already; what made them read as walls of text
 * was two paragraphs of standing prose bolted around the interactive part — a
 * lede above it and a dense sourcing note below. The Treaty Atlas is the one
 * that reads well and the reason is that it has no lede: the map does the
 * framing.
 *
 * So both become disclosures. Collapsed, the page is the thing you came to
 * use. Nothing is deleted — the sourcing is what makes a figure on these pages
 * checkable rather than asserted — it is just no longer in the way.
 * ------------------------------------------------------------------------- */
.orient, .sources {
  margin: 0 0 16px;
  border-left: 2px solid var(--line-dim);
  padding-left: 0;
}
.sources { margin: 22px 0 0; border-left: 0; border-top: 1px solid var(--line-dim); padding-top: 4px; }

.orient > summary, .sources > summary {
  cursor: pointer;
  list-style: none;
  padding: 7px 0 7px 11px;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-dim);
  transition: color .15s;
}
.sources > summary { padding-left: 0; }
.orient > summary:hover, .sources > summary:hover { color: var(--line); }

/* The default triangle sits at a different offset in every engine, so it is
   replaced with one that lines up with the text. */
.orient > summary::-webkit-details-marker,
.sources > summary::-webkit-details-marker { display: none; }
.orient > summary::before, .sources > summary::before {
  content: "▸ ";
  color: var(--line);
  display: inline-block;
  transition: transform .15s;
}
.orient[open] > summary::before, .sources[open] > summary::before { content: "▾ "; }

.orient > p, .sources > p {
  margin: 0 0 10px;
  padding-left: 11px;
  font-size: 12px; line-height: 1.8; color: var(--ink-dim);
  max-width: 80ch;
}
.sources > p { padding-left: 0; font-size: 10.5px; line-height: 1.75; }
.orient > p b { color: var(--ink); }

/* --- The game-over interjection --------------------------------------------
 *
 * One panel for every game. The roundabout already ended a run with a deadpan
 * line and it was the best moment on the site; nowhere else did it, and the
 * avatar had nothing to do with it. See assets/js/core/interject.js.
 *
 * Built by JS and appended to <body>, so it inherits nothing from the page it
 * lands on — which matters because it lands on ten games with their own CSS.
 * Everything here is namespaced .rl-inter / .ri-* for the same reason.
 * ------------------------------------------------------------------------- */
.rl-inter {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(6, 16, 28, .82);
  animation: ri-fade .18s ease both;
}
@keyframes ri-fade { from { opacity: 0; } to { opacity: 1; } }

.ri-card {
  width: 100%; max-width: 430px;
  background: var(--panel);
  border: 1px solid var(--line-dim); border-radius: 10px;
  padding: 20px;
  animation: ri-rise .26s cubic-bezier(.2, 1.2, .4, 1) both;
}
@keyframes ri-rise {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .rl-inter, .ri-card { animation: none; }
}

.ri-top { display: flex; gap: 15px; align-items: flex-start; }

.ri-face {
  flex: 0 0 auto; width: 76px; height: 76px;
  border-radius: 8px; overflow: hidden;
  background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line-dim);
}
.ri-face svg { display: block; width: 100%; height: 100%; }

.ri-said { min-width: 0; }
.ri-kicker {
  display: block;
  font-size: 9px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-dim);
}
.ri-line {
  margin: 5px 0 0;
  font-family: var(--disp); font-size: 15.5px; line-height: 1.5;
  color: var(--ink);
}
.ri-stat {
  display: block; margin-top: 7px;
  font-size: 11px; color: var(--line); font-variant-numeric: tabular-nums;
}

/* --- the accessory, offered rather than granted --------------------------- */
.ri-badge {
  display: flex; gap: 13px; align-items: center;
  margin-top: 16px; padding: 12px 13px;
  border: 1px solid var(--ok); border-radius: 8px;
  background: rgba(111, 231, 179, .07);
  animation: ri-pop .34s cubic-bezier(.2, 1.5, .4, 1) both;
}
@keyframes ri-pop {
  from { opacity: 0; transform: scale(.9); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .ri-badge { animation: none; } }

.ri-bart { flex: 0 0 auto; background: var(--panel-2); border-radius: 5px; padding: 3px; }
.ri-bart svg { display: block; }
.ri-btxt { min-width: 0; font-size: 10.5px; color: var(--ink-dim); line-height: 1.6; }
.ri-blab {
  display: block; font-size: 8.5px; letter-spacing: .15em;
  text-transform: uppercase; color: var(--ok);
}
.ri-btxt b { display: block; font-family: var(--disp); font-size: 14px; color: var(--ink); }

.ri-row { display: flex; gap: 8px; margin-top: 18px; }
.ri-btn {
  flex: 1;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .04em;
  text-align: center; text-decoration: none;
  padding: 10px 12px; border-radius: 6px; cursor: pointer;
  background: transparent; border: 1px solid var(--line-dim); color: var(--line);
  transition: border-color .15s, background .15s;
}
.ri-btn:hover { border-color: var(--line); background: rgba(94, 200, 216, .12); }
.ri-btn.primary { border-color: var(--ok); color: var(--ok); }
.ri-btn.primary:hover { background: rgba(111, 231, 179, .12); }
.ri-btn:disabled { opacity: .5; cursor: default; }

/* --- The pinned bottom bar --------------------------------------------------
 *
 * The follow links, the small print and the storage tag, on screen on every
 * page. See page_bar() in rl-lib/layout.php for why they are pinned rather
 * than in a footer.
 *
 * Every page reserves space for it via the body padding below, so it never
 * covers content. That reservation is the whole reason a fixed bar is
 * acceptable here — a floating strip over a centred game canvas would be worse
 * than no strip at all.
 * ------------------------------------------------------------------------- */
.rl-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 35;
  background: rgba(9, 24, 41, .94);
  backdrop-filter: blur(6px);
  border-top: 1px solid var(--line-dim);
}
.rl-bar-in {
  max-width: var(--wrap-max);
  margin: 0 auto;
  padding: 7px 16px;
  display: flex; align-items: center; gap: 8px 14px;
  flex-wrap: wrap;
  font-size: 10.5px;
}

.rl-bar-lk {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--line-dim); border-radius: 999px;
  color: var(--ink-dim); text-decoration: none;
  letter-spacing: .03em;
  transition: border-color .15s, color .15s, background .15s;
}
.rl-bar-lk:hover { border-color: var(--line); color: var(--ink); background: rgba(94, 200, 216, .1); }
.rl-bar-lk .rl-bar-ic { font-size: 9px; opacity: .85; }

/* The two real routes to a person, coloured so they read as the loudest thing
   in a row of small print. */
.rl-bar-lk.li { border-color: rgba(94, 200, 216, .55); color: var(--line); }
.rl-bar-lk.ig { border-color: rgba(201, 111, 168, .6); color: #C96FA8; }
.rl-bar-lk.ig:hover { border-color: #C96FA8; background: rgba(201, 111, 168, .1); }

/* Pushes the small print to the far end on a wide screen and collapses to
   nothing when the row wraps. */
.rl-bar-sp { flex: 1 1 0; min-width: 0; }

/* --- the small print, folded ------------------------------------------------
 * The affiliation notice has to be on every page, and it is four lines nobody
 * needs twice. Collapsed it costs one word; on hover or keyboard focus it says
 * the whole thing. Same mechanism as the section folds on the hub: max-height
 * rather than display:none, so the link inside stays reachable by tab.
 * ------------------------------------------------------------------------- */
.rl-bar-more {
  background: none; border: 0; cursor: help;
  font-family: var(--mono); font-size: 10px; letter-spacing: .04em;
  color: var(--ink-dim); opacity: .75;
  padding: 4px 2px; text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.rl-bar-more:hover, .rl-bar-more:focus-visible { color: var(--line); opacity: 1; }

.rl-bar-fine {
  max-height: 0;
  overflow: hidden;
  transition: max-height .25s ease;
}
.rl-bar:hover .rl-bar-fine,
.rl-bar:focus-within .rl-bar-fine { max-height: 140px; }

@media (prefers-reduced-motion: reduce) { .rl-bar-fine { transition: none; } }

.rl-bar-fine-in {
  max-width: var(--wrap-max);
  margin: 0 auto;
  padding: 2px 16px 10px;
  font-size: 10px; line-height: 1.75; color: var(--ink-dim);
}
.rl-bar-fine-in b { color: var(--ink); font-weight: 400; }
.rl-bar-fine-in a { color: var(--line); }
.rl-bar-tiny { color: var(--ink-dim); text-decoration: none; white-space: nowrap; }
.rl-bar-tiny:hover { color: var(--line); text-decoration: underline; }

.rl-bar .storagetag, .rl-bar .synctag { font-size: 10px; }

/* The reservation for the bar lives in bare.css and base.css, NOT here.

   It cannot be a plain `body` rule in this file: twenty-six page stylesheets
   set their own body padding as a Pass-A leftover, and every one of them loads
   AFTER components.css. A reservation here would be silently overridden on
   over half the site and the bar would sit on top of the content.

   bare.css is the file that already exists to win that argument -- it is loaded
   after the page stylesheet on purpose -- so the bare pages are reserved there.
   Full pages have no page stylesheet that touches body, so base.css does it. */

@media (max-width: 760px) {
  /* The notice used to be hidden here, because inline it took three lines
     away from the links people press. Folded, it costs one word, so it can
     stay on a phone too. */
  .rl-bar-in { padding: 6px 12px; gap: 6px 10px; }
  .rl-bar-lk { padding: 5px 9px; }
}

@media (max-width: 420px) {
  /* Icons only. The three destinations are recognisable without their names
     and the row has to fit on one line. */
  .rl-bar-lk { gap: 0; }
  .rl-bar-lk.li, .rl-bar-lk.ig, .rl-bar-lk.mb { font-size: 0; }
  .rl-bar-lk .rl-bar-ic { font-size: 12px; }
}

@media print { .rl-bar { display: none; } body { padding-bottom: 0; } }

/* --- Explainer tabs, as a segmented control --------------------------------
 *
 * Six of the eight explainers have three views behind three buttons. The
 * buttons were three separate outlined boxes with the active one tinted, which
 * reads as three options of which one has been noticed — not as "there are
 * three views here and you are on the first of them".
 *
 * A single enclosing track fixes that with no change to any page's markup or
 * JavaScript: the .tabs container and the .navbtn.on class are already there
 * on all six. That is the whole reason this is worth doing in one file rather
 * than redesigning six pages — the affordance was the problem, not the layout.
 *
 * Loaded from components.css, which the page stylesheets override, so each of
 * them is given the specificity to win: .tabs .navbtn beats a bare .navbtn.
 * ------------------------------------------------------------------------- */
.tabs {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--line-dim);
  border-radius: 6px;
  background: var(--panel);
  flex-wrap: wrap;
}

.tabs .navbtn {
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--ink-dim);
  padding: 7px 13px;
  letter-spacing: .06em;
  transition: background .15s, color .15s;
}
.tabs .navbtn:hover { background: rgba(94, 200, 216, .1); color: var(--ink); }

/* The active view, filled rather than outlined — so which one you are looking
   at is the strongest thing in the control instead of one of three equals. */
.tabs .navbtn.on {
  background: var(--drill);
  color: #10202f;
  font-weight: 600;
  border-color: transparent;
}
.tabs .navbtn.on:hover { background: var(--drill); color: #10202f; }
.tabs .navbtn:focus-visible { outline: 2px solid var(--line); outline-offset: 1px; }

/* --- The avatar inside a game's own game-over card -------------------------
 *
 * Inline mode. The modal styles above still exist for pages with no card of
 * their own; these are for the roundabout and the ten drills, whose overlay is
 * already full-screen. See assets/js/core/interject.js.
 * ------------------------------------------------------------------------- */
.go-avatar {
  margin: 0 0 16px;
  padding-bottom: 14px;
  border-bottom: 1px dashed var(--line-dim);
  text-align: left;
}
.go-avatar .ri-top { display: flex; gap: 14px; align-items: flex-start; }
.go-avatar .ri-badge { margin-top: 14px; }

/* Two ways out, in a row. The overlay covers the whole viewport including the
   back-link, so a single restart button was a trap. */
.go-row {
  display: flex; gap: 8px; justify-content: center;
  flex-wrap: wrap; margin-top: 4px;
}
/* display:inline-block explicitly. Both game stylesheets declare `.btn`
   with `display:none` -- the class doubles as a hidden "next" button that the
   engine reveals -- which is why the original restart button carried an inline
   style attribute. Without this the two new exits were in the DOM, had text,
   and occupied nothing. */
.go-row .btn { display: inline-block; }

.go-row .btn.ghost {
  background: transparent;
  border-color: var(--line-dim);
  color: var(--ink-dim);
}
.go-row .btn.ghost:hover { border-color: var(--line); color: var(--line); }

/* The Wear button, inside the badge row rather than in the button row: it acts
   on the accessory beside it, and a button two inches away from the thing it
   applies to is a button people do not connect to it. */
.ri-wear {
  margin-left: auto;
  flex: 0 0 auto;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .04em;
  padding: 7px 12px; border-radius: 5px; cursor: pointer;
  background: rgba(111, 231, 179, .14);
  border: 1px solid var(--ok); color: var(--ok);
  transition: background .15s;
}
.ri-wear:hover:not(:disabled) { background: rgba(111, 231, 179, .26); }
.ri-wear:disabled { cursor: default; }
.ri-wear.done { background: transparent; opacity: .7; }

/* The corner dismiss on the modal. Three complaints about not being able to
   leave the first version, and the answer to that is not a better-labelled
   button — it is the ✕ everybody already looks for. */
.ri-card { position: relative; }
.ri-x {
  position: absolute; top: 8px; right: 9px;
  background: none; border: 0; cursor: pointer;
  color: var(--ink-dim); font-size: 13px; line-height: 1;
  padding: 6px 8px; border-radius: 4px;
}
.ri-x:hover { color: var(--ink); background: rgba(94, 200, 216, .12); }

/* Tapped open on touch, where there is no hover to open it with. */
.rl-bar.fine-open .rl-bar-fine { max-height: 160px; }

/* --- Step pips, for the explainers ----------------------------------------
 *
 * A diagram with ten boxes shows the shape of a process. It does not show
 * where you are in it, and "Step 4 of 10" in a heading is a fact you have to
 * read rather than see. The pips are the position; the gates are marked,
 * because on several of these pages the count of veto points IS the lesson.
 *
 * Clickable, because a row of dots that is not clickable is a tease.
 * ------------------------------------------------------------------------- */
.pips { display: flex; gap: 5px; align-items: center; flex-wrap: wrap; }

.pips .pip {
  width: 9px; height: 9px; padding: 0;
  border: 1px solid var(--line-dim); border-radius: 50%;
  background: transparent; cursor: pointer;
  transition: background .15s, border-color .15s, transform .12s;
}
.pips .pip:hover { border-color: var(--line); transform: scale(1.3); }
.pips .pip.done { background: var(--line-dim); }
.pips .pip.on {
  background: var(--drill); border-color: var(--drill);
  transform: scale(1.35);
}
/* A veto point. Square rather than round, so the count is readable at a glance
   without reading a legend. */
.pips .pip.gate { border-radius: 2px; border-color: var(--no); }
.pips .pip.gate.done { background: rgba(232, 84, 74, .35); }
.pips .pip.gate.on { background: var(--no); border-color: var(--no); }

.pips .pip:focus-visible { outline: 2px solid var(--line); outline-offset: 2px; }

/* Screen-reader label inside a pip. */
.pips .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* An aside frame: the same panel as the detail, one step quieter, so it reads
   as supporting rather than as a second equal claim on your attention. */
.frame.aside { background: rgba(15, 39, 64, .55); }
.frame.aside .sub {
  font-family: var(--disp); font-size: 15px; margin: 2px 0 12px; font-weight: 700;
}

/* --- the shelf count in the corner -----------------------------------------
 *
 * On every page, beside the name. "Special earned badges need to be visible;
 * you need to feel proud of them" -- and the hub's shelf shows only NEW ones
 * and hides itself once they stop being new, so the moment a badge stopped
 * being news it stopped being visible anywhere you pass daily.
 *
 * Small on purpose: it is a reminder, not a scoreboard, and it shares a badge
 * that also has to fit on a phone. Tabular figures so it does not shift width
 * as the count climbs past 9.
 * ------------------------------------------------------------------------- */
.rl-badge-n {
  font-family: var(--mono); font-size: 9.5px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
  color: var(--ok);
  padding: 1px 5px;
  border: 1px solid rgba(111, 231, 179, .35);
  border-radius: 999px;
  white-space: nowrap;
}

/* ===========================================================================
 * THE LEAD-IN — the question a narrated explainer opens on
 * ---------------------------------------------------------------------------
 * These pages used to open on the apparatus: a ten-box process diagram, a
 * grid of twenty-seven member states, four voting methods. The subject came
 * afterwards, which reads as "here is a procedure, and by the way it happens
 * to somebody".
 *
 * The lead-in reverses that. It names how many real cases there are, asks you
 * to pick one, and puts the picker directly underneath — so the first thing on
 * the page is a choice and the apparatus below it is about your choice.
 *
 * Shared rather than per-page because accession, comitology and Parliament's
 * voting methods all do the same thing, and three copies of a component is how
 * three components slowly become different.
 * ========================================================================= */
.lead { margin: 2px 0 13px; }
.lead-q {
  font-family: var(--disp); font-weight: 600;
  font-size: 14px; line-height: 1.6;
  margin: 0 0 11px; max-width: 74ch; color: var(--ink-dim);
}
.lead-q b { color: var(--drill); font-weight: 700; }

/* The apparatus, once it is downstream of the choice, needs a caption saying
   what it is now showing — otherwise a diagram that used to be the headline
   turns up mid-page with no introduction. */
.lead-n {
  font-size: 10.5px; line-height: 1.65; color: var(--ink-dim);
  margin: 0 0 8px; max-width: 76ch;
}
.lead-n b { color: var(--ink); }

/* ===========================================================================
 * COMMIT, VERDICT, RECORD — the last two beats of a narrated explainer
 * ---------------------------------------------------------------------------
 * Brief, choose, COMMIT, your outcome, then what actually happened. The order
 * is the narrative and the CSS follows it: the record is visually the last
 * thing and set apart, because it is the only part that is not yours.
 *
 * Lived in page/comitology.css until the Article 294 walk became the second
 * page to need it. Promoted rather than copied — two record panels that drift
 * apart is the thing CSS Pass C exists to prevent.
 * ========================================================================= */
/* Closing the vote. A committee decision is a moment, and reading the answer
   while still moving the pieces is not the same experience as committing. */
.submit {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  border-top: 1px dashed var(--line-dim); padding-top: 11px; margin-top: 13px;
}
.sub-b {
  font-family: var(--mono); font-size: 12px; padding: 8px 16px;
  border: 1px solid var(--drill); border-radius: 2px;
  background: rgba(255, 159, 90, .1); color: var(--drill); cursor: pointer;
  white-space: nowrap;
}
.sub-b:hover { background: rgba(255, 159, 90, .2); }
.sub-b:focus-visible { outline: 1px solid var(--drill); outline-offset: 2px; }
.sub-n { font-size: 10.5px; color: var(--ink-dim); }

/* The verdict is empty until the vote is closed, so it must not reserve space
   or the page jumps as you work. */
.verdict:empty { display: none; }

/* The Article 5(4)(a) twist: the rule that blocks a plant-health file in the
   first room and lets it through in the second. */
.v-bar {
  display: block; margin-top: 9px; padding: 9px 11px;
  border-left: 2px solid var(--no);
  background: rgba(232, 115, 127, .07);
  font-size: 11.5px; line-height: 1.7;
}
.v-bar b { color: var(--no); }
.v-bar i { color: var(--ink); font-style: normal; }

.v-sting {
  display: block; margin-top: 9px;
  font-size: 11.5px; line-height: 1.7; color: var(--ink-dim);
}
.v-sting b { color: var(--ink); }

/* And the record. Set apart, and the only block on the page that is not
   about what you did. */
.real:empty { display: none; }
.real-in {
  margin-top: 12px; padding: 14px 16px;
  border: 1px dashed var(--line);
  border-radius: 3px;
  background: var(--panel);
}
.real-lab {
  display: block;
  font-size: 9px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--line); margin-bottom: 8px;
}
.real-h {
  font-family: var(--disp); font-weight: 700; font-size: 16px;
  line-height: 1.35; margin: 0 0 9px;
}
.real-b { font-size: 12px; line-height: 1.8; margin: 0 0 10px; max-width: 78ch; }
.real-b b { color: var(--ink); }
.real-b i { color: var(--line); font-style: normal; }
.real-s {
  font-size: 12px; line-height: 1.7; margin: 0 0 12px;
  padding-left: 11px; border-left: 2px solid var(--drill);
  color: var(--ink); max-width: 74ch;
}

/* ===========================================================================
 * STEPS — one thing on screen, the rest a single line each
 * ---------------------------------------------------------------------------
 * The explainers stopped being dense in words and stayed dense in THINGS: one
 * measured tab carried forty-three separate bordered or filled boxes, in six
 * background colours and eight border treatments, all visible at once. Nothing
 * told you where to start, because everything was emphasised equally.
 *
 * Two rules here, and they are the whole design:
 *
 *   ONE OBJECT PER STEP. The open step is the only thing with a border and a
 *   fill. Closed steps are a line of text. The rail is a line of text. So the
 *   page has exactly one visual object at any moment, and it is the thing you
 *   are supposed to be looking at.
 *
 *   THE MODEL KEEPS ITS EDGES, NOTHING ELSE GETS ANY. Inside an open step, the
 *   thing you operate — a vote grid, a map, a set of bars — may draw itself.
 *   Prose around it does not get a box, a tint or a left rule. That is what
 *   produced "many small highlights" in the first place.
 * ========================================================================= */
.stp-set { margin: 2px 0 18px; }

/* The rail. Deliberately not tabs: no fill, no border, no pill. It is a line
   of numbers that tells you how far along you are and nothing else. */
.stp-rail {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px;
  list-style: none; margin: 0 0 16px; padding: 0 0 12px;
  border-bottom: 1px solid var(--line-dim);
}
.stp-pip {
  display: flex; align-items: baseline; gap: 7px;
  font-size: 11px; color: var(--ink-dim);
}
.stp-pip b {
  display: grid; place-items: center;
  width: 17px; height: 17px; border-radius: 999px;
  border: 1px solid var(--line-dim);
  font-family: var(--mono); font-size: 9.5px; font-weight: 400;
  color: var(--ink-dim);
}
.stp-pip.done b { border-color: var(--ok); color: var(--ok); }
.stp-pip.on b   { border-color: var(--drill); background: var(--drill); color: var(--dark); font-weight: 700; }
.stp-pip.on span { color: var(--ink); }
.stp-pip.locked { opacity: .4; }

.stp-list { display: grid; gap: 1px; }

/* A step. Closed: a line. Open: the one object on the page. */
/* min-width:0 is the load-bearing half of this rule.

   .stp-list is a grid, so every .stp is a grid item, and a grid item
   defaults to min-width:auto -- meaning it refuses to be narrower than its
   own min-content width. Put anything wide inside a step (a diagram with a
   min-width, a wide table) and the STEP stretches to fit it, dragging the
   step body with it, and any overflow:auto scroll container inside is then
   already as wide as its content and never scrolls.

   Found on the enforcement funnel: a 760px diagram inside a 375px phone
   viewport expanded the step to 766px and the layout viewport to 781px, so
   the media query that was supposed to make it scroll stopped matching and
   switched itself off. */
.stp { border-top: 1px solid var(--line-dim); min-width: 0; }
.stp:first-child { border-top: 0; }

.stp-h {
  display: flex; align-items: baseline; gap: 11px; width: 100%;
  padding: 11px 2px; text-align: left;
  background: none; border: 0; color: inherit;
  font-family: var(--mono); font-size: 12px; cursor: pointer;
}
/* Through the state class, like .is-open and .is-done below, rather than
   through the button's disabled attribute. Same result; the difference is
   that `is-locked` was previously set by core/steps.js on every explainer
   and matched by no rule in any stylesheet. */
.stp.is-locked .stp-h { cursor: default; opacity: .38; }
.stp-h:not(:disabled):hover .stp-l { color: var(--line); }
.stp-h:focus-visible { outline: 1px solid var(--drill); outline-offset: -1px; }

.stp-n {
  flex: none; width: 17px; height: 17px; border-radius: 999px;
  display: grid; place-items: center;
  border: 1px solid var(--line-dim); font-size: 9.5px; color: var(--ink-dim);
}
.stp-l { font-family: var(--disp); font-weight: 600; font-size: 14px; color: var(--ink-dim); }
/* The collapsed step's answer. This is why a shut step is still worth having
   on screen: it is the record of what you decided. */
.stp-sum {
  margin-left: auto; text-align: right; font-size: 11px; color: var(--drill);
  max-width: 52ch; line-height: 1.5;
}

.stp.is-done .stp-n { border-color: var(--ok); color: var(--ok); }
.stp.is-done .stp-l { color: var(--ink); }

.stp.is-open { border-top-color: var(--drill); }
.stp.is-open .stp-h { padding-bottom: 4px; }
.stp.is-open .stp-n { border-color: var(--drill); background: var(--drill); color: var(--dark); font-weight: 700; }
.stp.is-open .stp-l { color: var(--ink); font-size: 17px; }

.stp-body { padding: 4px 2px 22px; }
/* The question the step asks. One per step, and the only display-face line in
   the body, so it is unambiguously where reading starts. */
.stp-ask {
  font-family: var(--disp); font-weight: 600; font-size: 14.5px; line-height: 1.6;
  color: var(--ink-dim); margin: 0 0 14px; max-width: 72ch;
}
.stp-ask b { color: var(--drill); font-weight: 700; }
/* Plain prose inside a step. No box, no tint, no rule — deliberately. */
.stp-body .stp-p { font-size: 12.5px; line-height: 1.8; margin: 0 0 11px; max-width: 76ch; }
.stp-body .stp-p b { color: var(--ink); }
.stp-body .stp-p:last-child { margin-bottom: 0; }

/* The one action that moves you on. There is never more than one. */
.stp-go {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 16px;
}
.stp-go .sub-b { margin: 0; }
.stp-note { font-size: 10.5px; color: var(--ink-dim); }

/* Inside a step, prose loses its box.
 *
 * The rule at the top of this block says the open step is the one object on
 * the page and only the thing you OPERATE draws itself. A brief in a bordered,
 * tinted panel sitting above a vote grid breaks that: two objects, competing,
 * and the reader has to decide which is the point. The brief keeps a left rule
 * — it is quoted material, and that is what a left rule means everywhere else
 * on the site — and gives up the border and the fill. */
.stp-body .brief {
  border: 0; border-left: 2px solid var(--line); border-radius: 0;
  background: none; padding: 2px 0 2px 14px; margin-bottom: 16px;
}

/* ===========================================================================
 * A DISCLOSURE ANIMATION I TRIED AND REVERTED
 * ---------------------------------------------------------------------------
 * "The page jumps if a menu unfolds" is true, and a <details> cannot animate
 * open on its own because height is not interpolable to `auto`.
 * `interpolate-size: allow-keywords` plus a transition on ::details-content is
 * the modern answer, and I shipped it.
 *
 * It broke every disclosure on the site. The CLOSED rule applied — panels
 * collapsed correctly — and the `[open]` rule did not, so ::details-content
 * stayed at height 0 with content-visibility:hidden in both states. Seventy-odd
 * panels of reference material became unreachable.
 *
 * Two things worth keeping from that:
 *
 * CSS.supports('selector(::details-content)') returned TRUE, and the base rule
 * visibly worked. That is exactly the shape of evidence that makes you stop
 * looking. What found it was reading getComputedStyle(el, '::details-content')
 * in both states, which is the only check that could have.
 *
 * And the trade was bad in principle. A panel that snaps open is an
 * annoyance; a panel that does not open is a broken page. Do not re-attempt
 * this without measuring the open state on the actual target browser.
 *
 * The jump fix that DOES work is core/swap.js, applied where content is
 * swapped by script rather than by the browser's own disclosure machinery.
 * ========================================================================= */
