/* ============================================================================
   Imposter Online v2 — page styles.
   Every color lives in a design token so the page has exactly two complete
   schemes (ledger §4c decision, 2026-08-17):
     Scheme A (default, no attribute): the classic Imposter dark look —
       matches apps/imposter/style.css palette. Default for EVERYONE.
     Scheme B (html[data-scheme="gof"]): the Game On Family brand —
       whitespace, greens, gold, per docs/design-guidelines.md.
   The toggle is in the header; choice persists per device.
   Mobile-first; single column, max 560px.
   ========================================================================== */

:root {
  /* Scheme A — Imposter dark (matches the live game) */
  --bg: #0f172a;
  --bg-glow: #1f2937;
  --panel: rgba(17, 24, 39, 0.85);
  --card: #0b1222;
  --card-raised: #111a2e;
  --text: #e5e7eb;
  --muted: #94a3b8;
  --line: rgba(255, 255, 255, 0.08);
  --accent: #22c55e;
  --accent-ink: #052e16;
  --accent-soft: rgba(34, 197, 94, 0.14);
  --gold: #ffb920;
  --danger: #ef4444;
  --danger-soft: rgba(239, 68, 68, 0.15);
  --btn: #1f2937;
  --btn-text: #ffffff;
  --input-bg: #0b1222;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
  --overlay: rgba(3, 7, 18, 0.72);
  --heading-font: "League Spartan", sans-serif;
  --body-font: "Arimo", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

html[data-scheme="gof"] {
  /* Scheme B — Game On Family brand */
  --bg: #f4f7fa;
  --bg-glow: #dde5ed;
  --panel: #ffffff;
  --card: #ffffff;
  --card-raised: #f2f6f9;
  --text: #2f2c28;
  --muted: #5e5c5e;
  --line: rgba(47, 44, 40, 0.14);
  --accent: #157623;
  --accent-ink: #ffffff;
  --accent-soft: rgba(155, 202, 62, 0.22);
  --gold: #ffb920;
  --danger: #de6739;
  --danger-soft: rgba(222, 103, 57, 0.15);
  --btn: #157623;
  --btn-text: #ffffff;
  --input-bg: #ffffff;
  --shadow: 0 8px 24px rgba(47, 44, 40, 0.12);
  --overlay: rgba(47, 44, 40, 0.45);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--body-font);
  font-size: 16px;
  background: radial-gradient(1200px 800px at 50% -100px, var(--bg-glow), var(--bg));
  color: var(--text);
}

.wrap {
  max-width: 560px;
  margin: 0 auto;
  padding: 10px clamp(10px, 3vw, 20px) 40px;
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

/* --- header (game title appears here ONCE — shell rule) -------------------
   Structure per apps/shared/HEADER_SPECS.md: game name with an other-games
   dropdown on the left, mode row under it, one login icon on the right. */
.top {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 2px;
}
.header-left { flex: 1; min-width: 0; }
.header-right { flex: none; }
.game-title-wrap { position: relative; }
.game-title-dropdown-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  border-radius: 10px;
  padding: 2px 6px 2px 2px;
}
.game-title-dropdown-trigger:hover { background: var(--card-raised); }
.game-title-chevron { color: var(--muted); font-size: 13px; }
.game-title-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 50;
  min-width: 200px;
  margin-top: 4px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 6px;
}
.game-title-dropdown[aria-hidden="true"] { display: none; }
.game-nav-link {
  display: block;
  padding: 10px 12px;
  border-radius: 8px;
  color: var(--text);
  text-decoration: none;
  font-size: 15px;
}
.game-nav-link:hover { background: var(--card-raised); }
.mode-row { display: flex; gap: 6px; margin-top: 6px; }
.mode-btn {
  font-family: var(--body-font);
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 12px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
}
.mode-btn[aria-pressed="true"] { background: var(--accent-soft); color: var(--text); }
.top h1 {
  font-family: var(--heading-font);
  font-size: clamp(20px, 5vw, 26px);
  font-weight: 800;
  margin: 0;
  letter-spacing: 0.2px;
}
.top h1 .tag {
  color: var(--gold);
  font-size: 0.62em;
  vertical-align: 0.22em;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.iconbtn {
  background: var(--btn);
  color: var(--btn-text);
  border: 1px solid var(--line);
  border-radius: 10px;
  min-width: 40px;
  height: 40px;
  font-size: 17px;
  cursor: pointer;
  padding: 0 10px;
}
.dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--muted);
  flex: none;
}
.dot.ok { background: var(--accent); }
.dot.bad { background: var(--danger); }

