/* DebateDaily.Today — Midnight + light Memphis accents (dark default, light theme supported) */
:root {
  --base: #0F1117;
  --card: #181B24;
  --card2: #14161d;
  --line: #2b3040;
  --line2: #22262f;
  --text: #E9EBF2;
  --muted: #9096A6;
  --brand: #6C5CE7;
  --teal: #19C2B3;
  --coral: #FF6B5A;
  --warn: #FFB13C;            /* staging/caution accent */
  --on-teal: #053b36;         /* legible text on a teal fill */
  --on-coral: #4d160e;        /* legible text on a coral fill */
  --offset: #0a0c12;          /* hard Memphis offset-shadow colour */
  --offset-soft: rgba(10, 12, 18, 0.45);
  --skel: #20242e;
  --accent: #6C5CE7;          /* overridden per category */
  --accent-ink: #ffffff;
  --accent-shadow: #3c3491;
}
html[data-theme="light"] {
  --base: #FBFAF7;
  --card: #ffffff;
  --card2: #f5f3ec;
  --line: #e4e1d7;
  --line2: #eeece5;
  --text: #1B1A2E;
  --muted: #6B6A63;
  --brand: #5B4FE0;
  --teal: #0E9186;
  --coral: #E4573F;
  --warn: #8A5300;
  --on-teal: #001a17;
  --on-coral: #000000;
  --offset: #1b1a2e;
  --offset-soft: rgba(27, 26, 46, 0.28);
  --skel: #e9e6dd;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  background: var(--base);
  color: var(--text);
  font-family: "Inter", system-ui, -apple-system, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  transition: background .2s ease, color .2s ease;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
.disp { font-family: "Space Grotesk", system-ui, sans-serif; }
.muted { color: var(--muted); }
.center-text { text-align: center; }

/* App shell: fixed header + fixed footer, spacers keep content clear.
   --hd-h / --ft-h drive both the chrome and its spacers so they animate in lockstep. */
/* --ft-h is taller than a single text line to fit the tagline + copyright stack
   (added for the legal-entity footer line) above the links row. */
#app { --hd-h: 66px; --ft-h: 84px; display: flex; flex-direction: column; min-height: 100vh; }
#app.collapsed { --hd-h: 48px; --ft-h: 40px; }
.wrap { max-width: 760px; margin: 0 auto; padding: 0 20px; width: 100%; }
main.main { flex: 1 0 auto; padding-bottom: 8px; }
main.center { display: flex; flex-direction: column; justify-content: center; }

@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes shimmer { from { background-position: -400px 0; } to { background-position: 400px 0; } }

/* Header (fixed, collapses on scroll) */
.hd { position: fixed; top: 0; left: 0; right: 0; z-index: 19; height: var(--hd-h);
  background: var(--base); border-bottom: 1px solid var(--line2);
  transition: height .28s cubic-bezier(.4,0,.2,1), background .2s ease; }
.hd-in { display: flex; justify-content: space-between; align-items: center; height: 100%; }
.hd-spacer { height: var(--hd-h); flex: none; transition: height .28s cubic-bezier(.4,0,.2,1); }
.brand { display: flex; align-items: center; gap: 11px; cursor: pointer;
  transform-origin: left center; transition: transform .28s cubic-bezier(.4,0,.2,1); }
#app.collapsed .brand { transform: scale(.82); }
.brand .mark { flex: none; }
.brand .name { font-family: "Space Grotesk"; font-weight: 700; font-size: 22px; color: var(--text); display: flex; align-items: center; }
.brand .name b { color: var(--brand); font-weight: 700; }
.brand .cat-prefix { color: var(--accent); }
.brand .tld { font-family: "Space Grotesk"; font-weight: 500; font-size: 0.7em; color: #fff;
  background: var(--brand); padding: 0 6px; border-radius: 6px; margin-left: 2px; }

.hd nav { display: flex; gap: 16px; align-items: center; font-size: 15px; position: relative; }
.nav-full { display: flex; gap: 16px; align-items: center; transition: opacity .22s ease; }
#app.collapsed .nav-full { opacity: 0; pointer-events: none; }
.nav-full a { color: var(--muted); text-decoration: none; cursor: pointer;
  padding-bottom: 5px; border-bottom: 3px solid transparent; transition: color .15s, border-color .15s; }
.nav-full a.on { color: var(--text); border-bottom-color: var(--accent); }
.nav-full a:hover { color: var(--text); text-decoration: none; }
.iconbtn { background: transparent; border: 1px solid var(--line); color: var(--muted); cursor: pointer;
  width: 34px; height: 34px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; padding: 0; transition: color .15s, border-color .15s; }
.iconbtn:hover { color: var(--text); border-color: var(--muted); }
.iconbtn svg { width: 17px; height: 17px; }

/* Beta notice bar: fixed strip directly under .hd, expands in place. Its height is
   JS-measured into .beta-spacer (syncBetaSpacer() in app.js) — like the mobile footer,
   the panel's wrapped text height isn't a fixed constant, so a CSS var alone can't reserve
   the right space at every viewport width. `top` tracks --hd-h so it stays glued under the
   header through the header's own scroll-collapse animation. */
.beta-bar { position: fixed; top: var(--hd-h); left: 0; right: 0; z-index: 18;
  background: var(--card2); border-bottom: 1px solid var(--line2);
  transition: top .28s cubic-bezier(.4,0,.2,1); }
.beta-spacer { flex: none; transition: height .28s cubic-bezier(.4,0,.2,1); }
.beta-toggle { width: 100%; display: flex; align-items: center; justify-content: center; gap: 6px;
  background: none; border: none; cursor: pointer; padding: 5px 10px;
  font: 700 11px "Space Grotesk", sans-serif; letter-spacing: .06em; color: var(--warn); }
.beta-toggle:hover { opacity: .85; }
.beta-chev { transition: transform .2s ease; flex: none; }
.beta-bar.expanded .beta-chev { transform: rotate(180deg); }
.beta-panel { max-height: 0; overflow: hidden; transition: max-height .28s cubic-bezier(.4,0,.2,1); }
.beta-bar.expanded .beta-panel { max-height: 200px; }
.beta-panel p { margin: 0 auto; padding: 0 16px 10px; max-width: 760px;
  font-size: 13px; line-height: 1.5; color: var(--muted); text-align: center; }
.beta-panel a { color: var(--warn); }
@media (prefers-reduced-motion: reduce) {
  .beta-panel, .beta-chev, .beta-spacer { transition: none; }
}

/* Mobile menu (category pages, small screens) */
.hamburger { display: none; background: transparent; border: 1px solid var(--line); color: var(--text);
  cursor: pointer; width: 34px; height: 34px; border-radius: 999px; align-items: center; justify-content: center; padding: 0; }
.hamburger svg { width: 16px; height: 16px; }
.mobile-menu { display: none; position: absolute; top: 44px; right: 0; z-index: 25; flex-direction: column;
  min-width: 170px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 8px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.25); gap: 2px; }
