/* ============================================
   ROLLIT — MAIN STYLESHEET
   ============================================ */

@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=DM+Sans:wght@300;400;500;600&display=swap');

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ---- LINK-ISED CARDS -------------------------------------------------------
   Cards, rows and posters that used to be onclick <div>s are real <a href>s
   now, so a title can be middle-clicked, opened in a new tab, long-pressed to
   copy the link, and followed by a crawler. These two classes make an anchor
   behave exactly like the div it replaced.

   They live HERE, at the top of the first stylesheet every page loads, on
   purpose: single-class rules this early lose to every later rule, so each
   element's own class — and any media query on it — keeps winning as before.
   Author styles still beat the UA sheet's blue-and-underlined default whatever
   the source order, which is the one thing we do need to override.

   Both are plain single-class rules, never `a.rl-link` — the typed form would
   outrank a later `.dpi-titlelink { color: var(--gold) }` and quietly grey out
   every link that styles its own colour. */
.rl-link  { color: inherit; text-decoration: none; }
.rl-block { display: block; }

/* For the cases where the clickable thing is an <img> (or anything whose own
   box we must not disturb): wrap it in an anchor that has no box of its own,
   so the child keeps its exact place in the parent's flex or grid. */
.rl-wrap  { display: contents; }

/* And for a card that contains its own buttons — a poster with Rate and
   Watchlist on it — where wrapping everything in an <a> would nest a button
   inside a link. Instead the link is an invisible sheet over the card, placed
   FIRST in the DOM so every positioned sibling after it (the rank, the stamp,
   the buttons) still paints on top and still takes its own clicks. No z-index
   needed: among positioned siblings, later simply wins. */
.rl-stretch { position: absolute; inset: 0; }

:root {
  --bg: #090a0f;
  --bg2: #0f1018;
  --bg3: #141520;
  --surface: #1a1b28;
  --surface2: #20213a;
  --border: rgba(255,255,255,0.06);
  --border2: rgba(255,255,255,0.11);
  --text: #eeecf5;
  --muted: #7a788e;
  --dim: #3a3850;
  --gold: #e8c96b;
  --toproll: #3ed49a;
  --flop: #e84d63;
  --meh: #e8a83e;
  --info: #6b9fe8;
  /* Prediction accent — a distinct "oracle" violet so a PREDICTION never reads
     as a RATING (which owns gold) at a glance. */
  --predict: #a78bfa;
  --predict-soft: rgba(167,139,250,.13);
  --predict-border: rgba(167,139,250,.42);
  --content-max: 1100px;   /* page content cap; widened on large screens */
  /* Height of the sticky nav. Anything that offsets itself below the nav
     (sticky sub-bars, full-viewport panes) should read this rather than
     hard-coding a number, so a future change to the header height can't
     slide content underneath it. Now one row at every width: the phone nav
     used to wrap to two rows (92px), but the page links moved to the bottom
     tab bar in js/mobilenav.397a2ebd.js. */
  --nav-h: 58px;
  /* Height of the phone-only bottom tab bar (js/mobilenav.397a2ebd.js). Anything fixed
     to the bottom of the viewport must clear this + the safe-area inset. */
  --tabbar-h: 56px;
}

html { scroll-behavior: smooth; overflow-x: hidden; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'DM Sans', sans-serif;
  font-size: 15px;
  line-height: 1.6;
}

/* ---- GLOBAL LINK RESET ---- */
a { color: var(--text); text-decoration: none; }
a:visited { color: var(--text); }
a:hover { color: var(--text); }
a:active { color: var(--text); }

/* ---- NAV ---- */
#main-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 2rem;
  height: var(--nav-h);
  background: rgba(9,10,15,0.97);
  border-bottom: 0.5px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 200;
  backdrop-filter: blur(20px);
}

/* The logo and the "Get the app" pill share this box so that #main-nav keeps
   exactly three flex children — a fourth would redistribute the whole
   space-between header. js/pwa.8b4db3c0.js builds it at runtime (and skips it in the
   installed app), so no page carries the markup. */
