/* Dark is the default theme. Light/dark is a simple toggle, remembered per browser (see app.js). */
:root {
  --bg: #1c1916;
  --paper: #262019;
  --ink: #ece4d6;
  --muted: #a1968a;
  --accent: #d99a5b;
  --accent-soft: #3a2e21;
  --line: #383027;
  --quote: #c7bdae;
  --gold: #e8b94a;
  --gold-soft: #3a2f16;
  --shadow: 0 1px 3px rgba(0, 0, 0, .5);
  /* Cap for full-bleed site chrome. `main` is already capped (760px, or 1040px
     with a .pane-layout), but the top bar spans the viewport -- it has to, since
     its background and bottom border are what separate it from the page. Only
     its CONTENTS are capped, so on an ultrawide monitor the brand and the tabs
     stop flying to opposite edges with the actual content stranded in the middle
     (Jonah's report, with screenshot). */
  --site-max: 1400px;
}

:root[data-theme="light"] {
  --bg: #f6f3ec;
  --paper: #fffdf8;
  --ink: #2a2622;
  --muted: #7a7268;
  --accent: #8a5a2b;
  --accent-soft: #efe3d3;
  --line: #e3dccf;
  --quote: #4a443c;
  --gold: #b8860b;
  --gold-soft: #f5e9c8;
  --shadow: 0 1px 3px rgba(0, 0, 0, .08);
}

body { transition: background-color .25s ease, color .25s ease; }

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: Georgia, "Iowan Old Style", "Times New Roman", serif;
  line-height: 1.65;
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .6rem max(1.2rem, calc((100% - var(--site-max)) / 2));
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow);
}

.brand { font-weight: bold; font-size: 1.15rem; cursor: pointer; user-select: none; }
.brand:hover { color: var(--accent); }

.tabs { display: flex; gap: .4rem; }