#app.menu-open .mobile-menu { display: flex; }
.mobile-menu a { color: var(--text); text-decoration: none; cursor: pointer; padding: 9px 10px; border-radius: 7px; font-size: 15px; }
.mobile-menu a.on { color: var(--accent); font-weight: 700; }
.mobile-menu a:hover { text-decoration: none; background: var(--card2); }
.mobile-menu .theme-seg { margin-top: 6px; }
.mobile-menu .lang-select { margin-top: 6px; width: 100%; }
.mobile-menu .menu-divider { height: 1px; background: var(--line); margin: 4px 2px; flex: none; }

/* Segmented control (feed sort, archive layout, theme picker) */
.seg { display: flex; gap: 2px; border: 1px solid var(--line); border-radius: 8px; padding: 2px; background: var(--card2); }
.seg button { font: 500 13px "Inter", sans-serif; padding: 6px 12px; border-radius: 6px; border: none; cursor: pointer;
  background: transparent; color: var(--muted); display: inline-flex; align-items: center; justify-content: center; gap: 6px; transition: background .12s, color .12s; }
.seg button:hover { color: var(--text); }
.seg button.on { background: var(--accent); color: #fff; }
.seg.icons button { padding: 7px 10px; }
.seg svg { width: 16px; height: 16px; }
.seg.theme-seg svg { width: 14px; height: 14px; }

/* Section titles */
.section-title { font-family: "Space Grotesk"; font-weight: 500; font-size: 15px; color: var(--muted);
  margin: 26px 0 12px; letter-spacing: .01em; }

.back-link { display: inline-block; color: var(--muted); font-size: 14px; text-decoration: none;
  margin-top: 14px; cursor: pointer; }
.back-link:hover { color: var(--text); }

/* Mode tabs — a horizontally scrollable chip row rather than wrapping, so an n-mode
   category (today up to 4) never pushes the matchup card down the page on mobile, or on
   a narrowed desktop window. .tabs-scroll-btn is only shown (see .can-scroll-*, set by
   bindTabsScroll() in app.js) when the row actually overflows, and a wheel listener there
   also lets a plain vertical mouse wheel drive the horizontal scroll. No CSS scroll-behavior
   here deliberately — Chrome applies it to *any* scrollLeft change, including the instant
   restore bindTabsScroll() does after a mode switch re-renders #view, which made that
   restore visibly animate/slide instead of snapping back. The scroll buttons opt into
   smooth scrolling explicitly via scrollBy({behavior:"smooth"}) instead. */
.tabs-wrap { position: relative; margin: 16px 0 18px; }
.tabs { display: flex; gap: 8px; flex-wrap: nowrap; overflow-x: auto; margin: 0;
  -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs-scroll-btn { position: absolute; top: 50%; transform: translateY(-50%); width: 26px; height: 26px;
  border-radius: 50%; border: 1px solid var(--line); background: var(--card2); color: var(--muted);
  cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 14px;
  line-height: 1; opacity: 0; pointer-events: none; transition: opacity .15s; z-index: 1; }
.tabs-scroll-btn:hover { color: var(--text); border-color: var(--muted); }
.tabs-scroll-btn.prev { left: -6px; }
.tabs-scroll-btn.next { right: -6px; }
.tabs-wrap.can-scroll-left .tabs-scroll-btn.prev,
.tabs-wrap.can-scroll-right .tabs-scroll-btn.next { opacity: 1; pointer-events: auto; }
.tab { font-size: 14px; padding: 8px 15px; border-radius: 999px; border: 1px solid var(--line);
  color: var(--muted); cursor: pointer; background: var(--card2); transition: all .15s;
  white-space: nowrap; flex: 0 0 auto; }
.tab:hover { color: var(--text); border-color: var(--muted); }
.tab.on { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); font-weight: 700; }

/* Matchup card */
.card { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 18px 20px; animation: fade .28s ease; }
.card-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.theme-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.theme { font-family: "Space Grotesk"; font-weight: 700; font-size: 15px; letter-spacing: .02em;
  text-transform: uppercase; color: var(--accent); }
.timer { font-size: 13px; color: var(--muted); white-space: nowrap; }

/* Handoff 29 — muted "Sample" pill on launch-seeded example content (matchups.is_sample).
   Never hardcoded: only ever rendered when the server-side is_sample flag is true, so it
   can't drift onto real days. Low-key on purpose — same neutral tokens as .soon-pill,
   not an accent colour, since this is a caveat, not a feature. */
.sample-tag { display: inline-flex; align-items: center; flex: none; background: var(--line);
  color: var(--muted); font-family: "Space Grotesk"; font-weight: 700; font-size: 10px;
  letter-spacing: .03em; text-transform: uppercase; padding: 2px 7px; border-radius: 999px;
  cursor: help; }

/* A category's full third-party attribution (e.g. TMDB's required notice + logo) — lives
   here, in normal document flow at the bottom of the matchup content, rather than the
   fixed footer. It used to be appended to the footer's tagline line, but that line's
   column width is capped at .wrap's 760px max-width regardless of viewport, so long
   attribution text could wrap onto an extra line inside the fixed-height footer at ANY
   width, not just a narrow range — this sidesteps that whole class of bug. */
.content-attribution { margin-top: 16px; font-size: 11px; color: var(--muted); line-height: 1.5; }
.content-attribution-logo { height: 10px; width: auto; vertical-align: -1px; opacity: .85; margin-right: 3px; }

/* align-items: stretch (grid default) so a longer title in one tile grows that
   tile's sibling to match, rather than the shorter one floating mid-height. */
.tiles { display: grid; grid-template-columns: 1fr auto 1fr; gap: 14px; align-items: stretch; margin: 16px 0 6px; }
.tile { position: relative; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--card2);
  cursor: pointer; text-align: left; padding: 0; color: inherit; font: inherit; box-shadow: 4px 4px 0 var(--offset);
  transition: transform .12s ease, box-shadow .3s ease; display: flex; flex-direction: column;
  /* Grid/flex items default to min-width:auto, which lets a child's intrinsic content size
     (here, a lazy-loaded <img>'s natural pixel width before it's sized by CSS) push this
     item wider than its 1fr track — Chrome factors that natural width into the min-content
     contribution of a replaced element, Safari doesn't, so only Chrome mis-sizes some covers. */
  min-width: 0; }