.nav-left { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

.nav-install {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  border: 0.5px solid rgba(232,201,107,.32);
  background: rgba(232,201,107,.09);
  color: var(--gold);
  font-family: inherit; font-size: 12px; font-weight: 600;
  text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background .18s, border-color .18s;
}
.nav-install:hover { background: rgba(232,201,107,.17); border-color: rgba(232,201,107,.5); }
.nav-install:visited { color: var(--gold); }
.nav-install i { font-size: 14px; }

/* The header is already tight before the links collapse, and the logo has to
   win. Drop the word first, then the pill — the phone gets the same link in
   the More sheet (js/mobilenav.397a2ebd.js). */
@media (max-width: 1180px) { .nav-install span { display: none; } .nav-install { padding: 5px 8px; } }
@media (max-width: 860px)  { .nav-install { display: none; } }

.logo { display: inline-flex; align-items: center; flex-shrink: 0; text-decoration: none; }
.logo-img { height: 30px; width: auto; display: block; }
.logo-light { display: none; }
[data-theme="light"] .logo-dark { display: none; }
[data-theme="light"] .logo-light { display: block; }
.logo .pk { color: var(--toproll); }
.logo .or { color: var(--dim); font-size: 1.2rem; }
.logo .fl { color: var(--flop); }

/* Shrink-and-scroll at every width, not just under a breakpoint. The icons
   below push the links row's natural width to ~1265px, which is wider than a
   common 1280 laptop once the logo and actions are counted — pinning the
   squeeze to a media query would leave a band of viewports where the nav
   overflowed and dragged the whole document into horizontal scroll. Letting it
   shrink on demand means it stays a plain row whenever there's room and
   degrades only when there genuinely isn't. */
.nav-center { display: flex; align-items: center; gap: 2px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.nav-center::-webkit-scrollbar { display: none; }
/* Each link carries the same glyph its phone tab-bar / More-sheet counterpart
   uses (see js/mobilenav.397a2ebd.js), so a destination looks the same in either nav. */
/* Horizontal padding is down from the pre-icon 13px: the glyph and its gap add
   ~19px per link, and without clawing some back the eight links no longer fit
   a 1280 laptop once a username or the admin shortcut is in the header. */
.nav-center a { display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto; white-space: nowrap; color: var(--muted); text-decoration: none; font-size: 13px; font-weight: 500; padding: 6px 9px; border-radius: 8px; transition: all .18s; }
.nav-center a i { font-size: 14px; line-height: 1; }
.nav-center a:hover { color: var(--text); background: rgba(255,255,255,0.05); }
.nav-center a.active { color: var(--text); background: rgba(255,255,255,0.07); }
.nav-center a:visited { color: var(--muted); }
.nav-center a.active:visited { color: var(--text); }

.nav-right { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

/* ---- SEARCH ---- */
.search-wrap {
  display: flex; align-items: center;
  background: var(--surface); border: 0.5px solid var(--border2);
  border-radius: 10px; padding: 0 10px; gap: 6px; height: 34px;
  position: relative;
}
.search-wrap input { background: none; border: none; outline: none; color: var(--text); font-size: 13px; width: 130px; font-family: inherit; }
.search-wrap input::placeholder { color: var(--dim); }
.search-wrap i { color: var(--muted); font-size: 14px; }

.search-dropdown {
  display: none; position: absolute; top: calc(100% + 8px); left: 0;
  min-width: 320px; background: var(--bg2); border: 0.5px solid var(--border2);
  border-radius: 14px; overflow: hidden; z-index: 300;
  box-shadow: 0 16px 40px rgba(0,0,0,.6);
}
.search-dropdown.open { display: block; }
.search-result-item { display: flex; align-items: center; gap: 12px; padding: 10px 14px; cursor: pointer; transition: background .15s; text-decoration: none; color: var(--text); }
.search-result-item:hover { background: rgba(255,255,255,.05); color: var(--text); }
.search-result-item:visited { color: var(--text); }
.search-thumb { width: 36px; height: 50px; object-fit: cover; border-radius: 5px; flex-shrink: 0; }
.search-thumb-ph { width: 36px; height: 50px; background: var(--surface2); border-radius: 5px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; color: var(--dim); font-size: 14px; }
/* People: circular avatar to distinguish from title posters */
.search-thumb-person { width: 40px; height: 40px; border-radius: 50%; object-position: center top; }
.search-item-title { font-size: 13px; font-weight: 500; color: var(--text); }
.search-item-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.search-loading { padding: 1rem; text-align: center; color: var(--muted); font-size: 13px; }
.search-empty { padding: 1rem; text-align: center; color: var(--dim); font-size: 13px; }

/* ---- BUTTONS ---- */
.btn { padding: 6px 16px; border-radius: 8px; font-size: 13px; font-weight: 500; cursor: pointer; font-family: inherit; border: none; transition: all .18s; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.btn-ghost { background: transparent; border: 0.5px solid var(--border2); color: var(--muted); }
.btn-ghost:hover { color: var(--text); border-color: rgba(255,255,255,0.2); }
.btn-primary { background: var(--gold); color: #1a1000; font-weight: 600; }
.btn-primary:hover { background: #f0d57a; transform: translateY(-1px); }
.btn-lg { padding: 10px 24px; font-size: 14px; border-radius: 10px; }

/* ---- HERO ---- */
.hero { padding: 3.5rem 2.5rem 2.5rem; max-width: var(--content-max, 1100px); margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }
.hero-eyebrow { display: inline-flex; align-items: center; gap: 6px; background: rgba(62,212,154,0.08); border: 0.5px solid rgba(62,212,154,0.2); border-radius: 20px; padding: 4px 12px; font-size: 11px; font-weight: 600; color: var(--toproll); margin-bottom: 1rem; letter-spacing: 1px; text-transform: uppercase; }
.live-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--toproll); animation: pulse 1.8s infinite; flex-shrink: 0; }
@keyframes pulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.4;transform:scale(.7)} }
.hero-title { font-family: 'Bebas Neue', sans-serif; font-size: 5rem; line-height: .88; letter-spacing: 3px; margin-bottom: 1.2rem; }
.hero-title em { font-style: normal; color: var(--gold); }
.hero-sub { color: var(--muted); font-size: 15px; line-height: 1.65; max-width: 420px; margin-bottom: 1.8rem; font-weight: 300; }
.hero-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.hero-stats { display: flex; gap: 2.5rem; margin-top: 1.5rem; padding-top: 1.5rem; border-top: 0.5px solid var(--border); }
.hstat-val { font-family: 'Bebas Neue', sans-serif; font-size: 1.7rem; color: var(--gold); line-height: 1; }
.hstat-lbl { font-size: 11px; color: var(--muted); margin-top: 1px; }

.featured-wrap { position: relative; height: 380px; perspective: 900px; }
.feat-card { position: absolute; width: 210px; border-radius: 14px; overflow: hidden; transition: all .5s cubic-bezier(.25,.8,.25,1); cursor: pointer; }
.feat-card.main { left: 50%; top: 0; transform: translateX(-50%); z-index: 3; box-shadow: 0 24px 60px rgba(0,0,0,.8); }
.feat-card.left { left: 2%; top: 40px; transform: rotateY(18deg) scale(.82); z-index: 2; opacity: .45; filter: brightness(.7); }
.feat-card.right { right: 2%; top: 40px; transform: rotateY(-18deg) scale(.82); z-index: 2; opacity: .45; filter: brightness(.7); }
.feat-poster { width: 100%; height: 275px; object-fit: cover; display: block; }
.feat-poster-ph { width: 100%; height: 275px; background: var(--surface2); display: flex; align-items: center; justify-content: center; color: var(--dim); font-size: 36px; }
.feat-body { background: var(--surface); padding: 12px 14px; }
.feat-title { font-weight: 600; font-size: 13.5px; margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.feat-bottom { display: flex; align-items: center; justify-content: space-between; }
.feat-score { font-family: 'Bebas Neue', sans-serif; font-size: 1.6rem; color: var(--gold); line-height: 1; }

/* ---- DEMOCRACY BANNER ---- */
.democracy-bar { background: linear-gradient(135deg, rgba(232,201,107,.06), rgba(62,212,154,.03)); border-top: 0.5px solid rgba(232,201,107,.15); border-bottom: 0.5px solid rgba(232,201,107,.1); padding: .8rem 2.5rem; display: flex; align-items: center; gap: 12px; }
.demo-icon { font-size: 20px; color: var(--gold); flex-shrink: 0; }
.demo-text { font-size: 13px; color: var(--muted); line-height: 1.4; }
.demo-text strong { color: var(--gold); }

/* Temporary review-bombing notice (see Integrity.bombNotice / buildBombBanner) */
.bomb-bar { background: linear-gradient(135deg, rgba(232,77,99,.12), rgba(232,77,99,.03)); border-top: 0.5px solid rgba(232,77,99,.3); border-bottom: 0.5px solid rgba(232,77,99,.18); border-left: 3px solid var(--flop); padding: .8rem 2.5rem; display: flex; align-items: center; gap: 12px; }
.bomb-icon { font-size: 22px; color: var(--flop); flex-shrink: 0; }
.bomb-text { font-size: 13px; color: var(--muted); line-height: 1.4; }
.bomb-text strong { color: var(--flop); }

/* Staff role badges (moderator / admin / owner) — profile + admin header */
.staff-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 8px; border: 1px solid transparent; white-space: nowrap; }
.staff-badge i { font-size: 13px; }
.staff-mod   { color: var(--info); background: rgba(107,159,232,.12); border-color: rgba(107,159,232,.3); }
.staff-admin { color: var(--toproll); background: rgba(62,212,154,.12); border-color: rgba(62,212,154,.3); }
.staff-owner { color: var(--gold); background: rgba(232,201,107,.14); border-color: rgba(232,201,107,.35); }

/* ---- SECTIONS ---- */
.section-wrap { max-width: var(--content-max, 1100px); margin: 0 auto; padding: 2rem 2.5rem; }
.sec-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.2rem; }
.sec-title { font-family: 'Bebas Neue', sans-serif; font-size: 1.55rem; letter-spacing: 2px; display: flex; align-items: center; gap: 8px; color: var(--text); }
.sec-title i { font-size: 18px; }
.sec-link { font-size: 12px; color: var(--muted); text-decoration: none; display: flex; align-items: center; gap: 3px; }
.sec-link:hover { color: var(--gold); }
.sec-link:visited { color: var(--muted); }
.section-divider { max-width: var(--content-max, 1100px); margin: 0 auto; border: none; border-top: 0.5px solid var(--border); }

/* ---- MEDIA CARDS ---- */
.cards-scroll { display: flex; gap: 14px; overflow-x: auto; overflow-y: visible; padding: 16px 4px; scrollbar-width: none; }
.cards-scroll::-webkit-scrollbar { display: none; }

.media-card {
  flex: 0 0 150px; width: 150px; /* enforce fixed width */
  background: var(--surface); border: 0.5px solid var(--border);
  border-radius: 12px; cursor: pointer;
  transition: transform .2s, border-color .2s; position: relative;
  text-decoration: none; color: var(--text) !important; display: flex;
  flex-direction: column;
  overflow: visible;
}
/* Poster rounds itself so card background shows correctly */
.media-poster { border-radius: 12px 12px 0 0; }
.media-poster-ph { border-radius: 12px 12px 0 0; }
.media-card:hover { transform: translateY(-4px) scale(1.02); border-color: var(--border2); color: var(--text) !important; }
.media-card:visited { color: var(--text) !important; }
.media-card:active { color: var(--text) !important; }

.media-poster { width: 100%; height: 210px; object-fit: cover; display: block; flex-shrink: 0; }
.media-poster-ph { width: 100%; height: 210px; background: var(--surface2); display: flex; align-items: center; justify-content: center; color: var(--dim); font-size: 28px; flex-shrink: 0; }

/* Rank badge — clean white number over dark pill */
.card-rank {
  position: absolute; top: 8px; left: 8px;
  font-family: 'Bebas Neue', sans-serif; font-size: 1.15rem;
  color: #fff;
  background: rgba(0,0,0,0.55);
  backdrop-filter: blur(4px);
  padding: 1px 7px; border-radius: 6px; line-height: 1.6;
  letter-spacing: .5px;
}

.card-verdict-stamp { position: absolute; top: 7px; right: 7px; }

.rate-btn {
  position: absolute; top: 174px; right: 8px; /* anchored to bottom-right of the 210px poster */
  height: 28px; box-sizing: border-box;
  background: rgba(9,10,15,.85); border: 0.5px solid rgba(255,255,255,.15);
  border-radius: 8px; padding: 0 9px; font-size: 10px; font-weight: 700;
  letter-spacing: .4px; cursor: pointer; color: rgba(255,255,255,.92);
  display: flex; align-items: center; gap: 4px; transition: all .2s; font-family: inherit;
  backdrop-filter: blur(4px); box-shadow: 0 2px 8px rgba(0,0,0,.4);
}
.rate-btn:hover { background: rgba(18,16,11,.9); border-color: rgba(232,201,107,.5); color: var(--gold); transform: translateY(-1px); }
.rate-btn.rated { color: var(--gold); border-color: rgba(232,201,107,.45); background: rgba(232,201,107,.12); }
.rate-btn.rated i { color: var(--gold); }
/* Locked (unreleased) — a clear lock chip, not a dimmed "Rate" pill. Square
   footprint so it reads as a lock indicator rather than a faded button. */
.rate-btn-locked {
  width: 28px; padding: 0; justify-content: center;
  background: rgba(9,10,15,.8); border-color: rgba(255,255,255,.14);
  color: rgba(255,255,255,.62); cursor: not-allowed;
}
.rate-btn-locked i { font-size: 13px; }
.rate-btn-locked:hover {
  background: rgba(9,10,15,.8); border-color: rgba(255,255,255,.14);
  color: rgba(255,255,255,.62); transform: none;
}
.media-card.first-card .rate-btn { top: 209px; } /* taller 245px poster */

/* ---- WATCHLIST: poster bookmark button (dark + classic) ---- */
.wl-btn {
  position: absolute; top: 174px; left: 8px; /* anchored to bottom-left of the 210px poster */
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(9,10,15,.85);
  border: 0.5px solid rgba(255,255,255,.15);
  border-radius: 8px;
  color: rgba(255,255,255,.72);
  font-size: 14px; line-height: 1;
  cursor: pointer; font-family: inherit;
  backdrop-filter: blur(4px);
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
  transition: all .2s;
}
.wl-btn:hover {
  color: var(--gold);
  border-color: rgba(232,201,107,.5);
  background: rgba(18,16,11,.9);
  transform: translateY(-1px);
}
.wl-btn.added {
  color: var(--gold);
  border-color: rgba(232,201,107,.5);
  background: rgba(232,201,107,.14);
  box-shadow: 0 2px 10px rgba(232,201,107,.18);
}

/* ---- WATCHLIST: title-page button (dark + classic) ---- */
.wl-title-btn {
  width: 100%; padding: 12px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  background: linear-gradient(180deg, #14151f, #0d0e16);
  border: 0.5px solid rgba(255,255,255,.12);
  border-radius: 12px; font-size: 14px; font-weight: 500;
  color: rgba(255,255,255,.6); cursor: pointer; font-family: inherit;
  letter-spacing: .3px;
  box-shadow: 0 4px 14px rgba(0,0,0,.35);
  transition: all .2s;
}
.wl-title-btn i { font-size: 17px; }
.wl-title-btn:hover {
  border-color: rgba(232,201,107,.45);
  color: var(--gold);
  background: linear-gradient(180deg, rgba(232,201,107,.1), rgba(232,201,107,.04));
}
.wl-title-btn.wl-title-added {
  background: linear-gradient(180deg, rgba(232,201,107,.14), rgba(232,201,107,.06));
  border-color: rgba(232,201,107,.4);
  color: var(--gold);
  box-shadow: inset 0 0 0 0.5px rgba(232,201,107,.15), 0 4px 14px rgba(0,0,0,.35);
}

/* Rewatch counter — a two-part pill built on the .wl-title-btn shell. */
.rewatch-ctrl { padding: 0; overflow: hidden; }
.rewatch-ctrl .rw-main,
.rewatch-ctrl .rw-minus {
  background: none; border: 0; color: inherit; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 500; letter-spacing: .3px;
  transition: background .2s, color .2s;
}
.rewatch-ctrl .rw-main {
  flex: 1; padding: 12px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.rewatch-ctrl .rw-main i { font-size: 17px; }
.rewatch-ctrl .rw-label b { font-weight: 700; }
.rewatch-ctrl .rw-minus {
  width: 40px; align-self: stretch;
  border-left: 0.5px solid rgba(255,255,255,.12);
  font-size: 20px; line-height: 1;
}
.rewatch-ctrl .rw-main:hover  { color: var(--gold); background: rgba(232,201,107,.08); }
.rewatch-ctrl .rw-minus:hover { color: #ff6b6b; background: rgba(255,107,107,.1); }
.wl-title-btn.rewatch-ctrl.rw-active {
  background: linear-gradient(180deg, rgba(232,201,107,.14), rgba(232,201,107,.06));
  border-color: rgba(232,201,107,.4);
  color: var(--gold);
  box-shadow: inset 0 0 0 0.5px rgba(232,201,107,.15), 0 4px 14px rgba(0,0,0,.35);
}

/* Watched — a "times seen" stepper on the .wl-title-btn shell, same two-part
   shape the rewatch pill used (it's now the + side of this one): the first tap
   is the watch, every tap after it is a rewatch, minus walks back down.
   Green rather than gold so "seen it" reads apart from the gold intent
   controls (watchlist / lists) beside it. */
.watched-ctrl { padding: 0; overflow: hidden; }
.watched-ctrl .wt-main,
.watched-ctrl .wt-minus {
  background: none; border: 0; color: inherit; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 500; letter-spacing: .3px;
  transition: background .2s, color .2s;
}
.watched-ctrl .wt-main {
  flex: 1; padding: 12px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.watched-ctrl .wt-main i { font-size: 17px; }
.watched-ctrl .wt-label b,
.watched-ctrl .wt-hint b { font-weight: 700; }

/* Hovering a watched title swaps the label for what the next tap will do —
   the rewatch counter is otherwise invisible until you've used it. */
.watched-ctrl .wt-hint { display: none; align-items: center; gap: 8px; white-space: nowrap; }
.watched-ctrl.has-hint .wt-main:hover .wt-hint,
.watched-ctrl.has-hint .wt-main:focus-visible .wt-hint { display: inline-flex; }
.watched-ctrl.has-hint .wt-main:hover > i,
.watched-ctrl.has-hint .wt-main:hover .wt-label,
.watched-ctrl.has-hint .wt-main:focus-visible > i,
.watched-ctrl.has-hint .wt-main:focus-visible .wt-label { display: none; }
.watched-ctrl .wt-minus {
  width: 40px; align-self: stretch;
  border-left: 0.5px solid rgba(255,255,255,.12);
  font-size: 20px; line-height: 1;
}
/* Hovering an unwatched title previews the watch → green, matching the state
   it's about to enter. Once watched, the next tap is a REWATCH, which is its
   own action and gets its own accent (--info blue): it can't be green (that's
   the watched state you're already in), gold (the watchlist/list buttons
   around it), or --meh orange (the app's "meh" verdict — a rewatch means the
   opposite). */
.watched-ctrl .wt-main:hover  { color: var(--toproll); background: rgba(62,212,154,.08); }
.watched-ctrl.has-hint .wt-main:hover,
.watched-ctrl.has-hint .wt-main:focus-visible { color: var(--info); background: rgba(107,159,232,.1); }
/* ...except a part-watched series, where the next tap finishes the run rather
   than logging a rewatch — so that one stays green. */
.watched-ctrl.watched-partial .wt-main:hover,
.watched-ctrl.watched-partial .wt-main:focus-visible { color: var(--toproll); background: rgba(62,212,154,.08); }
/* No light-theme override here on purpose: .wl-title-btn keeps its dark
   #14151f gradient in BOTH themes, so --info stays at 6.7:1 on it. A deeper
   "light mode" blue would be dark-on-dark (3.4:1) — worse, not better. */
.watched-ctrl .wt-minus:hover { color: #ff6b6b; background: rgba(255,107,107,.1); }
.wl-title-btn.watched-ctrl.watched-on {
  background: linear-gradient(180deg, rgba(62,212,154,.14), rgba(62,212,154,.06));
  border-color: rgba(62,212,154,.4);
  color: var(--toproll);
  box-shadow: inset 0 0 0 0.5px rgba(62,212,154,.15), 0 4px 14px rgba(0,0,0,.35);
}
/* Seen more than once — takes the rewatch counter's own blue, so a rewatched
   title reads apart from a watched-once one at a glance. This is the state the
   blue hover has been previewing all along: hover a green "Watched ✓" and it
   turns blue, click, and the button settles into that blue for good. */
.wl-title-btn.watched-ctrl.watched-rewatched {
  background: linear-gradient(180deg, rgba(107,159,232,.14), rgba(107,159,232,.06));
  border-color: rgba(107,159,232,.4);
  color: var(--info);
  box-shadow: inset 0 0 0 0.5px rgba(107,159,232,.15), 0 4px 14px rgba(0,0,0,.35);
}
/* Part-way through a series — same green, dashed to read as "in progress". */
.wl-title-btn.watched-ctrl.watched-partial { border-style: dashed; }

.media-body { padding: 8px 10px 10px; }
.media-title { font-weight: 500; font-size: 12.5px; margin-bottom: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.media-bottom { display: flex; align-items: center; justify-content: space-between; }
.media-type { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
.media-score { font-family: 'Bebas Neue', sans-serif; font-size: 1.25rem; color: var(--gold); line-height: 1; }
.media-score.na { font-size: 11px; font-family: inherit; color: var(--muted); }
.vote-count { font-size: 10px; color: var(--dim); margin-top: 2px; }

/* ---- ROLES SECTION ---- */
.roles-section { background: var(--bg2); border-top: 0.5px solid var(--border); border-bottom: 0.5px solid var(--border); padding: 2.5rem 2.5rem; }
.roles-inner { max-width: var(--content-max, 1100px); margin: 0 auto; }
.roles-sub { font-size: 13px; color: var(--muted); margin: .4rem 0 1.4rem; }
.roles-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.role-card { background: var(--surface); border: 0.5px solid var(--border2); border-radius: 14px; padding: 1.2rem; display: flex; flex-direction: column; gap: 10px; }
.role-card.featured { border-color: rgba(232,201,107,.3); background: linear-gradient(135deg, rgba(232,201,107,.05), var(--surface)); }
.role-badge { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; letter-spacing: .6px; width: fit-content; text-transform: uppercase; }
.rb-gold { background: rgba(232,201,107,.12); border: 1.5px solid rgba(232,201,107,.3); color: var(--gold); }
.rb-toproll { background: rgba(62,212,154,.1); border: 1.5px solid rgba(62,212,154,.25); color: var(--toproll); }
.rb-info { background: rgba(107,159,232,.1); border: 1.5px solid rgba(107,159,232,.25); color: var(--info); }
.rb-flop { background: rgba(232,77,99,.1); border: 1.5px solid rgba(232,77,99,.25); color: var(--flop); }
.rb-meh { background: rgba(232,168,62,.1); border: 1.5px solid rgba(232,168,62,.25); color: var(--meh); }
.rb-dim { background: rgba(122,120,142,.08); border: 1.5px solid rgba(122,120,142,.2); color: var(--muted); }
.rb-predict { background: var(--predict-soft); border: 1.5px solid var(--predict-border); color: var(--predict); }

/* ---- CRITIC SCORE + TASTE-MATCH chips (appear wherever a critic does) ---- */
.cscore-chip {
  display: inline-flex; align-items: center; gap: 3px; vertical-align: middle;
  font-family: 'Bebas Neue', sans-serif; font-size: 13px; letter-spacing: .5px; line-height: 1;
  padding: 2px 7px; border-radius: 6px;
  color: var(--cs, var(--gold)); border: 1px solid var(--cs, var(--gold)); background: transparent;
}
.cscore-chip i { font-size: 11px; }
.cscore-new { color: var(--muted); border-color: var(--border2); }
.taste-chip {
  display: inline-flex; align-items: center; gap: 3px; vertical-align: middle;
  font-size: 11px; font-weight: 600; line-height: 1; padding: 3px 7px; border-radius: 20px;
  color: var(--info); background: rgba(107,159,232,.1); border: 1px solid rgba(107,159,232,.25);
}
.taste-chip i { font-size: 11px; }
.taste-chip.taste-strong { color: var(--toproll); background: rgba(62,212,154,.1); border-color: rgba(62,212,154,.25); }
.taste-chip.taste-weak   { color: var(--muted);  background: rgba(122,120,142,.08); border-color: rgba(122,120,142,.2); }
/* Big headline version for the profile hero. */
.cscore-big { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; }
.cscore-big-num { font-family: 'Bebas Neue', sans-serif; font-size: 2.6rem; line-height: 1; color: var(--cs, var(--gold)); }
.cscore-big-lbl { font-size: 10px; text-transform: uppercase; letter-spacing: .6px; color: var(--muted); }
/* Critic Score as the headline value in the profile stats column. */
.pstat-critic { border-color: color-mix(in srgb, var(--cs) 30%, transparent); }
.cscore-headline { color: var(--cs, var(--gold)) !important; }
.role-name { font-family: 'Bebas Neue', sans-serif; font-size: 1.3rem; letter-spacing: 1.5px; color: var(--text); }
.role-desc { font-size: 12.5px; color: var(--muted); line-height: 1.55; }
.role-req { font-size: 11px; color: var(--dim); border-top: 0.5px solid var(--border); padding-top: 8px; }
.role-req span { color: var(--muted); }

/* ---- RATING MODAL ---- */
/* The modal NEVER outgrows the screen. It is centred, so anything taller than
   the viewport is clipped at BOTH ends with nothing to scroll — which is how
   the Submit button went missing once the body grew (stars + "when did you
   watch it" + hot take + privacy) on a short phone. So: cap the height, keep
   the head fixed, scroll the body, and pin the action to the bottom. */
.modal-bg { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.75); z-index: 500; align-items: center; justify-content: center; padding: 1rem; }
.modal-bg.open { display: flex; }
.modal { background: var(--bg2); border: 0.5px solid var(--border2); border-radius: 22px; width: 350px; max-width: 100%; overflow: hidden;
         max-height: calc(100vh - 2rem); max-height: calc(100dvh - 2rem); display: flex; flex-direction: column; }
.modal-head { display: flex; gap: 11px; padding: .95rem 1.1rem .7rem; border-bottom: 0.5px solid var(--border); position: relative; flex-shrink: 0; }
.modal-close-btn { position: absolute; top: 12px; right: 12px; background: rgba(255,255,255,.06); border: none; border-radius: 50%; width: 28px; height: 28px; cursor: pointer; color: var(--muted); font-size: 14px; display: flex; align-items: center; justify-content: center; transition: all .18s; }
.modal-close-btn:hover { background: rgba(255,255,255,.12); color: var(--text); }
.modal-poster { width: 58px; height: 82px; object-fit: cover; border-radius: 8px; flex-shrink: 0; }
.modal-poster-ph { width: 58px; height: 82px; background: var(--surface); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: var(--dim); flex-shrink: 0; font-size: 22px; }
.modal-ep-ph { width: 56px; height: 80px; background: var(--surface2); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: var(--dim); flex-shrink: 0; }
.modal-info { flex: 1; min-width: 0; padding-right: 2rem; }
.modal-title { font-weight: 600; font-size: 15px; margin-bottom: 3px; line-height: 1.3; color: var(--text); }
.modal-meta { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.modal-body { padding: .9rem 1.1rem 1.1rem; flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.rating-label { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .8px; margin-bottom: .7rem; }
.stars-box { background: var(--surface); border: 0.5px solid var(--border2); border-radius: 14px; padding: .7rem; margin-bottom: .6rem; }
.stars-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; margin-bottom: .35rem; }
/* A star cell is sized by its track, never by its glyph. Without min-width:0 a
   grid item is at least its automatic minimum size, and `aspect-ratio` turns
   the glyph line box (32px for a 20px star in DM Sans) into a ~52px minimum
   WIDTH — wider than the 1fr share, so the five columns overflowed the rate
   box and the last star punched straight through its right border. line-height:1
   keeps the box the ratio we asked for instead of the font's idea of a line. */
.star-cell { aspect-ratio: 1.55; min-width: 0; min-height: 0; line-height: 1; display: flex; align-items: center; justify-content: center; border-radius: 8px; cursor: pointer; font-size: 20px; transition: all .15s; background: var(--surface2); border: 0.5px solid var(--border); color: var(--dim); user-select: none; }
.star-cell:hover, .star-cell.lit { background: rgba(232,201,107,.12); border-color: rgba(232,201,107,.35); color: var(--gold); transform: scale(1.08); }
.star-nums { display: grid; grid-template-columns: repeat(5,1fr); gap: 5px; margin-bottom: .55rem; }
.star-num { text-align: center; font-size: 10px; color: var(--dim); font-weight: 500; }
.score-row { display: flex; align-items: center; justify-content: space-between; background: var(--bg3); border-radius: 10px; padding: .4rem .8rem; }
.score-display { font-family: 'Bebas Neue', sans-serif; font-size: 1.9rem; color: var(--gold); line-height: 1; }
.submit-btn { width: 100%; padding: 10px; border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; font-family: inherit; border: none; background: var(--gold); color: #1a1000; transition: all .18s; margin-top: .7rem; }
.submit-btn:hover { background: #f0d57a; }
.submit-btn:disabled { background: var(--surface2); color: var(--dim); cursor: default; }
.submit-done { background: rgba(62,212,154,.12) !important; color: var(--toproll) !important; border: 0.5px solid rgba(62,212,154,.3) !important; }
/* Primary button acting as a removal (star toggled off on a saved rating). */
.submit-btn.submit-remove { background: var(--flop); color: #fff; }
.submit-btn.submit-remove:hover { background: #d8455a; }

/* ---- "SEEN IT" — the other answer, under the submit ----
   Quiet on purpose: a score is still the thing the modal is for, so this reads
   as the secondary way out rather than competing with the gold button. Once
   the mark is on it goes green, because that's the colour a watched mark wears
   everywhere else on the site. */
.modal-watched-btn {
  width: 100%; margin-top: .45rem; padding: 9px 10px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer; transition: all .18s;
  border: 0.5px solid var(--border2); background: var(--surface2); color: var(--muted);
}
.modal-watched-btn:hover  { color: var(--text); border-color: var(--muted); }
.modal-watched-btn i      { font-size: 15px; }
.modal-watched-btn.is-on,
.modal-watched-btn.is-part {
  color: var(--toproll); border-color: rgba(62,212,154,.35);
  background: color-mix(in srgb, var(--toproll) 12%, transparent);
}
.modal-watched-btn.is-on:hover,
.modal-watched-btn.is-part:hover { background: color-mix(in srgb, var(--toproll) 20%, transparent); }
/* A part-watched series is an offer, not a state — keep it readable, not loud. */
.modal-watched-btn.is-part { font-weight: 500; }

/* ---- HOT TAKE (optional one-line opinion attached to a rating) ----
   Shared by the title-page rate box and the quick-rate modal. */
.hot-take       { margin-top: .8rem; }
.hot-take-input {
  width: 100%; box-sizing: border-box; resize: vertical; min-height: 44px;
  background: var(--bg3); color: var(--text);
  border: 0.5px solid var(--border2); border-radius: 10px;
  padding: 9px 11px; font-family: inherit; font-size: 13px; line-height: 1.45;
  transition: border-color .18s;
}
.hot-take-input::placeholder { color: var(--dim); }
.hot-take-input:focus { outline: none; border-color: var(--toproll); }
.hot-take-foot  { display: flex; justify-content: space-between; align-items: center; margin-top: 5px; }
.hot-take-foot-left { display: inline-flex; align-items: center; gap: 8px; }
.hot-take-hint  { font-size: 11px; color: var(--dim); }
.hot-take-count { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- THE OPTIONAL LINE, IN THE RATE MODAL ----
   The hot take and the privacy of the rating are both optional. Stacked as
   full rows they cost more height than the stars do, and the quick rate has
   to be answerable in one glance without scrolling — so they share one line
   as two chips, and the take opens in place when it is actually wanted. */
.rate-extras { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: .6rem; flex-wrap: wrap; }
.rate-extra-btn {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 11px; border-radius: 999px;
  font-family: inherit; font-size: 12px; font-weight: 600; cursor: pointer; transition: all .18s;
  border: 0.5px solid var(--border2); background: var(--surface2); color: var(--muted);
}
.rate-extra-btn:hover  { color: var(--text); border-color: var(--muted); }
.rate-extra-btn.is-on  { color: var(--gold); border-color: rgba(232,201,107,.45); background: rgba(232,201,107,.12); }
.rate-extra-btn i      { font-size: 13px; }
/* On the shared line the privacy pill drops its own row and its sentence —
   the button says the state, and its tooltip says what the state means. */
.rate-extras .rate-privacy   { margin-top: 0; }
.rate-extras .rate-priv-hint { display: none; }
/* One section, so it needs no section label — the head already names the title. */
#rate-modal .modal-body > .rating-label,
#ep-modal   .modal-body > .rating-label { display: none; }
#rate-modal .hot-take       { margin-top: .5rem; }
#rate-modal .hot-take-input { min-height: 40px; }

/* ---- PER-RATING PRIVACY TOGGLE (rate modal + title rate box) ---- */
.rate-privacy   { display: flex; align-items: center; gap: 8px; margin-top: .7rem; flex-wrap: wrap; }
.rate-priv-btn  {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 11px; border-radius: 999px;
  font-family: inherit; font-size: 12px; font-weight: 600; cursor: pointer; transition: all .18s;
  border: 0.5px solid var(--toproll); background: color-mix(in srgb, var(--toproll) 14%, transparent); color: var(--toproll);
}
.rate-priv-btn:hover { background: color-mix(in srgb, var(--toproll) 22%, transparent); }
.rate-priv-btn.is-private { border-color: var(--muted); background: var(--surface2); color: var(--text); }
.rate-priv-btn i { font-size: 13px; }
.rate-priv-hint { font-size: 11px; color: var(--dim); }

/* ---- "WHEN DID YOU WATCH IT" (rate modal + title page rate box) ----
   Deliberately loud for a secondary field: it is the difference between a
   rating that lands in your week and one that doesn't, and a wrap people
   don't trust is a wrap they stop opening. So it gets its own panel, a
   heading that ASKS, four chips whose answer is readable without opening
   anything, and a coloured line stating the consequence in words. */
.ww {
  margin-top: .6rem; padding: 8px 10px; border-radius: 14px;
  border: 0.5px solid var(--border2); background: var(--surface);
}
.ww-head {
  display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--muted);
}
.ww-head i { font-size: 14px; color: var(--gold); }
.ww-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.ww-chip {
  flex: 1 1 auto; padding: 6px 9px; border-radius: 999px; white-space: nowrap;
  font-family: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; transition: all .16s;
  border: 0.5px solid var(--border2); background: var(--surface2); color: var(--muted);
}
.ww-chip:hover { color: var(--text); border-color: var(--muted); }
.ww-chip.is-on {
  color: #0b0c14; background: var(--gold); border-color: var(--gold);
}
.ww-chip-out.is-on { color: #0b0c14; background: var(--meh); border-color: var(--meh); }
.ww-date {
  margin-top: 7px; width: 100%; font-family: inherit; font-size: 13px; font-weight: 600;
  padding: 7px 10px; border-radius: 10px; outline: none;
  border: 0.5px solid var(--border2); background: var(--surface2); color: var(--text);
}
.ww-date:focus { border-color: rgba(232,201,107,.45); }
/* Room for the pinned Submit button when the field scrolls itself into view. */
.ww-date { scroll-margin-bottom: 66px; }
.ww-note { display: flex; align-items: center; gap: 5px; margin-top: 6px; font-size: 11px; font-weight: 600; }
.ww-note i { font-size: 13px; }
.ww-note-in  { color: var(--toproll); }
.ww-note-out { color: var(--meh); }
.ww-note-ask { color: var(--muted); }

/* ---- SHORT SCREENS ----
   The quick rate is meant to be answered in one glance: stars, when, the
   optional line and the button, all on screen at once with nothing to
   scroll. A phone with the browser chrome showing is barely 550px tall, so
   below that the whole widget tightens rather than growing a scrollbar. */
@media (max-height: 700px) {
  .modal-head { padding: .8rem 1rem .6rem; gap: 10px; }
  .modal-poster, .modal-poster-ph { width: 48px; height: 68px; }
  .modal-body { padding: .75rem 1rem .9rem; }
  .stars-box  { padding: .6rem; margin-bottom: .5rem; }
  .star-cell  { aspect-ratio: 1.85; font-size: 17px; }
  .star-nums  { margin-bottom: .45rem; }
  .score-display { font-size: 1.65rem; }
  .score-row  { padding: .3rem .7rem; }
  .ww { margin-top: .5rem; padding: 7px 9px; }
  .ww-note { margin-top: 5px; }
  .rate-extras { margin-top: .5rem; }
  .submit-btn { margin-top: .55rem; }
  .modal-watched-btn { margin-top: .4rem; padding: 8px 10px; font-size: 12.5px; }
}

/* Tiniest screens (a small phone with the keyboard row showing): the
   community line goes, and the stars flatten a little further. */
@media (max-height: 560px) {
  .modal-head { padding: .65rem .9rem .5rem; }
  #modal-existing { display: none; }
  .star-cell { aspect-ratio: 2.1; }
  .star-nums { margin-bottom: .35rem; }
}

/* ---- AUTH MODAL ---- */
.auth-modal-bg { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.8); z-index: 600; align-items: center; justify-content: center; }
.auth-modal-bg.open { display: flex; }
.auth-modal { background: var(--bg2); border: 0.5px solid var(--border2); border-radius: 22px; width: 380px; overflow: hidden; position: relative; }
.auth-tabs { display: flex; border-bottom: 0.5px solid var(--border); }
.auth-tab { flex: 1; padding: 14px; text-align: center; cursor: pointer; font-size: 13px; font-weight: 600; color: var(--muted); border: none; background: none; font-family: inherit; transition: all .18s; border-bottom: 2px solid transparent; }
.auth-tab.active { color: var(--gold); border-bottom-color: var(--gold); }
.auth-body { padding: 1.5rem; }
.auth-field { margin-bottom: 1rem; }
.auth-field label { display: block; font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .8px; margin-bottom: 6px; }
.auth-field input { width: 100%; background: var(--surface); border: 0.5px solid var(--border2); border-radius: 10px; padding: 10px 14px; color: var(--text); font-family: inherit; font-size: 14px; outline: none; transition: border-color .18s; }
.auth-field input:focus { border-color: rgba(232,201,107,.4); }
.auth-field input::placeholder { color: var(--dim); }
.auth-submit { width: 100%; padding: 11px; border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; font-family: inherit; border: none; background: var(--gold); color: #1a1000; transition: all .18s; }
.auth-submit:hover { background: #f0d57a; }
.auth-divider { text-align: center; font-size: 12px; color: var(--dim); margin-top: 1rem; }
.auth-close { position: absolute; top: 12px; right: 14px; background: rgba(255,255,255,.06); border: none; border-radius: 50%; width: 28px; height: 28px; cursor: pointer; color: var(--muted); font-size: 14px; display: flex; align-items: center; justify-content: center; }
.auth-close:hover { background: rgba(255,255,255,.12); color: var(--text); }
.auth-error { font-size: 12px; color: var(--flop); margin-top: 8px; display: none; }
.auth-success { font-size: 13px; color: var(--toproll); text-align: center; padding: 1rem 0; display: none; }

/* ---- INJECTED AUTH UI (Google button, forgot-password, resend) ---- */
/* Why the modal opened. A logged-out visitor reads the whole site, so by the
   time we interrupt them they were mid-gesture — this is the sentence that says
   which one. */
.auth-context { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 1rem; padding: 10px 12px; border-radius: 10px; background: rgba(232,201,107,.08); border: 0.5px solid rgba(232,201,107,.25); color: var(--text); font-size: 13px; line-height: 1.45; }
.auth-context i { color: var(--gold); font-size: 15px; line-height: 1.35; flex-shrink: 0; }
.auth-oauth { margin-bottom: 1rem; }
.auth-oauth-btn { width: 100%; padding: 10px; border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; font-family: inherit; border: 0.5px solid var(--border2); background: var(--surface); color: var(--text); display: flex; align-items: center; justify-content: center; gap: 10px; transition: all .18s; }
.auth-oauth-btn:hover { border-color: rgba(255,255,255,0.22); background: rgba(255,255,255,0.04); }
.auth-oauth-btn svg { flex-shrink: 0; }
.auth-or { display: flex; align-items: center; gap: 12px; margin: 14px 2px 0; color: var(--dim); font-size: 11px; text-transform: uppercase; letter-spacing: .8px; }
.auth-or::before, .auth-or::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.auth-forgot-row { text-align: right; margin-top: 10px; }
.auth-forgot-link { color: var(--gold); cursor: pointer; font-size: 12px; }
.auth-forgot-link:hover { text-decoration: underline; }
.auth-forgot-copy { font-size: 12.5px; color: var(--muted); margin: 0 0 1rem; line-height: 1.5; }
.auth-forgot-notice { font-size: 12.5px; color: var(--meh); background: color-mix(in srgb, var(--meh) 12%, transparent); border: 1px solid color-mix(in srgb, var(--meh) 35%, transparent); border-radius: 8px; padding: 8px 10px; margin: 0 0 12px; line-height: 1.45; }
.auth-resend { margin-top: 10px; font-size: 12px; color: var(--muted); }

/* ---- LIVE USERNAME AVAILABILITY ---- */
.auth-uname-status { display: none; font-size: 12px; line-height: 1.5; margin-top: 6px; color: var(--muted); }
.auth-uname-status i { font-size: 13px; vertical-align: -2px; margin-right: 2px; }
.auth-uname-status.is-ok { color: var(--toproll); }
.auth-uname-status.is-bad { color: var(--flop); }
.auth-uname-status.is-checking { color: var(--dim); }
.auth-uname-status .spin { display: inline-block; animation: auth-uname-spin .8s linear infinite; }
@keyframes auth-uname-spin { to { transform: rotate(360deg); } }
.auth-uname-picks { margin-top: 7px; color: var(--muted); display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.auth-uname-chip { background: var(--surface); border: 0.5px solid var(--border2); border-radius: 999px; padding: 4px 11px; font-family: inherit; font-size: 12px; font-weight: 500; color: var(--gold); cursor: pointer; transition: all .18s; }
.auth-uname-chip:hover { border-color: rgba(232,201,107,.45); background: rgba(232,201,107,.08); }

/* ---- CONFIRMATION TOAST ---- */
.auth-toast { position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 20px); background: var(--bg3); border: 0.5px solid var(--border2); color: var(--text); font-size: 13px; font-weight: 500; padding: 12px 18px; border-radius: 12px; box-shadow: 0 12px 40px rgba(0,0,0,.5); display: flex; align-items: center; gap: 8px; z-index: 900; opacity: 0; transition: opacity .35s, transform .35s; }
.auth-toast.show { opacity: 1; transform: translate(-50%, 0); }
.auth-toast i { color: var(--toproll); font-size: 16px; }
.user-menu { display: flex; align-items: center; gap: 8px; }
.user-avatar { width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg,#2a1842,#1a2a3a); display: flex; align-items: center; justify-content: center; font-family: 'Bebas Neue',sans-serif; font-size: 1rem; color: var(--gold); border: 1.5px solid rgba(232,201,107,.3); cursor: pointer; overflow: hidden; }
/* A user's uploaded profile picture — fills whatever avatar circle it's dropped into. */
.uv-avatar-img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.user-name { font-size: 13px; font-weight: 500; color: var(--text); }
/* Username beside the header avatar. Was inline-styled in auth.js; it needs a
   class so the phone breakpoint can hide it (an inline display beats a rule). */
.user-name-link { display: flex; align-items: center; font-size: 13px; font-weight: 500; color: var(--text); text-decoration: none; }
.user-name-link:visited { color: var(--text); }
.signout-btn { font-size: 12px; color: var(--muted); cursor: pointer; background: none; border: none; font-family: inherit; padding: 0; transition: color .18s; }
.signout-btn:hover { color: var(--flop); }

/* ---- LOADING ---- */
.loading { text-align: center; padding: 3rem; color: var(--muted); font-size: 13px; }
.spinner { width: 22px; height: 22px; border: 2px solid var(--border2); border-top-color: var(--gold); border-radius: 50%; animation: spin .7s linear infinite; margin: 0 auto; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- FOOTER ---- */
.site-footer { text-align: center; padding: 2rem; font-size: 12px; color: var(--dim); border-top: 0.5px solid var(--border); margin-top: 2rem; }
.footer-logo { margin-bottom: 10px; }
.footer-logo .logo-img { height: 26px; width: auto; }
.tmdb-logo { display: inline-block; margin: 4px auto 0; opacity: 0.85; transition: opacity 0.15s; }
.tmdb-logo:hover { opacity: 1; }
.tmdb-logo img { height: 12px; width: auto; display: block; }
.tmdb-attr { font-size: 11px; color: var(--dim); margin: 6px auto 0; max-width: 620px; line-height: 1.5; }
.tmdb-attr a { color: var(--muted); }
.tmdb-attr a:hover { color: var(--gold); }

/* First card is slightly larger */
.media-card.first-card {
  flex: 0 0 175px; width: 175px;
}
.media-card.first-card .media-poster {
  height: 245px;
}
.media-card.first-card .media-poster-ph {
  height: 245px;
}
.media-card.first-card .wl-btn {
  top: 209px; /* anchored to bottom-left of the taller 245px poster */
}

/* ============================================
   THEME TOGGLE BUTTON (injected into the nav by theme.js)
   ============================================ */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 9px; cursor: pointer; flex-shrink: 0;
  background: var(--surface2); border: 0.5px solid var(--border2);
  color: var(--muted); transition: background .15s, color .15s, border-color .15s;
}
.theme-toggle:hover { color: var(--text); border-color: rgba(150,150,170,.45); }
.theme-toggle i { font-size: 17px; }

/* ============================================
   LIGHT THEME
   --------------------------------------------
   Only the neutral palette flips; the verdict accent colors (toproll/flop/meh)
   stay put so they match the hard-coded SVG glyph colors. Gold is darkened
   for readable contrast on light surfaces.
   ============================================ */
html[data-theme="light"] {
  --bg: #f5f6fa;
  --bg2: #eceef4;
  --bg3: #e3e5ee;
  --surface: #ffffff;
  --surface2: #eef0f6;
  --border: rgba(20,22,40,0.10);
  --border2: rgba(20,22,40,0.16);
  --text: #181a24;
  --muted: #5d5f70;
  --dim: #9a9bac;
  --gold: #9a7415;   /* darker gold so gold-on-white text stays readable */
}
html[data-theme="light"] body { background: var(--bg); color: var(--text); }
html[data-theme="light"] #main-nav {
  background: rgba(255,255,255,0.90);
  border-bottom: 0.5px solid var(--border);
}
/* Page hero gradients (defined dark across the various page CSS files) */
html[data-theme="light"] .community-hero,
html[data-theme="light"] .charts-hero,
html[data-theme="light"] .browse-hero,
html[data-theme="light"] .profile-hero {
  background: linear-gradient(135deg, #eef1f8 0%, #f3eef8 50%, #eaf2f8 100%);
}
html[data-theme="light"] .roles-section {
  background: linear-gradient(135deg, #eef1f8, #f4f5fa);
}
/* Gold button keeps its dark ink, but with the darker light-mode gold we want
   light text for contrast. */
html[data-theme="light"] .btn-primary { color: #fff; }
html[data-theme="light"] .btn-primary:hover { background: #b08a20; }

/* ============================================
   RESPONSIVE — phone / tablet / large screens
   ============================================ */

/* ---- Small laptop / large tablet ----
   The links row already shrinks and scrolls at every width (see .nav-center
   above), so this block only claws back the space around it: tighter nav
   padding, tighter link padding and a narrower search field, which together
   buy the links a few more visible items before they start scrolling.

   No `min-width: 769px` lower bound on purpose: on a fractional viewport
   (768.5px at some zoom levels / DPIs) neither `max-width: 768px` nor
   `min-width: 769px` matches, and the nav fell through both rules into a
   broken state. This block is instead placed ABOVE the phone block so the
   phone rules simply override it below 768px. */
/* ---- Nav link icons are a wide-screen affordance ----
   The eight glyphs add ~170px to the links row, which only fits once the
   viewport is around 1280 and up. Below that the row would scroll and push
   Calendar out of sight — exactly the hidden-link problem the phone tab bar
   was built to solve — so narrow desktops keep the text-only row they had
   before. Combined with the tighter padding above, they now fit MORE of the
   row than they did pre-icons, not less. */
@media (max-width: 1279px) {
  .nav-center a i { display: none; }
  .nav-center a { gap: 0; }
}

@media (max-width: 1000px) {
  #main-nav { padding: 0 1rem; gap: 10px; }
  .nav-center a { padding: 6px 7px; }
  .search-wrap { min-width: 0; }
  .search-wrap input { width: 100px; }
}

/* ---- Tablet ---- */
@media (max-width: 1024px) {
  .section-wrap { padding: 1.75rem 1.5rem; }
  .roles-section { padding: 2rem 1.5rem; }
  .roles-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---- Phone ---- */
@media (max-width: 768px) {
  /* One-row nav. The page links move out of the header entirely and into the
     fixed bottom tab bar built by js/mobilenav.397a2ebd.js, so --nav-h keeps its
     desktop 58px and every sticky offset that reads it stays exact. */
  #main-nav { height: var(--nav-h); padding: 8px 12px; gap: 8px; }
  .nav-center { display: none; }
  .nav-right { flex: 1; justify-content: flex-end; gap: 6px; min-width: 0; }
  .nav-right .btn { padding: 6px 12px; }
  /* Username and the admin shortcut move into the More sheet; the header keeps
     just the bell and the avatar. */
  .user-menu .user-name-link,
  .user-menu .admin-nav-link { display: none; }

  /* Search collapses to a 34px icon button; js/mobilenav.397a2ebd.js adds
     body.mnav-search-open to expand it across the row on tap. */
  .search-wrap { flex: 0 0 auto; width: 34px; height: 34px; padding: 0; justify-content: center; cursor: pointer; }
  .search-wrap input { width: 0; padding: 0; opacity: 0; pointer-events: none; }

  body.mnav-search-open .logo,
  body.mnav-search-open #auth-area,
  body.mnav-search-open #theme-toggle { display: none; }
  body.mnav-search-open .search-wrap { flex: 1 1 auto; width: auto; padding: 0 10px; justify-content: flex-start; cursor: auto; }
  body.mnav-search-open .search-wrap input { width: 100%; opacity: 1; pointer-events: auto; }
  body.mnav-search-open .mnav-search-close { display: inline-flex; align-items: center; }
  .search-dropdown { min-width: 0; width: 100%; max-width: calc(100vw - 24px); }

  /* Clear the fixed tab bar so page bottoms (footer, last feed card) stay
     reachable rather than sitting underneath it. */
  body { padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom)); }
  /* Sibling lifts for .settings-toast / .ach-toasts live in settings.css and
     profile.css — those load after this file, so an override here would lose
     the cascade at equal specificity. */
  .auth-toast { bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 16px); }

  .section-wrap { padding: 1.25rem 1rem; }
  .roles-section { padding: 1.75rem 1rem; }
  .roles-grid { grid-template-columns: 1fr; }
  .role-card { min-width: 0; }
  .site-footer { padding: 1.5rem 1rem; }
  .hero-stats { gap: 1.5rem; }
}

/* ---- Small phone ---- */
@media (max-width: 480px) {
  .logo-img { height: 26px; }
  .nav-right #auth-area .btn-ghost { display: none; } /* keep the primary "Join Free" CTA */
  .hero-stats { gap: 1.1rem; }
}

/* ============================================
   MOBILE TAB BAR + "MORE" SHEET
   --------------------------------------------
   Markup is injected by js/mobilenav.397a2ebd.js on every page that has #main-nav.
   Both are display:none above the phone breakpoint, so desktop is untouched.
   ============================================ */
/* Hidden by default at every width — the phone block below opts them back in.
   js/mobilenav.397a2ebd.js appends all three to the DOM unconditionally, so the
   desktop layout has to be the one that hides them. */
.mnav-tabs, .mnav-sheet-bg, .mnav-search-close { display: none; }
.mnav-search-close { background: none; border: none; color: var(--muted); cursor: pointer; padding: 0 2px; font-size: 15px; }

@media (max-width: 768px) {
  .mnav-tabs {
    display: flex;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 150;
    background: rgba(9,10,15,0.97);
    /* Hairline as an inset shadow, not a border: a border would add its
       rounded-up device pixel to the bar's height, and the body padding that
       clears the bar reads --tabbar-h alone — the mismatch left the footer
       tucked a pixel underneath. A shadow costs no layout. */
    box-shadow: inset 0 1px 0 var(--border);
    backdrop-filter: blur(20px);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .mnav-tab {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    height: var(--tabbar-h);
    background: none; border: none; font-family: inherit; cursor: pointer;
    color: var(--muted); text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: color .15s;
  }
  .mnav-tab i { font-size: 20px; line-height: 1; }
  .mnav-tab span { font-size: 10px; font-weight: 500; letter-spacing: .2px; }
  .mnav-tab:visited { color: var(--muted); }
  .mnav-tab.active, .mnav-tab.active:visited { color: var(--gold); }
  .mnav-tab:active { opacity: .6; }

  /* ---- sheet ---- */
  .mnav-sheet-bg {
    display: block; position: fixed; inset: 0; z-index: 400;
    background: rgba(0,0,0,.6);
    opacity: 0; pointer-events: none; transition: opacity .22s ease;
  }
  .mnav-sheet-bg.open { opacity: 1; pointer-events: auto; }
  /* Chrome claims a downward swipe for pull-to-refresh (and iOS for the
     document rubber-band) on the very first move — before the drag handler
     below has decided it wants the touch — and once the browser owns the
     gesture preventDefault() is a no-op for the rest of it, so the page
     bounced down instead of the sheet.
     touch-action goes on the sheet itself, not the overlay: the browser
     intersects an element's value with its ancestors', so `none` up on the
     overlay would cancel the pan-y that a scrollable sheet needs (mobilenav.js
     sets that at open time). The overscroll rules below cover the backdrop. */
  .mnav-sheet { touch-action: none; overscroll-behavior: contain; }
  .mnav-sheet {
    position: absolute; left: 0; right: 0; bottom: 0;
    background: var(--bg2);
    border-top: 0.5px solid var(--border2);
    border-radius: 18px 18px 0 0;
    padding: 8px 14px calc(18px + env(safe-area-inset-bottom));
    max-height: 82vh; overflow-y: auto;
    transform: translateY(100%); transition: transform .26s cubic-bezier(.25,.8,.25,1);
  }
  .mnav-sheet-bg.open .mnav-sheet { transform: translateY(0); }
  /* While a finger is on it the sheet is positioned frame by frame from JS —
     a transition here would lag the drag behind the thumb. */
  .mnav-sheet.mnav-dragging { transition: none; }
  .mnav-sheet-bg.mnav-dragging { transition: none; }

  /* The bar is 4px but the grabbable strip is the whole top of the sheet; the
     padding gives the handle itself a finger-sized target too. */
  .mnav-grab {
    width: 38px; height: 4px; border-radius: 99px; background: var(--dim);
    margin: 0 auto; padding: 0; box-sizing: content-box;
    background-clip: content-box; border-top: 8px solid transparent; border-bottom: 8px solid transparent;
    touch-action: none;
  }

  .mnav-sheet-user { display: flex; align-items: center; gap: 10px; padding: 2px 4px 12px; border-bottom: 0.5px solid var(--border); }
  .mnav-sheet-av {
    width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0;
    background: linear-gradient(135deg,#2a1842,#1a2a3a);
    display: flex; align-items: center; justify-content: center;
    font-family: 'Bebas Neue', sans-serif; font-size: 1rem; color: var(--gold);
    border: 1.5px solid rgba(232,201,107,.3);
  }
  .mnav-sheet-name { font-size: 15px; font-weight: 500; color: var(--text); }

  .mnav-group-label { font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--dim); margin: 14px 4px 4px; }
  .mnav-row {
    display: flex; align-items: center; gap: 12px; width: 100%;
    padding: 12px 10px; border-radius: 10px;
    background: none; border: none; font-family: inherit; font-size: 15px; text-align: left;
    color: var(--text); text-decoration: none; cursor: pointer;
  }
  .mnav-row:visited { color: var(--text); }
  .mnav-row i { font-size: 19px; color: var(--muted); width: 22px; text-align: center; flex-shrink: 0; }
  .mnav-row:active { background: rgba(255,255,255,.06); }
  .mnav-row.active { background: rgba(255,255,255,.07); }
  .mnav-row.active i { color: var(--gold); }
  .mnav-row-danger, .mnav-row-danger i { color: var(--flop); }

  /* The one row in the sheet that isn't a destination — it's a standing offer,
     so it's tinted to read as one without shouting over the links below it.
     The desktop nav pill (.nav-install) is hidden at this width; this is its
     counterpart. js/mobilenav.397a2ebd.js drops it inside the installed app. */
  .mnav-install {
    margin: 12px 0 2px;
    background: rgba(232,201,107,.09);
    border: 0.5px solid rgba(232,201,107,.28);
  }
  .mnav-install, .mnav-install:visited, .mnav-install i { color: var(--gold); }
  .mnav-install:active { background: rgba(232,201,107,.17); }

  /* overflow:hidden stops the document scrolling, but on Chrome Android a
     swipe that starts at the top still arms pull-to-refresh — that's a
     separate gesture, and only overscroll-behavior turns it off. Set on both
     html and body because the viewport takes its value from whichever of the
     two declares one. */
  body.mnav-locked { overflow: hidden; }
  html.mnav-locked, body.mnav-locked { overscroll-behavior-y: none; }
}

html[data-theme="light"] .mnav-tabs { background: rgba(255,255,255,0.95); }
html[data-theme="light"] .mnav-row:active { background: rgba(20,22,40,.06); }
html[data-theme="light"] .mnav-row.active { background: rgba(20,22,40,.07); }

/* ---- Large screens / TV ---- */
@media (min-width: 1700px) {
  :root { --content-max: 1480px; }
  body { font-size: 16px; }
  .nav-center a { font-size: 14px; }
}

/* ============================================================
   THE DESIGNED SCROLLER
   ------------------------------------------------------------
   Rollit's scrollbar: thin, a --border2 thumb on no track. It was
   already written out by hand in a dozen places (.hs-row, .fc-strip,
   .home-strip-row, .drops-strip-row, .emoji-grid …) with small
   inconsistencies, and every panel added since simply got the
   browser default — a fat grey bar down the side of a dark modal.

   This is the one definition. Add a scrolling container to the list
   below, or give it `.rl-scroll` if it is new markup; do not paste a
   fourth variant of the same four rules into another file.

   Panels only. The PAGE scrollbar is deliberately left alone — the
   window chrome is the browser's to draw, and thinning it is a change
   to every page on the site rather than to a component.
   ============================================================ */

.rl-scroll,
.hw-stage,                                   /* how-to-play demo stage */
.tl-results, .tl-modal, .tl-chips-genre,     /* tier list */
.cg-picker-bg, .cg-results, .cg-missed-list, /* cast grid */
.es-stage {                                  /* export studio */
  scrollbar-width: thin;
  scrollbar-color: var(--border2) transparent;
}

.rl-scroll::-webkit-scrollbar,
.hw-stage::-webkit-scrollbar,
.tl-results::-webkit-scrollbar, .tl-modal::-webkit-scrollbar, .tl-chips-genre::-webkit-scrollbar,
.cg-picker-bg::-webkit-scrollbar, .cg-results::-webkit-scrollbar, .cg-missed-list::-webkit-scrollbar,
.es-stage::-webkit-scrollbar { width: 6px; height: 6px; }

.rl-scroll::-webkit-scrollbar-track,
.hw-stage::-webkit-scrollbar-track,
.tl-results::-webkit-scrollbar-track, .tl-modal::-webkit-scrollbar-track, .tl-chips-genre::-webkit-scrollbar-track,
.cg-picker-bg::-webkit-scrollbar-track, .cg-results::-webkit-scrollbar-track, .cg-missed-list::-webkit-scrollbar-track,
.es-stage::-webkit-scrollbar-track { background: transparent; }

.rl-scroll::-webkit-scrollbar-thumb,
.hw-stage::-webkit-scrollbar-thumb,
.tl-results::-webkit-scrollbar-thumb, .tl-modal::-webkit-scrollbar-thumb, .tl-chips-genre::-webkit-scrollbar-thumb,
.cg-picker-bg::-webkit-scrollbar-thumb, .cg-results::-webkit-scrollbar-thumb, .cg-missed-list::-webkit-scrollbar-thumb,
.es-stage::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }

.rl-scroll::-webkit-scrollbar-thumb:hover,
.hw-stage::-webkit-scrollbar-thumb:hover,
.tl-results::-webkit-scrollbar-thumb:hover, .tl-modal::-webkit-scrollbar-thumb:hover,
.cg-picker-bg::-webkit-scrollbar-thumb:hover, .cg-results::-webkit-scrollbar-thumb:hover,
.es-stage::-webkit-scrollbar-thumb:hover { background: var(--muted); }