/* --- cards / buttons ------------------------------------------------------ */
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 16px;
  margin-top: 12px;
  box-shadow: var(--shadow);
}
.card h2 {
  font-family: var(--heading-font);
  font-size: 18px;
  margin: 0 0 8px;
}
.sub { color: var(--muted); font-size: 14px; margin: 4px 0 10px; }
.btn {
  font-family: var(--body-font);
  background: var(--btn);
  color: var(--btn-text);
  border: 1px solid var(--line);
  padding: 13px 16px;
  border-radius: 12px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  width: 100%;
}
.btn.primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.btn.danger { background: var(--danger); color: #fff; border-color: transparent; }
.btn.ghost { background: transparent; color: var(--text); }
.btn.slim { width: auto; padding: 9px 14px; font-size: 14px; }
.btn:disabled { opacity: 0.45; cursor: default; }
.rowflex { display: flex; gap: 8px; align-items: center; }
.rowflex > .grow { flex: 1; }

input[type="text"], select {
  width: 100%;
  font-family: var(--body-font);
  font-size: 16px;
  color: var(--text);
  background: var(--input-bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 13px 12px;
}
input.code { text-transform: uppercase; letter-spacing: 6px; font-weight: 800; text-align: center; }
input.attention { border-color: var(--gold); box-shadow: 0 0 0 2px var(--accent-soft); }
.sub.warn { color: var(--gold); font-weight: 700; }
.players li.merow { cursor: pointer; }
.players .pencil { color: var(--muted); font-size: 13px; }
label.check { display: flex; gap: 10px; align-items: center; padding: 8px 2px; font-size: 15px; cursor: pointer; }
label.check input { width: 18px; height: 18px; accent-color: var(--accent); }

/* --- room bar ------------------------------------------------------------- */
.roombar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 10px 12px;
}
.roombar .code {
  font-family: var(--heading-font);
  font-weight: 800;
  font-size: 22px;
  letter-spacing: 4px;
}
/* the code is itself a one-tap "copy the code" button */
.codebtn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: none;
  padding: 2px 4px;
  border-radius: 8px;
  color: var(--text);
  cursor: pointer;
}
.codebtn:active { background: var(--accent-soft); }
.codebtn .copyhint { color: var(--muted); font-size: 15px; }
.roombar .lockicon { color: var(--gold); }
.pill {
  display: inline-block;
  background: var(--card-raised);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12.5px;
  color: var(--muted);
  margin: 2px 4px 2px 0;
}
/* They looked like controls and were not. Now they are: any pill opens settings. */
.pill-btn { font-family: var(--body-font); cursor: pointer; }
.pill-btn:hover { border-color: var(--muted); color: var(--text); }
.pill-change { color: var(--text); }

/* --- players -------------------------------------------------------------- */
.players { list-style: none; padding: 0; margin: 8px 0 0; }
.players li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--line);
  font-size: 15.5px;
}
.players li:last-child { border-bottom: none; }
.players .who { flex: 1; display: flex; align-items: center; gap: 6px; min-width: 0; }
.players .who span.name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.players .away { color: var(--muted); font-size: 12.5px; }
.players .score { font-weight: 800; font-variant-numeric: tabular-nums; }
/* Host's remove control. Quiet until wanted: it sits on every other player's
   row all game long, and a row of red X's would read as an accusation rather
   than a tool. Turns red on hover/focus, and the confirm dialog is unchanged,
   so a mis-tap costs one tap to cancel. 34px square clears the 32px minimum
   touch target on a phone, where there is no hover to reveal anything. */
.players .kickx {
  flex: none;
  width: 34px;
  height: 34px;
  padding: 0;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: 9px;
  background: transparent;
  color: var(--muted);
  opacity: 0.65;
}
.players .kickx:hover,
.players .kickx:focus-visible {
  opacity: 1;
  color: var(--danger);
  border-color: var(--danger);
  background: var(--card-raised);
}
.badge { font-size: 11px; border-radius: 6px; padding: 2px 6px; background: var(--accent-soft); color: var(--text); }