.tile:disabled { cursor: default; }
/* Clip the hover zoom to the cover's own box so it can't bleed into the title below —
   .tile's own overflow:hidden only clips at the tile's outer edge, not this seam.
   Explicit width (not just block-stretch) so this box never sizes from the <img>'s
   own intrinsic dimensions in Chrome — see .tile's min-width:0 comment above. */
.tile .cover-wrap { position: relative; overflow: hidden; width: 100%; }
.tile .cover { width: 100%; aspect-ratio: 2 / 3; object-fit: cover; display: block; background: var(--line2); transition: transform .3s ease, filter .4s ease; }
/* Blur-up: a cover <img> starts blurred and sharpens in once it's actually loaded
   (onload strips this class — see tileHTML()/coverGridCellHTML()/coverImg() in
   app.js), softening the pop-in on a slow connection instead of a sudden blank-to-
   photo snap. A cached/instant image never visibly blurs at all — the class is gone
   before the first paint most of the time. Unscoped so the one rule covers every
   context that opts in (main tile, Archive grid, Archive list thumbnails) — each
   context supplies its own `transition: filter …` alongside its existing transitions
   (object-fit/background are already per-context) so the blur→sharp animates smoothly
   wherever it's used, not just here. */
.blur-load { filter: blur(16px); }
@media (prefers-reduced-motion: reduce) {
  .tile .cover, .arc-card .covers img, .arc-thumbs img { transition: none; }
}
.tile:hover .cover { transform: scale(1.05); }
.tile:not(:disabled):hover { transform: translateY(-3px); }
/* Title-card fallback for a missing cover, OR two sides that happen to share the exact
   same cover (e.g. two Books characters from the same source work, which has only one
   cover) — an image alone can't distinguish those, so the option's own name is shown
   instead of/over it. Used both on the main matchup tile and the (smaller) Archive
   grid card — unscoped so both contexts share it; "solid" fills whatever box its
   parent already sizes (the Archive grid's cover span already has aspect-ratio: 2/3;
   the main tile's cover-wrap doesn't, so it gets an explicit one of its own further
   below). "scrim" layers on top of a real (shared) <img> with a dark gradient for
   legibility instead, taking no box of its own. Left-aligned + vertically centered per
   design; the inner <span> (not this div) gets the line-clamp, since
   -webkit-line-clamp needs display:-webkit-box, which can't coexist on the same
   element as this flex centering. */
.cover-title-overlay { display: flex; align-items: center; justify-content: flex-start;
  padding: 14px; box-sizing: border-box; text-align: left; }
.cover-title-overlay span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; line-clamp: 4;
  overflow: hidden; font-family: "Space Grotesk"; font-weight: 700; line-height: 1.2;
  font-size: 20px; color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.45); }
.cover-title-overlay.small span { font-size: 16px; }
.cover-title-overlay.tiny span { font-size: 13px; -webkit-line-clamp: 5; line-clamp: 5; }
.cover-title-overlay.solid { width: 100%; height: 100%; }
.cover-title-overlay.solid.side-a { background: linear-gradient(135deg, var(--teal), color-mix(in srgb, var(--teal) 45%, black)); }
.cover-title-overlay.solid.side-b { background: linear-gradient(135deg, var(--coral), color-mix(in srgb, var(--coral) 45%, black)); }
.cover-title-overlay.scrim { position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(100deg, rgba(15,17,23,.88) 0%, rgba(15,17,23,.45) 55%, rgba(15,17,23,0) 100%); }
/* Main matchup tile only: .cover-wrap has no height of its own (it normally comes from
   the <img class="cover">'s own aspect-ratio, in .tile .cover below) — give the "solid"
   fallback the same ratio so it isn't collapsed to 0 height when there's no <img> at all. */
.tile .cover-title-overlay.solid { aspect-ratio: 2 / 3; }
/* Archive grid card: much smaller box, so a compact type scale + tighter clamp. */
.cover-title-overlay.compact { padding: 6px; }
.cover-title-overlay.compact span { font-size: 12px; line-height: 1.15; -webkit-line-clamp: 3; line-clamp: 3; }
.cover-title-overlay.compact.small span { font-size: 11px; }
.cover-title-overlay.compact.tiny span { font-size: 10px; -webkit-line-clamp: 4; line-clamp: 4; }
/* flex:1 lets the meta block absorb the extra height when .tiles stretches this
   tile to match a taller sibling, keeping both tiles' bottom edges aligned. */
