/* ============================================================================
   account.css — Box Office Watch accounts (auth + profile), v1
   ----------------------------------------------------------------------------
   Shared stylesheet for /login, /signup, /welcome, /verify, /reset,
   /u/<username>, /account/notifications, /account/settings.

   There is no global stylesheet on this site (styles are inlined per page), so
   this file is self-contained: it carries the v2 token block, the base reset,
   the .optb-nav header, .site-footer, and every account-specific component.

   THEME
   -----
   Dark is default. Light is opt-in via [data-theme="light"], same as the rest
   of the site. The hero zone (backdrop + nav overlay) stays dark in BOTH
   themes via the --hero-* tokens — do not add light overrides for .optb-nav.
   --acc-ground is the page ground *below* the profile hero; the hero fade
   resolves into it, so it flips with the theme and never leaves a seam.
============================================================================ */

/* ── TOKENS: DARK (default) — token-version v2 ───────────────────────────── */
:root,
/* Auth pages run a cinematic film backdrop, so they stay dark in BOTH themes —
   same rule the homepage hero follows. Rather than duplicating the dark values
   here, the cinema shell simply joins the :root declaration. It wins over
   [data-theme="light"] on specificity (0,2,0 beats 0,1,0), not source order,
   and because the class sits on <body> the dark tokens cascade to everything
   inside it — card, nav and footer alike. */
.acc-page.acc-page--cinema{
  --bg:#111;--bg-card:#18181b;--bg-tertiary:#222;--bg-elevated:#1f1f23;
  --text-primary:#fff;--text-body:rgba(255,255,255,.85);--text-secondary:rgba(255,255,255,.7);--text-tertiary:rgba(255,255,255,.6);--text-muted:rgba(255,255,255,.45);--text-faint:rgba(255,255,255,.35);--text-xfaint:rgba(255,255,255,.3);
  --border-subtle:rgba(255,255,255,.06);--border-light:rgba(255,255,255,.08);--border-medium:rgba(255,255,255,.1);--border-strong:rgba(255,255,255,.15);--border-checkbox:rgba(255,255,255,.25);
  --hover-bg:rgba(255,255,255,.04);--hover-subtle:rgba(255,255,255,.02);--overlay:rgba(0,0,0,.5);--shadow-card:0 1px 3px rgba(0,0,0,.3);--shadow-elevated:0 16px 48px rgba(0,0,0,.5);--focus-ring:rgba(34,197,94,.55);
  --accent-green:#22c55e;--accent-green-bright:#22c55e;--accent-green-text:#22c55e;--accent-green-bg:rgba(34,197,94,.1);--accent-green-border:rgba(34,197,94,.25);--accent-green-on:#052e16;
  --accent-red:#ef4444;--accent-red-text:#ef4444;--accent-red-bg:rgba(239,68,68,.08);--accent-red-border:rgba(239,68,68,.25);--accent-red-on:#fff;
  --accent-yellow:#eab308;--accent-yellow-text:#eab308;--accent-yellow-bg:rgba(234,179,8,.1);
  --accent-blue:#3b82f6;--accent-blue-text:#3b82f6;--accent-blue-bg:rgba(59,130,246,.1);
  --accent-purple:#a855f7;--accent-purple-text:#a855f7;--accent-purple-bg:rgba(168,85,247,.1);
  --scrollbar-track:rgba(255,255,255,.03);--scrollbar-thumb:rgba(255,255,255,.08);
  --hero-bg:#111;--hero-bg-deep:#0a0a0a;--hero-overlay:rgba(17,17,17,.75);--hero-overlay-strong:rgba(17,17,17,.92);
  --hero-text-primary:#fff;--hero-text-body:rgba(255,255,255,.85);--hero-text-secondary:rgba(255,255,255,.7);--hero-text-muted:rgba(255,255,255,.5);--hero-text-faint:rgba(255,255,255,.4);--hero-text-xfaint:rgba(255,255,255,.3);
  --hero-border:rgba(255,255,255,.12);--hero-border-subtle:rgba(255,255,255,.08);--hero-hover:rgba(255,255,255,.1);
  /* accounts-only */
  --acc-ground:#0a0a0a;          /* profile page ground, below the hero fade */
  /* Same colour as --acc-ground, as bare channels. The hero fade needs a
     dozen arbitrary alphas to ramp smoothly, and a fixed token per alpha
     does not scale — rgba(var(--acc-ground-rgb),<a>) gives any alpha while
     staying theme-aware. */
  --acc-ground-rgb:10,10,10;
  --acc-ground-95:rgba(10,10,10,.95);
  --acc-ground-70:rgba(10,10,10,.7);
  --acc-ground-60:rgba(10,10,10,.6);
  --acc-ground-30:rgba(10,10,10,.3);
  --acc-ground-15:rgba(10,10,10,.15);
  --lbx-orange:#ff8000;--lbx-green:#00e054;--lbx-blue:#40bcf4;
}

/* ── TOKENS: LIGHT (opt-in) — AA on #fafafa ──────────────────────────────── */
[data-theme="light"]{
  --bg:#fafafa;--bg-card:#fff;--bg-tertiary:#f0f0f0;--bg-elevated:#fff;
  --text-primary:#0f172a;--text-body:rgba(15,23,42,.88);--text-secondary:rgba(15,23,42,.72);--text-tertiary:rgba(15,23,42,.62);--text-muted:rgba(15,23,42,.55);--text-faint:rgba(15,23,42,.48);--text-xfaint:rgba(15,23,42,.36);
  --border-subtle:rgba(15,23,42,.06);--border-light:rgba(15,23,42,.1);--border-medium:rgba(15,23,42,.14);--border-strong:rgba(15,23,42,.22);--border-checkbox:rgba(15,23,42,.3);
  --hover-bg:rgba(15,23,42,.05);--hover-subtle:rgba(15,23,42,.025);--overlay:rgba(15,23,42,.4);--shadow-card:0 1px 3px rgba(15,23,42,.08);--shadow-elevated:0 16px 48px rgba(15,23,42,.18);--focus-ring:rgba(21,128,61,.6);
  --accent-green:#15803d;--accent-green-bright:#15803d;--accent-green-text:#15803d;--accent-green-bg:rgba(21,128,61,.1);--accent-green-border:rgba(21,128,61,.3);--accent-green-on:#fff;
  --accent-red:#dc2626;--accent-red-text:#b91c1c;--accent-red-bg:rgba(220,38,38,.08);--accent-red-border:rgba(220,38,38,.3);--accent-red-on:#fff;
  --accent-yellow:#b45309;--accent-yellow-text:#b45309;--accent-yellow-bg:rgba(180,83,9,.1);
  --accent-blue:#1d4ed8;--accent-blue-text:#1d4ed8;--accent-blue-bg:rgba(29,78,216,.08);
  --accent-purple:#7e22ce;--accent-purple-text:#7e22ce;--accent-purple-bg:rgba(126,34,206,.08);
  --scrollbar-track:rgba(15,23,42,.03);--scrollbar-thumb:rgba(15,23,42,.14);
  /* hero-* tokens intentionally inherited from :root — hero stays dark */
  --acc-ground:#fafafa;
  --acc-ground-rgb:250,250,250;
  --acc-ground-95:rgba(250,250,250,.95);
  --acc-ground-70:rgba(250,250,250,.7);
  --acc-ground-60:rgba(250,250,250,.6);
  --acc-ground-30:rgba(250,250,250,.3);
  --acc-ground-15:rgba(250,250,250,.15);
}

/* ── BASE ────────────────────────────────────────────────────────────────── */
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",sans-serif;
  background:var(--bg);color:var(--text-body);line-height:1.5;min-height:100vh;
  -webkit-font-smoothing:antialiased;
}
body.acc-profile-body{background:var(--acc-ground)}
a{color:var(--accent-green-text);text-decoration:none}
img{display:block}
button,input,textarea{font-family:inherit}
:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.acc-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
[hidden]{display:none!important}