/* --- phase bar / countdown ------------------------------------------------ */
.phasebar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  font-size: 14px;
  color: var(--muted);
}
.phasebar .phase { font-weight: 700; color: var(--text); }
.countdown {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  font-size: 18px;
  color: var(--text);
}
.countdown.hot { color: var(--danger); }
/* countdown repeated next to the action (clue box, discuss, vote) so the
   pressure is visible where the thumbs are, not just at the top */
.minitimer {
  float: right;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}
.minitimer.hot { color: var(--danger); }

/* --- in-room stacking order -----------------------------------------------
   Flex ordering rather than moving nodes, so nothing is destroyed and rebuilt
   as phases change. Two rules earn their keep:
     - the reveal outranks the action panel, because right after a round the
       room wants to know who it was, not what happens next
     - during the discussion the chat rises to sit under the panel, since the
       conversation is the activity rather than reference material */
#room { display: flex; flex-direction: column; }
#room > .roombar      { order: 1; }
/* A person waiting at the door outranks even the reveal: they are waiting on
   THIS host, and every other card can wait a few seconds. */
#room > #doorCard     { order: 1; }
#room > #resultsCard  { order: 2; }
#room > #actionPanel  { order: 3; }
#room > #lobbyView    { order: 4; }
#room > #roundView    { order: 5; }
#room > #chatCard     { order: 6; }
#room.discussing > #chatCard { order: 4; }

/* Inside a round, your own card leads while you are still being dealt in. Once
   the clues are on the board they become the evidence, and the card telling you
   a word you already know drops to last. Applies to discussion and voting. */
#roundView { display: flex; flex-direction: column; }
#roundView > #roleCard { order: 1; }
#roundView > #clueCard { order: 2; }
#room.discussing > #roundView > #roleCard,
#room.voting > #roundView > #roleCard { order: 2; }
#room.discussing > #roundView > #clueCard,
#room.voting > #roundView > #clueCard { order: 1; }

/* --- the action panel ------------------------------------------------------
   One fixed box directly under the room bar, present in every phase. It is the
   single place a player looks to answer "what now?", so its headline is the
   largest type on the screen. Two modes:
     passive  - you are waiting; quiet, no control
     .active  - it is on you; gold border, and the control sits inside the box
   Rebuilt from the 2026-08-23 family session, where the status line was the
   least noticeable element on the page and the control four cards below it. */
.actionpanel {
  margin-top: 12px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 14px;
}
.actionpanel.active {
  border: 2px solid var(--gold);
  background: var(--card-raised);
  padding: 13px; /* keep the box the same size as the 1px-border state */
}
.ap-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 700;
}
.ap-timer {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  font-weight: 800;
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
}
.ap-timer.hot { color: var(--danger); }
.ap-headline {
  font-family: var(--heading-font);
  font-size: clamp(19px, 4.8vw, 23px);
  font-weight: 800;
  line-height: 1.2;
  margin: 6px 0 0;
}
.ap-headline:empty { display: none; }
.ap-headline b { color: var(--gold); }
#apControl:not(:empty) { margin-top: 12px; }
/* Shown only when the connection is actually unhealthy. Replaces the permanent
   status dot, which nobody could interpret. */
.ap-trouble {
  margin-top: 8px;
  font-size: 14px;
  font-weight: 700;
  color: var(--gold);
}

/* --- role card (tap to reveal) -------------------------------------------- */
.rolecard {
  position: relative;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--card);
  margin-top: 12px;
  padding: 18px;
  min-height: 110px;
  text-align: center;
  cursor: pointer;
  user-select: none;
  overflow: hidden;
}
.rolecard .cover {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: repeating-linear-gradient(45deg, var(--card), var(--card) 12px, var(--card-raised) 12px, var(--card-raised) 24px);
  font-weight: 700;
  transition: opacity 0.15s;
}
.rolecard.revealed .cover { opacity: 0; pointer-events: none; }
.rolecard .word {
  font-family: var(--heading-font);
  font-size: 30px;
  font-weight: 800;
  margin: 6px 0;
}
.rolecard .word.imposter { color: var(--danger); }
.rolecard .hintline { color: var(--muted); font-size: 14.5px; }
.rolecard .peek { color: var(--muted); font-size: 12px; margin-top: 8px; }