.tile .meta { padding: 10px 12px; flex: 1; }
.tile .meta .t { font-family: "Space Grotesk"; font-weight: 700; font-size: 15px; line-height: 1.25; }
.tile .meta .s { font-size: 12px; color: var(--muted); margin-top: 2px; }
/* Full-colour Memphis offset shadows */
.tile.side-a { box-shadow: 4px 4px 0 var(--teal); }
.tile.side-b { box-shadow: 4px 4px 0 var(--coral); }
.tile.side-a:not(:disabled):hover { box-shadow: 5px 7px 0 var(--teal); }
.tile.side-b:not(:disabled):hover { box-shadow: 5px 7px 0 var(--coral); }
/* Inconclusive (Handoff 22) — trim only, not the cover art itself (matches the Archive
   grid's covers, which also stay full-colour and just drop the win-border). */
.tile.inconclusive.side-a, .tile.inconclusive.side-b { box-shadow: 4px 4px 0 var(--muted); }
/* Selected before voting */
.tile.pick-a { border: 2px solid var(--teal); }
.tile.pick-b { border: 2px solid var(--coral); }
/* Winning side after reveal */
.tile.win-a { border: 4px solid var(--teal); }
.tile.win-b { border: 4px solid var(--coral); }
/* Overlay badges */
/* Stacked (not side-by-side) so "✓ Your pick" + "Leading"/"Winner" never collide on
   narrow tiles — sits over the cover art, clear of the .meta text below. */