.tab {
  position: relative;
  font: inherit;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  padding: .35rem .9rem;
  border-radius: 999px;
  cursor: pointer;
}
.tab:hover { background: var(--accent-soft); }
.tab.active { background: var(--accent); color: #fff; }

/* floating "NEW!" badge on the Patch Notes tab */
.tab-badge {
  position: absolute;
  top: -.55rem;
  right: -.35rem;
  background: #e23b3b;
  color: #fff;
  font-family: system-ui, sans-serif;
  font-size: .58rem;
  font-weight: 800;
  letter-spacing: .04em;
  line-height: 1;
  padding: .18rem .32rem;
  border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
  pointer-events: none;
  animation: badge-pop .25s ease-out;
}
@keyframes badge-pop {
  from { transform: scale(0); }
  to { transform: scale(1); }
}

.topbar-right { display: flex; align-items: center; gap: .6rem; }

/* Hamburger toggle for the collapsed mobile nav (<=480px, see below). Hidden
   above that width -- the tab strip fits on one row and shows itself. Same
   square-button-with-inline-SVG treatment as the story "Jump to" collapse
   toggle, for the same reason (see hamburgerIcon() in app.js). Lives in the
   HTML as a direct child of .topbar, BEFORE .brand -- not inside
   .topbar-right -- so it stays put when .tabs opens/closes. .topbar-right
   is what jumps to its own full-width row while the dropdown is open (see
   the :has() rule below); keeping the toggle out of that element means the
   button that opened the menu doesn't itself relocate underneath your thumb. */
.nav-toggle-mobile {
  display: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  color: var(--muted);
}
.nav-toggle-mobile svg { display: block; }
.nav-toggle-mobile:hover { border-color: var(--accent); color: var(--accent); }
.theme-toggle {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: .9rem;
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 999px;
  padding: .35rem .7rem;
  min-width: 2.6rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }

/* Appearance row in Backstage → Settings — the theme toggle's new home. */
.theme-setting { font-family: system-ui, sans-serif; }
.theme-row { display: flex; align-items: center; justify-content: space-between; font-size: .95rem; }

.whoami {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: .85rem;
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 999px;
  padding: .25rem .7rem;
  max-width: 11rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.whoami:hover { border-color: var(--accent); color: var(--accent); }

/* sign-in gate (real accounts) */
.login-gate {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(0, 0, 0, .6);
  backdrop-filter: blur(2px);
}
.login-card {
  font-family: system-ui, sans-serif;
  width: min(440px, 100%);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 1.5rem;
  text-align: center;
}
.login-card h1 { margin: 0 0 .4rem; font-size: 1.4rem; }
.login-card p { color: var(--muted); margin: 0 0 1.1rem; }
/* the sign-in / request-an-account / waiting-room forms */
.login-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: .55rem; text-align: left; }
/* The author `display: grid` overrides the UA `[hidden]{display:none}`, so
   re-assert it explicitly or a hidden form still shows. */
.login-form[hidden] { display: none; }
.login-form input, .login-form textarea {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: 1rem;
  padding: .65rem 1rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  color: var(--ink);
  width: 100%;
}
.login-form textarea { resize: vertical; }
.login-form input:focus, .login-form textarea:focus { outline: none; border-color: var(--accent); }
.login-submit {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: 1rem;
  cursor: pointer;
  padding: .65rem 1rem;
  border: 1px solid var(--accent);
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
}
.login-submit:disabled { opacity: .6; cursor: default; }
.login-row { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.login-row .btn-ghost { margin-top: 0; }
/* `.login-card p` (0,1,1) outranks a bare `.login-err` (0,1,0) and was painting
   errors muted-grey. Match the card selector so the red actually lands. */
.login-card p.login-err, .login-err {
  color: #e23b3b;
  font-size: .9rem;
  font-weight: 600;
  margin: 0;
  min-height: 1.1em;
}
.login-card p.login-err.ok, .login-err.ok { color: var(--accent); }
/* Shown only after a failed sign-in: the refusal is deliberately vague about
   which half was wrong, so this supplies the next move. */
.login-card p.login-hint {
  margin: .7rem 0 0 !important;
  padding: .6rem .8rem;
  border-left: 3px solid var(--line);
  text-align: left;
  font-size: .88rem;
  line-height: 1.5;
}
.login-card p.login-hint[hidden] { display: none; }
.login-hint code {
  padding: .05rem .3rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--bg);
}
.login-alt {
  margin-top: 1rem;
  padding-top: .9rem;
  border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; gap: .5rem; flex-wrap: wrap;
}
.login-requestbtn, .login-backbtn, .login-startover {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: .95rem;
  cursor: pointer;
  background: transparent;
  border: none;
  color: var(--accent);
  text-decoration: underline;
  padding: 0;
}
.login-pending, .login-approved, .login-declined {
  color: var(--ink) !important;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: .8rem 1rem;
  margin: 0 0 .9rem !important;
  text-align: left;
}
.login-pending { border-left: 3px solid var(--accent); }
.login-approved { border-left: 3px solid #2e9e5b; }
.login-declined { border-left: 3px solid #e23b3b; }
.login-note-back {
  margin: 0 0 1rem;
  padding: .6rem .9rem;
  border-left: 3px solid var(--line);
  color: var(--muted);
  font-style: italic;
  text-align: left;
}

/* the one-time password reveal after a create/reset */
.pw-reveal .pw-value {
  margin: 0 0 1rem;
  padding: .9rem 1rem;
  border: 1px dashed var(--accent);
  border-radius: 10px;
  background: var(--bg);
}
.pw-reveal .pw-value code {
  font-size: 1.35rem;
  letter-spacing: .02em;
  user-select: all;
  word-break: break-all;
}

/* ghosting: an admin viewing as another reader. Sits directly under the top bar
   and sticks there — at the foot of the page it was easy to miss entirely, and a
   banner you don't notice is no safeguard at all. */
.ghost-banner {
  position: sticky;
  top: var(--topbar-h, 0);
  z-index: 60;
  display: flex; align-items: center; justify-content: center;
  gap: 1rem; flex-wrap: wrap;
  padding: .55rem 1rem;
  font-family: system-ui, sans-serif;
  font-size: .95rem;
  background: #6b3fa0;
  color: #fff;
  box-shadow: 0 2px 12px rgba(0, 0, 0, .3);
}
.ghost-banner .ghost-stop {
  font: inherit;
  cursor: pointer;
  padding: .3rem .8rem;
  border: 1px solid rgba(255, 255, 255, .6);
  border-radius: 8px;
  background: transparent;
  color: #fff;
}
.ghost-banner .ghost-stop:hover { background: rgba(255, 255, 255, .15); }
/* A purple hairline down both edges, so even scrolled past the banner it's
   obvious you're not in your own session. */
body.is-ghosting { box-shadow: inset 4px 0 #6b3fa0, inset -4px 0 #6b3fa0; }

/* top-bar identity chip — only rendered while ghosting or waiting as a guest */
.whoami.ghosting { background: #6b3fa0; color: #fff; border-color: #6b3fa0; }
.whoami.waiting { border-style: dashed; }

/* signed out: the gate is translucent, so blank what's behind it */
body.is-signed-out main { display: none; }

/* account card (Backstage → Settings) */
.admin-badge {
  font-family: system-ui, sans-serif;
  font-size: .65rem;
  font-weight: 700;
  letter-spacing: .06em;
  vertical-align: middle;
  margin-left: .4rem;
  padding: .1rem .4rem;
  border-radius: 4px;
  background: var(--accent);
  color: #fff;
}
/* Your account is a different kind of setting from the story ones above it, so
   separate the two groups properly instead of stacking the cards flush. */
.settings-pane .account-card {
  margin-top: 2.25rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--line);
}
.account-actions { display: flex; gap: .75rem; flex-wrap: wrap; align-items: center; }
.account-actions[hidden] { display: none; }
/* .btn-ghost's base rule carries `margin-top: 1rem` -- meant for a link sitting
   BELOW a field it's dismissing (e.g. a form's Cancel), not for a peer sitting
   NEXT TO a button in a row. Left in place here it dropped Sign out below
   Change password's baseline instead of level with it. */
.account-actions .btn-ghost { margin-top: 0; }
.account-card .account-pwform, .account-card .account-userform { margin-top: .9rem; max-width: 420px; }
.acct-username-hint { font-size: .85rem; margin: -.2rem 0 0; line-height: 1.5; }
/* A plain fact list beats stuffing name / username / date into one prose line. */
.account-facts {
  margin: .8rem 0 1rem;
  padding: .7rem .9rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  font-family: system-ui, sans-serif;
  font-size: .92rem;
  display: grid;
  gap: .35rem;
}
.account-facts > div { display: flex; gap: .75rem; align-items: baseline; }
.account-facts dt { color: var(--muted); min-width: 7.5rem; flex: none; }
.account-facts dd { margin: 0; }
.account-facts code {
  padding: .05rem .35rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--paper);
}
.account-facts .account-changeuser { margin-left: .5rem; font-size: .85rem; }

/* admin: the username beside a person's name, and the create-account field */
.admin-user {
  font-size: .82rem;
  margin-left: .4rem;
  padding: .05rem .35rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  color: var(--muted);
}
.admin-field {
  display: grid;
  gap: .3rem;
  text-align: left;
  font-family: system-ui, sans-serif;
  font-size: .9rem;
  color: var(--muted);
}
.pw-reveal .pw-line {
  display: flex; align-items: baseline; gap: .75rem;
  padding: .25rem 0;
}
.pw-reveal .pw-line span {
  font-family: system-ui, sans-serif;
  font-size: .85rem;
  color: var(--muted);
  min-width: 5.5rem;
  text-align: left;
}

/* Backstage → 🛠 Admin */
.admin-block { margin-bottom: 1.6rem; }
.admin-hint { margin: .2rem 0 .8rem; font-size: .9rem; }
.admin-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.admin-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  padding: .7rem .9rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  font-family: system-ui, sans-serif;
}
.admin-who { min-width: 12rem; flex: 1 1 12rem; }
.admin-you {
  font-size: .7rem; color: var(--muted); margin-left: .35rem;
  border: 1px solid var(--line); border-radius: 4px; padding: .05rem .3rem;
}
.admin-status { font-size: .85rem; color: var(--muted); margin-top: .15rem; }
.admin-status.ok { color: #2e9e5b; }
.admin-status.warn { color: #c07a1e; }
.admin-status.disabled { color: #e23b3b; }
.admin-acts { display: flex; gap: .4rem; flex-wrap: wrap; }
.admin-act {
  margin-top: 0;
  font-size: .88rem;
  padding: .3rem .65rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  text-decoration: none;
  color: var(--ink);
  background: var(--bg);
}
.admin-act:hover { border-color: var(--accent); color: var(--accent); }
.admin-act.primary { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.admin-req .sugg-note { margin-top: .4rem; }
.admin-handled { margin-top: .8rem; font-family: system-ui, sans-serif; }
.admin-handled summary { cursor: pointer; color: var(--muted); font-size: .9rem; }
.admin-handled .admin-list { margin-top: .5rem; }
.btn-ghost {
  font: inherit;
  font-family: system-ui, sans-serif;
  margin-top: 1rem;
  cursor: pointer;
  background: transparent;
  border: none;
  color: var(--muted);
  text-decoration: underline;
}

/* identity line in vote / submit boxes, and the inline "switch" link */
.vote-as, .submit-as { font-family: system-ui, sans-serif; margin-bottom: .5rem; }
.link-btn {
  font: inherit;
  cursor: pointer;
  background: transparent;
  border: none;
  padding: 0;
  color: var(--accent);
  text-decoration: underline;
}
.vote-box.locked .option-btn,
.vote-box.locked .pitch-options { opacity: .5; pointer-events: none; }
.submit-box.locked .submit-attrs { opacity: .6; }

.toast {
  position: fixed;
  bottom: 1.2rem;
  left: 50%;
  transform: translateX(-50%) translateY(1rem);
  background: var(--ink);
  color: var(--bg);
  padding: .65rem 1.1rem;
  border-radius: 10px;
  font-family: system-ui, sans-serif;
  font-size: .9rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .35);
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease, transform .25s ease;
  z-index: 50;
  max-width: 90%;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

main {
  max-width: 760px;
  margin: 0 auto;
  padding: 1.5rem 1.2rem 4rem;
}

/* story layout: nav sidebar + reading column */
.story-layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 2.2rem;
  align-items: start;
}
main:has(.story-layout) { max-width: 1040px; }
/* Missing this was the one grid column on the site without it (.pane-main and
   .backstage-main already have the same fix): a grid item's default min-width
   is content-based, not the track's minmax(0,...), so wide reveal-panel
   content -- the fenced RNG-JSON block inside "Behind the scenes" -- could
   force the whole column, and the page, wider than the viewport on mobile
   when the panel was expanded. */
.story-main { min-width: 0; }

/* Two-pane layout with a left sidebar (like the story nav). Shared by the Info
   tab (About / Patch Notes) and Backstage (Feedback / Character Profile). */
main:has(.pane-layout) { max-width: 1040px; }
.pane-layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 2.2rem;
  align-items: start;
}
.pane-nav {
  position: sticky;
  /* Both offsets below are pulled up by the badge gutter's .7rem so the rows land
     where they always did: the negative margin covers the un-stuck flow position,
     the trimmed `top` covers the stuck one (sticky pins the border box to `top`
     and ignores the margin, so one alone would fix a single state and shift the
     other). */
  top: calc(var(--topbar-h, 62px) + 8px - .7rem);   /* clear the sticky topbar (its real height, kept in --topbar-h by app.js) */
  max-height: calc(100vh - var(--topbar-h, 62px) - 20px + .7rem);
  overflow: auto;
  display: grid;
  gap: .4rem;
  /* Badge gutter. The NEW! pill on a sidebar row is absolutely positioned to
     poke above and past its button's top-right corner, but `overflow: auto`
     clips anything outside this box -- so on the Awards sidebar, where the
     badged Ceremonies row sits FIRST, the pill was sliced off along both edges
     (Jonah's and Calvin's reports). Pad the scroll box out far enough to hold
     the overhang, then pull the box back by the same amount so every row stays
     exactly where it was. */
  padding: .7rem .5rem 0 0;
  margin: -.7rem -.5rem 0 0;
}
.pane-navbtn {
  position: relative;            /* anchor for the NEW! badge */
  font: inherit;
  font-size: 1rem;
  text-align: left;
  cursor: pointer;
  padding: .55rem .85rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  color: var(--ink);
}
.pane-navbtn:hover { border-color: var(--accent); color: var(--accent); }
.pane-navbtn.active { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.pane-main { min-width: 0; }

/* Tablet & mobile top bar: group the brand + nav on the LEFT instead of flinging
   the nav to the right edge. The desktop `justify-content: space-between` left a
   wide empty gap on tablet and crammed every control against the right on phones
   (Jonah's report). Below 860px the brand and the nav group sit together, left-
   aligned, wrapping onto more rows as needed. */
@media (max-width: 860px) {
  .topbar { justify-content: flex-start; flex-wrap: wrap; row-gap: .45rem; }
  .topbar-right { flex-wrap: wrap; justify-content: flex-start; row-gap: .45rem; }
  /* Tabs WRAP to a second row when they don't fit, rather than scrolling. The old
     `overflow-x: auto` clipped the floating "NEW!" badge (it pokes above the tab,
     and overflow-x:auto forces overflow-y to clip) and showed a phantom scrollbar.
     Wrapping avoids both — the badge is never clipped and there's nothing to scroll. */
  .tabs { flex-wrap: wrap; }
}
@media (max-width: 640px) {
  .pane-layout { grid-template-columns: 1fr; gap: .8rem; }
  /* A row of Systems Feedback / Profile Suggestions / Character Profile / Settings
     (+ Admin) buttons is wider than a phone screen -- scroll it in its own lane
     instead of letting it overflow past main's right padding to the screen edge
     (Jonah's report). Same fix already used for .story-nav ul below. */
  /* Keep the badge gutter's padding (this lane clips vertically too), but drop
     the negative right margin -- full-width here, it would push the lane past
     main's right padding rather than into a column gap. The extra .5rem just
     joins the scrollable width instead. */
  .pane-nav { position: static; grid-auto-flow: column; justify-content: start; overflow-x: auto; margin-right: 0; }
  .topbar { padding: .5rem .8rem; }
  .whoami { max-width: 46vw; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
@media (max-width: 480px) {
  /* On a phone the tab strip doesn't fit "Live Archive Awards Backstage Info"
     on one row -- it used to wrap, stranding "Info" alone on a second line
     (Jonah's report, with screenshot). Collapse it behind the hamburger
     toggle instead: closed by default, opens as a full-width column below the
     brand row (not an overlay -- the sticky top bar just grows a row taller,
     tracked automatically by the --topbar-h ResizeObserver in app.js). */
  .nav-toggle-mobile { display: flex; }
  .tabs {
    display: none;
    flex-direction: column;
    align-items: stretch;
    flex-basis: 100%;
    gap: .3rem;
    margin-top: .3rem;
  }
  .tabs.mobile-open { display: flex; }
  .tab { width: 100%; text-align: left; border-radius: 8px; }
  /* .topbar-right normally shrink-wraps to its own contents (just whoami,
     sized to sit next to the brand) -- .tabs's flex-basis:100% above is
     only 100% of THAT width, not the viewport, so an open dropdown would be
     squeezed into a narrow column beside the brand instead of spanning the
     bar. Only while open, force topbar-right onto its own full-width row so
     the dropdown underneath it actually reaches edge to edge. The hamburger
     toggle itself lives outside .topbar-right (see .nav-toggle-mobile above)
     specifically so this reflow never moves the button you just tapped. */
  .topbar-right:has(.tabs.mobile-open) { flex-basis: 100%; }
}

.story-nav {
  position: sticky;
  top: calc(var(--topbar-h, 62px) + 8px);
  max-height: calc(100vh - var(--topbar-h, 62px) - 20px);
  overflow: auto;
  font-family: system-ui, sans-serif;
}
/* Jumped-to sections clear the sticky top bar instead of tucking under it. */
[id^="sec-"] { scroll-margin-top: calc(var(--topbar-h, 62px) + 1rem); }
.nav-toggle {
  /* A real square, flex-centered, holding an SVG icon rather than a text glyph
     -- see hamburgerIcon() in app.js for why. */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  color: var(--muted);
  margin-bottom: .5rem;
}
.nav-toggle svg { display: block; }
.nav-toggle:hover { border-color: var(--accent); color: var(--accent); }
.story-nav .nav-title {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  margin-bottom: .5rem;
}
.story-nav ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .15rem; }
.story-nav a {
  display: block;
  padding: .3rem .6rem;
  border-left: 2px solid transparent;
  border-radius: 0 6px 6px 0;
  color: var(--muted);
  text-decoration: none;
  font-size: .9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.story-nav a:hover { background: var(--accent-soft); color: var(--ink); }
.story-nav a.active {
  border-left-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
  font-weight: 600;
}

/* collapsed nav: column shrinks to just the toggle, reading column widens */
.story-layout.nav-collapsed { grid-template-columns: auto minmax(0, 1fr); }
.nav-collapsed .nav-body { display: none; }

@media (max-width: 860px) {
  .story-layout { grid-template-columns: 1fr; gap: .6rem; }
  .story-layout.nav-collapsed { grid-template-columns: 1fr; }
  /* The "Jump to" strip stays pinned while you read (sticky just under the top
     bar), so you can always see where you are and hop between parts. Jonah's
     request. Sits below the top bar in the stack (lower z-index than the bar). */
  .story-nav {
    position: sticky;
    top: var(--topbar-h, 62px);
    z-index: 5;
    background: var(--bg);
    max-height: none;
    border-bottom: 1px solid var(--line);
    padding-top: .4rem;
    padding-bottom: .5rem;
    margin-bottom: .4rem;
  }
  .story-nav ul { grid-auto-flow: column; grid-auto-columns: max-content; overflow-x: auto; gap: .3rem; }
  .story-nav a { border-left: none; border-bottom: 2px solid transparent; border-radius: 6px; }
  .story-nav a.active { border-left: none; border-bottom-color: var(--accent); }
  /* On mobile the strip is pinned ABOVE the content too, so jumped-to sections
     must clear the top bar AND the strip. */
  [id^="sec-"] { scroll-margin-top: calc(var(--topbar-h, 62px) + 3.2rem); }
}

/* Navigation menus (header tab strip + the two sidebars) stay scrollable when
   their content overflows, but never show a scrollbar track. Without this, the
   overflow:auto containers render a phantom scrollbar whenever the content
   sits at or a hair past the container — a thin bar that flickers in at rest and
   auto-hides once you interact with it. It's chrome nobody needs on a menu; the
   nav still scrolls by wheel/trackpad/swipe/drag. */
.tabs,
.story-nav,
.story-nav ul,
.pane-nav {
  scrollbar-width: none;              /* Firefox */
  -ms-overflow-style: none;          /* legacy Edge/IE */
}
.tabs::-webkit-scrollbar,
.story-nav::-webkit-scrollbar,
.story-nav ul::-webkit-scrollbar,
.pane-nav::-webkit-scrollbar {
  width: 0;
  height: 0;                          /* Chrome/Safari/Edge — hide both axes */
}

/* archive browser: search box + windowed pager over the story list */
.archive-controls { display: flex; align-items: center; gap: .8rem; margin-bottom: .9rem; flex-wrap: wrap; }
.archive-search {
  flex: 1; min-width: 0; font: inherit; font-size: 1rem;
  padding: .5rem .8rem; border: 1px solid var(--line); border-radius: 10px;
  background: var(--paper); color: var(--ink);
}
.archive-search:focus { outline: none; border-color: var(--accent); }
.archive-count { font-size: .85rem; white-space: nowrap; font-family: system-ui, sans-serif; }
.archive-empty { list-style: none; padding: 1.2rem .2rem; }

.pager { display: flex; align-items: center; justify-content: center; gap: .3rem; margin-top: 1.1rem; flex-wrap: nowrap; }
.pager-nums { display: inline-flex; align-items: center; gap: .3rem; }
.pager-btn {
  font: inherit; font-family: system-ui, sans-serif; font-size: .9rem;
  min-width: 2.1rem; padding: .35rem .55rem; cursor: pointer;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--paper); color: var(--ink);
}
.pager-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.pager-btn:disabled { opacity: .4; cursor: default; }
.pager-num.active { background: var(--accent); color: #fff; border-color: var(--accent); font-weight: 600; }
.pager-ellipsis { color: var(--muted); padding: 0 .1rem; }
.pager-status { display: none; font-size: .9rem; color: var(--muted); font-family: system-ui, sans-serif; padding: 0 .5rem; }
/* Narrow screens: drop the number buttons and show a compact "Page X / N", so
   the pager can never overflow no matter how many pages the archive grows to. */
@media (max-width: 460px) {
  .pager-nums { display: none; }
  .pager-status { display: inline; }
}

/* story list */
.story-list { list-style: none; padding: 0; margin: 0; display: grid; gap: .7rem; }
.story-card {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  padding: .9rem 1.1rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 10px;
  cursor: pointer;
  box-shadow: var(--shadow);
}
.story-card:hover { border-color: var(--accent); }
.story-card .num { color: var(--muted); font-variant-numeric: tabular-nums; }
.story-card .title { font-weight: bold; font-size: 1.1rem; flex: 1; }
.badge {
  font-family: system-ui, sans-serif;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .01em;
  padding: .2rem .6rem;
  border-radius: 999px;
  white-space: nowrap;
  background: var(--accent-soft);
  color: var(--accent);
}
/* one color per story mode (works on both light & dark via translucent tints) */
.badge[data-mode="standard"]    { background: rgba(79, 142, 219, .16);  color: #4f8edb; }
.badge[data-mode="elimination"] { background: rgba(224, 114, 107, .16); color: #e0726b; }
.badge[data-mode="cyoa"]        { background: rgba(92, 184, 138, .18);  color: #5cb88a; }

/* Archive/Live story cards on a phone: a long title plus the mode badge crowd
   together when the title wraps to multiple lines (Jonah's report, with
   screenshot). Number+title keep sharing the top row (title wraps within it
   same as before); the badge drops to its own row underneath instead of
   sitting baseline-aligned against whichever line of the title it lands next
   to. Placed here, after the base .story-card rule, so the override actually
   wins the cascade at this width instead of losing to source order. */
@media (max-width: 480px) {
  .story-card {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: .6rem;
    row-gap: .35rem;
    align-items: baseline;
  }
  .story-card .num { grid-column: 1; grid-row: 1; }
  .story-card .title { grid-column: 2; grid-row: 1; }
  .story-card .badge { grid-column: 1 / -1; grid-row: 2; justify-self: start; }
}

.muted { color: var(--muted); }
.empty { color: var(--muted); font-style: italic; padding: 2rem 0; text-align: center; }

/* Live tab when nothing's in progress: the "what's next" poll, then a pointer
   to the most-recent story beneath it */
.live-empty .empty { padding: 2rem 0 .5rem; }
.poll-box { max-width: 640px; margin: 0 auto 1.6rem; }
.poll-idea-row { margin-top: .9rem; }
.recent-cta {
  display: grid;
  gap: .5rem;
  max-width: 520px;
  margin: 0 auto;
}
.recent-cta-label {
  font-family: system-ui, sans-serif;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  text-align: center;
}
.recent-card {
  font: inherit;
  color: var(--ink);   /* a <button> won't inherit --ink the way the <li> cards do */
  width: 100%;
  text-align: left;
}

.backlink {
  display: inline-block;
  font-family: system-ui, sans-serif;
  font-size: .85rem;
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  padding: 0 0 1rem;
}

/* story reading */
.story-head h1 { margin: .2rem 0 .3rem; }
.section { border-top: 1px solid var(--line); padding-top: 1rem; margin-top: 1.5rem; }
.section:first-of-type { border-top: none; }
.section-label {
  font-family: system-ui, sans-serif;
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  margin-bottom: .3rem;
}
/* "What the party chose" card, shown between parts. */
.decision-card {
  font-family: system-ui, sans-serif;
  margin: 1.6rem 0 .4rem;
  padding: .7rem 1rem;
  border: 1px solid var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  background: var(--accent-soft);
  box-shadow: var(--shadow);
}
.decision-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .5rem;
}
.decision-kicker {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--muted);
}
.decision-chosen { font-weight: 700; color: var(--accent); }
.decision-summary { margin-top: .35rem; font-size: .95rem; color: var(--ink); }
.decision-why { margin-top: .45rem; font-size: .85rem; color: var(--muted); }
.decision-why summary {
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: .7rem;
}
.decision-why > div { margin-top: .35rem; line-height: 1.55; }

.prose h1, .prose h2, .prose h3 { line-height: 1.25; }
.prose blockquote {
  margin: .8rem 0;
  padding: .2rem 0 .2rem 1rem;
  border-left: 3px solid var(--accent-soft);
  color: var(--quote);
}
.prose hr { border: none; border-top: 1px solid var(--line); margin: 1.5rem 0; }
.prose img { max-width: 100%; }
/* Authored markdown is free-form -- a long unbroken word/token or a table could
   push past the reading column's right edge on a narrow screen with no visible
   scrollbar to hint at it (part of Jonah's "runs to the edge on mobile" report).
   Belt-and-suspenders: wrap long tokens, and let a table scroll in its own lane
   rather than overflow the page. */
.prose { overflow-wrap: break-word; }
.prose table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; }
.prose th, .prose td { padding: .35rem .6rem; border: 1px solid var(--line); }
/* Fenced code blocks (e.g. the RNG JSON in behind-the-scenes) must scroll,
   not clip. Default <pre> has no overflow, so long lines were cut off. */
.prose pre {
  overflow-x: auto;
  max-width: 100%;
  background: rgba(127, 127, 127, .10);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: .75rem .9rem;
  margin: .8rem 0;
  line-height: 1.45;
}
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .85em;
}
.prose :not(pre) > code {
  background: rgba(127, 127, 127, .14);
  padding: .1em .35em;
  border-radius: 4px;
}
.prose pre code { background: none; padding: 0; white-space: pre; }

/* reveal panels (archive) */
.reveal {
  margin-top: 2rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  overflow: hidden;
}
.reveal > summary {
  cursor: pointer;
  padding: .8rem 1rem;
  font-family: system-ui, sans-serif;
  font-weight: 600;
  background: var(--accent-soft);
}
.reveal .reveal-body { padding: 1rem; }
.rng-grid { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: .85rem; }
.rng-grid div { padding: .15rem 0; }
.spoiler-note { font-family: system-ui, sans-serif; font-size: .8rem; color: var(--muted); }

/* voting */
.vote-box {
  margin-top: 2rem;
  padding: 1.1rem 1.2rem;
  border: 2px solid var(--accent-soft);
  border-radius: 12px;
  background: var(--paper);
}
.vote-box h3 { margin-top: 0; font-family: system-ui, sans-serif; }
.vote-name { font-family: system-ui, sans-serif; margin-bottom: .8rem; }
.vote-name input, .pitch-row input, .feedback-form input, .feedback-form textarea, .feedback-form select {
  font: inherit;
  /* Companion to the minmax(0, 1fr) columns above: the track can now shrink, so
     stop any single control from growing back past it. */
  max-width: 100%;
  min-width: 0;
  /* Override the parent <label>'s .85rem (13.6px) — iOS Safari auto-zooms on
     focusing any text input under 16px, which was the actual bug here. */
  font-size: 1rem;
  color: var(--ink);
  padding: .5rem .6rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
}
.options { display: grid; gap: .5rem; }
.option-btn {
  text-align: left;
  font: inherit;
  color: var(--ink);
  padding: .7rem .9rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  cursor: pointer;
  display: flex;
  gap: .6rem;
  align-items: baseline;
}
.option-btn:hover { border-color: var(--accent); }
.option-btn.mine { border-color: var(--accent); background: var(--accent-soft); }
/* Current front-runner — gold ring + crown, stacks over .mine's background. */
.option-btn.leading { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold); }
.option-btn.leading .count::before { content: "👑 "; }
.option-btn .letter {
  font-family: system-ui, sans-serif;
  font-weight: 700;
  color: var(--accent);
  min-width: 1.2em;
}
.option-btn .count {
  margin-left: auto;
  font-family: system-ui, sans-serif;
  font-size: .95rem;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}
.option-btn.leading .count { color: var(--gold); }
.option-btn .otext { flex: 1; }
.option-btn .voters { display: block; font-size: .85rem; color: var(--quote); margin-top: .25rem; }
.option-btn .voters:not(:empty)::before { content: "🗳 "; }
.option-btn .pmeta { display: block; font-size: .75rem; color: var(--accent); margin-top: .15rem; font-family: system-ui, sans-serif; }
.pitch-group { margin-top: 1rem; }
.pitch-options { display: grid; gap: .5rem; }
/* Story-mode picker for a poll write-in — no pick, no submit. */
.pitch-mode {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .3rem .9rem;
  margin: .5rem 0 0;
  padding: 0;
  border: 0;
  font-family: system-ui, sans-serif;
  font-size: .85rem;
}
.pitch-mode[disabled] { opacity: .5; }
.pitch-mode-label { color: var(--muted); }
.pitch-mode label { display: inline-flex; align-items: center; gap: .3rem; cursor: pointer; }
.pitch-mode input { cursor: pointer; }
/* profile suggestions — a card, used both on the Suggestions board and (via
   .sugg-item alone) anywhere else a single suggestion needs rendering */
.sugg-item {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: .7rem .9rem;
  margin: .5rem 0;
  display: grid;
  gap: .45rem;
  background: var(--paper);
}
.sugg-meta { font-size: .78rem; color: var(--muted); font-family: system-ui, sans-serif; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.sugg-when { margin-left: auto; font-variant-numeric: tabular-nums; }
.sugg-text { font-style: italic; }
.sugg-synth {
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 8px 8px 0;
  padding: .45rem .7rem;
  font-size: .92rem;
}
.sugg-synth-label { display: block; font-size: .72rem; font-weight: 700; color: var(--accent); font-family: system-ui, sans-serif; margin-bottom: .15rem; }
.sugg-note { font-size: .85rem; color: var(--muted); font-style: italic; }
.sugg-actions { display: flex; gap: .5rem; }
.me-badge.declined { color: #c0392b; }

/* Backstage → Suggestions: swim-lane board. Sits in .pane-main, so it gets
   ~800px — the auto-fit lands on 2 lanes there, 1 on mobile. */
.sugg-page { font-family: system-ui, sans-serif; }
/* the "suggest a trait" form -- reuses .feedback-form's field styling and
   .part-card's bordered look, just needs to sit above the board with room to
   breathe. */
.sugg-new-form { margin-bottom: 1.4rem; }
.sugg-who-note { font-size: .85rem; margin: -.2rem 0 0; }
.sugg-page.backstage-pane { max-width: none; }
.sugg-board {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1rem;
  align-items: start;
  margin-top: 1rem;
}
.sugg-lane {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .9rem 1rem 1.1rem;
  min-width: 0;
}
.sugg-lane-head { font-size: .95rem; font-weight: 700; color: var(--ink); display: flex; align-items: center; gap: .4rem; }
.sugg-lane-sub { font-size: .76rem; margin-top: .1rem; }
.sugg-lane-body { margin-top: .6rem; }
.sugg-lane-empty { font-size: .85rem; padding: .3rem 0; }
@media (max-width: 640px) {
  .sugg-board { grid-template-columns: 1fr; }
}

/* read-only vote history inside the decision card */
.past-vote { margin-top: .6rem; font-size: .88rem; }
.past-vote summary { cursor: pointer; color: var(--accent); font-family: system-ui, sans-serif; }
.past-vote-body { display: grid; gap: .4rem; padding-top: .5rem; }
/* Read-only look-back at character setups (archive + live mid-story). */
.past-setups { margin: 1.4rem 0 .4rem; }
.past-setups summary { cursor: pointer; color: var(--accent); font-family: system-ui, sans-serif; font-weight: 700; }
.past-setups-body { display: grid; gap: .9rem; padding-top: .7rem; }
.setup-entry {
  border-left: 2px solid var(--line);
  padding: .1rem 0 .1rem .8rem;
}
.setup-who {
  font-family: system-ui, sans-serif;
  font-weight: 700;
  color: var(--ink);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .2rem .6rem;
}
.setup-words { font-weight: 400; font-size: .78rem; color: var(--muted); }
.setup-text { white-space: pre-wrap; margin-top: .25rem; color: var(--quote); }
.setup-text.muted { font-style: italic; color: var(--muted); }
.past-question {
  font-style: italic;
  color: var(--muted);
  padding: .2rem 0 .1rem;
}
.past-option {
  display: flex;
  gap: .6rem;
  align-items: baseline;
  padding: .55rem .8rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
}
.past-option .letter { font-family: system-ui, sans-serif; font-weight: 700; color: var(--accent); min-width: 1.2em; }
.past-option .otext { flex: 1; }
.past-option .voters { display: block; font-size: .78rem; color: var(--muted); margin-top: .2rem; }
.past-option .pmeta { display: block; font-size: .75rem; color: var(--accent); margin-top: .15rem; font-family: system-ui, sans-serif; }
.past-option .count { margin-left: auto; font-family: system-ui, sans-serif; font-size: .82rem; color: var(--muted); white-space: nowrap; }

/* opt-in hidden answers / traits */
.hide-toggle {
  display: block;
  margin-top: .5rem;
  font-size: .82rem;
  color: var(--ink);
  cursor: pointer;
  user-select: none;
}
.hide-toggle input { margin-right: .35rem; }
.pitch-lockrow {
  display: flex;
  gap: .6rem;
  align-items: baseline;
  padding: .7rem .9rem;
  border: 1px dashed var(--line);
  border-radius: 10px;
  color: var(--muted);
  font-style: italic;
}
.sub-peek { width: 100%; margin-top: .3rem; font-size: .82rem; }
.sub-peek summary { cursor: pointer; color: var(--accent); }
.sub-peek-text { white-space: pre-wrap; padding: .4rem .2rem 0; color: var(--ink); }

/* your own suggestion: option button + 🗑 delete side by side */
.pitch-line { display: flex; gap: .4rem; align-items: stretch; }
.pitch-line .option-btn { flex: 1; }
.pitch-delete {
  font: inherit;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  color: var(--muted);
  cursor: pointer;
  padding: 0 .55rem;
}
.pitch-delete:hover { border-color: #c0392b; color: #c0392b; }
.no-pitches { font-size: .85rem; }
.pitch-row { display: flex; gap: .5rem; margin-top: .9rem; }
.pitch-row input { flex: 1; }

/* prompt (type-your-answer) menu variant */
.prompt-question {
  font-size: 1.02rem;
  line-height: 1.5;
  padding: .8rem 1rem;
  margin: .2rem 0 1rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 8px 8px 0;
}
.pitch-row.prompt-row { align-items: flex-start; }
.pitch-row textarea.pitch-input {
  flex: 1;
  font: inherit;
  color: var(--ink);
  padding: .5rem .6rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  min-height: 4.5rem;
  resize: vertical;
  box-sizing: border-box;
}
.btn {
  font: inherit;
  font-family: system-ui, sans-serif;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: .5rem 1rem;
  cursor: pointer;
}
.btn:hover:not(:disabled) { filter: brightness(1.05); }
/* Jonah's report (server-feedback.md, 2026-08-17T20:56): a disabled .btn still
   looked fully clickable — pointer cursor, hover brightness bump — with no
   visual sign it wasn't. Base-class fix so every "class=btn" button site-wide
   picks it up automatically (general feedback, Suggest it, pitch-send, etc). */
.btn:disabled { opacity: .5; cursor: default; }
.pitches { margin-top: 1rem; }
.pitches .section-label { margin-bottom: .4rem; }
.pitch-item { font-size: .9rem; padding: .3rem 0; border-top: 1px dashed var(--line); }
.pitch-item .who { color: var(--accent); font-family: system-ui, sans-serif; }

.vote-hint { font-size: .82rem; margin: .1rem 0 .8rem; }

/* setup phase: submission widget + Hall of Fame leaderboard, side by side */
.submit-row {
  margin-top: 2rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 250px;
  gap: 1rem;
  align-items: start;
}
.submit-row .submit-box { margin-top: 0; }
@media (max-width: 720px) {
  .submit-row { grid-template-columns: 1fr; }
}

/* 📖 most-detailed all-time leaderboard (class name is legacy from the retired
   first-in medal — kept to avoid churn) */
.first-leaderboard {
  font-family: system-ui, sans-serif;
  padding: 1.1rem 1.2rem;
  border: 2px solid var(--accent-soft);
  border-radius: 12px;
  background: var(--paper);
  position: sticky;
  top: 70px;
}
.first-leaderboard h3 { margin: 0 0 .15rem; font-size: 1rem; }
.fl-sub { font-size: .76rem; margin: 0 0 .8rem; }
.fl-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.fl-row {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  font-size: .9rem;
  padding: .35rem .5rem;
  border: 1px solid var(--line);
  border-radius: 7px;
}
.fl-row.mine { border-color: var(--accent); background: var(--accent-soft); }
.fl-rank { min-width: 1.7em; text-align: center; }
.fl-name {
  flex: 1;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fl-count { color: var(--muted); font-variant-numeric: tabular-nums; }
.fl-empty { font-size: .85rem; font-style: italic; padding: .2rem 0; }
@media (max-width: 720px) {
  .first-leaderboard { position: static; }
}

/* "first in" medal on the submitted-so-far list */
.detail-badge { font-size: .72rem; color: var(--accent); font-weight: 700; white-space: nowrap; }

/* participation: per-story Live-tab strip + Backstage global switch */
.part-strip {
  font-family: system-ui, sans-serif;
  margin: 1.6rem 0 0;
  padding: .8rem 1rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
}
.part-strip.in { border-color: var(--accent); background: var(--accent-soft); }
.part-strip.is-locked { border-style: dashed; }
.part-strip.is-locked .part-toggle { cursor: default; }
.part-toggle { display: flex; align-items: center; gap: .55rem; cursor: pointer; font-weight: 600; }
.part-toggle input { width: 1.1rem; height: 1.1rem; cursor: pointer; }
.part-toggle input:disabled { cursor: default; }
.part-sub { margin: .35rem 0 0; font-size: .85rem; }
/* Settings pane: stack its sections (notifications, then the participation card)
   vertically, full width. The shared .backstage-pane is a two-column flex row, so
   override it to a plain block (two-class selector to win on specificity). The
   notify-setting's own border-bottom divides the two. */
.backstage-pane.settings-pane { display: block; }

/* Settings: the "being in stories" card with a real toggle switch. */
.part-card {
  font-family: system-ui, sans-serif;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--paper);
  padding: 1.1rem 1.2rem 1.2rem;
  box-shadow: var(--shadow);
  transition: border-color .18s ease;
}
.part-card.on { border-color: var(--accent); }
.part-card-head { display: flex; gap: .75rem; align-items: flex-start; }
.part-card-icon { font-size: 1.55rem; line-height: 1; }
.part-card-title { margin: 0 0 .25rem; font-size: 1.05rem; }
.part-card-desc { margin: 0; color: var(--muted); font-size: .9rem; line-height: 1.5; }
.part-switch-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  cursor: pointer;
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.part-switch-label { font-weight: 600; }
.part-card .part-note { margin: .6rem 0 0; color: var(--muted); font-size: .85rem; }
/* the toggle switch (visually-hidden checkbox drives an adjacent track) */
.part-switch-row .part-every { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track {
  flex: none;
  width: 46px;
  height: 26px;
  border-radius: 999px;
  background: var(--line);
  padding: 3px;
  display: inline-flex;
  align-items: center;
  transition: background .18s ease;
}
.switch-thumb {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .4);
  transition: transform .18s ease;
}
.part-every:checked + .switch-track { background: var(--accent); }
.part-every:checked + .switch-track .switch-thumb { transform: translateX(20px); }
.part-every:focus-visible + .switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* character submission box (setup phase) */
.submit-box {
  font-family: system-ui, sans-serif;
  margin-top: 2rem;
  padding: 1.1rem 1.2rem;
  border: 2px solid var(--accent-soft);
  border-radius: 12px;
  background: var(--paper);
}
.submit-box h3 { margin-top: 0; }
.submit-attrs {
  font: inherit;
  width: 100%;
  min-height: 110px;
  resize: vertical;
  color: var(--ink);
  padding: .5rem .6rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
}
.submit-send { margin-top: .6rem; }
.submit-status { margin-top: 1rem; }
.submit-list { list-style: none; padding: 0; margin: .3rem 0 0; display: grid; gap: .25rem; }
.submit-list li {
  display: flex;
  flex-wrap: wrap;              /* lets the .sub-peek traits block drop to a full-width row */
  justify-content: space-between;
  gap: .2rem 1rem;
  font-size: .9rem;
  padding: .3rem .5rem;
  border-radius: 6px;
  border: 1px solid var(--line);
}
.submit-list li.done { border-color: var(--accent); }
.submit-list li .who { font-weight: 600; }
.submit-list li.done .state { color: var(--accent); }
.submit-list li.pending .state { color: var(--muted); }

/* feedback: "my profile" + "my submissions" panels below the form */
.feedback-page { max-width: 720px; }
/* Backstage Feedback pane: the submission form + your own submissions. The
   suggestions inbox is its own Backstage section (see .sugg-board). */
.backstage-pane { max-width: 720px; }
.backstage-main { min-width: 0; }
/* Separate the submissions list from the form, the way .me-section used to. */
.backstage-pane .me-subs { margin-top: 1.6rem; padding-top: 1.2rem; border-top: 1px solid var(--line); }
.notify-setting { margin-bottom: 1.2rem; padding-bottom: 1.1rem; border-bottom: 1px solid var(--line); font-family: system-ui, sans-serif; }
.notify-toggle { display: flex; align-items: center; gap: .5rem; cursor: pointer; font-size: .95rem; }
.notify-toggle input { cursor: pointer; }
.notify-note { font-size: .82rem; margin: .35rem 0 0; }
.me-section {
  margin-top: 1.8rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}
.me-signin { font-family: system-ui, sans-serif; margin: 0; }
.me-panel { font-family: system-ui, sans-serif; margin-bottom: 1.2rem; }
/* .me-panel reuses .reveal for the profile; this just spaces the submissions block */
.me-subs .section-label { margin-bottom: .5rem; }
.me-fb-head {
  font-size: .8rem;
  font-weight: 700;
  color: var(--ink);
  margin: .2rem 0 .5rem;
}
.me-fb-n {
  font-size: .72rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.me-fb-resolved { margin-top: .9rem; }
.me-fb-resolved > summary {
  cursor: pointer;
  font-size: .8rem;
  font-weight: 700;
  color: var(--ink);          /* summaries don't inherit color reliably */
  list-style-position: inside;
}
.me-fb-resolved > summary:hover { color: var(--accent); }
.me-fb-list { list-style: none; margin: .4rem 0 0; padding: 0; display: grid; gap: .5rem; }
.me-fb-item {
  padding: .55rem .7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
}
/* flex-wrap so a row of pills that doesn't fit sends a whole pill to the next
   line, rather than letting an individual pill's own text wrap mid-word (the
   "backlog" / "choose your own adventure" / "reviewed" row cramping into a
   two-line pill -- Jonah's report, with screenshot). */
.me-fb-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; margin-bottom: .25rem; }

/* "Withdraw" on a still-pending submission in Backstage -> Your feedback. Quiet
   and secondary -- it sits in the metadata row next to the status badge, so it
   should read as an available action rather than compete with Submit. */
.btn-withdraw {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: .72rem;
  margin-left: auto;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .1rem .55rem;
  cursor: pointer;
}
.btn-withdraw:hover:not(:disabled) { border-color: #c0392b; color: #c0392b; }
.btn-withdraw:disabled { opacity: .5; cursor: default; }

/* inline-flex + centering so the text sits dead-center in the pill instead of
   just top-left-anchored by default span flow, and never wraps internally --
   pairs with .me-fb-meta's flex-wrap above so a long label ("Choose Your Own
   Adventure") pushes the whole pill to the next line rather than breaking its
   own text into two (Jonah's report, with screenshot). */
.me-fb-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  white-space: nowrap;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--accent);
  background: var(--accent-soft);
  padding: .1rem .45rem;
  border-radius: 999px;
}
.me-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  white-space: nowrap;
  font-size: .68rem;
  font-weight: 700;
  padding: .1rem .45rem;
  border-radius: 999px;
}
.me-badge.pending { color: #b5781f; background: rgba(217, 154, 91, .18); }
.me-badge.done { color: #3e7d52; background: rgba(92, 184, 138, .18); }
.me-badge.revise { color: #4a6fa5; background: rgba(90, 130, 189, .18); }
.me-fb-text { font-size: .9rem; color: var(--ink); line-height: 1.5; }

/* feedback */
/* Every single-column form grid below uses `minmax(0, 1fr)` rather than the
   default implicit column. An implicit column's minimum is `auto` = the widest
   item's MIN-content width, and some form controls have a min-content they
   refuse to shrink below -- `input[type=file]` most of all, since its button
   plus "No file chosen" is unbreakable text. On a narrow phone that forced the
   column wider than main's content box, so the file input AND the width:100%
   textarea riding the same column both spilled past the right padding to the
   screen edge (Jonah's report, with screenshot). `minmax(0, 1fr)` drops that
   floor so the column tracks the container instead; the max-width guard below
   then keeps individual controls inside it. */
.feedback-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: .8rem; max-width: 720px; }
.fb-identity { font-family: system-ui, sans-serif; font-size: .9rem; color: var(--muted); }
.fb-own-profile { font-size: .85rem; margin: .2rem 0 0; }
.feedback-form label { font-family: system-ui, sans-serif; font-size: .85rem; font-weight: 600; }
.feedback-form textarea { min-height: 160px; resize: vertical; width: 100%; box-sizing: border-box; }
.fb-backlog-wrap { display: grid; grid-template-columns: minmax(0, 1fr); gap: .7rem; }
.fb-backlog-wrap input, .fb-backlog-wrap select { width: 100%; box-sizing: border-box; }
.fb-backlog-hint { margin: 0; font-size: .88em; }
.fb-optional { font-weight: 400; color: var(--muted); font-size: .85em; }
/* Screenshot attach on "general" feedback (Item 4) -- up to FB_IMAGE_MAX_COUNT
   per submission, so both the compose-time preview (one .fb-image-thumb-row per
   selected file, each with its own remove button) and the submitted view (one
   .fb-image-thumb-row holding every attached thumbnail) need to wrap rather
   than overflow. */
.fb-image-wrap { display: grid; grid-template-columns: minmax(0, 1fr); gap: .5rem; }
.fb-image-preview { display: flex; flex-direction: column; gap: .5rem; }
.fb-image-thumb-row { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; }
.fb-thumb {
  max-width: 140px;
  max-height: 140px;
  border-radius: 6px;
  margin-top: .4rem;
  display: block;
  object-fit: cover;
  border: 1px solid var(--line);
}
.fb-image-remove { color: var(--muted); font-size: .82rem; }

/* Item 3 of the same report: the attach-screenshots control was a raw
   `input[type=file]`, so the picker button rendered in the browser's default
   chrome -- a small grey system button, the only one on the site that didn't
   look like the site. `::file-selector-button` restyles it in place, keeping the
   native picker behaviour, and matches .btn-ghost's quiet bordered look so it
   reads as secondary to the real Submit button below it. */
.feedback-form input[type="file"] {
  width: 100%;
  padding: .4rem .5rem;
  cursor: pointer;
}
.feedback-form input[type="file"]::file-selector-button {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: .9rem;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: .35rem .8rem;
  margin-right: .7rem;
  cursor: pointer;
}
.feedback-form input[type="file"]::file-selector-button:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.notice {
  font-family: system-ui, sans-serif;
  font-size: .85rem;
  padding: .6rem .8rem;
  border-radius: 8px;
  margin-top: .6rem;
}
.notice.ok { background: #e3f0e3; color: #2e5e2e; }
.notice.err { background: #f3dede; color: #7a2a2a; }
.hint { font-family: system-ui, sans-serif; font-size: .82rem; color: var(--muted); }

/* reactions: thumbs (up/meh/down) + an optional comment, per part, per Setup,
   and per story. Deliberately quiet — a private aside, not another vote widget
   competing for attention. */
.reaction-widget {
  font-family: system-ui, sans-serif;
  margin: .6rem 0 1.6rem;
  padding: .6rem .9rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
}
/* The story-level one sits right under the title, so it reads as a header
   control rather than a between-parts aside — same widget, a touch bolder. */
.reaction-story {
  margin: 0 0 1.8rem;
  background: var(--bg);
  border-style: dashed;
}
.reaction-row {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
}
.reaction-label { font-size: .88rem; color: var(--muted); margin-right: auto; }
.reaction-thumbs { display: flex; gap: .3rem; }
.reaction-thumb {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.15rem;
  height: 2.15rem;
  padding: 0;
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  filter: grayscale(1);
  opacity: .55;
}
.reaction-thumb:hover { opacity: .85; }
.reaction-thumb.active { filter: none; opacity: 1; border-color: var(--accent); background: var(--accent-soft); }
.reaction-comment-toggle {
  font: inherit;
  font-size: .85rem;
  cursor: pointer;
  background: transparent;
  border: none;
  color: var(--accent);
  text-decoration: underline;
  padding: 0;
}
.reaction-comment-box { margin-top: .6rem; }
.reaction-comment {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  font-size: .92rem;
  padding: .55rem .7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  resize: vertical;
}
.reaction-comment-actions { margin-top: .5rem; }
.reaction-comment-actions .btn { margin-top: 0; }

/* patch notes */
.patchnotes { max-width: 760px; }
.patchnotes .prose h2 {
  margin-top: 2rem;
  padding-bottom: .3rem;
  border-bottom: 1px solid var(--line);
}
.patchnotes .prose h3 {
  margin-top: 1.4rem;
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
}
/* Collapsible version blocks: newest opens by default, history stays folded. */
.pn-intro { margin-bottom: .3rem; }
.pn-version { border-top: 1px solid var(--line); }
.pn-version:first-of-type { border-top: none; }
.pn-summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: .5rem;
  font-weight: 700;
  font-size: 1.15rem;
  padding: .75rem 0;
  color: var(--ink);
}
.pn-summary::-webkit-details-marker { display: none; }
.pn-summary::before {
  content: "▸";
  color: var(--accent);
  font-size: .85em;
}
.pn-version[open] > .pn-summary::before { content: "▾"; }
.pn-version[open] > .pn-summary { border-bottom: 1px solid var(--line); }
.pn-body { padding: .2rem 0 1.2rem; }
.pn-body h3:first-child { margin-top: .6rem; }

/* End-of-story Awards ceremony — the "bonus awards" card on its own Awards tab.
   Gold-trimmed to feel celebratory; the ceremony body is plain prose. Authored
   markdown has no title heading of its own (the page supplies "🏅 Awards"), but
   h1/h2 styling is kept in case an author ever reaches for a section break. */
.awards-box {
  background: var(--paper);
  border: 1px solid var(--line);
  border-top: 3px solid var(--gold);
  border-radius: 8px;
  box-shadow: var(--shadow);
  padding: 1.1rem 1.4rem 1.3rem;
  margin-bottom: 1.4rem;
}
.awards-body.prose > :first-child { margin-top: 0; }
.awards-body.prose > :last-child { margin-bottom: 0; }
/* Each award: the category name (h3/strong) reads as the "trophy" line, the
   plain sentence beneath it as the citation. */
.awards-body.prose h1,
.awards-body.prose h2 {
  color: var(--gold);
  border-bottom: 1px solid var(--gold-soft);
  padding-bottom: .35rem;
}
.awards-body.prose h3 { color: var(--accent); margin-top: 1.1rem; }
.awards-body.prose strong { color: var(--ink); }
.awards-body.prose ul { list-style: none; padding-left: 0; }
.awards-body.prose ul li {
  border-left: 3px solid var(--gold-soft);
  padding: .15rem 0 .15rem .8rem;
  margin: .6rem 0;
}
/* "Nothing awarded yet" teaser (Ceremonies pane's empty state). */
.awards-teaser p { color: var(--ink); }
.awards-teaser p.muted { color: var(--muted); }

/* Awards → Hall of Fame: sidebar panes (Ceremonies / Characters / Belts).
   Reuses .pane-nav/.pane-navbtn/.pane-main verbatim (style.css ~497-519, the
   same layout Backstage's sidebar uses) — these rules style each pane's own
   content inside .pane-main. Replaced the old single-ceremony page + its
   collapsible "Full history & belts" <details>. */
.awards-pane-title {
  font-family: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  color: var(--gold);
  margin: 0 0 .2rem;
  font-size: 1.15rem;
}
.awards-pane-sub { margin: 0 0 1rem; font-size: .88rem; color: var(--muted); }

/* Ceremonies list + Characters leaderboard share the same clickable-row shape. */
.awards-cer-list,
.awards-board { list-style: none; margin: 0 0 1.2rem; padding: 0; display: grid; gap: .35rem; }
.awards-cer-row,
.awards-board-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem;
  padding: .5rem .7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  background: var(--paper);
}
.awards-cer-row:hover,
.awards-board-row:hover { border-color: var(--accent); }
.awards-cer-row.active,
.awards-board-row.active { border-color: var(--accent); background: var(--accent-soft); }
.awards-cer-count,
.awards-board-count { font-family: ui-monospace, monospace; font-size: .8rem; color: var(--muted); }
.awards-latest-tag {
  font-family: system-ui, sans-serif;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--accent);
  background: var(--accent-soft);
  padding: .08rem .4rem;
  border-radius: 999px;
  margin-left: .3rem;
}
/* Detail view under either list (a ceremony's full text, or a character's
   award history). Reuses .awards-box/.awards-body.prose for the ceremony case. */
.awards-detail { border-top: 1px solid var(--line); padding-top: 1rem; }
.awards-detail .awards-box { margin-bottom: 0; }
.awards-detail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: .3rem;
}
.awards-detail-head h5 {
  font-family: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  font-size: 1.1rem;
  margin: 0;
  color: var(--ink);
}

/* Characters: name + belt dots in the leaderboard row, badges + award list
   in the detail view. */
.awards-board-name { font-weight: 600; display: flex; align-items: center; gap: .45rem; }
.awards-belt-dot { font-size: .82rem; }
.awards-belt-badges { display: flex; gap: .4rem; flex-wrap: wrap; margin: .5rem 0 1rem; }
.awards-belt-badge {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: .78rem;
  color: var(--gold);
  background: var(--gold-soft);
  border: none;
  border-radius: 999px;
  padding: .18rem .6rem;
  cursor: pointer;
}
.awards-belt-badge:hover { filter: brightness(1.1); }
.awards-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.awards-item { border-left: 3px solid var(--gold-soft); padding: .3rem 0 .3rem .8rem; }
.awards-item-cat { font-weight: 600; color: var(--ink); }
.awards-item-src {
  font-family: ui-monospace, monospace;
  font-size: .74rem;
  color: var(--accent);
  display: block;
  margin: .1rem 0 .25rem;
}
.awards-item-cite { font-size: .9rem; color: var(--muted); }

/* Belts: one card per anchor. Emoji + title header, the record explained as
   regular readable text (not a muted caption), the current holder as its own
   prominent panel, and a collapsed-by-default holder-history timeline. */
.awards-belt-list { display: grid; gap: 1.1rem; }
.awards-belt-card {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 1.1rem 1.2rem;
  background: var(--paper);
}
.awards-belt-card-head { display: flex; align-items: center; gap: .6rem; }
.awards-belt-emoji { font-size: 1.5rem; line-height: 1; }
.awards-belt-title {
  font-family: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  font-size: 1.15rem;
  color: var(--gold);
  margin: 0;
}
.awards-belt-record { font-size: .98rem; color: var(--ink); margin: .4rem 0 .9rem; line-height: 1.5; }
.awards-belt-current-panel {
  background: var(--accent-soft);
  border: 1px solid var(--gold-soft);
  border-radius: 8px;
  padding: .75rem .9rem;
  margin-bottom: .7rem;
}
.awards-belt-current-label {
  font-family: system-ui, sans-serif;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--muted);
  margin-bottom: .2rem;
}
.awards-belt-current-name {
  font-family: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  font-size: 1.3rem;
  color: var(--ink);
  line-height: 1.2;
}
.awards-belt-current-since { font-family: system-ui, sans-serif; font-size: .86rem; color: var(--muted); margin-top: .15rem; }
.awards-belt-toggle {
  font: inherit;
  font-family: system-ui, sans-serif;
  font-size: .8rem;
  color: var(--accent);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}
.awards-timeline { list-style: none; margin: .8rem 0 0; padding: 0; border-top: 1px dashed var(--line); display: none; }
.awards-timeline.shown { display: grid; }
.awards-timeline li { padding: .65rem 0; border-bottom: 1px dashed var(--line); font-size: .88rem; }
.awards-timeline li:last-child { border-bottom: none; }
.awards-tl-story { font-family: system-ui, sans-serif; font-weight: 600; color: var(--accent); font-size: .84rem; margin-bottom: .2rem; }
.awards-tl-who { color: var(--ink); font-weight: 600; }
.awards-tl-note { color: var(--muted); display: block; margin-top: .15rem; font-size: .85rem; }