/* --- clue board ----------------------------------------------------------- */
.clueboard { list-style: none; margin: 8px 0 0; padding: 0; counter-reset: clue; }
.clueboard li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 4px;
  border-bottom: 1px solid var(--line);
  font-size: 15.5px;
}
.clueboard li:last-child { border-bottom: none; }
.clueboard li::before {
  counter-increment: clue;
  content: counter(clue);
  color: var(--muted);
  font-size: 12px;
  min-width: 16px;
}
.clueboard .cname { color: var(--muted); min-width: 30%; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clueboard .ctext { font-weight: 700; }
.clueboard li.current { background: var(--accent-soft); border-radius: 8px; }
.clueboard li.pending .ctext { color: var(--muted); font-weight: 400; }
.clueboard .skipped { color: var(--muted); font-style: italic; font-weight: 400; }
.clueboard .thinking { color: var(--muted); font-weight: 400; }
/* Separator between a player's clues across passes. */
.clueboard .cluesep { color: var(--muted); margin: 0 6px; font-weight: 400; }
.clueboard .ctext { overflow-wrap: anywhere; }

/* Locked premium rows: still visible, still tappable, and they go somewhere. */
label.check.locked { cursor: pointer; opacity: 0.72; }
label.check.locked:hover { opacity: 1; }
label.check.locked .lockstar { color: var(--gold); margin-left: auto; }

.yourturn {
  border: 2px solid var(--gold);
  border-radius: 14px;
  padding: 12px;
  margin-top: 12px;
  background: var(--card);
}
.yourturn .lead { font-weight: 800; margin-bottom: 8px; }

/* --- vote ----------------------------------------------------------------- */
.votegrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.votegrid .btn { padding: 15px 8px; }
.votegrid .btn.picked { outline: 3px solid var(--gold); }

/* --- results -------------------------------------------------------------- */
.resultcard { text-align: center; }
/* WHO it was is the fact the room wants; the outcome phrase explains it below. */
.resultcard .headline {
  font-family: var(--heading-font);
  font-size: clamp(23px, 6.4vw, 30px);
  font-weight: 800;
  line-height: 1.15;
  margin: 2px 0 4px;
}
.resultcard .flavour { font-size: 16px; color: var(--muted); margin: 0 0 10px; }
.resultcard .wordreveal { font-size: 17px; margin: 6px 0; }
.resultcard .wordreveal b { color: var(--gold); }
.roundlabel {
  margin-top: 14px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  font-weight: 700;
  color: var(--muted);
  text-align: left;
}
.resulttable {
  width: 100%;
  border-collapse: collapse;
  margin-top: 12px;
  font-size: 14.5px;
  text-align: left;
}
.resulttable th {
  color: var(--muted);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  font-weight: 700;
  padding: 4px 8px;
  border-bottom: 1px solid var(--line);
}
.resulttable td {
  padding: 7px 8px;
  border-bottom: 1px solid var(--line);
}
.resulttable tr:last-child td { border-bottom: none; }
.resulttable tr.improw td { background: var(--danger-soft); }
.resulttable td.pts { font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.resulttable .tick { color: var(--accent); font-weight: 800; }
.resulttable .dimvote { color: var(--muted); font-style: italic; }
.legend { color: var(--muted); font-size: 12.5px; margin: 8px 0 0; text-align: left; }
.legend .tick { color: var(--accent); font-weight: 800; }

/* --- chat ----------------------------------------------------------------- */
#chatlog {
  height: 190px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  padding: 8px;
  font-size: 14.5px;
  margin-bottom: 8px;
}
#chatlog .sys { color: var(--muted); font-style: italic; }
#chatlog div { padding: 2px 0; overflow-wrap: anywhere; }

/* --- modals --------------------------------------------------------------- */
.overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 40;
  padding: 12px;
}
@media (min-width: 480px) { .overlay { align-items: center; } }
.modal {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow);
  width: 100%;
  max-width: 460px;
  max-height: 86vh;
  overflow-y: auto;
  padding: 16px;
}
.modal h2 { font-family: var(--heading-font); margin: 0 0 10px; font-size: 19px; }
.modal .section { border-top: 1px solid var(--line); margin-top: 12px; padding-top: 10px; }
.modal .section h3 { font-size: 14px; margin: 0 0 6px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; }
.catgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 8px; }
.catgrid label.check { padding: 5px 2px; font-size: 13.5px; }
.locknote { color: var(--muted); font-size: 12px; }
.kickrow { display: flex; align-items: center; gap: 8px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.kickrow:last-child { border-bottom: none; }
.kickrow .who { flex: 1; }

/* --- someone at the door (host only) -------------------------------------- */
/* Gold like the action panel, because it is the same kind of thing: something
   only this person can resolve, and the room is stopped on it. */
.doorcard { margin-top: 12px; border: 2px solid var(--gold); }
.doorhead {
  font-family: var(--heading-font);
  font-size: 17px;
  font-weight: 800;
  margin-bottom: 8px;
}
.doorrow { padding: 6px 0; border-bottom: 1px solid var(--line); }
.doorrow:last-child { border-bottom: none; }
.doorwho { font-size: 16px; }
.doorwho .sub { display: block; font-size: 13.5px; color: var(--muted); margin-top: 2px; }
.doorbtns { display: flex; gap: 8px; margin-top: 8px; }
.doorbtns .btn { flex: 1; }

/* --- toast / notice ------------------------------------------------------- */
#toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
  border-radius: 999px;
  padding: 10px 18px;
  box-shadow: var(--shadow);
  z-index: 60;
  max-width: 90vw;
  text-align: center;
  transition: opacity 0.25s;
}
#toast.hidden { opacity: 0; pointer-events: none; }
.notice { border-left: 4px solid var(--gold); }