.tile .badge-stack { position: absolute; top: 8px; left: 8px; z-index: 2;
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.tile .badge { font-family: "Space Grotesk"; font-weight: 700;
  font-size: 11px; padding: 3px 8px; border-radius: 999px; }
.tile .badge.pick { display: inline-flex; align-items: center; gap: 4px; box-shadow: 0 1px 4px rgba(0,0,0,0.3); }
.tile .badge.pick.a { background: var(--teal); color: var(--on-teal); }
.tile .badge.pick.b { background: var(--coral); color: var(--on-coral); }
.tile .badge.lead { background: rgba(15,17,23,0.78); color: #fff; }
/* align-self: center opts the badge out of .tiles' stretch (added for equal tile heights)
   so it centers on the row instead of stretching full-height and pinning to the top. */
.vs { font-family: "Space Grotesk"; font-weight: 700; font-size: 13px; color: var(--base);
  background: var(--text); width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  align-self: center; }

/* Vote bar with Memphis black split */
.bar { display: flex; height: 26px; border-radius: 7px; overflow: hidden; margin-top: 15px; box-shadow: 3px 3px 0 var(--offset); }
.bar .a, .bar .b { font-family: "Space Grotesk"; font-weight: 700; font-size: 15px; letter-spacing: .01em;
  display: flex; align-items: center; min-width: 36px; transition: width .5s ease; }
.bar .a { background: var(--teal); color: var(--on-teal); padding-left: 10px; border-right: 5px solid var(--base); }
.bar .b { background: var(--coral); color: var(--on-coral); justify-content: flex-end; padding-right: 10px; }
/* Inconclusive (Handoff 22) — same desaturated treatment as the Archive's bar, so a
   no-verdict day never reads as a real, confident split on the matchup page either. */
.bar.inconclusive .a, .bar.inconclusive .b { background: var(--muted); filter: grayscale(1); opacity: .45; }
.votes-total { font-size: 12px; color: var(--muted); margin-top: 7px; }
.share-row { margin-top: 14px; text-align: center; }
.share-cta { display: inline-flex; }

/* Handoff 36: "first take" celebration — a one-shot pop-in note on the results reveal,
   inserted straight after .bar by celebrateFirstTake() in app.js (server-confirmed
   is_first, never client-inferred). .pop is only added when motion is allowed; without
   it the note/pill just appear in place, no animation, no sheen — satisfying
   prefers-reduced-motion. The animated teal→brand→coral gradient lives on the OUTER
   .first-take-note as a thick padded frame; the text sits on an inner .first-take-pill
   with a solid --card2 fill, so it's always on the ordinary --text-on-card2 pairing used
   everywhere else in the app (>15:1, both themes) — never directly on the gradient
   itself, which measured as low as 1.87:1 for --text depending on theme and which
   segment the text landed over, well under WCAG AA's 4.5:1. */
.first-take-note { margin-top: 10px; padding: 5px; border-radius: 7px;
  background: linear-gradient(90deg, var(--teal), var(--brand), var(--coral), var(--teal));
  background-size: 300% 100%; }
.first-take-note.pop { animation: first-take-pop .5s cubic-bezier(.34,1.56,.64,1) both, first-take-sheen 2.2s ease-in-out .5s 1; }
.first-take-pill { display: block; padding: 6px 14px; border-radius: 4px; text-align: center;
  background: var(--card2); color: var(--text); font-size: 12.5px; font-weight: 700; }
@keyframes first-take-pop {
  0% { opacity: 0; transform: translateY(-4px) scale(.94); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes first-take-sheen { 0% { background-position: 0% 0; } 100% { background-position: 200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .first-take-note.pop { animation: none; opacity: 1; transform: none; background-position: 0% 0; }
}
.first-take-confetti { position: fixed; inset: 0; pointer-events: none; z-index: 60; }
@media (prefers-reduced-motion: reduce) {
  .first-take-note.pop { animation: none; opacity: 1; transform: none; }
}

/* Toast (share "Link copied") — sits above the fixed footer, dismisses itself. */
.toast { position: fixed; left: 50%; bottom: calc(var(--ft-h, 84px) + 16px); z-index: 30;
  transform: translate(-50%, 8px); background: var(--card); border: 1px solid var(--line); color: var(--text);
  font: 500 13px "Inter", sans-serif; padding: 9px 16px; border-radius: 999px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.25); opacity: 0; pointer-events: none;
  transition: opacity .2s ease, transform .2s ease; }
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* Justification form */
.form { margin-top: 18px; }
.form textarea { width: 100%; background: var(--card2); color: var(--text); border: 1px solid var(--line);
  border-radius: 10px; padding: 12px 13px; font: 400 15px "Inter"; resize: vertical; min-height: 82px; }
.form textarea:focus { outline: none; border-color: var(--accent); }
.form .row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 9px; flex-wrap: wrap; }
.cf-turnstile { margin-top: 12px; }
.count-row { display: flex; justify-content: flex-end; margin-top: 5px; }
.form input[type=text] { background: var(--card2); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: 9px 11px; font: 400 14px "Inter"; }
.count { font-size: 13px; color: var(--muted); }
.count.warn { color: var(--coral); }
.chk { display: flex; align-items: center; gap: 7px; font-size: 14px; color: var(--muted); cursor: pointer; }
.chk-group { display: inline-flex; align-items: center; gap: 6px; }
.spoiler-info { display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--line); background: transparent;
  color: var(--muted); font-size: 12px; line-height: 1; padding: 0; cursor: pointer; }
.spoiler-info:hover { color: var(--text); border-color: var(--muted); }
.spoiler-info[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
.hint { font-size: 13px; color: var(--muted); margin-top: 9px; }
.hint code { background: var(--card2); padding: 1px 5px; border-radius: 4px; font-size: 12px; }
.hint b.na { color: var(--teal); }
.hint b.nb { color: var(--coral); }

.btn { font-family: "Space Grotesk"; font-weight: 700; font-size: 15px; border: none; cursor: pointer;
  background: var(--accent); color: var(--accent-ink); padding: 11px 18px; border-radius: 9px; box-shadow: 3px 3px 0 var(--accent-shadow); transition: transform .06s; }
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 var(--accent-shadow); }
.btn:disabled { opacity: .5; cursor: default; box-shadow: none; transform: none; }

/* Justifications feed */
.feed { margin-top: 22px; padding-bottom: 30px; }
.feed-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; }
.feed-head h2 { font-family: "Space Grotesk"; font-weight: 500; font-size: 17px; margin: 0; }
/* Inconclusive (Handoff 22) — replaces the whole feed section, so it gets its own
   box (same border/radius/background language as a .jf take card) rather than
   sitting bare under a "Why people picked" heading that no longer applies. */
.inconclusive-note { border: 1px solid var(--line); border-radius: 10px; padding: 16px;
  background: var(--card2); color: var(--muted); font-size: 15px; text-align: center; }
.jf { border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; margin-bottom: 10px; background: var(--card2); animation: fade .28s ease; }
.jf .top { display: flex; justify-content: space-between; align-items: center; font-size: 13px; margin-bottom: 6px; }
.jf .for-a { color: var(--teal); font-weight: 500; }
.jf .for-b { color: var(--coral); font-weight: 500; }
.jf .who-wrap { display: flex; align-items: center; gap: 6px; }
.jf .who { color: var(--muted); }
.jf .body { font-size: 15px; color: var(--text); }
.readmore { display: block; margin-top: 4px; font: 500 13px "Inter"; background: none; border: none;
  padding: 0; color: var(--accent); cursor: pointer; }
.jf .react { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.rx { display: flex; align-items: center; gap: 5px; background: transparent; border: 1px solid var(--line);
  color: var(--muted); border-radius: 999px; padding: 5px 11px; font: 500 13px "Inter"; cursor: pointer; transition: all .12s; }
.rx:hover { border-color: var(--muted); color: var(--text); }
.rx.up.on { color: var(--teal); border-color: var(--teal); }
.rx.down.on { color: var(--coral); border-color: var(--coral); }
.net { font-size: 13px; color: var(--muted); margin-right: 2px; }
/* Icon-only actions read better as plain glyphs than as bordered pills (which suggested
   they were labelled buttons like the vote counts) — border/background only appear on hover
   as a focus cue, not as a permanent outline. */
.rx.share, .rx.report { margin-left: 0; border-color: transparent; background: transparent; padding: 5px 7px; opacity: .6; }
.rx.share { margin-left: auto; }
.rx.share:hover, .rx.report:hover { opacity: 1; border-color: var(--line); background: var(--card2); }
.rx.share svg, .rx.report svg { width: 16px; height: 16px; }
.reported-note { margin-left: auto; font-size: 13px; color: var(--muted); }
.jf.reported { opacity: .55; }
.more { display: block; width: 100%; font: 600 14px "Space Grotesk", sans-serif; padding: 11px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--card2); color: var(--text); cursor: pointer; transition: border-color .12s; }
.more:hover { border-color: var(--muted); }

/* Spoiler masking */
.spoiler { color: transparent; border-radius: 3px; cursor: pointer; padding: 0 2px; user-select: none;
  box-shadow: inset 0 0 0 99px var(--muted); }
.spoiler.shown { color: inherit; box-shadow: none; user-select: auto; cursor: auto; }
.spoiler-mask { filter: blur(6px); user-select: none; }
.reveal-btn { display: inline-block; margin-top: 6px; font-size: 13px; color: var(--accent); cursor: pointer; }

/* Hub */
.hero { text-align: center; padding: 20px 0 4px; animation: fade .28s ease; }
.hero h1 { font-family: "Space Grotesk"; font-weight: 700; font-size: 36px; line-height: 1.12; margin: 16px 0 12px; }
.hero p { color: var(--muted); font-size: 17px; max-width: 480px; margin: 0 auto; }
.how { list-style: none; padding: 0; margin: 12px 0 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.how .step { display: flex; gap: 11px; align-items: flex-start; background: transparent; border: none; padding: 4px 2px; }
.how .step .n { flex: none; width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: var(--accent-ink);
  font-family: "Space Grotesk"; font-weight: 700; font-size: 14px; display: flex; align-items: center; justify-content: center; }
.how .step b { display: block; font-family: "Space Grotesk"; font-weight: 500; font-size: 15px; color: var(--text); }
.how .step span { display: block; font-size: 13.5px; color: var(--muted); margin-top: 2px; }

.cat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; padding-bottom: 30px; }
.cat { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--card); position: relative;
  display: flex; flex-direction: column; color: inherit; }
.cat.live { cursor: pointer; box-shadow: 4px 4px 0 var(--offset-soft); transition: transform .12s ease, box-shadow .12s ease; }
.cat.live:hover { transform: translateY(-3px); text-decoration: none; }
.cat .strip { height: 6px; }
.cat .in { padding: 15px 16px; display: flex; flex-direction: column; flex: 1; }
.cat h3 { font-family: "Space Grotesk"; font-weight: 700; font-size: 18px; margin: 0; }
.cat p { font-size: 13px; color: var(--muted); margin: 5px 0 14px; }
.cat.soon { opacity: .7; }
.cat.soon .in { padding-bottom: 15px; }
/* Card CTA anchors to the card's bottom edge even when a taller sibling in the same
   grid row stretches this card — margin-top:auto pushes it down within the flex column. */