/* ── HEADER: .optb-nav (absolute overlay, always dark) ───────────────────── */
.optb-nav{display:flex;align-items:center;padding:0 40px;height:54px;gap:24px;background:transparent;position:absolute;top:0;left:0;right:0;z-index:100}
.optb-nav .optb-logo{font-family:'Alfa Slab One',serif;font-size:20px;color:#fff;text-decoration:none;white-space:nowrap}
.optb-nav .optb-nav-right{display:flex;align-items:center;gap:16px;margin-left:auto}
.optb-nav .optb-links{display:flex;gap:20px}
.optb-nav .optb-links a{font-size:11.5px;color:rgba(255,255,255,.45);letter-spacing:1.2px;text-transform:uppercase;text-decoration:none;font-weight:600}
.optb-nav .optb-links a:hover{color:#fff}
.search-wrap{position:relative;display:flex;align-items:center}
.search-btn{background:none;border:1px solid rgba(255,255,255,.2);cursor:pointer;padding:7px 8px;color:rgba(255,255,255,.7);display:flex;align-items:center;justify-content:center;transition:all .2s;border-radius:8px}
.search-btn:hover{color:#fff;border-color:rgba(255,255,255,.4);background:rgba(255,255,255,.1)}
.search-btn svg{width:18px;height:18px}
.search-input-wrap{position:absolute;top:50%;right:0;transform:translateY(-50%);width:0;opacity:0;overflow:hidden;transition:width .3s ease,opacity .3s ease;display:flex;align-items:center}
.search-input-wrap.open{width:260px;opacity:1}
.search-input-wrap input{width:100%;padding:8px 14px;border-radius:10px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.6);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);color:#fff;font-size:14px;outline:none;font-family:inherit}
.search-input-wrap input::placeholder{color:rgba(255,255,255,.4)}
.search-input-wrap input:focus{border-color:rgba(255,255,255,.3)}
.search-dropdown{position:absolute;top:calc(100% + 8px);right:0;width:320px;max-height:400px;overflow-y:auto;background:rgba(20,20,20,.95);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,.1);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.5);display:none;z-index:300}
.search-dropdown.visible{display:block}
.search-result{display:flex;align-items:center;gap:10px;padding:8px 12px;text-decoration:none;color:#fff;transition:background .15s}
.search-result:hover{background:rgba(255,255,255,.07)}
.search-result img{width:36px;height:54px;border-radius:4px;object-fit:cover;flex-shrink:0;background:rgba(255,255,255,.08)}
.search-result-title{font-size:13px;font-weight:600}
.search-no-results{padding:16px 14px;color:rgba(255,255,255,.4);font-size:13px;text-align:center}
.hamburger-btn{display:none;background:none;border:none;cursor:pointer;padding:8px;margin-top:4px;border-radius:8px;transition:background .2s;color:rgba(255,255,255,.7)}
.hamburger-btn:hover{color:#fff;background:rgba(255,255,255,.1)}
.hamburger-btn .bar{display:block;width:24px;height:2.5px;background:currentColor;border-radius:1px;margin-bottom:5px}
.hamburger-btn .bar:last-child{margin-bottom:0}
.optb-backdrop{display:none;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:190}
.optb-backdrop.open{display:block}
.optb-menu{display:none;position:fixed;top:54px;right:16px;width:220px;background:var(--bg-tertiary);border-radius:12px;border:1px solid var(--border-medium);box-shadow:0 16px 48px rgba(0,0,0,.4);padding:6px 0;z-index:200}
.optb-menu.open{display:block}
.optb-menu .hamburger-menu-item{display:flex;align-items:center;padding:12px 16px;font-size:13px;font-weight:600;color:var(--text-secondary);text-decoration:none;transition:color .2s}
.optb-menu .hamburger-menu-item:hover{color:var(--text-primary)}
.optb-menu .hamburger-menu-item.is-danger{color:var(--text-muted)}
.optb-menu .hamburger-menu-item.is-danger:hover{color:var(--accent-red-text)}
.optb-menu .optb-menu-rule{height:1px;background:var(--border-light);margin:6px 0}

/* Signed-in avatar in the nav (32px, unread dot, dropdown) */
.nav-avatar-wrap{position:relative;display:inline-flex}
.nav-avatar{width:32px;height:32px;border-radius:50%;background:rgba(34,197,94,.15);border:1px solid rgba(34,197,94,.4);display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;color:#22c55e;cursor:pointer;padding:0;transition:background .2s,border-color .2s}
.nav-avatar:hover{background:rgba(34,197,94,.25);border-color:rgba(34,197,94,.7)}
.nav-avatar-dot{position:absolute;top:-2px;right:-2px;width:10px;height:10px;border-radius:50%;background:#ef4444;border:2px solid var(--acc-ground);pointer-events:none}
.acc-auth-links{display:flex;align-items:center;gap:14px;flex-shrink:0}
.acc-nav-login{font-size:11.5px;color:rgba(255,255,255,.45);letter-spacing:1.2px;text-transform:uppercase;font-weight:600;white-space:nowrap}
.acc-nav-login:hover{color:#fff}
.acc-nav-signup{font-size:11.5px;letter-spacing:1.2px;text-transform:uppercase;font-weight:700;color:#22c55e;border:1px solid rgba(34,197,94,.4);background:rgba(34,197,94,.12);border-radius:100px;padding:6px 14px;transition:background .2s,border-color .2s;white-space:nowrap;flex-shrink:0}
.acc-nav-signup:hover{background:rgba(34,197,94,.2);border-color:rgba(34,197,94,.7)}
/* Log in / Sign up inside the hamburger — phones only (see nav-auth.js).
   Selector is doubled up because .optb-menu .hamburger-menu-item would
   otherwise outrank a bare .bow-auth-mobile and leave these showing on desktop. */
.optb-menu .bow-auth-mobile,.bow-auth-mobile{display:none}
.optb-menu .bow-auth-signup{color:var(--accent-green-text);font-weight:700}

/* Account dropdown injected by nav-auth.js.
   nav-auth.js carries its own copy of these rules for pages that DON'T load
   this stylesheet, and skips injecting when it sees account.css. It therefore
   has to be defined HERE as well, or the menu renders unstyled and permanently
   open on exactly the pages that do load account.css (/u/*, /account/*).
   Keep the two copies in step. */
.bow-acct-menu{display:none;position:fixed;top:54px;right:16px;width:220px;background:var(--bg-tertiary);border-radius:12px;border:1px solid var(--border-medium);box-shadow:0 16px 48px rgba(0,0,0,.4);padding:6px 0;z-index:210}
.bow-acct-menu.open{display:block}
.bow-acct-menu a,.bow-acct-menu button{display:flex;align-items:center;justify-content:space-between;width:100%;padding:12px 16px;font-size:13px;font-weight:600;color:var(--text-secondary);text-decoration:none;background:none;border:none;cursor:pointer;font-family:inherit;text-align:left;transition:color .2s}
.bow-acct-menu a:hover,.bow-acct-menu button:hover{color:var(--text-primary)}
.bow-acct-menu .bow-acct-rule{height:1px;background:var(--border-light);margin:6px 0}
.bow-acct-menu .bow-acct-badge{min-width:16px;height:16px;border-radius:8px;background:var(--accent-green);color:var(--accent-green-on);font-size:10px;font-weight:800;display:inline-flex;align-items:center;justify-content:center;padding:0 4px}
.bow-acct-menu .bow-acct-out{color:var(--text-muted)}
.bow-acct-menu .bow-acct-out:hover{color:var(--accent-red-text)}

/* ── FOOTER ──────────────────────────────────────────────────────────────── */
.site-footer{padding:60px 64px 40px;border-top:1px solid var(--border-subtle);margin-top:60px;text-align:center}
.site-footer p{font-size:11px;color:var(--text-xfaint);line-height:1.7;margin:0 0 4px}
.site-footer a{color:var(--text-faint);text-decoration:none;transition:color .2s}
.site-footer a:hover{color:var(--text-tertiary)}

/* ============================================================================
   AUTH SCREENS — /login /signup /welcome /verify /reset
============================================================================ */
.acc-page{min-height:100vh;display:flex;flex-direction:column;background:var(--bg)}
.acc-shell{flex:1;display:flex;align-items:center;justify-content:center;padding:94px 20px 48px}
.acc-card{width:420px;max-width:100%;background:var(--bg-card);border:1px solid var(--border-light);border-radius:16px;padding:36px 38px;box-shadow:var(--shadow-card)}

/* ── Predict the Weekend, on the profile ──────────────────────────────────
   A ruled band, NOT .pf-marquee. This used to reuse the films marquee on the
   theory that one person's record should share one rhythm — but the two rows
   then sat directly above each other rendering identically, and the game
   numbers read as four more film stats. The 1px-gap ruled cells are what
   separate "this is the game" from "this is the collection". */
.pf-band{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--border-subtle);
  border:1px solid var(--border-light);border-radius:14px;overflow:hidden;
  max-width:960px;margin:26px auto 0}
/* Three fixed rows: mark, value, label. The first cell's medal used to make it
   a row taller than the other three, which pushed its label onto its own line
   and left the band looking mis-set. Fixing the row heights makes the four
   labels share a baseline whatever sits above them. */
.pf-band-cell{background:var(--bg-card);padding:18px 18px 20px;text-align:center;
  display:grid;grid-template-rows:40px 28px auto;justify-items:center;align-items:center;
  /* align-content:start, or the outer grid's equal-height stretch is absorbed
     by the auto label row — and centring a two-line caption inside a taller
     track lifts it above the one-line captions beside it. That is the 8px that
     made the row look mis-set in the first place. */
  align-content:start;gap:6px}
/* The mark is a medal for the podium and the plain ordinal for everyone else,
   so it carries type styling too. */
.pf-band-mark{display:grid;place-items:center;height:40px;font-size:24px;font-weight:800;
  line-height:1;color:var(--text-primary);letter-spacing:-.02em}
.pf-band-i{display:grid;place-items:center;width:26px;height:26px;color:var(--text-faint)}
.pf-band-i svg{width:100%;height:100%;display:block}
.pf-band-cell:hover .pf-band-i{color:var(--text-muted)}
.pf-band-n{font-size:26px;font-weight:800;line-height:1;color:var(--text-primary)}
.pf-band-n.is-green{color:var(--accent-green-text)}
.pf-band-l{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint)}
/* The placing leads the cell, so when it is a medal the cell gives it the line
   rather than trying to baseline it against a numeral it is not. */
/* A 30px medal reads small against the 26px numerals beside it — a numeral
   fills its box, a rosette does not. */
.pf-band-mark.is-badge .pw-champ-medal{width:38px;height:38px}
/* The first cell's value is a score, not a count — "76 / 80 pts" — so it takes
   a smaller, tabular treatment inside the same fixed row. */
.pf-band-cell:first-child .pf-band-n{font-size:15px;font-weight:800;
  color:var(--text-primary);font-variant-numeric:tabular-nums}

/* Status line under the band: deadline · picks-in · board link · leaderboard. */
.pf-gstatus{text-align:center;padding:16px 64px 0;font-size:12.5px;color:var(--text-faint)}
.pf-gstatus .sep{opacity:.5;margin:0 2px}
.pf-gstatus .pf-gs-warn{color:var(--accent-yellow-text);font-weight:600}
.pf-gstatus .pf-gs-go{color:var(--accent-green-text);font-weight:600;text-decoration:none}
.pf-gstatus .pf-gs-go:hover{text-decoration:underline}

.pf-game-flair{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:18px;padding:0 20px}
.pf-chip{border-radius:5px;padding:3px 9px;font-size:9.5px;font-weight:800;letter-spacing:.08em;white-space:nowrap}
.pf-chip--green{background:rgba(34,197,94,.12);border:1px solid rgba(34,197,94,.35);color:var(--accent-green-text)}
.pf-chip--gold{background:rgba(234,179,8,.12);border:1px solid rgba(234,179,8,.35);color:var(--accent-yellow-text)}
.pf-game-weeks{display:flex;justify-content:center;flex-wrap:wrap;gap:10px;margin-top:20px;padding:0 20px}
.pf-game-week{flex:0 0 128px;background:var(--bg-card);border:1px solid var(--border-light);border-radius:12px;padding:14px 10px;text-align:center;text-decoration:none;display:block;transition:border-color .2s,background .2s}
a.pf-game-week:hover{border-color:var(--accent-green-border);background:var(--hover-bg)}
.pf-game-week .v{display:flex;align-items:center;justify-content:center;min-height:26px;
  font-size:22px;font-weight:800;line-height:1;color:var(--text-primary)}
.pf-game-week .l{display:block;font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin-top:6px}
.pf-game-week .s{display:block;font-size:11.5px;font-weight:700;color:var(--text-secondary);margin-top:5px;
  font-variant-numeric:tabular-nums}
.pf-game-week .p{display:block;font-size:9.5px;color:var(--accent-yellow-text);margin-top:4px}
/* A medal is 22px of artwork where a 22px numeral used to sit; centre it and
   give the row the same optical height either way. */
.pf-game-week.is-podium .v .pw-champ-medal{width:26px;height:26px}
.pf-game-week.is-prelim .v{color:var(--text-body)}

/* ── Cinematic shell ─────────────────────────────────────────────────────────
   A featured film backdrop fills the page behind a frosted card, matching the
   language of the profile hero. Two stacked overlays do the work: a coloured
   radial glow for depth, then a vertical fade that resolves into the #0a0a0a
   ground so the footer never sits on a hard edge.

   The <img> is a real element rather than a background-image so it can carry
   loading/decoding hints and a graceful onerror — if TMDB is unreachable the
   image hides itself and you are left with a dark gradient, which is a fine
   page rather than a broken one. */
.acc-page--cinema{background:var(--acc-ground);position:relative;overflow-x:hidden}
.acc-cinema-bg{position:fixed;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 20%;filter:brightness(.35);z-index:0}
/* One glow per screen, not both on every screen. The design gives login a
   cool blue cast from the upper right and signup a violet one from the upper
   left, so two consecutive screens in the same flow don't read as the same
   still. --acc-glow is set per page; the vertical fade into the #0a0a0a
   ground is shared, and the blue is the default for screens that don't pick. */
.acc-cinema-veil{position:fixed;inset:0;z-index:1;background:
  var(--acc-glow,radial-gradient(ellipse 80% 50% at 70% 20%,rgba(59,130,246,.10),transparent)),
  linear-gradient(to top,#0a0a0a 0%,rgba(10,10,10,.9) 8%,rgba(10,10,10,.5) 45%,rgba(10,10,10,.3) 100%)}
.acc-glow-violet{--acc-glow:radial-gradient(ellipse 60% 40% at 30% 30%,rgba(139,92,246,.08),transparent)}
.acc-page--cinema .optb-nav,
.acc-page--cinema .acc-shell,
.acc-page--cinema .site-footer{position:relative;z-index:5}
.acc-page--cinema .optb-nav{z-index:100}
.acc-page--cinema .site-footer{border-top:1px solid rgba(255,255,255,.06);background:none}

/* Frosted card. The blur is what sells it — without backdrop-filter you just
   get a flat dark panel, so the fallback alpha is raised for browsers that
   don't support it (a plain .88 over a bright backdrop is unreadable). */
.acc-page--cinema .acc-card{background:rgba(24,24,27,.94);border-color:rgba(255,255,255,.1);box-shadow:0 24px 80px rgba(0,0,0,.6)}
@supports ((backdrop-filter:blur(16px)) or (-webkit-backdrop-filter:blur(16px))){
  .acc-page--cinema .acc-card{background:rgba(24,24,27,.88);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}
}
.acc-card--wide{width:460px}
.acc-card--mid{width:480px}
.acc-title{font-size:23px;font-weight:700;color:var(--text-primary);letter-spacing:-.01em;margin-bottom:4px}
.acc-card--mid .acc-title{font-size:21px;margin-bottom:6px}
.acc-sub{font-size:13.5px;color:var(--text-tertiary);margin-bottom:26px;line-height:1.55}
.acc-sub strong{color:var(--text-primary);font-weight:600}

/* OAuth / passkey buttons */
.acc-oauth-row{display:flex;flex-direction:column;gap:10px}
.acc-oauth-row--split{flex-direction:row;margin-bottom:20px}
.acc-oauth{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;background:none;border:1px solid var(--border-strong);border-radius:10px;padding:11px 0;font-size:14px;font-weight:600;color:var(--text-primary);cursor:pointer;transition:background .2s,border-color .2s}
.acc-oauth:hover{background:var(--hover-bg)}
.acc-oauth:disabled{opacity:.5;cursor:default}
.acc-oauth-row--split .acc-oauth{flex:1;gap:9px;font-size:13.5px}
[data-theme="light"] .acc-oauth .apple-mark{fill:#0f172a}

/* Divider */
.acc-divider{display:flex;align-items:center;gap:12px;margin:22px 0}
.acc-divider::before,.acc-divider::after{content:'';flex:1;height:1px;background:var(--border-light)}
.acc-divider span{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-faint)}
.acc-divider--tight{margin:0 0 20px}

/* Fields — the site's .contact-field recipe */
.acc-field{display:flex;flex-direction:column;gap:7px}
.acc-fields{display:flex;flex-direction:column;gap:16px}
.acc-label{font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--text-muted)}
.acc-label .opt{text-transform:none;letter-spacing:0;font-weight:600;color:var(--text-xfaint)}
.acc-input{width:100%;background:var(--bg-tertiary);border:1px solid var(--border-medium);border-radius:10px;padding:12px 14px;font-size:14.5px;color:var(--text-primary);transition:border-color .2s,box-shadow .2s}
.acc-input::placeholder{color:var(--text-muted)}
.acc-input:focus{outline:none;border-color:var(--accent-green);box-shadow:0 0 0 3px var(--accent-green-bg)}
.acc-input:disabled{opacity:.55}
/* Same autofill problem on the card fields — but these sit on an opaque panel,
   so here the inset box-shadow IS the right tool: it repaints the plate in the
   field's own colour rather than trying to make it disappear. */
.acc-input:-webkit-autofill,
.acc-input:-webkit-autofill:hover,
.acc-input:-webkit-autofill:focus,
.acc-input:-webkit-autofill:active{
  -webkit-text-fill-color:var(--text-primary);
  caret-color:var(--text-primary);
  -webkit-box-shadow:0 0 0 1000px var(--bg-tertiary) inset;
  box-shadow:0 0 0 1000px var(--bg-tertiary) inset;
  font-family:inherit !important;
  font-size:14.5px;
}
.acc-input:-webkit-autofill:focus{
  -webkit-box-shadow:0 0 0 1000px var(--bg-tertiary) inset,0 0 0 3px var(--accent-green-bg);
  box-shadow:0 0 0 1000px var(--bg-tertiary) inset,0 0 0 3px var(--accent-green-bg);
}
.acc-input:autofill{color:var(--text-primary);font-family:inherit}
.acc-input-at{position:relative}
.acc-input-at::before{content:'@';position:absolute;left:14px;top:50%;transform:translateY(-50%);font-size:14.5px;color:var(--text-muted);pointer-events:none}

/* Password field with a reveal control. Typing a password you cannot read is
   how people end up locked out of an account they just created. */
.acc-input-pw{position:relative;display:block}
.acc-input-pw .acc-input{padding-right:46px}
.acc-pw-toggle{position:absolute;right:6px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:8px;line-height:0;color:var(--text-muted);border-radius:8px;transition:color .2s,background .2s}
.acc-pw-toggle:hover{color:var(--text-primary);background:var(--hover-bg)}
.acc-pw-toggle svg{width:18px;height:18px;display:block}
.acc-pw-toggle .icon-hide{display:none}
.acc-pw-toggle.is-shown .icon-show{display:none}
.acc-pw-toggle.is-shown .icon-hide{display:block}
.acc-input-at .acc-input{padding-left:32px}
.acc-help{font-size:12px;color:var(--text-muted);line-height:1.6}
.acc-help--mt{margin-top:12px}
.acc-hint{font-size:11.5px;color:var(--text-muted)}
.acc-status{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:600;min-height:16px}
.acc-status.is-ok{color:var(--accent-green-text)}
.acc-status.is-bad{color:var(--accent-red-text)}
.acc-status.is-idle{color:var(--text-muted)}

/* Primary button */
.acc-btn{width:100%;background:var(--accent-green);color:#fff;border:none;border-radius:10px;padding:12px 0;font-size:14px;font-weight:700;cursor:pointer;transition:opacity .2s}
.acc-btn:hover{opacity:.9}
.acc-btn:disabled{opacity:.5;cursor:default}
.acc-btn--inline{width:auto;padding:11px 28px;font-size:13.5px}
.acc-link{color:var(--accent-green-text);font-weight:600;cursor:pointer;background:none;border:none;padding:0;font-size:inherit}
.acc-link:hover{opacity:.85}
.acc-cardfoot{border-top:1px solid var(--border-light);margin-top:24px;padding-top:18px;font-size:13.5px;color:var(--text-tertiary)}
.acc-cardfoot--tight{margin-top:22px;padding-top:16px}
.acc-backlink{margin-top:16px;font-size:13px;color:var(--text-muted)}

/* Consent checkboxes */
/* Sits under a primary button to explain what pressing it will do. */
.acc-helper{margin-top:10px;font-size:12px;color:var(--text-muted);line-height:1.5;text-align:center}

.acc-checks{display:flex;flex-direction:column;gap:12px;padding-top:2px}
.acc-check{display:flex;align-items:flex-start;gap:10px;cursor:pointer}
.acc-check input{position:absolute;opacity:0;width:0;height:0}
.acc-check .box{width:16px;height:16px;border-radius:4px;border:1px solid var(--border-checkbox);flex-shrink:0;margin-top:2px;display:inline-flex;align-items:center;justify-content:center;transition:background .2s,border-color .2s}
.acc-check .box svg{opacity:0;width:11px;height:11px}
.acc-check input:checked + .box{background:var(--accent-green);border-color:var(--accent-green)}
.acc-check input:checked + .box svg{opacity:1}
.acc-check input:focus-visible + .box{outline:2px solid var(--focus-ring);outline-offset:2px}
.acc-check .txt{font-size:13px;color:var(--text-secondary);line-height:1.5}
/* A lone .acc-check sitting directly under a field's input rather than inside an
   .acc-checks stack — the log modal's "I don't remember when". The stack owns the
   gap between siblings; a single one needs its own breathing room from the input
   it qualifies. */
.acc-field > .acc-check{margin-top:9px}

/* Error box — the site's .contact-error pattern */
.acc-error{display:none;padding:12px;background:var(--accent-red-bg);border:1px solid var(--accent-red-border);border-radius:12px;font-size:13px;font-weight:600;color:var(--accent-red-text);margin-top:12px;line-height:1.5}
.acc-error.show{display:block}
.acc-note{display:none;padding:12px;background:var(--accent-green-bg);border:1px solid var(--accent-green-border);border-radius:12px;font-size:13px;font-weight:600;color:var(--accent-green-text);margin-top:12px;line-height:1.5}
.acc-note.show{display:block}

/* 6-digit code inputs */
.acc-code{display:flex;gap:8px;margin-bottom:22px}
/* flex:1 rather than a fixed 52px: the number of boxes comes from the OTP
   length in config.js, and six 52px boxes happened to fit the 480px card
   while eight do not. Letting them divide the row keeps the layout right
   for any length, with no second number to hold in step. */
.acc-code input{flex:1 1 0;min-width:0;height:58px;background:var(--bg-tertiary);border:1px solid var(--border-medium);border-radius:10px;text-align:center;font-size:22px;font-weight:700;color:var(--text-primary);transition:border-color .2s,box-shadow .2s}
.acc-code input:focus{outline:none;border-color:var(--accent-green);box-shadow:0 0 0 3px var(--accent-green-bg)}
.acc-coderow{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px}
.acc-coderow .muted{color:var(--text-muted)}

/* ============================================================================
   PROFILE — /u/<username>
============================================================================ */
.pf-hero{position:relative;min-height:70vh;display:flex;align-items:flex-end;overflow:hidden;background:var(--hero-bg-deep)}
/* object-position here is only the no-JS floor: u/index.html emits an inline
   object-position from the film's images.backdropPosition on every render.
   Kept at 50% rather than `center top` because most obsession artwork is a
   portrait poster, and the top third of a poster is sky/title treatment —
   cropping there cuts the face off. */
.pf-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 50%}
.pf-hero::before{content:'';position:absolute;inset:0;z-index:1;background:radial-gradient(ellipse 80% 50% at 70% 20%,rgba(59,130,246,.10),transparent),radial-gradient(ellipse 60% 40% at 30% 70%,rgba(139,92,246,.08),transparent)}
/* The hero fade.

   The old version was five stops on ONE gradient: opaque at the bottom, 60% at
   35%, 15% at 55%, then back up to 30% at the top. Two things made the seam
   Nate could see. The alpha reversed direction in the middle — down to 15%,
   back up to 30% — which puts a visible waist across the image where the ramp
   turns around. And the stops were far apart with big alpha steps between
   them (95 -> 60 -> 15), so the linear interpolation between them changed
   slope abruptly at each stop; the eye reads those slope changes as bands,
   most obviously against a flat field of colour, which is exactly what the
   Kill Bill backdrop is.

   Now two gradients, each moving one way only, each eased. The ground fade
   follows a smoothstep curve (t^2*(3-2t)) sampled every 8% so it leaves the
   bottom and arrives at transparent with the slope flattened at both ends —
   no edge to see at either end of the fade. The top scrim that darkens behind
   the nav is its own layer, so it can no longer bend the ground ramp back on
   itself. */
.pf-hero::after{
  content:'';position:absolute;inset:0;z-index:2;
  background:
    linear-gradient(to bottom,
      rgba(var(--acc-ground-rgb),.30) 0%,
      rgba(var(--acc-ground-rgb),.27) 8%,
      rgba(var(--acc-ground-rgb),.19) 18%,
      rgba(var(--acc-ground-rgb),.10) 28%,
      rgba(var(--acc-ground-rgb),.035) 36%,
      rgba(var(--acc-ground-rgb),0) 44%),
    linear-gradient(to top,
      rgba(var(--acc-ground-rgb),1) 0%,
      rgba(var(--acc-ground-rgb),.97) 8%,
      rgba(var(--acc-ground-rgb),.90) 16%,
      rgba(var(--acc-ground-rgb),.80) 24%,
      rgba(var(--acc-ground-rgb),.67) 32%,
      rgba(var(--acc-ground-rgb),.53) 40%,
      rgba(var(--acc-ground-rgb),.40) 48%,
      rgba(var(--acc-ground-rgb),.28) 56%,
      rgba(var(--acc-ground-rgb),.18) 64%,
      rgba(var(--acc-ground-rgb),.105) 72%,
      rgba(var(--acc-ground-rgb),.055) 80%,
      rgba(var(--acc-ground-rgb),.022) 88%,
      rgba(var(--acc-ground-rgb),0) 100%)
}
.pf-hero-inner{position:relative;z-index:3;width:100%;max-width:900px;margin:0 auto;padding:0 40px 44px;display:flex;flex-direction:column;align-items:center;text-align:center}
/* Icon/shape avatars. The SVG scales with the circle so one preset looks
   right at 32px in the nav and 88px on the profile hero. */
.av-art{width:55%;height:55%;display:block}
.nav-avatar .av-art{width:60%;height:60%}
.st-preset .av-art{width:56%;height:56%}

.pf-name{font-size:52px;font-weight:800;letter-spacing:-.03em;line-height:1.05;color:#fff;text-shadow:0 2px 30px rgba(0,0,0,.6);margin-bottom:12px}
.pf-meta{display:flex;gap:8px;align-items:center;justify-content:center;font-size:14px;color:rgba(255,255,255,.55);flex-wrap:wrap}
.pf-meta .handle{color:#22c55e;font-weight:600}
.pf-meta .sep{opacity:.3}
.lbx-pill{display:inline-flex;align-items:center;gap:7px;background:rgba(0,0,0,.4);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.18);border-radius:100px;padding:4px 12px 4px 9px;transition:border-color .2s}
.lbx-pill:hover{border-color:rgba(255,255,255,.45)}
.lbx-pill .name{font-size:12px;font-weight:600;color:rgba(255,255,255,.85)}
.lbx-dots{display:inline-flex}
.lbx-dots i{width:9px;height:9px;border-radius:50%;display:block}
.lbx-dots i:nth-child(1){background:var(--lbx-orange)}
.lbx-dots i:nth-child(2){background:var(--lbx-green);margin-left:-3px}
.lbx-dots i:nth-child(3){background:var(--lbx-blue);margin-left:-3px}
.lbx-dots--sm i{width:8px;height:8px}
.lbx-dots--sm i:nth-child(2),.lbx-dots--sm i:nth-child(3){margin-left:-2px}
.lbx-dots--lg i{width:14px;height:14px}
.lbx-dots--lg i:nth-child(2),.lbx-dots--lg i:nth-child(3){margin-left:-4px}
.pf-obsession{margin-top:14px;font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.35)}
.pf-obsession .film{color:rgba(255,255,255,.7)}
.pf-obsession .acc-link{margin-left:8px;letter-spacing:.04em;font-weight:700;color:#22c55e}

/* Stat marquee */
.pf-marquee{max-width:1100px;margin:0 auto;padding:8px 64px 0;display:grid;grid-auto-flow:column;grid-auto-columns:1fr;text-align:center}
.pf-stat{padding:0 18px}
.pf-stat-n{font-size:40px;font-weight:800;color:var(--text-primary);letter-spacing:-.02em;line-height:1}
.pf-stat-n.is-green{color:var(--accent-green-text)}
.pf-stat-l{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);margin-top:8px}

/* Pill nav / filter pills — one recipe */
.pf-pills{display:flex;justify-content:center;gap:10px;padding:32px 64px 0;flex-wrap:wrap}
.pf-pill{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-tertiary);padding:9px 20px;border-radius:100px;border:1px solid var(--border-strong);background:var(--hover-subtle);cursor:pointer;transition:color .2s,border-color .2s,background .2s}
.pf-pill:hover{color:var(--text-primary);border-color:var(--border-strong)}
.pf-pill.is-active{color:var(--accent-green-text);background:var(--accent-green-bg);border-color:var(--accent-green-border)}
.pf-pill-badge{min-width:16px;height:16px;border-radius:8px;background:var(--accent-green);color:var(--accent-green-on);font-size:10px;font-weight:800;display:inline-flex;align-items:center;justify-content:center;padding:0 4px;letter-spacing:0}
.pf-pill--filter{font-size:12px;font-weight:700;letter-spacing:0;text-transform:none;padding:7px 15px;gap:6px}
.pf-pill--filter .n{font-weight:600;color:var(--text-muted)}
.pf-pill--filter.is-active .n{color:inherit;opacity:.7}

/* Section dividers */
.pf-divider{display:flex;align-items:center;gap:16px;max-width:1200px;margin:0 auto;padding:40px 64px 0}
.pf-divider::before,.pf-divider::after{content:'';flex:1;height:1px;background:var(--border-light)}
.pf-divider span{display:inline-flex;align-items:center;gap:9px;font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);white-space:nowrap}

/* Poster rows */
.pf-row{display:flex;justify-content:center;align-items:flex-start;gap:18px;padding:26px 64px 0;flex-wrap:wrap}
/* Centred link under a poster row. Same rhythm as the .pf-gstatus line under
   the game band, so the two "there is more this way" links on the page read
   as the same thing. */
.pf-seeall{text-align:center;padding:18px 64px 0;margin:0}
.pf-seeall a{font-size:12.5px;font-weight:600;color:var(--accent-green-text);text-decoration:none}
.pf-seeall a:hover{text-decoration:underline}
.pf-row--recent{padding-top:24px}
/* The five-star wall is five posters and has to stay ONE line — a five-poster
   wall that wraps to 4+1 reads as a broken four-poster wall, which is exactly
   the layout this replaced. So the posters are sized off the row rather than
   fixed: 150px until five of them stop fitting, then whatever fifth of the row
   is left. The gap lives in a custom property because the width has to
   subtract the same number the gap adds. Below 700px the row becomes the
   site's horizontal scroll strip and this is overridden back to a fixed width
   like every other poster row. */
.pf-row--wall{--wall-gap:18px;gap:var(--wall-gap)}
.pf-row--wall .pf-poster{width:min(150px,calc((100% - 4 * var(--wall-gap)) / 5))}
.pf-poster{width:150px;text-align:center}
.pf-poster .art{border-radius:10px;overflow:hidden;box-shadow:0 16px 48px rgba(0,0,0,.5);background:var(--border-light);aspect-ratio:2/3}
.pf-poster .art img{width:100%;height:100%;object-fit:cover}
.pf-poster .stars{font-size:11px;letter-spacing:3px;color:var(--accent-green-text);margin-top:9px}
.pf-poster--sm{width:110px}
.pf-poster--sm .art{border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.4)}
.pf-poster--sm .stars{font-size:10px;letter-spacing:2px;margin-top:7px}
.pf-poster .date{font-size:10.5px;color:var(--text-faint);margin-top:2px}
.star-off{color:var(--text-xfaint)}

/* Locked Predict-the-Weekend board, five across.
   Deliberately the /play/board/ card at profile scale — same green rank chip
   in the same corner, same bottom scrim with the title over the call — because
   a player recognising their own board at a glance is the whole point of
   putting it here. Card width and type sizes are the only things that shrink;
   .pw-card is 190px and carries an editable input, this is 132px and inert.
   Sizes track .pw-card / .pw-chip / .pw-scrim in /play/play.css. */
.pf-row--picks{gap:14px}
.pf-pick{width:132px;position:relative;border-radius:10px;overflow:hidden;
  box-shadow:0 12px 36px rgba(0,0,0,.5);background:var(--bg-card)}
.pf-pick > img{width:100%;display:block;aspect-ratio:2/3;object-fit:cover}
.pf-pick-ph{aspect-ratio:2/3;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(160deg,#26262a,#121214);font-size:22px;font-weight:800;
  color:rgba(255,255,255,.3)}
.pf-pick-chip{position:absolute;top:8px;left:8px;width:22px;height:22px;border-radius:7px;
  background:var(--accent-green);color:var(--accent-green-on);display:inline-flex;
  align-items:center;justify-content:center;font-size:12px;font-weight:800}
.pf-pick-scrim{position:absolute;left:0;right:0;bottom:0;padding:38px 9px 11px;
  background:linear-gradient(transparent,rgba(0,0,0,.94));text-align:center}
/* Two lines reserved for the title so a one-line film and a two-line film put
   their grosses on the same baseline across the row. */
.pf-pick-scrim .t{display:block;font-size:11px;font-weight:700;color:#fff;
  line-height:1.25;min-height:2.5em;margin-bottom:4px}
.pf-pick-scrim .v{display:block;font-size:17px;font-weight:800;color:#fff}

/* Star rows — half-star aware (ratings step by 0.5).
   The half state paints the glyph with a hard-stop gradient and clips it to the
   text, so one ★ reads as exactly half filled at any font size. */
.stars i{font-style:normal;display:inline-block}
.stars .s-full{color:var(--accent-green-text)}
.stars .s-off{color:var(--text-xfaint)}
.stars .s-half{
  background:linear-gradient(90deg,var(--accent-green-text) 0 50%,var(--text-xfaint) 50% 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.pf-logslot{width:110px;aspect-ratio:2/3;display:flex;align-items:center;justify-content:center;border:1px dashed var(--border-strong);border-radius:8px;cursor:pointer;background:none;transition:border-color .2s}
.pf-logslot:hover{border-color:rgba(34,197,94,.5)}
.pf-logslot span{font-size:11.5px;font-weight:600;color:var(--text-muted);text-align:center;padding:0 10px;line-height:1.5}
.pf-caption{text-align:center;padding:16px 64px 0;font-size:11.5px;color:var(--text-faint)}
.pf-caption a{color:var(--text-tertiary);font-weight:600}
.pf-empty{text-align:center;padding:26px 64px 0;font-size:13px;color:var(--text-muted)}

/* Compact hero (films / notifications / settings) */
.pf-hero--compact{height:210px;min-height:0}
/* The 210px strip is the harshest crop on the site, so it needs the film's
   focal point most — the inline object-position wins here too. 50% is the
   no-JS floor; the old hard-coded 25% is gone because it was tuned for wide
   backdrops and beheaded every poster-sourced one. */
.pf-hero--compact .pf-hero-img{object-position:center 50%;filter:brightness(.4)}
.pf-hero--compact::before{display:none}
/* Same easing, shorter throw — this strip is 210px and stays darker overall
   because settings text sits on it. */
.pf-hero--compact::after{
  background:linear-gradient(to top,
    rgba(var(--acc-ground-rgb),1) 0%,
    rgba(var(--acc-ground-rgb),.96) 10%,
    rgba(var(--acc-ground-rgb),.88) 22%,
    rgba(var(--acc-ground-rgb),.76) 34%,
    rgba(var(--acc-ground-rgb),.63) 46%,
    rgba(var(--acc-ground-rgb),.51) 58%,
    rgba(var(--acc-ground-rgb),.41) 70%,
    rgba(var(--acc-ground-rgb),.34) 82%,
    rgba(var(--acc-ground-rgb),.30) 100%)
}
.pf-chead{position:relative;z-index:5;display:flex;align-items:center;gap:14px;padding:0 64px 22px;width:100%;max-width:none}
.pf-chead-avatar{width:48px;height:48px;border-radius:50%;background:rgba(34,197,94,.2);border:2px solid rgba(255,255,255,.25);display:inline-flex;align-items:center;justify-content:center;font-size:15px;font-weight:800;color:#22c55e;flex-shrink:0}
.pf-chead-txt{flex:1;min-width:0}
.pf-chead-title{font-size:22px;font-weight:800;letter-spacing:-.02em;color:#fff}
.pf-chead-sub{font-size:12.5px;color:rgba(255,255,255,.55)}
.pf-chead-sub .handle{color:#22c55e;font-weight:600}
.pf-chead-action{font-size:12px;font-weight:600;color:#22c55e;cursor:pointer;background:none;border:none}
.pf-chead-cta{display:inline-flex;align-items:center;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#052e16;padding:9px 20px;border-radius:100px;background:#22c55e;cursor:pointer;border:none;transition:opacity .2s}
.pf-chead-cta:hover{opacity:.9}

/* ── Films (the member's logged films and ratings) ──────────────────────── */
.rv-filters{display:flex;justify-content:center;align-items:center;gap:8px;padding:26px 64px 0;flex-wrap:wrap}
.rv-filters-label{font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--text-faint);margin-right:6px}
.rv-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:26px 64px 48px;max-width:1140px;margin:0 auto}
.rv-card{display:flex;gap:16px;background:var(--bg-card);border:1px solid var(--border-light);border-radius:14px;padding:16px}
.rv-card-art{width:92px;flex-shrink:0;border-radius:8px;overflow:hidden;box-shadow:0 8px 24px rgba(0,0,0,.4);align-self:flex-start;background:var(--border-light);aspect-ratio:2/3}
.rv-card-art img{width:100%;height:100%;object-fit:cover}
.rv-card-body{flex:1;min-width:0;display:flex;flex-direction:column}
.rv-card-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.rv-card-title{font-size:15px;font-weight:700;color:var(--text-primary)}
.rv-card-stars{font-size:11px;letter-spacing:2px;color:var(--accent-green-text)}
.rv-card-meta{font-size:11px;color:var(--text-faint);margin-top:3px}
/* Rev 3: the rating IS the card. The review body, the like/comment row and the
   whole comment thread that used to live here are gone — deleted rather than
   hidden, so nothing can drift back in behind a display:none. */
.rv-card-foot{display:flex;align-items:center;margin-top:auto;padding-top:12px}
.rv-card-edit{font-size:12px;font-weight:600;color:var(--accent-green-text);cursor:pointer;margin-left:auto;background:none;border:none}
.rv-card-edit:hover{text-decoration:underline}

/* ── Notifications ───────────────────────────────────────────────────────── */
.nt-wrap{width:760px;max-width:100%;margin:0 auto;padding:28px 20px 48px}
.nt-card{background:var(--bg-card);border:1px solid var(--border-light);border-radius:16px;padding:8px 0;overflow:hidden}
.nt-row{display:flex;gap:12px;padding:14px 30px;border-bottom:1px solid var(--border-subtle);cursor:pointer;transition:background .2s;text-align:left;width:100%;background:none;border-left:none;border-right:none;border-top:none}
.nt-row:last-child{border-bottom:none}
.nt-row:hover{background:var(--hover-bg)}
.nt-dot{width:7px;height:7px;border-radius:50%;background:var(--border-strong);flex-shrink:0;margin-top:6px}
.nt-row.is-unread .nt-dot{background:var(--accent-green)}
.nt-body{font-size:13.5px;color:var(--text-tertiary);line-height:1.5}
.nt-row.is-unread .nt-body{color:var(--text-primary)}
.nt-body strong{font-weight:700}
.nt-time{font-size:11px;color:var(--text-faint);margin-top:3px}
.nt-foot{font-size:12.5px;color:var(--text-muted);margin-top:14px;text-align:center}
.nt-empty{padding:40px 30px;text-align:center;font-size:13.5px;color:var(--text-muted)}

/* ── Settings ────────────────────────────────────────────────────────────── */
.st-wrap{width:760px;max-width:100%;margin:0 auto;padding:30px 20px 48px;display:flex;flex-direction:column;gap:20px}
.st-card{background:var(--bg-card);border:1px solid var(--border-light);border-radius:16px;padding:28px 30px}
.st-card-title{font-size:16px;font-weight:700;color:var(--text-primary);margin-bottom:20px}
.st-card-title--tight{margin-bottom:6px}
.st-card-sub{font-size:12.5px;color:var(--text-muted);margin-bottom:14px}
.st-block{display:flex;flex-direction:column;gap:8px;margin-bottom:20px}
.st-presets{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.st-preset-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.st-preset-row-label{font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--text-faint);width:100%;margin-bottom:2px}
.st-preset{width:44px;height:44px;border-radius:50%;border:1px solid var(--border-strong);display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;cursor:pointer;background:var(--hover-bg);transition:border-color .2s,transform .15s;padding:0;flex-shrink:0}
.st-preset:hover{transform:translateY(-1px)}
.st-preset.is-active{width:52px;height:52px;border:2px solid var(--accent-green);font-size:16px}
.st-presets-note{font-size:12px;color:var(--text-muted);margin-left:4px}
.st-obsession{display:flex;align-items:center;gap:14px}
.st-obsession-thumb{width:84px;height:47px;border-radius:8px;overflow:hidden;flex-shrink:0;border:1px solid var(--border-strong);background:var(--border-light)}
.st-obsession-thumb img{width:100%;height:100%;object-fit:cover}
.st-rowtitle{font-size:13.5px;font-weight:600;color:var(--text-primary)}
.st-rowsub{font-size:12px;color:var(--text-muted);margin-top:2px}
.st-row{display:flex;align-items:center;gap:12px;padding:14px 0;border-bottom:1px solid var(--border-subtle)}
.st-row:last-child{border-bottom:none}
.st-row-main{flex:1;min-width:0}
.st-row-sub{font-size:12.5px;color:var(--text-muted);margin-top:2px;overflow-wrap:anywhere}
/* Fixed "letterboxd.com/" prefix sitting inside the field, same trick as the
   "@" prefix on the username input — the prefix is a sibling, absolutely
   positioned over padded input space, so the caret never lands on top of it. */
.st-prefix-wrap{position:relative;display:block}
.st-prefix{position:absolute;left:14px;top:50%;transform:translateY(-50%);font-size:14.5px;color:var(--text-muted);pointer-events:none;white-space:nowrap}
.st-prefix-input{padding-left:124px!important}

/* Inline password / email editors. These replace window.prompt(), which
   rendered whatever was typed as plain text on screen — a real shoulder-surfing
   hole on a password field, and reported as one. The input is type="password"
   with an explicit, user-driven reveal. */
.st-inline-form{display:none;padding:0 0 16px;flex-direction:column;gap:10px}
.st-inline-form.open{display:flex}
.st-pw-wrap{position:relative;display:block}
.st-pw-wrap .acc-input{padding-right:66px}
.st-pw-reveal{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;padding:4px 6px;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);cursor:pointer}
.st-pw-reveal:hover{color:var(--accent-green-text)}
.st-inline-actions{display:flex;gap:10px;align-items:center}
.st-inline-hint{font-size:12px;color:var(--text-muted)}
.st-action{font-size:13px;font-weight:600;color:var(--accent-green-text);cursor:pointer;background:none;border:none;white-space:nowrap}
.st-action--muted{color:var(--text-muted)}
.st-action--muted:hover{color:var(--accent-red-text)}
.st-chip{display:inline-flex;align-items:center;gap:5px;background:var(--accent-green-bg);border-radius:6px;padding:3px 9px;font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--accent-green-text)}
.st-toggle-row{display:flex;align-items:center;gap:12px;padding:12px 0;border-bottom:1px solid var(--border-subtle)}
.st-toggle-row:last-child{border-bottom:none}
.st-toggle-label{flex:1;font-size:13.5px;color:var(--text-primary)}
.st-toggle{width:36px;height:21px;border-radius:11px;background:var(--border-strong);position:relative;cursor:pointer;flex-shrink:0;border:none;padding:0;transition:background .2s}
.st-toggle::after{content:'';position:absolute;top:2.5px;left:2.5px;width:16px;height:16px;border-radius:50%;background:#fff;transition:left .2s}
.st-toggle.is-on{background:var(--accent-green)}
.st-toggle.is-on::after{left:17.5px}
.st-grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:18px}
.st-danger{background:var(--accent-red-bg);border:1px solid var(--accent-red-border);border-radius:16px;padding:24px 30px;display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.st-danger-title{font-size:14px;font-weight:700;color:var(--accent-red-text)}
.st-danger-sub{font-size:12.5px;color:var(--text-tertiary);margin-top:3px}
.st-danger-btn{background:none;border:1px solid rgba(239,68,68,.4);border-radius:8px;padding:9px 18px;font-size:12.5px;font-weight:700;color:var(--accent-red-text);cursor:pointer;transition:background .2s}
.st-danger-btn:hover{background:rgba(239,68,68,.12)}

/* ── Modal (movie picker, log a movie, confirm delete) ───────────────────── */
.acc-modal{position:fixed;inset:0;z-index:500;display:none;align-items:center;justify-content:center;padding:20px;background:rgba(0,0,0,.6);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.acc-modal.open{display:flex}
.acc-modal-card{width:460px;max-width:100%;max-height:86vh;overflow-y:auto;background:var(--bg-card);border:1px solid var(--border-light);border-radius:16px;padding:28px 30px;box-shadow:var(--shadow-elevated)}
.acc-modal-title{font-size:18px;font-weight:700;color:var(--text-primary);margin-bottom:6px}
.acc-modal-sub{font-size:13px;color:var(--text-muted);margin-bottom:18px;line-height:1.55}
.acc-modal-actions{display:flex;gap:10px;margin-top:20px}
.acc-modal-actions .acc-btn{flex:1}
.acc-btn--ghost{background:none;border:1px solid var(--border-strong);color:var(--text-secondary)}
.acc-btn--ghost:hover{background:var(--hover-bg);opacity:1}
.acc-btn--danger{background:var(--accent-red);color:#fff}
.acc-picker-results{margin-top:12px;max-height:280px;overflow-y:auto;display:flex;flex-direction:column;gap:2px}
.acc-picker-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;cursor:pointer;background:none;border:none;text-align:left;width:100%;transition:background .15s}
.acc-picker-item:hover{background:var(--hover-bg)}
.acc-picker-item img{width:34px;height:51px;border-radius:4px;object-fit:cover;flex-shrink:0;background:var(--border-light)}
.acc-picker-item span{font-size:13px;font-weight:600;color:var(--text-primary)}
.acc-stars-pick{display:flex;gap:2px;align-items:center}
.acc-star-btn{background:none;border:none;cursor:pointer;font-size:26px;line-height:1;color:var(--text-xfaint);padding:0 1px;transition:color .15s}
.acc-star-btn.is-on{color:var(--accent-green-text)}
.acc-seg{display:flex;gap:8px}
.acc-seg button{flex:1;padding:9px 0;border-radius:10px;border:1px solid var(--border-strong);background:var(--hover-subtle);color:var(--text-tertiary);font-size:12.5px;font-weight:700;cursor:pointer;transition:all .2s}
.acc-seg button.is-on{color:var(--accent-green-text);background:var(--accent-green-bg);border-color:var(--accent-green-border)}
.acc-textarea{width:100%;min-height:96px;resize:vertical;background:var(--bg-tertiary);border:1px solid var(--border-medium);border-radius:10px;padding:12px 14px;font-size:14px;color:var(--text-primary);line-height:1.55}
.acc-textarea:focus{outline:none;border-color:var(--accent-green);box-shadow:0 0 0 3px var(--accent-green-bg)}
.acc-textarea::placeholder{color:var(--text-muted)}

/* ── Loading / gate states ───────────────────────────────────────────────── */
.acc-loading{padding:120px 20px;text-align:center;font-size:13px;color:var(--text-muted)}
.acc-gate{padding:140px 20px 100px;text-align:center}
.acc-gate h1{font-size:26px;font-weight:800;color:var(--text-primary);margin-bottom:10px}
.acc-gate p{font-size:14px;color:var(--text-muted);margin-bottom:22px}

/* ── The shimmer primitive ──────────────────────────────────────────────────
   One block of grey that sweeps, and nothing else. Every skeleton on the site
   is this class plus a width and a height — the geometry belongs to whatever
   is loading, the material belongs here.

   It started in play/play.css, for the game screens. It lives here now because
   the profile pages needed the same shimmer and do not load play.css, whereas
   every page that loads play.css loads this file first — so this is the one
   place on the site that can define it for all of them. The game-specific
   geometry (.pw-skband, .pw-skstage, .pw-skboard) stays in play.css and reads
   .pw-sk from here. The name stays .pw-sk rather than being tidied to .acc-sk,
   because it is already in the markup of shipped pages and a rename buys
   nothing.

   Reduced motion stops the sweep and leaves the block: the job is to show
   where content will land, and that survives without the animation. */
@keyframes pwShimmer{0%{background-position:-420px 0}100%{background-position:420px 0}}
.pw-sk{border-radius:10px;background:linear-gradient(90deg,
  rgba(255,255,255,.035) 0%,rgba(255,255,255,.085) 50%,rgba(255,255,255,.035) 100%);
  background-size:840px 100%;animation:pwShimmer 1.4s linear infinite}
@media(prefers-reduced-motion:reduce){.pw-sk{animation:none}}

/* ── The profile skeleton ───────────────────────────────────────────────────
   /u/<handle> opened on the words "Loading profile…" centred in 120px of
   padding, then replaced the whole document with a full-bleed hero — so the
   page jumped by most of a screen every single time, and while it waited it
   said nothing about what was coming.

   This is the hero's own geometry instead: 70vh, the name and handle stacked
   and centred where they really sit, the stat marquee under them, a poster row
   below. Tracks .pf-hero / .pf-hero-inner / .pf-marquee / .pf-row above; if
   those move, this moves with them. */
.acc-skprofile{animation:accSkIn .25s ease-out both}
@keyframes accSkIn{from{opacity:0}to{opacity:1}}
@media(prefers-reduced-motion:reduce){.acc-skprofile{animation:none}}

.acc-skprofile .sk-hero{position:relative;min-height:70vh;display:flex;
  align-items:flex-end;overflow:hidden;background:var(--hero-bg-deep)}
.acc-skprofile .sk-hero-in{position:relative;z-index:3;width:100%;max-width:900px;
  margin:0 auto;padding:0 40px 44px;display:flex;flex-direction:column;
  align-items:center;gap:12px}
.acc-skprofile .sk-name{width:min(360px,74%);height:52px;border-radius:12px}
.acc-skprofile .sk-meta{width:200px;height:14px;border-radius:100px}

.acc-skprofile .sk-marquee{max-width:1100px;margin:0 auto;padding:34px 64px 0;
  display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:36px}
.acc-skprofile .sk-stat{display:flex;flex-direction:column;align-items:center;gap:10px}
.acc-skprofile .sk-stat i{display:block;font-style:normal}
.acc-skprofile .sk-stat .n{width:56px;height:40px}
.acc-skprofile .sk-stat .l{width:84px;height:11px;border-radius:100px}

.acc-skprofile .sk-row{display:flex;justify-content:center;gap:18px;
  padding:44px 64px 0;flex-wrap:wrap}
.acc-skprofile .sk-row i{display:block;font-style:normal;width:150px;
  aspect-ratio:2/3;border-radius:10px}
.acc-skprofile .sk-row i:nth-child(4){opacity:.66}
.acc-skprofile .sk-row i:nth-child(5){opacity:.4}

/* Values below are lifted straight off the mobile .pf-marquee / .pf-row /
   .pf-poster rules further up, not eyeballed — including flex-start, which
   matters: centring a nowrap row that overflows clips it at BOTH ends, so the
   first poster arrived half off the left edge and the skeleton promised a
   layout the page does not have. */
@media(max-width:700px){
  .acc-skprofile .sk-hero{min-height:56vh}
  .acc-skprofile .sk-hero-in{padding:0 20px 32px}
  .acc-skprofile .sk-name{height:34px}
  .acc-skprofile .sk-marquee{padding:20px 12px 0;gap:0}
  .acc-skprofile .sk-stat{gap:6px;padding:0 4px}
  .acc-skprofile .sk-stat .n{width:44px;height:30px}
  .acc-skprofile .sk-stat .l{width:58px;height:9px}
  .acc-skprofile .sk-row{justify-content:flex-start;flex-wrap:nowrap;overflow:hidden;
    gap:12px;padding:20px 20px 4px}
  .acc-skprofile .sk-row i{width:120px;flex:0 0 auto}
}

/* Between the phone strip and the width where five 150px posters fit, the
   wall trades side padding and gap for poster size — 64px of air on each side
   is a desktop rhythm, and at 800px it is just squeezing the posters. */
@media(max-width:960px) and (min-width:701px){
  .pf-row--wall{--wall-gap:14px;padding-left:28px;padding-right:28px}
}

/* ── RESPONSIVE — site convention is a 700px breakpoint ──────────────────── */
@media(max-width:700px){
  .optb-nav{padding:0 16px;height:48px;gap:16px}
  .optb-nav .optb-links{display:none}
  .optb-nav .hamburger-btn{display:block}
  .optb-menu,.bow-acct-menu{top:48px}
  .acc-auth-links{display:none}
  .optb-menu .bow-auth-mobile,.bow-auth-mobile{display:flex}
  .search-wrap{position:static}
  .search-input-wrap{position:fixed;top:0;left:0;right:0;transform:none;height:48px;padding:6px 16px;background:rgba(0,0,0,.85);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);z-index:400}
  .search-input-wrap.open{width:auto}
  .search-dropdown{position:fixed;top:48px;left:8px;right:8px;width:auto;max-height:60vh;z-index:400}

  .acc-shell{padding:80px 20px 40px}
  .acc-card,.acc-card--wide,.acc-card--mid{width:100%;padding:28px 20px}
  .acc-oauth-row--split{flex-direction:column}
  .acc-code{gap:6px}
  .acc-code input{height:52px;font-size:19px}
  .acc-coderow{flex-direction:column;align-items:flex-start;gap:8px}

  /* Was 85vh, which on a phone left nothing but hero above the fold — the
     stats row sat entirely below it. 78vh keeps the hero dominant while the
     first row of numbers peeks in, so the page reads as a profile rather than
     a full-bleed poster. Desktop stays at 70vh. */
  .pf-hero{min-height:78vh}
  .pf-hero-inner{padding:0 20px 32px}
  .pf-name{font-size:32px;margin-bottom:10px}
  .pf-meta{font-size:12.5px;gap:6px}
  /* Three across, not 2x2. The odd third cell stranded on its own row read
     as a layout bug on a phone. Type steps down so FIVE-STAR FILMS still
     fits a ~110px column without wrapping. */
  .pf-marquee{grid-auto-flow:column;grid-auto-columns:1fr;grid-template-columns:none;gap:0;padding:20px 12px 0}
  .pf-stat{padding:0 4px}
  .pf-stat-n{font-size:30px}
  .pf-stat-l{font-size:9px;letter-spacing:.045em;margin-top:6px}
  /* Band wraps 4 -> 2x2 like the marquee above it. The 1px gap becomes the
     rule between all four cells, so the grid keeps its ruled look. */
  .pf-band{grid-template-columns:1fr 1fr;margin:22px 20px 0}
  .pf-band-cell{padding:14px 10px 16px;grid-template-rows:34px 26px auto;gap:5px}
  .pf-band-mark{height:34px;font-size:20px}
  .pf-band-i{width:22px;height:22px}
  .pf-band-mark.is-badge .pw-champ-medal{width:32px;height:32px}
  .pf-band-n{font-size:22px}
  .pf-band-cell:first-child .pf-band-n{font-size:14px}
  .pf-band-l{font-size:9.5px;letter-spacing:.05em}
  .pf-gstatus{padding:14px 20px 0;font-size:12px;line-height:1.7}
  .pf-pills{padding:26px 16px 0;gap:8px}
  .pf-pill{padding:8px 15px;font-size:11px}
  .pf-divider{padding:32px 20px 0;gap:12px}

  /* poster rows become horizontal scroll — the site's .pstrip pattern */
  .pf-row{justify-content:flex-start;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding:20px 20px 4px;gap:12px}
  .pf-row::-webkit-scrollbar{display:none}
  .pf-poster{width:120px;flex-shrink:0}
  /* Beats the fluid .pf-row--wall .pf-poster rule above (two classes to one),
     which is the point: on a phone the wall scrolls like the rows around it
     instead of squeezing five posters into 320px. */
  .pf-row--wall .pf-poster{width:120px}
  .pf-poster--sm{width:96px}
  /* Inherits the scroll strip above, so all five stay reachable on a phone
     rather than wrapping into a ragged 3+2. */
  .pf-pick{width:112px;flex-shrink:0}
  .pf-pick-scrim{padding:32px 8px 10px}
  .pf-pick-scrim .v{font-size:15px}
  .pf-logslot{width:96px;flex-shrink:0}
  .pf-caption{padding:14px 20px 0}
  .pf-seeall{padding:16px 20px 0}

  .pf-hero--compact{height:190px;min-height:0}
  .pf-chead{padding:0 20px 18px;gap:10px;flex-wrap:wrap}
  .pf-chead-title{font-size:19px}
  .pf-chead-avatar{width:40px;height:40px;font-size:13px}
  .pf-chead-cta{width:100%;justify-content:center;margin-top:4px}

  .rv-filters{justify-content:flex-start;padding:22px 20px 0;overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none}
  .rv-filters::-webkit-scrollbar{display:none}
  .rv-pill-scroll{flex-shrink:0}
  .rv-grid{grid-template-columns:1fr;padding:22px 20px 40px;gap:12px}
  .rv-card{padding:14px;gap:12px}
  .rv-card-art{width:74px}

  .nt-wrap,.st-wrap{padding-left:16px;padding-right:16px}
  .nt-row{padding:14px 18px}
  .st-card{padding:22px 18px}
  .st-grid2{grid-template-columns:1fr;gap:16px}
  .st-danger{padding:20px 18px}
  .st-danger-btn{width:100%}
  .site-footer{padding:40px 24px 30px}
}

/* ============================================================================
   REV 3 · EDITORIAL AUTH  — /login /signup /welcome /verify /reset
   ----------------------------------------------------------------------------
   The rev-2 auth screens were a frosted card floated in the middle of a film
   still. Rev 3 throws the card away: the form sits flush-left directly on the
   backdrop, in the same language as a movie-page hero — kicker, big headline
   with a period, underline fields, uppercase pills. Nothing here is a new
   invention; every value is lifted from a component the site already ships
   (the newsletter form's underline inputs, the homepage's hv2-btn pills, the
   analysis rules).

   These classes live alongside the rev-2 .acc-card set rather than replacing
   it, because /account/settings and the modals still use cards and should.
   Anything named .acc-cine* belongs to this layer.

   Both themes stay dark here: .acc-page--cinema already joins the :root
   token declaration, and these screens are hero-zone by definition.
============================================================================ */

/* ── Shell ────────────────────────────────────────────────────────────────
   Flush-left, vertically centred, on a full-bleed backdrop. The 96px inset
   matches the movie-page hero's content inset at desktop width. */
.acc-cine .acc-shell{justify-content:flex-start;padding:40px 96px;align-items:center}
.acc-cine-col{width:420px;max-width:100%}
.acc-cine-col--wide{width:620px;max-width:100%}

/* The rev-2 veil fades bottom-to-top, which is right for a centred card and
   wrong for left-anchored type — the left third needs to be dense enough to
   carry 46px white text at AA while the right stays open enough to read as a
   film still. So: a 100deg horizontal ramp first, the vertical fade second. */
.acc-cine .acc-cinema-bg{filter:brightness(.4)}
.acc-cine .acc-cinema-veil{background:
  linear-gradient(100deg,rgba(10,10,10,.96) 0%,rgba(10,10,10,.88) 34%,rgba(10,10,10,.45) 60%,rgba(10,10,10,.2) 100%),
  linear-gradient(to top,#0a0a0a 0%,rgba(10,10,10,.4) 22%,transparent 45%)}
/* Signup carries two columns of content, so its ramp has to hold density
   further across the frame than login's does. */
.acc-cine--split .acc-cinema-bg{filter:brightness(.35)}
.acc-cine--split .acc-cinema-veil{background:
  linear-gradient(100deg,rgba(10,10,10,.97) 0%,rgba(10,10,10,.92) 40%,rgba(10,10,10,.6) 70%,rgba(10,10,10,.35) 100%),
  linear-gradient(to top,#0a0a0a 0%,rgba(10,10,10,.4) 20%,transparent 42%)}
/* The short panels (handle, code, reset) are 620px of content on a 960px
   frame — denser still, and held further right. */
.acc-cine--panel .acc-cinema-bg{filter:brightness(.3)}
.acc-cine--panel .acc-cinema-veil{background:
  linear-gradient(100deg,rgba(10,10,10,.97) 0%,rgba(10,10,10,.9) 45%,rgba(10,10,10,.5) 100%),
  linear-gradient(to top,#0a0a0a 0%,rgba(10,10,10,.3) 25%,transparent 55%)}

/* ── Type ─────────────────────────────────────────────────────────────────
   Kicker → headline → lede, the site's standard editorial stack. The headline
   carries a text-shadow because it sits on photography, not on a panel. */
.acc-kicker{font-size:11px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;color:var(--accent-green-text);margin-bottom:14px}
.acc-head{font-size:46px;font-weight:800;letter-spacing:-.03em;line-height:1.05;color:#fff;text-shadow:0 2px 30px rgba(0,0,0,.6);margin:0 0 12px}
.acc-head--md{font-size:44px;line-height:1.08;letter-spacing:-.03em}
.acc-head--sm{font-size:34px;line-height:1.15;letter-spacing:-.02em;margin-bottom:8px}
.acc-lede{font-size:14.5px;color:rgba(255,255,255,.65);line-height:1.6;margin:0 0 36px}
.acc-lede--tight{margin-bottom:30px;font-size:14px;color:rgba(255,255,255,.55)}
.acc-lede strong{color:#fff;font-weight:600}

/* ── Underline fields — the newsletter-form pattern ───────────────────────
   No side borders, no fill, no radius. Focus moves the bottom rule to green;
   nothing else changes, so the field never jumps. */
.acc-ul-label{display:block;font-size:11px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;color:rgba(255,255,255,.4);margin-bottom:2px}
.acc-ul-label .opt{letter-spacing:.02em;text-transform:none;font-weight:600;color:rgba(255,255,255,.3)}
.acc-ul-label--sp{margin-top:24px}
.acc-ul{width:100%;background:none;border:none;border-bottom:1px solid rgba(255,255,255,.25);border-radius:0;padding:10px 0 12px;font-size:17px;color:#fff;font-family:inherit;transition:border-color .2s}
.acc-ul::placeholder{color:rgba(255,255,255,.35)}
.acc-ul:focus{outline:none;border-bottom-color:var(--accent-green)}
.acc-ul:focus-visible{outline:none}
.acc-ul:disabled{opacity:.5}
/* Baked "@" prefix: the rule belongs to the wrapper so the glyph sits inside
   the same underline as the text rather than above its own stub. */
.acc-ul-at{display:flex;align-items:baseline;border-bottom:1px solid rgba(255,255,255,.25);transition:border-color .2s}
.acc-ul-at:focus-within{border-bottom-color:var(--accent-green)}
.acc-ul-at .at{font-size:17px;color:rgba(255,255,255,.4);padding:10px 2px 12px 0}
.acc-ul-at .acc-ul{flex:1;border-bottom:none}

/* account.js wraps every password input in .acc-input-pw and drops an eye
   button in the corner. That recipe was written for the 44px-tall filled
   .acc-input; an underline field is taller and carries no right padding, so
   without these two rules the eye lands under the text and a long value runs
   straight through it. */
.acc-input-pw .acc-ul{padding-right:44px}
.acc-cine .acc-input-pw{position:relative;display:block}
.acc-cine .acc-input-pw .acc-pw-toggle{right:-6px;top:20px;transform:none}

/* ── Browser autofill ─────────────────────────────────────────────────────
   Chrome and Safari paint their own pale-blue plate, text colour and font
   straight over an autofilled field. On these screens that turns a hairline
   underline on a film still into a solid white slab with system-font text in
   it — which is exactly what it looks like.

   You cannot just re-declare `background`: the UA autofill rule wins. The
   usual workaround, `box-shadow: 0 0 0 1000px <colour> inset`, needs an
   OPAQUE colour to cover the plate, and painting a solid block over the
   backdrop is the same problem in a different colour.

   So two techniques that keep the field genuinely transparent:
     · background-clip:text  clips the autofill plate to the glyphs themselves,
       so there is no slab left to see;
     · the long transition on background-color is the belt-and-braces fallback
       for engines that ignore the clip — the plate is applied as a transition,
       so an effectively infinite duration means it never visibly lands.
   -webkit-text-fill-color beats the UA text colour (plain `color` does not),
   and font-family/size are restated because Chrome swaps the face too. */
.acc-ul:-webkit-autofill,
.acc-ul:-webkit-autofill:hover,
.acc-ul:-webkit-autofill:focus,
.acc-ul:-webkit-autofill:active,
.acc-digit:-webkit-autofill,
.acc-digit:-webkit-autofill:focus{
  -webkit-text-fill-color:#fff;
  caret-color:#fff;
  -webkit-background-clip:text;
  background-clip:text;
  transition:background-color 600000s 0s,color 600000s 0s,border-color .2s;
  font-family:inherit !important;
}
.acc-ul:-webkit-autofill{font-size:17px}
.acc-digit:-webkit-autofill{font-size:26px;-webkit-text-fill-color:#fff}
/* Firefox, and the standardised alias. Deliberately NOT the `background`
   shorthand: Chrome matches BOTH :-webkit-autofill and :autofill, and a
   shorthand here resets background-clip to border-box, quietly undoing the
   clip in the rule above and leaving the transition as the only thing holding
   the plate back. Long-hand only, and restate the clip. */
.acc-ul:autofill{
  background-color:transparent;
  -webkit-background-clip:text;
  background-clip:text;
  -webkit-text-fill-color:#fff;
  color:#fff;
  font-family:inherit;
}

/* Availability / inline field status. One slot, three states — reserving the
   height stops the button below hopping every time the check resolves. */
.acc-avail{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:600;margin-top:8px;min-height:16px;color:rgba(255,255,255,.4)}
.acc-avail svg{width:13px;height:13px;flex-shrink:0}
.acc-avail.is-ok{color:var(--accent-green-text)}
.acc-avail.is-bad{color:var(--accent-red-text)}

/* ── Buttons ──────────────────────────────────────────────────────────────
   Primary = solid green pill. flex-shrink:0 + nowrap are load-bearing: these
   sit in a flex row next to a text link and would otherwise squeeze. */
.acc-pill{display:inline-flex;align-items:center;justify-content:center;background:var(--accent-green);color:#fff;border:none;border-radius:100px;padding:12px 32px;flex-shrink:0;white-space:nowrap;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;cursor:pointer;font-family:inherit;transition:opacity .2s}
.acc-pill:hover{opacity:.85}
.acc-pill:disabled{opacity:.5;cursor:default}
.acc-pillrow{display:flex;align-items:center;gap:16px;margin-top:26px;flex-wrap:wrap}
.acc-pillrow--sp{margin-top:30px}
.acc-pillrow .acc-aside{font-size:12.5px;color:rgba(255,255,255,.45)}
.acc-pillrow .acc-aside a,.acc-cine-link{color:var(--accent-green-text);font-weight:600;text-decoration:none;cursor:pointer}
/* Several of these links are <button> elements (they run JS rather than
   navigate). Without the reset the UA border and grey face show through and
   they read as tiny grey boxes sitting in a line of prose. */
button.acc-cine-link{background:none;border:none;padding:0;font-family:inherit;font-size:inherit;line-height:inherit}
button.acc-cine-link:focus-visible,.acc-cine-link:focus-visible{outline:2px solid var(--focus-ring);outline-offset:3px;border-radius:3px}
.acc-pillrow .acc-aside a:hover,.acc-cine-link:hover{text-decoration:underline}
.acc-cine-link--plain{font-size:13px}

/* Secondary / OAuth = outlined uppercase pill, the homepage hv2-btn recipe. */
.acc-opills{display:flex;gap:10px;flex-wrap:wrap}
.acc-opills--split .acc-opill{flex:1;padding:10px 0}
.acc-opill{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.7);padding:10px 20px;border-radius:100px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.03);cursor:pointer;font-family:inherit;transition:color .2s,border-color .2s}
.acc-opill:hover{color:#fff;border-color:rgba(255,255,255,.3)}
.acc-opill:disabled{opacity:.5;cursor:default}
.acc-opill svg{flex-shrink:0}

/* ── Rules & dividers ─────────────────────────────────────────────────────*/
.acc-rule{display:flex;align-items:center;gap:14px;margin:34px 0 18px}
.acc-rule::before,.acc-rule::after{content:'';flex:1;height:1px;background:rgba(255,255,255,.12)}
.acc-rule span{font-size:10px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;color:rgba(255,255,255,.4)}
.acc-rule--tight{margin:0 0 22px}
.acc-cine-foot{border-top:1px solid rgba(255,255,255,.12);margin-top:34px;padding-top:18px;font-size:13.5px;color:rgba(255,255,255,.55)}
.acc-cine-foot--tight{margin-top:28px;padding-top:16px}

/* ── Signup: ruled benefit rows ───────────────────────────────────────────*/
.acc-benefits{border-top:1px solid rgba(255,255,255,.12);margin-top:28px}
.acc-benefit{padding:15px 0;border-bottom:1px solid rgba(255,255,255,.08)}
.acc-benefit b{font-size:14.5px;font-weight:700;color:#fff}
.acc-benefit span{font-size:14px;color:rgba(255,255,255,.55)}
/* ── Signup: benefit chips (phone widths only) ────────────────────────────
   Under 700px the four ruled benefit rows are what pushed the form below the
   fold, so they swap for three equal chips on one row (markup sits right
   after .acc-benefits in signup/index.html). Desktop keeps the rows; the
   chips do not exist there. Equal size comes from the grid, not the content:
   three 1fr tracks and a fixed height, labels wrapping inside. */
.acc-chips{display:none}
@media(max-width:700px){
  .acc-benefits{display:none}
  .acc-chips{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin-top:18px}
  .acc-chip{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;
    height:64px;padding:8px 6px;border-radius:12px;border:1px solid rgba(255,255,255,.14);
    background:rgba(255,255,255,.03);font-size:11px;font-weight:700;color:rgba(255,255,255,.7);
    text-align:center;line-height:1.25}
  .acc-chip svg{flex-shrink:0}
  /* Two headline lines are one too many over the chips; the first line hides
     and "The whole box office." carries the page. */
  .acc-head-line1{display:none}
}

.acc-cine-split{display:flex;align-items:center;gap:96px;flex-wrap:wrap}
.acc-cine-split .acc-cine-left{width:440px;max-width:100%}
.acc-cine-split .acc-cine-right{width:400px;max-width:100%}

/* ── Compact checkboxes (15px, not the card set's 16px) ───────────────────*/
.acc-checks--sm{gap:12px;margin-top:24px}
.acc-check--sm .box{width:15px;height:15px;border-radius:3px;border-color:rgba(255,255,255,.3)}
.acc-check--sm .box svg{width:10px;height:10px}
.acc-check--sm .txt{font-size:12.5px;color:rgba(255,255,255,.65)}

/* ── One-time code: eight underline digit cells ───────────────────────────
   Fixed 40px cells rather than flex:1, because the design's rhythm depends on
   the gap staying 10px at every width; below 700px they shrink together. */
.acc-digits{display:flex;gap:10px;margin-bottom:26px}
.acc-digit{width:40px;flex:0 0 40px;text-align:center;font-size:26px;font-weight:800;color:#fff;background:none;border:none;border-radius:0;padding:4px 0 10px;border-bottom:2px solid rgba(255,255,255,.2);font-family:inherit;transition:border-color .2s}
.acc-digit:focus{outline:none;border-bottom-color:var(--accent-green)}
.acc-digit::-webkit-outer-spin-button,.acc-digit::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.acc-coderow--cine{display:flex;align-items:center;justify-content:space-between;gap:16px;font-size:13px;color:rgba(255,255,255,.45);flex-wrap:wrap}

/* Errors read on photography, so they get a tinted plate rather than bare
   red text the way the card version could get away with. */
.acc-cine .acc-error:not(:empty){margin-top:20px;background:rgba(239,68,68,.12);border:1px solid rgba(239,68,68,.3);border-radius:10px;padding:10px 14px}

/* ── Responsive — the site's 700px break ──────────────────────────────────*/
@media(max-width:1100px){
  .acc-cine .acc-shell{padding:40px 56px}
  .acc-cine-split{gap:56px}
}
@media(max-width:900px){
  /* Two columns stop fitting well before 700px: the benefit rows go full
     width above the form rather than squeezing to 240px each. */
  .acc-cine-split{flex-direction:column;align-items:stretch;gap:40px}
  .acc-cine-split .acc-cine-left,.acc-cine-split .acc-cine-right{width:100%}
}
@media(max-width:700px){
  .acc-cine .acc-shell{padding:88px 20px 40px;align-items:flex-start}
  .acc-cine-col,.acc-cine-col--wide{width:100%}
  .acc-head{font-size:34px}
  .acc-head--md{font-size:32px}
  .acc-head--sm{font-size:27px}
  .acc-lede{margin-bottom:28px}
  .acc-opills .acc-opill{flex:1 1 100%}
  .acc-opills--split .acc-opill{flex:1 1 0}
  .acc-pillrow .acc-pill{width:100%}
  /* Eight fixed 40px cells + seven 10px gaps needs 390px. Below that they
     share the width instead, and the gap tightens with them. */
  .acc-digits{gap:6px}
  .acc-digit{width:auto;flex:1 1 0;min-width:0;font-size:22px}
}

/* ── Predict the Final, on a profile ────────────────────────────────────────
   A list, not a stat band. The weekend game is a score — four numbers say it
   all — but a final call is one number about one film and only reads with the
   film beside it. Rows link straight to that film's card on /play/final/. */
/* Two-up from 960px (Aug 2026). A call row is short — poster, title, one
   number — so a single 900px column left half the band empty and pushed a
   five-film list well below the fold. The box widens to the page's standard
   1200/64 so it lines up with .pf-divider above it instead of sitting inset
   from it. Below 960px it stays one column: two columns of ~300px ellipsize
   a title like "Spider-Man: Brand New Day" into nothing. */
.pf-fc-list{max-width:1200px;margin:0 auto;padding:18px 64px 0;
  display:grid;grid-template-columns:minmax(0,1fr);column-gap:36px}
.pf-fc-row{display:flex;align-items:center;gap:14px;padding:12px 0;text-decoration:none;
  border-bottom:1px solid var(--border-light)}
.pf-fc-row:last-child{border-bottom:none}
@media(min-width:960px){
  .pf-fc-list{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* Grid fills row-major, so "no border" has to track the last ROW, not the
     last item. That row is the final item plus the one before it WHEN THE
     COUNT IS EVEN — and on an even count the second-to-last item always sits
     at an odd 1-based index. On an odd count :nth-child(odd) fails there,
     which is right: that item belongs to the row above and keeps its rule. */
  .pf-fc-row:nth-last-child(2):nth-child(odd){border-bottom:none}
}
.pf-fc-art{width:40px;flex-shrink:0;border-radius:5px;overflow:hidden;background:var(--bg-card)}
.pf-fc-art img{width:100%;display:block;aspect-ratio:2/3;object-fit:cover}
.pf-fc-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.pf-fc-title{font-size:14.5px;font-weight:600;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pf-fc-meta{font-size:11.5px;color:var(--text-faint)}
.pf-fc-right{text-align:right;flex-shrink:0}
.pf-fc-val{font-size:17px;font-weight:800;color:#fff;font-variant-numeric:tabular-nums}
.pf-fc-sub{font-size:11px;color:var(--text-muted);margin-top:2px}
.pf-fc-row:hover .pf-fc-title{color:var(--accent-green-text)}

@media(max-width:700px){
  .pf-fc-list{padding:16px 20px 0}
  .pf-fc-title{font-size:13.5px}
  .pf-fc-val{font-size:15.5px}
}

/* ── Five-star wall picker (settings) ──────────────────────────────────────
   The summary row in the Profile card, and the modal it opens. Poster grid
   rather than a list because the wall itself is posters — you are choosing a
   picture, so you should be looking at the picture while you choose. */
.st-wall-mini{display:flex;gap:5px;flex-shrink:0}
.st-wall-thumb{width:32px;height:47px;border-radius:5px;overflow:hidden;flex-shrink:0;border:1px solid var(--border-strong);background:var(--border-light)}
.st-wall-thumb img{width:100%;height:100%;object-fit:cover;display:block}
/* An unset wall shows four empty frames, so the row still reads as four
   slots waiting to be filled rather than as a missing image. */
.st-wall-thumb.is-empty{border-style:dashed;background:var(--hover-subtle)}

/* Wider than the search-style pickers: this one shows a poster grid, and at
   460px four columns leave the posters too small to recognise. */
.acc-modal-card--wide{width:560px}

.st-wall-count{font-size:11.5px;font-weight:600;color:var(--text-muted);margin:2px 0 14px}
.st-wall-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;max-height:46vh;overflow-y:auto;padding:2px}
.st-wall-pick{position:relative;padding:0;border:none;background:none;cursor:pointer;border-radius:8px;overflow:hidden;aspect-ratio:2/3;transition:transform .12s}
.st-wall-pick img{width:100%;height:100%;object-fit:cover;display:block;border-radius:8px;background:var(--border-light)}
/* Unchosen posters sit back so the chosen four read as the wall at a glance;
   dimming the rest does more work here than highlighting the picks would. */
.st-wall-pick img{opacity:.45;transition:opacity .12s}
.st-wall-pick:hover img{opacity:.75}
.st-wall-pick.is-on img{opacity:1}
.st-wall-pick.is-on{outline:2px solid var(--accent-green-text);outline-offset:-2px}
.st-wall-pick:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.st-wall-badge{position:absolute;top:5px;left:5px;min-width:19px;height:19px;border-radius:50%;background:var(--accent-green-text);color:var(--accent-green-on);font-size:11px;font-weight:800;line-height:19px;text-align:center;box-shadow:0 1px 4px rgba(0,0,0,.4)}

@media (max-width:560px){
  .st-wall-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
  .st-wall-mini{gap:3px}
  .st-wall-thumb{width:23px;height:34px}
}

/* Narrowest phones (SE, mini): three marquee columns drop to ~100px, so the
   longest label (FIVE-STAR FILMS) needs one more step down to stay on a line. */
@media (max-width:380px){
  .pf-marquee{padding:20px 8px 0}
  .pf-stat{padding:0 2px}
  .pf-stat-n{font-size:26px}
  .pf-stat-l{font-size:8.5px;letter-spacing:.03em}
}

/* ── Floating toast ──────────────────────────────────────────────────────────
   For messages belonging to a control with no error slot of its own — see
   BOW.toast() in account.js. Fixed to the bottom centre so it cannot reflow the
   card it was fired from; pointer-events off so it can never swallow a tap on
   whatever is underneath it. */
.acc-toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,12px);z-index:120;
  max-width:min(460px,calc(100vw - 32px));padding:11px 16px;border-radius:10px;
  background:rgba(18,18,20,.96);border:1px solid rgba(255,255,255,.14);
  box-shadow:0 10px 30px rgba(0,0,0,.45);color:#fff;font-size:13.5px;line-height:1.45;
  text-align:center;opacity:0;pointer-events:none;
  transition:opacity .18s ease,transform .18s ease}
.acc-toast.show{opacity:1;transform:translate(-50%,0)}
.acc-toast--error{border-color:rgba(239,68,68,.55)}
@media(prefers-reduced-motion:reduce){.acc-toast{transition:none}}

/* ── Champion badge (mirrors play.css; markup from PW.champBadge) ────────────────────────────────────────────────────────
   Drawn by PW.champBadge(). Gold is expressed as a gradient on the medal and a
   flat tint on the text so the mark reads at 18px in a table row and at 64px on
   a podium without two separate treatments. */
.pw-champ{display:inline-flex;align-items:center;gap:8px;vertical-align:middle}
.pw-champ-medal{display:inline-grid;place-items:center;flex:none;color:#f5c542;
  filter:drop-shadow(0 1px 3px rgba(234,179,8,.35))}
.pw-champ-medal svg{width:100%;height:100%;display:block;overflow:visible}
.pw-champ-medal .lf{opacity:.75}
.pw-champ-t{font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--accent-yellow-text);white-space:nowrap}

.pw-champ--sm .pw-champ-medal{width:20px;height:20px}
.pw-champ--sm .pw-champ-t{font-size:9.5px}
.pw-champ--md .pw-champ-medal{width:30px;height:30px}
.pw-champ--md .pw-champ-t{font-size:11px}
.pw-champ--lg{flex-direction:column;gap:10px}
.pw-champ--lg .pw-champ-medal{width:64px;height:64px}
.pw-champ--lg .pw-champ-t{font-size:12px;letter-spacing:.14em}

/* The tier tints. These were only ever in play.css, which the profile pages do
   NOT load — so every medal on a profile drew gold, including the silvers and
   the bronzes. Harmless while the medal only appeared inside a tinted chip;
   wrong the moment a bare medal leads the stat band. Keep in step with the
   same block in play.css. */
.pw-champ--gold   .pw-champ-medal{color:#f5c542;filter:drop-shadow(0 1px 3px rgba(234,179,8,.35))}
.pw-champ--gold   .pw-champ-t{color:#f5c542}
.pw-champ--silver .pw-champ-medal{color:#cbd2da;filter:drop-shadow(0 1px 3px rgba(203,210,218,.25))}
.pw-champ--silver .pw-champ-t{color:#cbd2da}
.pw-champ--bronze .pw-champ-medal{color:#cc8b52;filter:drop-shadow(0 1px 3px rgba(204,139,82,.3))}
.pw-champ--bronze .pw-champ-t{color:#cc8b52}

/* Placing chips on a profile — the medal sits inside the chip, so the chip's
   own tint follows the tier rather than a single gold for all three. */
.pf-chip--badge{display:inline-flex;align-items:center;gap:7px;padding-left:6px}
.pf-chip--gold{background:rgba(234,179,8,.12);border-color:rgba(234,179,8,.35);color:#f5c542}
.pf-chip--silver{background:rgba(203,210,218,.1);border-color:rgba(203,210,218,.3);color:#cbd2da}
.pf-chip--bronze{background:rgba(204,139,82,.12);border-color:rgba(204,139,82,.32);color:#cc8b52}

/* Footer nav row — About / Privacy / Terms / Contact. Higher specificity than
   .site-footer a so it wins regardless of source order. */
.site-footer .footer-links{display:flex;flex-wrap:wrap;justify-content:center;gap:6px 20px;margin:0 0 14px;padding:0}
.site-footer .footer-links a{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);text-decoration:none;transition:color .2s}
.site-footer .footer-links a:hover{color:var(--text-primary)}
@media(max-width:560px){.site-footer .footer-links{gap:6px 13px}.site-footer .footer-links a{font-size:10.5px;letter-spacing:.05em}}

/* ── Provider-row agreement line (/signup/) ──────────────────────────────────
   Replaces a terms-checkbox gate that used to live inside the OAuth click
   handler. The buttons are at the top of the card, the checkbox was inside the
   form below them, and the refusal rendered under the whole form — so the
   provider buttons read as broken. Consent is stated here instead, in the one
   place a reader is actually looking when they reach for Google. Deliberately
   quiet: it is fine print, not an instruction. */
.acc-oauth-terms{margin:-14px 0 22px;font-size:11.5px;line-height:1.5;
  color:var(--text-faint);max-width:420px}
.acc-oauth-terms[hidden]{display:none}