/* --- the article, below the game -------------------------------------------
   Merged in from the separate page that used to sit at this URL. Deliberately
   built on the SAME design tokens as the game rather than carrying its own
   palette across, so it inherits both colour schemes for free and cannot drift
   from the game it sits under. Kept visually quieter than the game: someone who
   came here to play should not have their eye pulled into prose. */
.prose {
  margin-top: 34px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 16px;
  line-height: 1.65;
  color: var(--text);
}
.prose h2 {
  font-family: var(--heading-font);
  font-size: clamp(21px, 5vw, 25px);
  font-weight: 800;
  line-height: 1.2;
  margin: 0 0 6px;
}
.prose h3 {
  font-family: var(--heading-font);
  font-size: 19px;
  font-weight: 800;
  margin: 30px 0 6px;
}
.prose h4 { font-size: 16px; font-weight: 700; margin: 16px 0 2px; }
.prose p { margin: 0 0 12px; }
.prose a { color: var(--accent); }
html[data-scheme="gof"] .prose a { color: var(--accent); }
.prose .byline { font-size: 13px; color: var(--muted); line-height: 1.7; margin: 0 0 10px; }
.prose .byline .upd { opacity: 0.75; }
.prose .lede { font-size: 17.5px; margin: 12px 0 20px; }

.prose ol.steps { list-style: none; padding: 0; counter-reset: s; margin: 8px 0 14px; }
.prose ol.steps > li { counter-increment: s; position: relative; padding: 0 0 14px 42px; }
.prose ol.steps > li::before {
  content: counter(s);
  position: absolute;
  left: 0;
  top: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 800;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.prose ol.steps h4 { margin: 2px 0 3px; }

.prose ul.why { list-style: none; padding: 0; margin: 10px 0 14px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px 20px; }
.prose ul.why li { position: relative; padding-left: 22px; }
.prose ul.why li::before { content: ""; position: absolute; left: 2px; top: 9px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
@media (max-width: 520px) { .prose ul.why { grid-template-columns: 1fr; } }

.prose .callout {
  background: var(--card-raised);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px 16px;
  margin: 16px 0;
}
.prose .callout p:last-child { margin-bottom: 0; }

.prose .makers { display: grid; gap: 14px; margin-top: 10px; }
.prose .maker { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; }
.prose .maker h4 { margin: 0 0 2px; }
.prose .mcred { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.prose .maker p { font-size: 15px; margin: 0; }
.prose .proselinks { margin-top: 24px; font-size: 14.5px; color: var(--muted); }

/* --- footer (GoF branding lives here — shell rule) ------------------------ */
footer {
  margin-top: auto;
  padding-top: 26px;
  text-align: center;
  font-size: 13px;
  color: var(--muted);
}
footer a { color: var(--muted); }
.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 18px;
}
.footer-links a { text-decoration: none; }
.footer-links a:hover { color: var(--text); text-decoration: underline; }
.hidden { display: none !important; }