.cat .play { display: inline-block; align-self: flex-start; margin-top: auto; font-family: "Space Grotesk"; font-weight: 700; font-size: 13px; padding: 9px 14px; border-radius: 8px; }
.cat .soon-pill { position: absolute; top: 13px; right: 13px; background: var(--line); color: var(--muted);
  font-size: 10px; font-weight: 500; padding: 3px 9px; border-radius: 999px; }

/* Archive — shared genre tag */
.gtag { font-family: "Space Grotesk"; font-weight: 700; font-size: 11px; letter-spacing: .03em;
  text-transform: uppercase; color: var(--accent); }
.arc-head { display: flex; justify-content: space-between; align-items: center; margin: 26px 0 12px; flex-wrap: wrap; gap: 10px; }
.arc-head .section-title { margin: 0; }

/* Archive — list layout */
.arc { display: grid; gap: 10px; animation: fade .28s ease; padding-bottom: 30px; }
.arc-row { display: flex; align-items: center; gap: 13px; border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 13px; background: var(--card2); cursor: pointer; width: 100%; text-align: left; color: inherit; font: inherit; transition: border-color .12s, transform .12s; }
.arc-row:hover { border-color: var(--muted); transform: translateX(2px); }
.arc-thumbs { display: flex; flex: none; }
.arc-thumbs img, .arc-thumbs .noimg { width: 26px; height: 38px; object-fit: cover; border-radius: 4px;
  border: 1px solid var(--line); background: var(--line2); display: block; transition: filter .4s ease; }
.arc-thumbs img:last-child, .arc-thumbs .noimg:last-child { margin-left: -8px; }
/* The 2nd thumbnail's negative margin overlaps it onto the 1st, and plain (static-
   positioned) elements paint in DOM order — so without this, the 2nd/right-hand
   option (option_b) always sits on top of the overlap regardless of which side
   actually won that day. .win (added to whichever side's img/noimg actually won —
   see archiveList()) lifts that one into its own stacking position instead, so the
   winner reads as "in front" — left/right position (option_a/option_b) is unchanged,
   only which one visually overlaps the other. */
.arc-thumbs .win { position: relative; z-index: 1; }
/* Same side-coloured gradient as .cover-title-overlay.solid, without the text overlay —
   at 26x38px there's no room to lay a name in, but a flat grey box still read as
   "broken," not "no cover yet." No .compact/.tiny size classes needed since there's no
   text at all in this variant. */
.arc-thumbs .noimg.side-a { background: linear-gradient(135deg, var(--teal), color-mix(in srgb, var(--teal) 45%, black)); }
.arc-thumbs .noimg.side-b { background: linear-gradient(135deg, var(--coral), color-mix(in srgb, var(--coral) 45%, black)); }
.arc-meta { flex: 1; font-size: 14px; min-width: 0; }
.arc-meta .names b { font-weight: 500; }
.arc-meta .names .na { color: var(--teal); }
.arc-meta .names .nb { color: var(--coral); }
.arc-meta .names.inconclusive .na, .arc-meta .names.inconclusive .nb { color: var(--muted); }
.arc-sub { display: flex; align-items: center; gap: 7px; color: var(--muted); font-size: 13px; margin-top: 2px; flex-wrap: wrap; }
.arc-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; width: 110px; flex: none; }
.arc-bar .a { background: var(--teal); border-right: 4px solid var(--base); }
.arc-bar .b { background: var(--coral); }
/* Handoff 22 — a no-engagement day is desaturated so its (always 50/50) bar reads
   unambiguously as "no verdict", never as a coloured, genuinely-tied result. */
.arc-bar.inconclusive .a, .arc-bar.inconclusive .b { background: var(--muted); filter: grayscale(1); opacity: .45; }

/* Archive — grid layout */
.arc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; animation: fade .28s ease; padding-bottom: 30px; }
.arc-card { display: block; text-align: left; border: 1px solid var(--line); border-radius: 12px; padding: 12px;
  background: var(--card2); cursor: pointer; color: inherit; font: inherit; width: 100%; transition: border-color .12s, transform .12s; }
.arc-card:hover { border-color: var(--muted); transform: translateY(-2px); }
.arc-card .head { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); margin-bottom: 10px; }
.arc-card .covers { display: flex; gap: 6px; margin-bottom: 10px; }
/* Direct-child combinator (not a plain descendant selector) — the cover-title-overlay
   fallback (see .cover-title-overlay above) nests its own <span> for line-clamping
   INSIDE this cell, and a bare ".arc-card .covers span" would match that nested span
   too (any descendant, not just this cell's own wrapper), stamping it with this cell's
   own sizing/background/border and producing a second, smaller boxed-in look nested
   inside the real cell. */
.arc-card .covers > span { position: relative; flex: 1; width: 0; aspect-ratio: 2 / 3; border-radius: 6px; border: 1px solid var(--line);
  background: var(--line2); display: block; overflow: hidden; }
.arc-card .covers > span.win-a { border: 4px solid var(--teal); }
.arc-card .covers > span.win-b { border: 4px solid var(--coral); }
.arc-card .covers img { width: 100%; height: 100%; object-fit: cover; display: block; transition: filter .4s ease; }
.arc-card .titles { font-size: 14px; margin-bottom: 8px; }
.arc-card .titles .na { font-weight: 500; color: var(--teal); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arc-card .titles .vsep { color: var(--muted); font-size: 12px; margin: 2px 0; }
.arc-card .titles .nb { font-weight: 500; color: var(--coral); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arc-card .titles.inconclusive .na, .arc-card .titles.inconclusive .nb { color: var(--muted); }
.arc-card .mini { display: flex; height: 8px; border-radius: 4px; overflow: hidden; margin-bottom: 6px; }
.arc-card .mini .a { background: var(--teal); border-right: 4px solid var(--base); display: block; }
.arc-card .mini .b { background: var(--coral); display: block; }
.arc-card .mini.inconclusive .a, .arc-card .mini.inconclusive .b { background: var(--muted); filter: grayscale(1); opacity: .45; }
.arc-card .foot { font-size: 12px; color: var(--muted); }

/* Skeleton loaders */
.skel { pointer-events: none; }
.sk-pill, .sk-tile, .sk-bar, .sk-row, .sk-line, .sk-jf { background: var(--skel);
  background-image: linear-gradient(90deg, var(--skel) 0, var(--line) 40px, var(--skel) 80px);
  background-size: 800px 100%; animation: shimmer 1.4s infinite linear; border-radius: 8px; }
.sk-pill { width: 110px; height: 34px; border-radius: 999px; }
.sk-tile { aspect-ratio: 2 / 3; border-radius: 12px; }
.sk-bar { height: 26px; margin-top: 15px; }
.sk-row { height: 60px; border-radius: 10px; }
.sk-vs { width: 32px; height: 32px; border-radius: 50%; background: var(--line2); }
.sk-line { display: block; width: 150px; height: 17px; border-radius: 4px; margin-bottom: 14px; }
.sk-jf { height: 76px; border-radius: 10px; margin-bottom: 10px; }

/* Info pages */
.info h1 { font-family: "Space Grotesk"; font-weight: 700; font-size: 28px; }
.info p { font-size: 16px; }
.credits-list { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 8px; }
.credits-list li { font-size: 15px; color: var(--text); border: 1px solid var(--line);
  border-radius: 10px; padding: 11px 14px; background: var(--card2); }
.credit-logo { height: 14px; width: auto; vertical-align: -2px; margin: 0 1px; }

/* Footer (fixed, collapses on scroll; Ko-fi tip floats).
   viewport-fit=cover (index.html) makes env(safe-area-inset-bottom) non-zero on notched/
   home-indicator devices; without accounting for it the fixed bar's content sits behind
   the OS gesture area and gets clipped, and the in-flow spacer under-reserves the gap. */
.ft { position: fixed; left: 0; right: 0; bottom: 0; z-index: 15; background: var(--base);
  border-top: 1px solid var(--line2); box-shadow: 0 -2px 12px rgba(0,0,0,0.18);
  padding-bottom: env(safe-area-inset-bottom, 0px); }
.ft-in { position: relative; height: var(--ft-h); transition: height .28s cubic-bezier(.4,0,.2,1); }
.ft-spacer { height: calc(var(--ft-h) + env(safe-area-inset-bottom, 0px)); flex: none;
  transition: height .28s cubic-bezier(.4,0,.2,1); }
.ft-textrow { position: absolute; inset: 0; display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 12px; padding-right: 150px; font-size: 14px; color: var(--muted);
  transition: opacity .22s ease, transform .22s ease; }
#app.collapsed .ft-textrow { opacity: 0; transform: translateY(-8px); pointer-events: none; }
.ft-lines { display: flex; flex-direction: column; gap: 2px; }
.ft-copy { font-size: 12px; opacity: .75; }
.ft-version { opacity: .7; }
.ft-links { display: flex; gap: 15px; align-items: center; }
.ft a { color: var(--muted); text-decoration: none; }
.ft a:hover { text-decoration: underline; }
.lang-select { font: 500 13px "Inter", sans-serif; color: var(--muted); background: transparent;
  border: 1px solid var(--line); border-radius: 6px; padding: 3px 6px; cursor: pointer; }
.lang-select:hover { color: var(--text); border-color: var(--muted); }
/* ".ft a" (a class+type selector) otherwise outranks a bare ".kofi" class selector and
   overrides its color with the muted footer-link gray — illegible against the amber fill,
   especially in dark mode where --muted is a light tone. ".ft .kofi" (two classes) wins. */
.ft .kofi { position: absolute; top: 50%; left: calc(100% - 20px); transform: translate(-100%, -50%);
  transition: left .32s cubic-bezier(.4,0,.2,1), transform .32s cubic-bezier(.4,0,.2,1), filter .15s ease;
  display: inline-flex; align-items: center; gap: 6px; font-family: "Space Grotesk"; font-weight: 700;
  font-size: 13px; color: #3a2a06; background: #FFC24B; padding: 7px 13px; border-radius: 999px;
  border: 1px solid #a3760e; box-shadow: 2px 2px 0 #9c7413; text-decoration: none; white-space: nowrap; }
.ft .kofi:hover { filter: brightness(1.06); box-shadow: 3px 3px 0 #9c7413; text-decoration: none; }
.ft .kofi:active { filter: brightness(0.97); box-shadow: 1px 1px 0 #9c7413; transform: translate(-100%, -50%) translateY(1px); }
#app.collapsed .ft .kofi:active { transform: translate(-50%, -50%) scale(.86) translateY(1px); }
#app.collapsed .kofi { left: 50%; transform: translate(-50%, -50%) scale(.86); }

/* Staging/preview badge — bottom offset tracks --ft-h (the same variable the footer's
   height transitions on), so it animates in lockstep with the header/footer collapse
   instead of chasing a JS-measured snapshot mid-transition. syncFooterSpacer() overrides
   this inline only on mobile, where the footer's real height diverges from --ft-h. */
.staging-badge { position: fixed; left: 12px; bottom: calc(var(--ft-h) + 12px); z-index: 17;
  display: flex; align-items: center; gap: 6px; background: var(--card); border: 1px solid var(--warn);
  color: var(--warn); font: 700 12px "Space Grotesk", sans-serif; letter-spacing: .04em;
  padding: 6px 10px; border-radius: 999px; box-shadow: 2px 2px 0 var(--offset-soft);
  transition: bottom .28s cubic-bezier(.4, 0, .2, 1); }
.staging-badge button { background: none; border: none; color: inherit; cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0; }

.notice { text-align: center; color: var(--muted); padding: 44px 0; font-size: 16px; }
.err { color: var(--coral); font-size: 13px; margin-top: 8px; min-height: 18px; }

/* Permalink hook page (functions/t/[id].js) — server-rendered, no app.js, so its own
   small static header/footer instead of the SPA's fixed/collapsing chrome. */
.t-shell { display: flex; flex-direction: column; min-height: 100vh; }
.t-hd { padding: 22px 0 8px; }
.t-hd .brand { display: inline-flex; }
.t-page { padding: 18px 0 40px; animation: fade .28s ease; }
.t-eyebrow { font-family: "Space Grotesk"; font-weight: 700; font-size: 12px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 12px; }
.t-headline { font-family: "Space Grotesk"; font-weight: 700; font-size: 34px; line-height: 1.25; margin: 6px 0 22px; }
.t-page .for-a { color: var(--teal); }
.t-page .for-b { color: var(--coral); }
.t-card { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 22px 24px; box-shadow: 4px 4px 0 var(--offset-soft); }
.t-body { font-size: 19px; line-height: 1.55; }
.t-who { color: var(--muted); font-size: 14px; margin: 14px 0 0; }
.t-how { color: var(--muted); font-size: 14px; margin: 24px 0 0; }
.t-others { margin-top: 30px; }
.t-others h2 { font-family: "Space Grotesk"; font-weight: 500; font-size: 15px; color: var(--muted); margin: 0 0 10px; }
.t-other { border: 1px solid var(--line); border-radius: 10px; padding: 11px 14px; margin-bottom: 8px; background: var(--card2); }
.t-other .for { font-size: 12px; font-weight: 500; }
.t-other p { font-size: 14px; margin: 5px 0 0; color: var(--text); }
.t-cta-row { margin-top: 30px; text-align: center; }
.t-cta-row .btn { display: inline-block; padding: 13px 24px; font-size: 16px; position: relative; overflow: hidden; }
/* A periodic light sweep to draw the eye to the CTA — a still page has no other motion. */
.t-cta-row .btn::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 46%;
  background: linear-gradient(115deg, transparent, rgba(255,255,255,0.55), transparent);
  transform: translateX(-220%) skewX(-20deg);
  animation: cta-shimmer 3.6s ease-in-out infinite;
}
@keyframes cta-shimmer {
  0% { transform: translateX(-220%) skewX(-20deg); }
  22% { transform: translateX(320%) skewX(-20deg); }
  100% { transform: translateX(320%) skewX(-20deg); }
}
@media (prefers-reduced-motion: reduce) {
  .t-cta-row .btn::after { animation: none; content: none; }
}
.t-ft { padding: 30px 0 26px; margin-top: 10px; border-top: 1px solid var(--line2);
  font-size: 13px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: center; }
.t-ft a { color: var(--muted); }
.t-ft a:hover { color: var(--text); }
.t-ft-links { display: flex; gap: 14px; flex-wrap: wrap; }

/* 521-760px ("tablet"): the footer's single-row desktop layout (tagline + 5 nav links +
   language select + Ko-fi pill) doesn't fit, but it's still wide enough to keep the
   left-tagline/right-links split rather than switching to mobile's centered stack.
   .ft-textrow already flex-wraps — the actual bug was .ft-in's fixed height + .ft-textrow's
   position:absolute taking it out of flow, so wrapped content silently rendered past the
   fixed footer's (viewport-pinned) bounds instead of growing the box. Letting it size to
   content fixes that. 760px is .wrap's own max-width (see above), not a tuned magic number:
   footer content never gets wider above that, so anything that fits at 760px fits at every
   larger width too — this range can't reappear at 900px, 1200px, etc. */
@media (min-width: 521px) and (max-width: 760px) {
  .ft-in { height: auto; padding: 14px 20px; }
  .ft-textrow { position: static; }
  #app.collapsed .ft-textrow { display: none; }
}

@media (max-width: 520px) {
  body { font-size: 16px; }
  .how { grid-template-columns: 1fr; gap: 10px; }
  .hero h1 { font-size: 28px; }
  .hd nav { gap: 12px; }
  /* Collapse Today/Archive/theme (hub too, not just category pages) into a menu button */
  .nav-full { display: none; }
  .hamburger { display: inline-flex; }
  /* Footer stacks; scrolling down collapses it to just the Ko-fi tip. About/Privacy/
     language move into the mobile menu above instead, so the footer stays slim. */
  .ft-in { height: auto; padding: 14px 20px; text-align: center; }
  .ft-textrow { position: static; inset: auto; flex-direction: column; text-align: center; padding-right: 0; gap: 8px; }
  #app.collapsed .ft-textrow { display: none; }
  .ft-links { display: none; }
  /* Must match ".ft .kofi"'s specificity (two classes) — a bare ".kofi" here would lose
     to the desktop absolute-positioning rule and the pill would stay right-anchored. */
  .ft .kofi { position: static; transform: none; margin: 10px auto 0; }
  /* Mobile: the tip pill sits centred in normal flow already — collapsing should
     only scale it down, never re-translate it (the desktop rule's translate(-50%,-50%)
     would otherwise still apply and shift it). */
  #app.collapsed .ft .kofi { margin-top: 0; transform: scale(.86); }

  /* Category header: shrink the wordmark so "Anime.DebateDaily.Today" plus the
     hamburger button fits on narrow phones without crowding or overflow. */
  .brand .name { font-size: 18px; }
  .brand { gap: 8px; }

  /* Archive list rows: the split bar drops to its own full-width line below the
     thumbnails/title (matches the design's mobile layout) instead of a narrow
     strip squeezed to the right. */
  .arc-row { flex-wrap: wrap; }
  .arc-bar { flex: 1 1 100%; width: auto; }
}

/* Handoff 40: the Social panel reports how far ahead captions are prepared. A day with
   nothing prepared posts nothing, so a gap has to be visible before it arrives. */
.pack-prepared { margin: 6px 0 0; font-size: 13px; }
.pack-prepared.ok { color: var(--ok, #19C2B3); }
.pack-prepared.warn { color: var(--warn, #FFB13C); }
