/* FilmJinx. Mobile-first (spec req 3). Two visual acts:
   front-of-house = pink+cyan neon marquee (home, lobby);
   auditorium = calm dark navy with one cyan action colour (everything past setup).
   Fonts self-hosted (offline-capable, no external calls). */

/* ---- self-hosted fonts ---- */
@font-face{font-family:'Monoton';src:url('/fonts/monoton.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Marcellus';src:url('/fonts/marcellus.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Hanken Grotesk';src:url('/fonts/hanken-400.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Hanken Grotesk';src:url('/fonts/hanken-500.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Hanken Grotesk';src:url('/fonts/hanken-600.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'Space Mono';src:url('/fonts/spacemono-400.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Space Mono';src:url('/fonts/spacemono-700.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}

:root{
  /* front-of-house neon */
  --pink:#F86AB0; --cyan-neon:#3FD3DC; --bulb:#FFE7B0; --bulb-glow:rgba(245,193,71,.8);
  /* auditorium (calm interior) */
  --page:#0b0e1a; --panel:#12162f; --card:#141a2e; --line:#262c48; --line2:#323a63;
  --cream:#E8E6DF; --dim:#8B90A8;
  /* the single action colour + its quiet tint */
  --accent:#40D0DA; --accent-ink:#052a2e;
  --accent-tint:rgba(64,208,218,.13); --accent-tint-line:rgba(64,208,218,.42); --accent-tint-ink:#9be9ef;
  --amber:#E0A94A; --danger:#E23B4E;
  /* UI-uplift R1: anchors take the one action colour, underlined, so no visible
     link falls back to browser-default blue/purple (invisible on the dark card). */
  --link:#40D0DA;
  --font-body:'Hanken Grotesk',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --font-head:'Marcellus',Georgia,serif;
  --font-mono:'Space Mono',ui-monospace,monospace;
  --font-neon:'Monoton',cursive;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0;color:var(--cream);font-family:var(--font-body);
  background:#0b0e1a;position:relative;overflow-x:hidden;isolation:isolate}
/* ---- UI-uplift W2 T0: animated neon background system. Fixed, negative-z
   layers behind every screen; html,body sets isolation:isolate so they stay
   contained and paint behind content. The old opaque page gradient's job moves
   into .stage (now a radial). bg.js spawns the drifting .bokeh/.streak and
   gates itself on reduced motion; the guard here is the CSS backstop for the
   static grain and anything already in the DOM. ---- */
.stage{position:fixed;inset:0;z-index:-3;pointer-events:none;
  background:radial-gradient(140% 120% at 20% 10%,#171d38 0%,#10142b 45%,#0b0e1a 100%)}
.vignette{position:fixed;inset:0;pointer-events:none;z-index:-1;
  background:radial-gradient(120% 120% at 50% 50%,transparent 55%,rgba(0,0,0,.53) 100%)}
.grain{position:fixed;inset:-50%;pointer-events:none;z-index:-1;opacity:.135;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grainShift 8s steps(6) infinite}
@keyframes grainShift{0%,100%{transform:translate(0,0)}20%{transform:translate(-3%,2%)}40%{transform:translate(2%,-3%)}60%{transform:translate(-2%,-2%)}80%{transform:translate(3%,2%)}}
.bokeh{position:absolute;border-radius:50%;mix-blend-mode:screen;opacity:0;will-change:transform,opacity;filter:blur(41px);z-index:-2}
.streak{position:absolute;height:2px;border-radius:50%;mix-blend-mode:screen;opacity:0;will-change:transform,opacity;filter:blur(6px);z-index:-2}
@keyframes drift{0%{opacity:0;transform:translate(0,0) scale(1)}15%{opacity:var(--peak)}85%{opacity:var(--peak)}100%{opacity:0;transform:translate(var(--dx),var(--dy)) scale(1.15)}}
@media (prefers-reduced-motion:reduce){.grain{animation:none}.bokeh,.streak{display:none}}
body{animation:page-fade .35s ease-out}
@keyframes page-fade{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){body{animation:none}}
/* T7b: bottom padding 24 -> 10. This is the space Harley saw under the version
   line. It applies to every screen, not just the landing, which is the point:
   24px of dead space at the foot of a phone screen is a cost everywhere. */
#app{max-width:480px;margin:0 auto;padding:10px 16px 10px;min-height:80vh}
#app.stage-rating{padding-top:0;padding-bottom:0}

/* ---- topbar: persistent small neon wordmark + Home exit ---- */
#topbar{position:sticky;top:0;z-index:5;display:flex;align-items:center;justify-content:space-between;
  padding:8px 14px;background:rgba(9,12,26,.85);backdrop-filter:blur(6px);border-bottom:1px solid var(--line)}
#topbar.hidden{display:none}
.wordmark{font-family:var(--font-neon);font-size:1.05rem;line-height:1;letter-spacing:.01em}
/* WF3: wordmark is now an inline SVG. Topbar tier: subtle glow (parity with old text). */
.wm-film{fill:#d3fbff;filter:drop-shadow(0 0 6px rgba(64,211,220,.45))}
.wm-jinx{fill:#ffd9ee;filter:drop-shadow(0 0 6px rgba(248,106,176,.5))}
.wordmark .wm-svg{height:1.05rem;width:auto;display:block}
/* flicker now applies in both sites (n and x of Jinx), harmless in the topbar too */
.wm-flicker{animation:neon-flicker 2.2s infinite}
.wm-flicker-alt{animation-duration:3.4s;animation-delay:.9s}
.navbtn{width:auto;margin:0;min-height:34px;padding:5px 12px;font-size:.8rem;color:var(--dim);
  background:var(--card);border:1px solid var(--line);border-radius:999px;font-family:var(--font-mono);letter-spacing:.04em}

/* ---- type ---- */
h1{font-family:var(--font-head);font-weight:400;font-size:1.7rem;line-height:1.12;margin:14px 0 6px}
h2{font-family:var(--font-head);font-weight:400;font-size:1.25rem;margin:10px 0}
p{line-height:1.5}
/* UI-uplift R1.1: every anchor takes the single action colour, underlined. */
a{color:var(--link);text-decoration:underline;text-underline-offset:2px}
.muted{color:var(--dim)}
/* T7b: margin-top was 18px. The space UNDER it is #app's bottom padding. */
.version{font-family:var(--font-mono);font-size:.7rem;margin-top:10px;margin-bottom:0;text-align:center;opacity:.7}

/* ---- buttons: hierarchy by fill / tint / ghost / faint, one hue ---- */
button{font:inherit;border:0;border-radius:12px;padding:14px 16px;background:var(--card);color:var(--cream);
  width:100%;margin:6px 0;min-height:48px;cursor:pointer;font-weight:500}
button.primary,button.good{background:var(--accent);color:var(--accent-ink);font-weight:600}
/* UI-uplift R2 (buttons card): the opt-in ambient glow on the ONE flow-advancing
   primary per screen. Wordmark recipe - a tight core shadow on the button plus a
   soft radial cyan wash behind it (a ::before in the button's own stacking
   context), no wide blur so it cannot haze. A modifier class, not the card's
   wrapper div (deviation, recorded), so it also works for a primary inside a flex
   row and can never land on .good (rating buttons share the fill; R2.3/E11). */
button.primary.glow{position:relative;z-index:0;
  box-shadow:0 0 10px rgba(64,208,218,.8),0 0 3px rgba(234,254,255,.6)}
button.primary.glow::before{content:"";position:absolute;left:50%;top:50%;width:110%;height:320%;
  transform:translate(-50%,-50%);border-radius:50%;z-index:-1;pointer-events:none;
  background:radial-gradient(closest-side,rgba(64,208,218,.38),transparent 70%)}
button.tint{background:var(--accent-tint);border:1px solid var(--accent-tint-line);color:var(--accent-tint-ink);font-weight:600}
/* UI-uplift R9.1: tint button with a mono count badge (buttons card). */
button.tint.icon{display:flex;align-items:center;justify-content:center;gap:8px}
.count{font-family:var(--font-mono);font-size:.85rem;font-weight:700;padding:2px 8px;border-radius:999px;
  border:1px solid var(--accent-tint-line);background:rgba(64,208,218,.12)}
button.ghost{background:rgba(255,255,255,.08);border:1px solid var(--line2);color:var(--cream)}
/* WF3: "Seen it" gets real weight (filled tint), still off the yes/no axis
   (RB2: it is a fact, not a desire, so it stays off the green/red colours). */
button.seen-it{background:rgba(63,211,220,.16);border:0;color:var(--cyan-neon);font-weight:600;font-size:.9rem;min-height:58px}
button.seen-it:active{background:rgba(63,211,220,.28)}
button.open{background:rgba(64,208,218,.08);border:1px solid var(--accent-tint-line);color:var(--accent-tint-ink);font-weight:600;min-height:58px}
button.undo{background:rgba(255,255,255,.06);border:1px solid var(--line);color:var(--dim)}
button:disabled{opacity:.45;cursor:default}
button.back{width:auto;margin:0 0 6px;padding:8px 12px;min-height:36px;font-size:.85rem;border-radius:999px;
  font-family:var(--font-mono);color:var(--dim);background:transparent;border:1px solid var(--line)}

input{font:inherit;width:100%;padding:14px;border-radius:11px;border:1px solid var(--line2);
  background:#141a3a;color:var(--cream);margin:6px 0;min-height:48px}
input::placeholder{color:#6f77a0}
.row{display:flex;gap:8px}
.row>*{flex:1}

/* ---- join screen: segmented OTP-style code entry (W1 Task 4) ---- */
.otp-row{display:flex;gap:10px;justify-content:center;margin:8px 0 20px}
.otp-box{width:48px;height:56px;padding:0;margin:0;text-align:center;font:700 24px var(--font-mono);
  background:var(--card);border:2px solid var(--line);border-radius:10px;color:inherit}
.otp-box:focus{outline:none;border-color:var(--accent)}

/* ---- neon marquee sign (home hero) ---- */
/* UI fidelity T7b (Harley, 2026-07-17): the landing still needed ~10% less
   height. The bulb frame is .bulbs{inset:8px}, so the gap he saw under the
   tagline was this 30px bottom padding plus the tagline's own 14px margin, less
   that 8px inset - about 36px of dead space inside the lit box. Bottom padding
   drops to 14 and the top to 26 (the wordmark's 22px drop-shadow glow still
   clears the bulbs, and .sign has no overflow:hidden so it cannot clip). */
.sign{position:relative;border-radius:16px;padding:26px 22px 14px;text-align:center;margin:8px 0 12px}
.sign .wm{font-family:var(--font-neon);font-size:2.4rem;line-height:1}
/* WF3 fix + tester feedback 2026-07-11 item 4: sign tier neon glow is TWO
   tiers per group, a tight full-colour core (8px) plus one wide faded bloom
   (22px at .65 alpha) to bring back the neon spill the single-shadow version
   lost. Never chain three full-strength shadows: space-separated filter
   functions compound (each shadows the previous glow) and fill the wordmark's
   bounding box with solid haze. The faded wide pass spreads too thin to box. */
.sign .wm-film{fill:#dcffff;filter:drop-shadow(0 0 8px var(--cyan-neon)) drop-shadow(0 0 22px rgba(63,211,220,.65))}
.sign .wm-jinx{fill:#ffe3f2;filter:drop-shadow(0 0 8px var(--pink)) drop-shadow(0 0 22px rgba(248,106,176,.65))}
.sign .wm-svg{height:2.4rem;width:auto;display:block;margin:0 auto;overflow:visible}
.sign .sign-sub{margin:12px 2px 0;color:var(--dim);font-size:.9rem}
/* T7b: was margin:2px 0 14px. The 14px sat on top of .sign's bottom padding and
   read as a gap between this line and the bottom of the lit frame. */
.tagline{font-size:0.95em;opacity:0.75;margin:2px 0 2px}
/* Neon stutter on Jinx's 'n' and 'x' only (Film renders steady): two irregular
   dips per cycle on short, non-harmonic durations, deliberately unsynced so the
   pair never reads as a matched, synced flicker. */
@keyframes neon-flicker{0%,8%,10%,36%,39%,100%{opacity:1}9%{opacity:.5}37%{opacity:.75}38%{opacity:.45}}

/* ---- landing: how-it-works numbered strip + button helper lines ---- */
.how{list-style:none;counter-reset:how;margin:0 0 10px;padding:0}
.how li{counter-increment:how;position:relative;padding:4px 0 4px 30px;color:var(--dim);font-size:.9rem;line-height:1.4}
.how li::before{content:counter(how);position:absolute;left:0;top:6px;width:20px;height:20px;border-radius:50%;
  background:var(--accent-tint);border:1px solid var(--accent-tint-line);color:var(--accent-tint-ink);
  font-family:var(--font-mono);font-size:.7rem;line-height:1;display:flex;align-items:center;justify-content:center}
/* UI fidelity T7: the landing's two sub-lines moved INSIDE their buttons, under
   the label (Harley, 2026-07-17), which reclaims two rows. That left .btn-sub
   with zero consumers app-wide, so it is retired here per the uplift's
   R-CSS-RETIRE ("retire once replaced"); .btn-sub-in replaces it.
   .btn-stack is the landing's column button: icon+label row on top, sub beneath.
   The sub uses opacity rather than --dim so it reads correctly on BOTH the
   accent-filled primary (dark ink) and the ghost button (cream ink). */
.btn-stack{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;padding:10px 16px}
.btn-stack .btn-main{display:flex;align-items:center;justify-content:center;gap:8px}
.btn-stack .btn-sub-in{font-size:.72rem;font-weight:400;opacity:.72;line-height:1.2}
.btn-stack .btn-main svg{flex:none}
.auth-pitch{max-width:none;margin:0 0 12px;text-align:center}
.welcome-back{margin:4px 0 8px;text-align:center}
/* UI fidelity T5 (Harley, 2026-07-17): the Movies/Series toggle shipped from H5
   with NO rule at all - it sat with no spacing and a bare .muted label directly
   under a fully styled .sliderow. Uplift ruling R-LIVE required live features the
   mocks never drew to stay "restyled to fit"; this one never got the restyle.
   Centred per Harley. .chips is a shared flex row (left-aligned elsewhere, e.g.
   the genre picker), so the centring is scoped here rather than changed globally. */
.mediumrow{margin:10px 0;text-align:center}
.mediumrow p{margin:0 0 6px}
.mediumrow .chips{justify-content:center;margin:0}
.linklike{background:none;border:none;min-height:auto;padding:6px 0;color:var(--accent);font:inherit}
/* ---- UI-uplift R3: home hamburger menu (buttons card). The three bare home
   utility links move in here; a guest sees only Leave (E2, no empty rows). ---- */
.home-menu-wrap{position:relative;display:flex;justify-content:flex-end;margin:0 0 2px}
.burger{width:44px;min-height:44px;margin:0;padding:0;border-radius:999px;flex:none;
  background:transparent;border:1px solid var(--line);color:var(--dim);
  display:inline-flex;align-items:center;justify-content:center;cursor:pointer}
.burger svg{width:16px;height:16px}
.home-menu{position:absolute;right:0;top:calc(100% + 4px);z-index:6;width:220px;padding:6px;
  border-radius:14px;background:var(--panel);border:1px solid var(--line2);box-shadow:0 12px 30px rgba(0,0,0,.45)}
.home-menu.hidden{display:none}
.home-menu button{width:100%;margin:0;min-height:42px;padding:10px 12px;border-radius:9px;
  background:transparent;border:0;color:var(--cream);text-align:left;font-size:.85rem;cursor:pointer}
.home-menu button.quiet{color:var(--dim);display:flex;align-items:center;gap:9px}
.home-menu button.quiet svg{width:14px;height:14px;flex:none}
/* UI-uplift2 T2 (R-CSS-RETIRE): .stat-tiles/.tile retired - screen 12 now uses
   the dash-grid / dash-card / dash-detail block further down (mono figures live
   in .dash-card-n, mono micro-labels in .dash-card-h). .pick-row STAYS: the
   screen-12 detail lists and the "What you watched" list both use it. */
.pick-row{margin:6px 0}
/* D3: a small dimmed mono tag marking a tv (series) night in the stats lists. */
.series-tag{font-family:var(--font-mono);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);margin-left:5px;opacity:.8}
.explainer-list{text-align:left;margin:0;padding-left:18px}
.explainer-list li{margin:6px 0}

/* even, corner-anchored marquee bulbs (JS fills these) */
.bulbs{position:absolute;inset:8px;pointer-events:none}
.bulbs i{position:absolute;width:7px;height:7px;border-radius:50%;margin:-3.5px 0 0 -3.5px;
  background:var(--bulb);box-shadow:0 0 6px 2px var(--bulb-glow);animation:chase 1.5s linear infinite}
@keyframes chase{0%,100%{opacity:.2}45%{opacity:1}}
/* UI-uplift R13.2: still the marquee bulbs and the wordmark flicker for phones
   that ask for no motion (the two remaining decorative loops). */
@media (prefers-reduced-motion:reduce){
  .bulbs i{animation:none;opacity:.7}
  .wm-flicker{animation:none}
}

/* ---- lobby: the code hand-off is the hero ---- */
.lobby-hero{position:relative;border-radius:16px;padding:22px 18px 20px;text-align:center;margin:10px 0 16px;overflow:hidden;
  background:linear-gradient(180deg,#141a36,#0b1022);box-shadow:0 0 0 4px #0e1430}
.qr{background:#fff;border-radius:12px;padding:12px;margin:6px auto 12px;width:fit-content;max-width:70%}
.qr svg{display:block;width:196px;height:auto}
.share-code{font-family:var(--font-mono);font-weight:700;font-size:1.9rem;letter-spacing:.28em;text-align:center;
  color:var(--cyan-neon);text-shadow:0 0 14px rgba(63,211,220,.6);padding:6px 0 2px;margin:4px 0}
/* UI-uplift R11: the quiet "Show the code instead" disclosure. Collapsed by
   default; the code and host-entry line live inside it. */
.code-reveal{margin:8px 0 0}
.code-reveal summary{list-style:none;cursor:pointer;color:var(--dim);font-size:.8rem;
  font-family:var(--font-mono);letter-spacing:.04em;text-decoration:underline}
.code-reveal summary::-webkit-details-marker{display:none}
.code-reveal[open] summary{margin-bottom:6px}

/* ---- WF3 R3: ready-screen pick summary ---- */
.pick-summary{margin:12px 0;padding:6px 14px;border-radius:12px;background:var(--card);border:1px solid var(--line)}

/* ---- H4: group roster panel (joined names + ready ticks) ---- */
.roster-list{margin:12px 0}
.roster-row{margin:4px 0}

/* ---- mode chooser: cinema tickets ---- */
.mode-list{display:flex;flex-direction:column;gap:12px;margin:16px 0}
/* Tester feedback 2026-07-11 item 1: "or" dividers so the three tickets read
   as alternative doors, not sequential steps. */
.or-div{text-align:center;color:var(--dim);font-family:var(--font-mono);font-size:.85rem;
  letter-spacing:.18em;text-transform:uppercase;margin:10px 0}
/* FB1 R8 (item 4): a card shadow + pressed state so the tickets read as tappable
   buttons, not an info list. Neutral drop shadow (never an accent glow - ui-uplift
   R2.3/E11 keeps the one-glow-primary-per-screen rule; the tickets stay unglowed). */
.ticket{position:relative;display:flex;align-items:stretch;width:100%;text-align:left;color:var(--cream);
  background:var(--card);border:1px solid var(--line);border-radius:16px;overflow:hidden;margin:0;min-height:auto;padding:0;
  box-shadow:0 4px 14px rgba(0,0,0,.32);transition:transform .08s ease,box-shadow .08s ease}
.ticket:active{transform:translateY(1px);box-shadow:0 1px 4px rgba(0,0,0,.3)}
.ticket .stub{flex:0 0 58px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;
  position:relative;background:var(--dim)}
.ticket .ic{font-size:1.15rem;line-height:1;color:#fff;display:flex}
.ticket .ic svg{width:22px;height:22px;display:block}
.ticket .adm{font-family:var(--font-mono);font-size:.52rem;letter-spacing:.1em;color:#fff;
  text-align:center;line-height:1.3;font-weight:700}
.ticket .stub::before,.ticket .stub::after{content:"";position:absolute;right:-9px;width:18px;height:18px;
  border-radius:50%;background:var(--page)}
.ticket .stub::before{top:-9px}.ticket .stub::after{bottom:-9px}
.ticket .tbody{padding:14px 15px;flex:1}
.ticket .tbody strong{display:block;font-family:var(--font-head);font-weight:400;font-size:1.08rem;margin-bottom:3px}
.ticket .tbody span{color:var(--dim);font-size:.85rem;line-height:1.35}

/* ---- genre chips ---- */
.chips{display:flex;flex-wrap:wrap;gap:9px;margin:14px 0}
.chip{width:auto;padding:11px 18px;border-radius:999px;margin:0;min-height:46px;font-weight:500;font-size:.95rem;
  border:1px solid var(--line2);background:transparent;color:var(--cream);
  display:inline-flex;align-items:center;gap:8px;
  transition:background-color .2s,border-color .2s,box-shadow .3s,color .2s}
.chip.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:600;animation:chip-glow-in .5s ease-out}
.chip-sub{font-size:.72em;color:var(--dim);font-weight:400;margin-left:4px}

/* ---- host settings panel ---- */
.settings-panel{border:1px solid var(--line);border-radius:12px;padding:12px 14px;margin:16px 0;background:var(--card)}
.settings-panel h3{font-family:var(--font-head);font-weight:400;font-size:1.05rem;margin:0 0 8px}
.setrow{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:10px 0;
  font-family:var(--font-mono);font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.setrow select{width:auto;min-width:130px;margin:0;min-height:40px;padding:8px 10px;border-radius:8px;
  font-family:var(--font-body);font-size:.95rem;letter-spacing:normal;text-transform:none;
  border:1px solid var(--line2);background:#141a3a;color:var(--cream)}
.mini{font-size:.78rem;margin:4px 0 0}
/* ---- UI-uplift R7: free-range filter sliders (filters card). Real range
   inputs, >=44px hit target (R7.7), accent track/thumb. ---- */
/* UI fidelity T7: the approved landing is 1080px tall against a phone's ~750px,
   so the design itself scrolled. Spacing tightened throughout the landing
   (.sliderow 16->12, .how 16->10 + shorter li padding, .welcome-back 10->8). */
.sliderow{margin:12px 0}
/* T7: "Just me" / "Up to 6" ride the ENDS of the slider on its own line rather
   than a separate .hint row underneath. .rng needs flex:1 to take the slack;
   the labels must not wrap or they steal width from the track. */
.rngrow{display:flex;align-items:center;gap:10px;margin:2px 0 0}
.rngrow .rng{flex:1;min-width:0;margin:0}
.rng-end{font-size:.7rem;color:var(--dim);white-space:nowrap;flex:none}
.sliderow .lab{display:flex;justify-content:space-between;align-items:baseline;
  font-family:var(--font-mono);font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.sliderow .val{font-family:var(--font-mono);font-size:.85rem;color:var(--accent-tint-ink);letter-spacing:.04em;text-transform:none}
.sliderow .hint{font-size:.7rem;color:var(--dim);margin:2px 4px 0;display:flex;justify-content:space-between}
input[type=range].rng{-webkit-appearance:none;appearance:none;width:100%;height:44px;min-height:44px;
  background:transparent;border:0;margin:0;padding:0;cursor:pointer}
input[type=range].rng:focus{outline:none}
input[type=range].rng::-webkit-slider-runnable-track{height:4px;border-radius:999px;background:var(--line2)}
input[type=range].rng::-moz-range-track{height:4px;border-radius:999px;background:var(--line2)}
input[type=range].rng::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:22px;height:22px;
  margin-top:-9px;border-radius:50%;background:var(--accent);border:2px solid #0b0e1a;box-shadow:0 0 0 1px var(--accent)}
input[type=range].rng::-moz-range-thumb{width:22px;height:22px;border-radius:50%;background:var(--accent);
  border:2px solid #0b0e1a;box-shadow:0 0 0 1px var(--accent)}
input[type=range].rng:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 3px var(--accent-tint-line)}
input[type=range].rng:focus-visible::-moz-range-thumb{box-shadow:0 0 0 3px var(--accent-tint-line)}
/* R7.3 two-ended range: overlaid inputs (thumbs live), a shared track + fill drawn under. */
.dual{position:relative;height:44px}
.dual-track{position:absolute;left:0;right:0;top:50%;height:4px;transform:translateY(-50%);border-radius:999px;background:var(--line2)}
.dual-fill{position:absolute;top:0;bottom:0;border-radius:999px;background:var(--accent)}
.dual .dual-rng{position:absolute;left:0;top:0;pointer-events:none}
.dual .dual-rng::-webkit-slider-runnable-track{background:transparent}
.dual .dual-rng::-moz-range-track{background:transparent}
.dual .dual-rng::-webkit-slider-thumb{pointer-events:auto}
.dual .dual-rng::-moz-range-thumb{pointer-events:auto}
/* ---- UI-uplift R8: Bridget-mode toggle switch + nested certification subrow. ---- */
.sw2{position:relative;width:46px;height:26px;min-height:26px;border-radius:999px;background:var(--line2);
  border:0;cursor:pointer;flex:0 0 auto;transition:background .15s;padding:0;margin:0}
.sw2::after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;
  background:var(--cream);transition:transform .15s}
.sw2[aria-pressed="true"]{background:var(--accent)}
.sw2[aria-pressed="true"]::after{transform:translateX(20px)}
.subrow{margin:10px 0 4px 14px;padding-left:14px;border-left:2px solid var(--line2)}
.subrow .setrow{margin:8px 0}
.setblock{margin:10px 0}
.setlabel{display:block;font-family:var(--font-mono);font-size:.72rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dim)}
.stream-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px 12px;margin-top:8px}
.streamcheck{display:flex;align-items:center;gap:6px;font-family:var(--font-body);
  font-size:.85rem;letter-spacing:normal;text-transform:none;color:var(--cream)}
.streamcheck input{width:auto;min-height:auto;margin:0}

/* ---- host filters: collapsed expander on the Host setup screen ---- */
.filters{border:1px solid var(--line);border-radius:12px;margin:6px 0 12px;background:var(--card);overflow:hidden}
.filters-toggle{display:flex;align-items:center;justify-content:space-between;width:100%;margin:0;min-height:auto;
  background:transparent;border:0;border-radius:0;padding:13px 15px;color:var(--cream);font-weight:600}
.filters-toggle .chev{color:var(--dim);font-size:.75rem}
.filters-body{padding:4px 15px 14px;border-top:1px solid var(--line)}
/* filters-landing-rework: five stacked "optional" menus, each its own .filters card */
.filters-wrap{margin:6px 0 12px}
.filters-lead{font-family:var(--font-mono);font-size:.72rem;letter-spacing:.1em;color:var(--dim);margin:0 4px 6px}
.fmenu{margin:8px 0}
.fmenu-val{font-size:.82rem;margin-right:6px}

/* ---- seed autocomplete ---- */
.seed-results{display:flex;flex-direction:column;gap:6px;margin:4px 0}
.seed-suggest{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:8px 10px;margin:0;
  min-height:auto;border:1px solid var(--line);background:var(--card);border-radius:10px}
.seed-suggest img{width:34px;height:51px;object-fit:cover;border-radius:6px}
.noposter{width:34px;height:51px;border-radius:6px;background:var(--line)}
.seed-chosen{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0 20px}
.seed-chip{width:auto;margin:0;padding:8px 12px;border-radius:999px;min-height:40px;font-size:.92rem;
  border:1px solid var(--accent);background:var(--accent-tint);color:var(--accent-tint-ink)}

/* ---- rating card: portrait poster with scrim, title overlaid ---- */
.poster{position:relative;border-radius:14px;overflow:hidden;margin:6px 0;aspect-ratio:3/4;max-height:44vh;background:#12172b}
.poster img{width:100%;height:100%;object-fit:cover;display:block}
.poster-scrim{position:absolute;inset:0;background:linear-gradient(to top,rgba(6,8,16,.9) 0,transparent 44%)}
.poster-title{position:absolute;left:14px;right:14px;bottom:12px;margin:0;font-family:var(--font-head);font-weight:400;
  font-size:1.6rem;line-height:1.05;color:var(--cream);text-shadow:0 2px 12px rgba(0,0,0,.75)}
.cbody{padding:4px 2px 0}
.meta{color:var(--dim);font-size:.85rem;margin:2px 0 4px;line-height:1.7;flex-wrap:wrap}
.cert-chip{border:1px solid currentColor;border-radius:4px;padding:0 4px;font-size:.85em}
/* UI-uplift R9.2: trailer pill (tint-voice outline, video-badge play icon).
   Wins over the global a{} rule (class beats element), so no underline/link blue. */
.trailer{width:auto;display:inline-flex;align-items:center;gap:8px;margin:12px 0 0;padding:9px 16px 9px 12px;
  min-height:40px;border-radius:999px;background:transparent;border:1px solid var(--accent-tint-line);
  color:var(--accent-tint-ink);font-weight:500;font-size:.85rem;text-decoration:none}
.trailer svg{width:20px;height:14px;flex:none}
/* .credits-line/.scores-line retired (UI-uplift wave 2 T6): film-details.js now
   renders the labelled-box treatment (credits-box/scores-box); nothing emits the
   old stacked lines. .award-badges stays: the done screen winner card (results-
   view.js renderDone) still groups its award badges in a .award-badges row. */
.award-badges{margin:8px 0 0}
.award-badge{display:inline-block;border:1px solid var(--amber);color:var(--amber);border-radius:8px;padding:6px 12px;font-size:.88rem;font-weight:600}
.award-badge{margin:0 6px 4px 0}
.runtime{display:inline-block;background:#20264a;color:var(--cream);border-radius:6px;padding:1px 8px;font-weight:600;
  font-size:.8rem;font-family:var(--font-mono);margin-right:2px;white-space:nowrap}
.syn{color:var(--dim);font-size:.9rem;line-height:1.45;margin:0 0 10px}
/* "Why you're seeing this" reasons, shown inside the synopsis reveal. */
.why{margin:14px 0 11px;padding:9px 12px;background:var(--accent-tint);
  border:1px solid var(--accent-tint-line);border-radius:10px}
.why-label{margin:0 0 6px;font-family:var(--font-mono);font-size:.64rem;letter-spacing:.07em;
  text-transform:uppercase;color:var(--accent-tint-ink)}
.why ul{list-style:none;margin:0;padding:0}
.why li{position:relative;padding-left:16px;color:var(--cream);font-size:.85rem;line-height:1.5;margin:4px 0}
.why li::before{content:"";position:absolute;left:2px;top:.55em;width:6px;height:6px;border-radius:50%;
  background:var(--accent)}
.rate-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-top:10px}
.rate-grid button{margin:0;height:58px;box-sizing:border-box;font-size:.78rem;padding:0 6px;white-space:nowrap;gap:6px}
.progress{font-family:var(--font-mono);font-size:.72rem;color:var(--dim);letter-spacing:.04em;margin:6px 0;text-transform:uppercase}

/* One-screen rating card: flex column sized to the viewport minus the sticky
   topbar; the poster is the only flexible child, so the button cluster is
   always visible without scrolling. Scoped to .ratecard — other screens scroll. */
.ratecard{display:flex;flex-direction:column;height:calc(100dvh - var(--topbar-h, 48px));min-height:0}
.ratecard .poster{flex:0 1 auto;min-height:0;max-height:none;aspect-ratio:2/3;margin:6px 0}
.ratecard .poster img{width:100%;height:100%;object-fit:cover}
.ratecard .rateinfo{flex:0 0 auto}
.ratecard .ratebtns{flex:0 0 auto}
.ratecard>.notice,.ratecard>.error{flex:0 0 auto}

/* WF3: card flip region. Front sets the height; back matches and scrolls. The
   .flipped class toggles on the live element so the spin only plays on an
   intentional flip, never on a render() rebuild (WF/F2-safe). */
.flip{flex:1;min-height:0;position:relative;perspective:1200px}
.flip-inner{position:absolute;inset:0;transform-style:preserve-3d;transition:transform .5s ease}
.flip.flipped .flip-inner{transform:rotateY(180deg)}
.flip .face{position:absolute;inset:0;display:flex;flex-direction:column;
  backface-visibility:hidden;-webkit-backface-visibility:hidden}
.flip .face.back{transform:rotateY(180deg);overflow-y:auto}
.flip .face .poster{flex:1;min-height:0;aspect-ratio:auto}
.flip .back-body{padding:12px 14px 16px}
/* FB1 R10 (item 10): the muted streaming-availability line under the front meta. */
.provline{font-size:.8rem;margin:2px 0 0;line-height:1.3;flex:0 0 auto}
.flip .back-title{margin:0 0 8px}
/* Tester feedback 2026-07-11 item 3: the old full-width bottom strip read as
   poster shadow, not a button (missed across ~20 swipes). Now a floating pill
   that looks pressable: bordered, rounded, centered above the bottom edge. */
.flip-ctl{position:absolute;left:50%;transform:translateX(-50%);bottom:10px;width:auto;min-height:auto;
  margin:0;padding:8px 16px;border:1px solid rgba(255,255,255,.4);border-radius:999px;
  display:flex;align-items:center;gap:6px;
  background:rgba(0,0,0,.68);color:#fff;font:inherit;font-size:.88rem;white-space:nowrap;
  cursor:pointer;backdrop-filter:blur(2px);box-shadow:0 2px 10px rgba(0,0,0,.45)}
.flip-ctl .fc-ic{margin-right:2px}
/* Rating-tidy R4: the front control shares the poster's bottom row with the
   title instead of floating over the card face. Scoped to .poster-foot so the
   back face's .flip-ctl-inline is untouched. */
.poster-foot{position:absolute;left:14px;right:12px;bottom:12px;
  display:flex;align-items:flex-end;gap:10px}
.poster-foot .poster-title{position:static;left:auto;right:auto;bottom:auto;
  flex:1 1 auto;min-width:0}
.poster-foot .flip-ctl{position:static;transform:none;left:auto;flex:0 0 auto}
/* night-flow R3/R5/R6: the same "More" control in a static (non-flip) context
   - ranking rows, the single-match confirm screen, Tonight's movie - so it
   sits in normal flow instead of .flip-ctl's absolute-over-the-card position.
   UI fidelity T3 (2026-07-17): the rule was copy-pasted from .flip-ctl and
   kept its position:absolute/left:50%/translateX, contradicting the comment
   above. Only .card-poster is positioned (and only wraps this control on the
   single-confirm screen), so on the ranking rows and Tonight's movie the
   button escaped to the nearest positioned ancestor - body - and every row's
   button stacked at the bottom-centre of the PAGE. Confirmed on Harley's
   phone. Now genuinely normal-flow and centred, mirroring .flip-ctl-inline;
   the .card-poster override below restores absolute for screen 37.
   NOTE: the approved design carries the identical defect, so the app now
   deliberately diverges from the mock here. Sweep up at re-export.
   width:auto is load-bearing - the base button rule sets width:100%. */
.film-more-ctl{width:auto;min-height:auto;
  margin:10px auto 0;padding:8px 16px;border:1px solid rgba(255,255,255,.4);border-radius:999px;
  display:flex;align-items:center;gap:6px;background:rgba(0,0,0,.68);color:#fff;font:inherit;font-size:.88rem;
  white-space:nowrap;cursor:pointer;backdrop-filter:blur(2px);box-shadow:0 2px 10px rgba(0,0,0,.45)}
.film-details{margin-top:8px}
@media (prefers-reduced-motion: reduce){
  .flip-inner{transition:none}
}
.undo-link{width:auto;min-height:auto;margin:6px auto 0;display:block;padding:4px 8px;background:transparent;
  border:0;color:var(--dim);font-size:.78rem;text-decoration:underline;opacity:.8}
/* UI fidelity T8d: the round-done undo carries font-size:1rem in the approved
   screen (28); the rating card's undo (24) does not, and both share the class
   AND the id, hence a modifier. It was dropped when the button gained btn-ico.
   MUST stay after .undo-link: equal specificity (0,1,0), so source order decides. */
.undo-lg{font-size:1rem}
/* H6 Task 8/req 18a: quiet like Undo, but danger-tinted so it reads as
   distinct and one-way (a two-tap inline confirm, no modal). */
.never-link{width:auto;display:flex;flex-direction:row;align-items:center;justify-content:center;gap:6px;
  margin:0;padding:0 6px;background:rgba(226,59,78,.06);border:1px solid var(--danger);border-radius:10px;
  text-align:left;height:58px;box-sizing:border-box;color:var(--danger);font-size:.68rem;font-weight:500;text-decoration:none}

/* G6: rewatch prompt overlays the button cluster without shifting layout.
   .ratebtns-main reserves exactly the height of the 4 main rating buttons
   (.rb-buttons); they never leave the DOM, so that height never changes.
   While the rewatch question is showing, .rw-hidden keeps the buttons (and
   the Undo link) occupying their space via visibility:hidden - not
   display:none, which would collapse the box - and .rw-prompt covers the box
   as an out-of-flow absolute layer that contributes no height of its own. */
.ratebtns-main{position:relative}
.rw-hidden{visibility:hidden}
.rw-prompt{position:absolute;inset:0;display:flex;flex-direction:column;align-items:stretch;
  justify-content:center;gap:14px;text-align:center;background:transparent;border-radius:12px;padding:0 4px}
.rw-prompt p{margin:0}
.rw-prompt button{margin:0;min-height:42px;font-size:.85rem;padding:8px 10px;width:100%}

/* Rating-tidy R6: heading left, Cancel right, on one row so the prompt's
   height (and therefore .ratebtns-main's reserved height) is unchanged.
   .rw-head p{margin:0} was dropped as redundant: .rw-prompt p{margin:0} is
   equal specificity, earlier in the file, and already matches every p inside
   .rw-head (which only ever renders inside .rw-prompt). */
.rw-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
/* Whole-branch review: .rw-prompt button{width:100%} has specificity (0,1,1)
   and was beating both .linklike rules (0,1,0), including the one setting
   width:auto - so #rw-cancel rendered as a full-width answer-shaped button
   instead of a compact link, squeezing the heading onto two lines and
   growing .rw-head past its intended height. Two classes outrank one class
   plus one element ((0,2,0) > (0,1,1)), so this wins the cascade outright. */
.rw-head .linklike{width:auto;min-height:auto;padding:6px 0;flex:0 0 auto}

/* M1: bars + pill share one row so the pill never adds a full extra line to
   the one-screen rating card. */
.progress-row{display:flex;align-items:center;gap:10px;margin:4px 0 2px}
.progressbars{flex:1 1 auto;display:flex;flex-direction:column;gap:4px;margin:0}
.pbar{height:5px;border-radius:999px;background:var(--line);overflow:hidden}
.pbar-fill{height:100%;border-radius:999px;transition:width .25s ease}
/* H4 Task 7: hue is the participant's roster INDEX (stable across phones),
   not their host/guest role. p0/p1 match the old host-pink/guest-cyan couple
   colours; p2-p5 are the new group-mode hues. */
.pbar-p0 .pbar-fill{background:var(--pink)}
.pbar-p1 .pbar-fill{background:var(--cyan-neon)}
.pbar-p2 .pbar-fill{background:var(--amber)}
.pbar-p3 .pbar-fill{background:#B487F0}
.pbar-p4 .pbar-fill{background:#7FE08A}
.pbar-p5 .pbar-fill{background:#F08A5A}
.round-label{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim);flex:1;text-align:center}

/* M1: tappable match counter, lives in the progress row (not a new one) */
.match-pill{flex:0 0 auto;width:auto;margin:0;border-radius:999px;padding:6px 12px;font-weight:700;
  font-size:.8rem;background:transparent;border:2px solid var(--pink, #ff3d8b);color:inherit;
  min-height:auto;white-space:nowrap}

/* ---- simple card (done / single match) ---- */
.card{background:var(--card);border-radius:14px;overflow:hidden;margin:6px 0}
.card img{width:100%;display:block;max-height:44vh;object-fit:cover}
.card .body{padding:10px 14px}
.card h2{margin:6px 0 4px}
.card .meta{margin:6px 0 8px}
.card .syn{color:var(--dim);font-size:.9rem;line-height:1.45}

.notice{background:#20264a;border:1px solid var(--amber);border-radius:12px;padding:10px 12px;margin:10px 0;font-size:.95rem}
/* WF/F3: compact dismissible line replacing the old .notice thin-pool block. */
.thin-line{font-size:0.85em;margin:4px 0}
.linklike{background:transparent;border:0;padding:0;margin-left:6px;color:var(--dim);
  font-size:inherit;text-decoration:underline;opacity:.8;cursor:pointer;
  width:auto;min-height:auto;display:inline}
.error{background:#2a1720;border:1px solid var(--danger);border-radius:12px;padding:10px 12px;margin:10px 0}

/* ---- match overlay: now proposals-only (the panel styling is below). The
   celebration visuals moved to #splash (Task 5b), which has its own copies;
   .match-title and the curtain-l/curtain-r/match-pop keyframes stay here
   unprefixed because #splash's markup (built in showSplash()) still uses
   them directly. ---- */
#overlay{position:fixed;inset:0;background:rgba(6,8,16,.93);display:flex;align-items:center;justify-content:center;
  padding:20px;z-index:10}
#overlay.hidden{display:none}
.match-title{font-family:var(--font-neon);font-size:1.7rem;line-height:1.1;margin:8px 0 4px;
  color:#ffe3f2;text-shadow:0 0 4px #fff,0 0 12px var(--pink),0 0 26px var(--pink)}
@keyframes curtain-l{to{transform:translateX(-102%)}}
@keyframes curtain-r{to{transform:translateX(102%)}}
@keyframes match-pop{0%{transform:scale(.9);opacity:.4}100%{transform:scale(1);opacity:1}}

/* ---- M1/Task 6: matches panel — the other thing #overlay shows: either the
   pill's full match list, or a live proposal folded into that same list. ---- */
#overlay .panel{max-width:420px;width:100%;max-height:82vh;overflow-y:auto;text-align:left;
  background:var(--card);border-radius:16px;padding:18px 16px;box-shadow:0 12px 44px rgba(0,0,0,.55)}
#overlay .panel h2{margin:0 0 10px;font-family:var(--font-head);text-align:center}
#overlay .panel #panel-close{margin-top:12px}
.match-row{display:flex;flex-wrap:wrap;gap:8px 10px;align-items:center;padding:12px;
  margin:0 0 12px;background:rgba(255,255,255,.05);border:1px solid var(--line2, #333a63);border-radius:12px}
.match-row img,.match-row .noposter{width:44px;flex:0 0 auto}
.match-row img{border-radius:6px}
.match-row-main{flex:1 1 160px;text-align:left}
.match-row button{width:auto;flex:1 1 auto;margin:0;min-height:40px;padding:9px 12px;font-size:.85rem}

/* ---- C2 coach card: lighter dim so the first poster peeks through ---- */
#coach{position:fixed;inset:0;background:rgba(6,8,16,.72);display:flex;align-items:center;justify-content:center;
  padding:22px;z-index:11}
#coach.hidden{display:none}
.coach-card{position:relative;max-width:360px;width:100%;background:var(--card);border:1px solid var(--line2);
  border-radius:16px;padding:22px 20px 18px;box-shadow:0 12px 44px rgba(0,0,0,.55)}
.coach-card h2{margin:0 0 12px}
.coach-card ul{list-style:none;margin:0 0 16px;padding:0}
.coach-card li{position:relative;padding-left:18px;margin:9px 0;line-height:1.45;font-size:.95rem}
/* UI fidelity T8e: the approved coach card draws this inline info icon at 12px
   with a 3px gap and a 1px optical drop. The shared registry emits one size
   (14px, which the rating card's pill needs), so the size and spacing are
   corrected here rather than by forking the registry entry. Scoped to the
   <strong> so the coach's button icons below are untouched. */
.coach-card li strong svg{width:12px;height:12px;vertical-align:-1px;margin-right:3px}
.coach-card li::before{content:"";position:absolute;left:2px;top:.55em;width:6px;height:6px;border-radius:50%;
  background:var(--accent)}
.coach-x{position:absolute;top:6px;right:6px;width:auto;min-height:auto;margin:0;padding:6px 11px;
  background:transparent;border:0;color:var(--dim);font-size:1.2rem;line-height:1}

/* ---- W2/M1 Task 5b: strong-match splash — full-screen celebratory chrome for
   a both-keen match, no buttons, self-dismissing. Reuses the overlay's
   celebration visuals (.celebrate/.curtain/.reveal/.match-title are generic
   classes) but needs its own #splash-scoped rules since the existing ones are
   scoped to #overlay. Sits above #overlay/#coach/#toast (z-index) but never
   blocks the rating card underneath once it clears — it's a dedicated element,
   not the proposal overlay, so it can't be killed or gate anything. ---- */
#splash{position:fixed;inset:0;background:rgba(6,8,16,.93);display:flex;align-items:center;justify-content:center;
  padding:20px;z-index:50}
#splash.hidden{display:none}
#splash .inner{max-width:420px;width:100%;text-align:center;position:relative;overflow:hidden}
#splash img{max-width:58%;border-radius:12px;box-shadow:0 0 30px rgba(248,106,176,.35)}
#splash h2{font-family:var(--font-head)}
#splash .curtain{display:none}
#splash .inner.celebrate .curtain{display:block;position:absolute;top:0;bottom:0;width:52%;z-index:3;
  pointer-events:none;background:linear-gradient(90deg,#5a0c14,#8e1620 55%,#6b0f18);box-shadow:inset 0 0 40px rgba(0,0,0,.55)}
#splash .inner.celebrate .curtain.left{left:0;animation:curtain-l .9s ease-in-out forwards}
#splash .inner.celebrate .curtain.right{right:0;animation:curtain-r .9s ease-in-out forwards}
#splash .inner.celebrate .reveal{animation:match-pop .9s ease-out both}
@media (prefers-reduced-motion:reduce){
  #splash .inner.celebrate .curtain{display:none}
  #splash .inner.celebrate .reveal{animation:none}
}

/* ---- M1: non-blocking match toast, a signal, never a takeover.
   UI-uplift R4 (toast card, Proposal B): the calm-act card - --card ground, a
   1px --pink border and a soft pink outer glow carry the signal, while the
   film title and quip sit on the auditorium surface (eyebrow/title/subtitle
   anatomy) so the eye finds the film name first. ---- */
#toast{position:fixed;top:calc(var(--topbar-h, 48px) + 8px);left:50%;
  transform:translateX(-50%);background:var(--card);color:var(--cream);
  border:1px solid var(--pink);box-shadow:0 0 18px rgba(248,106,176,.28);
  max-width:min(92vw, 420px);width:max-content;padding:12px 16px;
  border-radius:14px;line-height:1.4;z-index:40;
  pointer-events:none;animation:toast-in 200ms ease-out}
#toast.hidden{display:none}
#toast .toast-eyebrow{font-family:var(--font-mono);font-size:.6rem;letter-spacing:.16em;font-weight:700;
  text-transform:uppercase;color:var(--pink);margin:0;text-align:center}
#toast .toast-title{font-size:.95rem;font-weight:600;color:var(--cream);line-height:1.2;margin:0;text-align:center}
#toast .toast-sub{font-size:.85rem;font-weight:400;font-style:italic;color:var(--dim);line-height:1.4;margin:0;text-align:center}
@keyframes toast-in{from{opacity:0;transform:translate(-50%,-8px)}}
@media (prefers-reduced-motion:reduce){#toast{animation:none}}
/* H4 Task 9 / R4.3 / E9: the solo bank toast's own action button. Parent is
   pointer-events:none (a signal, not a takeover); this opts back in. */
#toast .toast-action{display:block;margin-top:8px;min-height:36px;
  border-radius:999px;padding:8px 14px;font-size:.85rem;font-weight:600;border:0;
  background:var(--accent);color:var(--accent-ink);pointer-events:auto;cursor:pointer}

/* ---- ranking ---- */
.rank-item{display:flex;align-items:center;gap:10px;background:var(--card);border-radius:12px;padding:8px;margin:8px 0}
.rank-item img{width:52px;border-radius:8px}
.rank-badge{background:var(--accent);color:var(--accent-ink);min-width:32px;height:32px;border-radius:999px;
  display:flex;align-items:center;justify-content:center;font-weight:700;font-family:var(--font-mono)}
.rank-badge.empty{background:var(--line2);color:transparent}
/* night-flow R3: the title + More control + expanded details column, so the
   badge/poster stay fixed while this side wraps and grows with the panel. */
.rank-item-main{flex:1;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:2px}

/* ---- recap table (WF3 R4): per-person icon table. Fits 360px, no page side-scroll.
   H4 Task 10: N>=3 columns (a group's roster) can exceed a narrow phone's width;
   .recap-scroll scrolls the table horizontally instead of squeezing it (mirrors
   the memory table's .mem-table-wrap idiom). At N=2 the table still fits inside
   the wrapper, so couples never see a scrollbar. ---- */
.recap-scroll{overflow-x:auto;margin:0}
/* H4 Task 10b (review fix): table-layout was 'fixed' with per-column widths
   as a %, which always sums to <=100% of the wrapper and so can never
   overflow it (the bug: a 4-person group squeezed the title column to ~12%
   instead of scrolling). Auto layout plus a fixed min-width per column
   (below) makes the table's natural width grow linearly with roster size N
   and reliably overflow into .recap-scroll at N>=3, mirroring the .mem-table
   min-width force-overflow idiom at ~line 470. Fixed layout ignores min-width
   on cells (it only reads 'width' from the first row), which is why this
   fix needs auto layout to work at all. */
.recap-table{width:100%;border-collapse:collapse}
.recap-table th,.recap-table td{padding:8px 6px;text-align:center;vertical-align:top}
.recap-table th:first-child,.recap-table td.recap-film{text-align:left;width:auto;min-width:150px}
/* Two 56px icon columns plus the title's 150px minimum (262px) still fit a
   360px phone (296px inside the wrapper), so couples (N=2) see no premature
   scroll; three or more (318px+) reliably overflow into .recap-scroll. */
.recap-table th:not(:first-child){min-width:56px}
.recap-film{word-break:break-word}
.recap-row{cursor:pointer}
.recap-reveal td{padding:0 6px 8px;text-align:left}
.recap-cell{display:inline-flex;align-items:center;justify-content:center;
  width:26px;height:26px;border-radius:50%;font-size:.95rem;line-height:1}
/* UI-uplift R5.2: shape + colour per level (survives colour-blindness/brightness). */
.recap-cell.lv-would{background:rgba(63,211,220,.18);color:var(--cyan-neon)}
.recap-cell.lv-open{background:rgba(224,169,74,.15);border:1px solid rgba(224,169,74,.4);color:var(--amber)}
.recap-cell.lv-no{background:transparent;border:1px solid var(--line2);color:var(--dim)}
.recap-cell.lv-blank{background:transparent;color:var(--line2)}
/* R5.1: the key leads, above the data, not after it. */
.recap-legend{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:2px 0 10px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---- UI-uplift R6: the one waiting pill (waiting card). Replaces the old
   animated dots everywhere the app waits on the other person or the server.
   Reduced motion: the ring stops spinning and dims, no motion. ---- */
.wpill{display:inline-flex;align-items:center;gap:10px;background:var(--panel);border:1px solid var(--line2);
  border-radius:999px;padding:14px 24px;font-size:1.15rem;color:var(--cream)}
.wpill.small{padding:6px 12px;font-size:.8rem;gap:8px}
.wpill-line{display:flex;justify-content:center;margin:10px 0}
/* FB1 R5 (item 16): the "Building your pool" heading centres so it lines up with
   the centred waiting pill below it (was a left-aligned h1 over a centred pill). */
.building-title{text-align:center}
/* FB1 R14 (item 20b): the memory screen's inline "Add a film" search block. */
.mem-add{margin:8px 0 12px}
/* FB1 R12 (items 1+2): warm-up step labels + the running "In your memory" list. */
.step-label{font-family:var(--font-mono);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;margin:0 0 2px}
.warmup-mem{margin:10px 0}
.warmup-mem-h{font-family:var(--font-mono);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;margin:0 0 4px}
.warmup-mem-row{margin:2px 0;font-size:.9rem;color:var(--cream);position:relative;padding-left:16px}
.wspin{width:15px;height:15px;border-radius:50%;border:2px solid var(--line2);border-top-color:var(--accent);
  animation:wspin .8s linear infinite;flex:0 0 auto}
.wpill.small .wspin{width:11px;height:11px}
@keyframes wspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.wspin{animation:none;opacity:.55}}

/* ---- footer attribution (spec req 26) ---- */
#footer{padding:14px 14px 18px;background:none;border-top:1px solid var(--line);
  font-size:.72rem;color:var(--dim);display:flex;flex-direction:column;gap:8px;
  align-items:center;justify-content:center;text-align:center}
/* night-flow R4.5: the softened one-line footer credit - the mark sits inline
   and small (much smaller than the old standalone logo row), quiet by design. */
.credit-line{margin:0;line-height:1.5}
.tmdb-mark{vertical-align:middle;margin-right:4px;opacity:.75}
/* UI-uplift R10: the done screen's curtain line (type card). Marcellus, centred,
   bulb-coloured dots either side; no session code (D4). */
.close-line{font-family:var(--font-head);font-size:1.12rem;text-align:center;color:var(--cream);letter-spacing:.02em;margin:14px 0 6px}
.close-line::before,.close-line::after{content:"·";color:var(--bulb);margin:0 10px;opacity:.85}
.want-list{padding-left:0;list-style:none}
.want-list li{padding:8px 0;border-bottom:1px solid var(--line)}

/* ---- H6 Task 8: "Delete my profile", clearly the destructive action ---- */
button.danger{background:transparent;border:1px solid var(--danger);color:var(--danger);
  width:auto;display:block;margin:24px auto 0;min-height:36px;padding:7px 14px;font-size:.78rem}

/* UI-uplift2 T2 (R-CSS-RETIRE): the H6 memory TABLE (.mem-table*, .mem-poster,
   the table-header .mem-sort/th.mem-tick-h, .mem-tick*) is retired - screen 14
   is now the card list styled by the .mem-sortbar/.mem-legend/.mem-list block
   further down. The mono micro-label voice moved onto .mem-sortbar .mem-sort. */

/* ---- H6 Task 8: warm-up mini-cards, part one (strip) and part two (search
   follow-up), reusing the seed-picker's row layout (.seed-results/.seed-suggest). ---- */
.warmup-list{display:flex;flex-direction:column;gap:8px;margin:8px 0}
.warmup-card{display:flex;gap:12px;background:#1e2444;border:1px solid var(--line2);border-radius:12px;padding:10px;align-items:stretch;box-shadow:0 4px 18px rgba(0,0,0,.4),0 0 16px rgba(64,208,218,.12)}
.warmup-card img,.warmup-card .noposter{width:96px;align-self:stretch;height:auto;object-fit:cover;border-radius:6px;flex:0 0 auto}
.warmup-card-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center}
.warmup-title{margin:0 0 8px;font-weight:600}
.warmup-card-body button{margin:0}

/* ============================================================================
   UI-uplift wave 2 (T0 foundations): gallery-only selectors, added verbatim
   from the approved design (specs/ui-uplift-2-deltas/foundations.md). The
   in-place rules above were retuned to the same approved truth; these are the
   net-new classes the cluster screens (T1-T6) wire up. The gallery @font-face
   block is NEVER copied (self-hosted fonts above stay byte-exact). The animated
   background system lives up top with html,body. Grouped to mirror the annex.
   ============================================================================ */

/* ---- home / dashboard: stat cards, sparkline, bar chart, copy-link row, pills ---- */
.btn-pill{width:100%;display:block;margin:6px 0;padding:10px 20px;min-height:40px;border-radius:999px;
  background:transparent;border:1px solid var(--line2);color:var(--cream);font-size:.85rem;font-weight:500;text-align:center}
.dash-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:10px 0}
.dash-card{text-align:left;padding:14px;border:1px solid var(--line);border-radius:12px;background:var(--panel);
  width:auto;margin:0;min-height:auto;cursor:pointer;transition:border-color .15s,box-shadow .15s;
  display:flex;flex-direction:column;gap:2px}
.dash-card[aria-expanded="true"]{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),0 0 14px rgba(63,211,220,.3)}
.dash-card-h{color:var(--dim);font-size:.68rem;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em}
.dash-card-n{font-size:1.7em;font-family:var(--font-mono);color:var(--cream)}
.dash-unit{font-size:.55em;margin-left:1px;color:var(--dim)}
.dash-card-sub{font-size:.72rem}
.dash-card .spark{width:100%;height:24px;margin-top:2px}
.dash-card .spark polyline{fill:none;stroke:var(--accent);stroke-width:2;vector-effect:non-scaling-stroke}
.dash-detail{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:14px 16px;margin:0 0 16px}
.dash-detail-h{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);margin:0 0 8px}
.bar-chart{display:flex;flex-direction:column;gap:10px}
.bar-row{display:grid;grid-template-columns:64px 1fr 24px;align-items:center;gap:8px}
.bar-label{font-size:.82rem}
.bar-track{height:8px;border-radius:999px;background:var(--line);overflow:hidden}
.bar-fill{height:100%;border-radius:999px;background:var(--accent)}
.bar-val{font-family:var(--font-mono);font-size:.78rem;color:var(--dim);text-align:right}
.link-copy-row{display:flex;gap:8px;margin:10px 0}
.link-copy-input{flex:1;min-height:44px;padding:10px 12px;border-radius:10px;background:var(--card);
  border:1px solid var(--line);color:var(--cream);font-family:var(--font-mono);font-size:.82rem;min-width:0}
.link-copy-btn{width:auto;flex:0 0 auto;min-height:44px;margin:0;padding:0 16px;border-radius:10px;
  background:var(--accent-tint);border:1px solid var(--accent-tint-line);color:var(--accent-tint-ink);
  font-weight:600;font-size:.85rem;display:flex;align-items:center;gap:6px}
/* UI fidelity T7 (Harley, 2026-07-17): the memory pill sits NEXT TO the
   welcome-back greeting rather than on its own row below it. inline-flex (was
   flex + margin:auto, which forced it onto its own centred row) lets it flow
   with the greeting text and wrap as a whole unit on a narrow phone. Only the
   landing memory link uses this class. */
.pill-inline{width:fit-content;display:inline-flex;vertical-align:middle;margin:0 0 0 6px;
  padding:6px 14px;min-height:auto;
  border-radius:999px;background:var(--accent-tint);border:1px solid var(--accent-tint-line);
  color:var(--accent-tint-ink);font-size:.85rem;font-weight:500}
@keyframes home-pulse{0%,100%{transform:scale(1)}16%{transform:scale(1.035)}32%{transform:scale(1)}}
.home-pulse{animation:home-pulse 3s ease-in-out infinite}
.home-pulse-a{animation-delay:0s}
.home-pulse-b{animation-delay:1.5s}
/* UI-uplift2 T2 (R-CSS-RETIRE): the .tile[aria-expanded]/.tile-detail scaffolding
   is retired; the expandable dashboard is the .dash-card/.dash-detail block above. */

/* ---- ready-screen pick summary (new row structure) ---- */
.ps-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 0;border-bottom:1px solid var(--line)}
.ps-row:last-child{border-bottom:0}
.ps-label{display:flex;align-items:center;gap:8px;color:var(--dim);font-size:.85rem}
.ps-val{font-weight:600;font-size:.9rem;text-align:right}

/* ---- mode chooser tickets: coloured stubs, arrow, animated icons, sequence pulse ---- */
.mode-list-badge{text-align:center;font-family:var(--font-head);font-weight:400;font-size:1.72rem;
  color:var(--cream);margin:0 0 12px;display:flex;align-items:center;justify-content:center;gap:10px}
.ticket .tarrow{flex:0 0 auto;display:flex;align-items:center;padding:0 14px;color:var(--dim)}
.ticket-pink .stub{background-color:var(--pink)}
.ticket-pink .tarrow{color:var(--pink)}
.ticket-cyan .stub{background-color:var(--cyan-neon)}
.ticket-cyan .tarrow{color:var(--cyan-neon)}
.ticket-amber .stub{background-color:var(--amber)}
.ticket-amber .tarrow{color:var(--amber)}
@keyframes tic-heartbeat{0%,100%{transform:scale(1)}15%{transform:scale(1.18)}30%{transform:scale(1)}45%{transform:scale(1.12)}60%{transform:scale(1)}}
.ticket-pink .ic svg{animation:tic-heartbeat 2.6s ease-in-out infinite}
@keyframes tic-grid-a{0%,100%{opacity:.35}50%{opacity:1}}
.ticket-cyan .ic svg rect:nth-child(1){animation:tic-grid-a 1.8s ease-in-out infinite}
.ticket-cyan .ic svg rect:nth-child(2){animation:tic-grid-a 1.8s ease-in-out infinite .3s}
.ticket-cyan .ic svg rect:nth-child(3){animation:tic-grid-a 1.8s ease-in-out infinite .6s}
.ticket-cyan .ic svg rect:nth-child(4){animation:tic-grid-a 1.8s ease-in-out infinite .9s}
@keyframes tic-die-shake{0%,100%{transform:rotate(0)}20%{transform:rotate(-12deg)}40%{transform:rotate(10deg)}60%{transform:rotate(-6deg)}80%{transform:rotate(4deg)}}
.ticket-amber .ic svg{animation:tic-die-shake 2.4s ease-in-out infinite;transform-origin:50% 50%}
@keyframes ticket-seq-pulse{0%,100%{transform:scale(1)}16%{transform:scale(1.035)}32%{transform:scale(1)}}
.ticket{animation:ticket-seq-pulse 3s ease-in-out infinite}
/* UI fidelity T8b: the approved round-done screen breathes its two buttons in
   sequence (Another round, then Rank a second later). The keyframe shipped with
   the uplift but was only ever bound to .ticket, so the buttons sat static. Both
   ids are unique to the round-done screen, so no markup change is needed. The
   reduced-motion guard below is extended to match. */
#more{animation:ticket-seq-pulse 3s ease-in-out infinite}
.ticket-pink{animation-delay:0s}
.ticket-cyan{animation-delay:1s}
.ticket-amber{animation-delay:2s}

/* ---- genre chips: icon slot + glow-in ---- */
.chip svg{flex:none}
@keyframes chip-glow-in{0%{box-shadow:0 0 0 0 rgba(64,208,218,.7)}100%{box-shadow:0 0 10px 2px rgba(64,208,218,.35)}}

/* ---- filter sliders: party-size (pink) thumb variant ---- */
input[type=range].party-rng::-webkit-slider-thumb{background:var(--pink);box-shadow:0 0 0 1px var(--pink)}
input[type=range].party-rng::-moz-range-thumb{background:var(--pink);box-shadow:0 0 0 1px var(--pink)}

/* ---- rating card / film details: labelled credits, scores, awards, streaming boxes.
   Shared by the swipe card back face (card-view.js) and the "More" panel
   (film-details.js) since T6 retired the old .credits-line/.scores-line lines. ---- */
.credits-box{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:9px 12px;margin:0 0 12px}
.credits-row{margin:5px 0;font-size:.85rem;color:var(--cream)}
.credits-row:first-child{margin-top:0}
.credits-row:last-child{margin-bottom:0}
.credits-label{display:inline-block;min-width:58px;font-family:var(--font-mono);font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;color:var(--dim);margin-right:8px;vertical-align:baseline;line-height:inherit}
.scores-box{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 12px;
  background:var(--card);border:1px solid var(--line);border-radius:10px;padding:9px 12px}
.scores-label{width:100%;font-family:var(--font-mono);font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;color:var(--dim);margin:0 0 2px}
.score-chip{background:var(--accent-tint);border:1px solid var(--accent-tint-line);color:var(--accent-tint-ink);
  border-radius:999px;padding:6px 14px;font-size:.92rem;font-weight:700;font-family:var(--font-mono);letter-spacing:.02em;
  display:inline-flex;align-items:center;gap:5px}
.score-chip svg{flex:none}
.awards-box{background:rgba(224,169,74,.08);border:1px solid rgba(224,169,74,.3);border-radius:10px;padding:9px 12px;margin:0 0 10px}
.awards-label{font-family:var(--font-mono);font-size:.62rem;letter-spacing:.07em;text-transform:uppercase;color:var(--amber);margin:0 0 6px}
.syn-row{display:block;margin:5px 0 0}
.credits-label-block{display:block;margin:0 0 3px;font-weight:700}
.syn-row .syn-col{margin:0 0 8px}
.trailer-wide{width:100%;justify-content:center;margin:0}
.stream-box{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:9px 12px;margin:11px 0 0;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.stream-label{width:100%;font-family:var(--font-mono);font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;color:var(--dim);margin:0 0 2px}
.rate-grid button[data-r="not_seen_no"]{background:rgba(240,168,120,.06);border-color:var(--line2);color:var(--cream)}

/* Rating-tidy R5: the never-again cell is guest-gated, and its absence used to
   reflow the auto-flow grid and move "Open to it" from the right column to the
   left. The sides carry meaning, so every cell is pinned explicitly and no
   appearing or disappearing cell can reshuffle the others. */
.rate-grid button[data-r="not_seen_no"]{grid-area:1/1}
.rate-grid button[data-r="not_seen_want"]{grid-area:1/2}
.rate-grid #never-again{grid-area:2/1}
.rate-grid button[data-r="not_seen_maybe"]{grid-area:2/2}

/* ---- card flip: visibility toggling, inline flip control, poster placeholder, provider badge ---- */
.flip .face.back{visibility:hidden;pointer-events:none}
.flip.flipped .face.back{visibility:visible;pointer-events:auto}
.flip.flipped .face.front{visibility:hidden;pointer-events:none}
.flip .face .noposter{width:100%;height:100%}
.prov-badge{width:16px;height:16px;border-radius:4px;color:#fff;font-size:.62rem;font-weight:700;
  display:inline-flex;align-items:center;justify-content:center;line-height:1}
.flip-ctl svg{flex:none;display:block}
.flip-ctl-inline{position:static;transform:none;margin:14px auto 0;display:flex;background:transparent;border:1px solid var(--line2);box-shadow:none;backdrop-filter:none;color:var(--cream)}
.film-more-ctl svg{flex:none}

/* ---- never-again + rewatch prompt (new layouts) ---- */
.never-link svg{flex:none}
.never-link-text{display:flex;flex-direction:column;gap:0;line-height:1.15}
.rw-row{display:flex;gap:8px;width:100%;flex:1}
.rw-row button{margin:0;height:100%;font-size:.78rem;padding:34px 8px 10px;width:auto;flex:1;
  display:grid;grid-template-rows:24px 1fr;align-items:start;justify-items:center;gap:8px;white-space:normal;line-height:1.25}
.rw-row button svg{align-self:center}
.rw-row button svg{width:22px;height:22px;align-self:center}

/* ---- rating-button micro-animations (icon wiggle/pulse) ---- */
@keyframes soft-wiggle{0%,100%{transform:rotate(0)}25%{transform:rotate(-8deg)}75%{transform:rotate(8deg)}}
.match-count-badge{display:inline;padding:2px 8px;
  width:auto;margin:0;min-height:0;border:0;font:inherit;cursor:pointer;
  border-radius:999px;background:var(--accent);color:var(--accent-ink);font-weight:700;font-size:.85em}
#more .count{display:inline-block}
#seen-nope svg,#seen-liked svg{animation:soft-wiggle 2.6s ease-in-out infinite}
@keyframes soft-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.15)}}
@keyframes soft-pulse-btn{0%,100%{transform:scale(1)}50%{transform:scale(1.03)}}
#coach-ok{animation:soft-pulse-btn 2.2s ease-in-out infinite}
#seen-loved svg{animation:soft-pulse 1.8s ease-in-out infinite}
.rate-grid button[data-r="not_seen_no"] svg,#never-again svg{animation:soft-wiggle 2.6s ease-in-out infinite}
.rate-grid button[data-r="not_seen_want"] svg,.rate-grid button[data-r="not_seen_maybe"] svg,#seen-it svg{animation:soft-pulse 1.8s ease-in-out infinite}

/* ---- progress bar: leader pulse (adds to the p0 colour rule above) ---- */
@keyframes pbar-pulse{0%,100%{opacity:.85;box-shadow:0 0 4px var(--pink)}50%{opacity:1;box-shadow:0 0 10px var(--pink)}}
.pbar-p0 .pbar-fill{box-shadow:0 0 6px var(--pink);animation:pbar-pulse 1.8s ease-in-out infinite}

/* ---- simple card (done / single match): poster placeholder overlays ---- */
.card-poster{position:relative}
.card .noposter{width:100%;height:auto;aspect-ratio:2/3;display:block}
.card-poster .poster-title{bottom:auto;top:14px}
/* UI fidelity T3: .film-more-ctl is normal-flow by default now, so the
   single-confirm screen's over-the-poster placement has to opt back IN to
   absolute here. .card-poster{position:relative} above is the containing
   block. margin:0 cancels the base rule's centring margin. */
.card-poster .film-more-ctl{position:absolute;margin:0;left:auto;right:12px;transform:none;bottom:12px}

/* ---- match reveal / celebration: subtitle, double-feature colouring, spotlight beams ---- */
.match-subtitle{font-family:var(--font-body);font-size:.95rem;color:var(--dim);margin:0 0 14px}
@keyframes letter-wiggle{0%,100%{transform:rotate(0)}25%{transform:rotate(-6deg)}75%{transform:rotate(6deg)}}
.df-cyan{color:#dcffff;text-shadow:0 0 6px var(--cyan-neon),0 0 16px rgba(63,211,220,.6)!important}
.df-pink{color:#ffe3f2;text-shadow:0 0 6px var(--pink),0 0 16px rgba(248,106,176,.6)!important}
.reveal{position:relative;overflow:hidden;border-radius:12px}
.spotlight{position:absolute;bottom:0;width:26px;height:90px;pointer-events:none;z-index:0;
  clip-path:polygon(35% 0,65% 0,100% 100%,0 100%);
  background:linear-gradient(to bottom,rgba(255,255,255,.28),rgba(255,255,255,.03));
  mix-blend-mode:screen;animation:spotlight-pulse 3s ease-in-out infinite}
.spotlight-l{left:8px}
.spotlight-r{right:8px}
@keyframes spotlight-pulse{0%,100%{opacity:.35}50%{opacity:.75}}
.reveal>*:not(.spotlight){position:relative;z-index:1}

/* ---- matches panel rows: card rows, vote chips, pending spinner ---- */
.match-votes{display:flex;flex-direction:column;gap:6px;margin:5px 0;align-items:flex-start}
.mv{font-size:.72rem;font-weight:600;padding:2px 8px;border-radius:999px}
.mv-yes{background:var(--accent-tint);border:1px solid var(--accent-tint-line);color:var(--accent-tint-ink)}
.mv-pending{background:transparent;border:1px solid var(--line2);color:var(--dim);display:inline-flex;align-items:center;gap:5px}
.mv-spin{width:9px;height:9px;flex:none}

/* ---- coach card: button preview ---- */
.coach-sub{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.07em;text-transform:uppercase;color:var(--dim);margin:14px 0 6px}
.coach-btn-preview{display:flex;flex-direction:column;gap:8px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:12px}
.coach-btn-preview .cbp-row{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.coach-btn-preview button{margin:0;cursor:pointer;height:58px;box-sizing:border-box;min-height:0}
.coach-btn-preview button svg{width:20px;height:20px}
.coach-btn-preview button{font-size:.68rem}
.mini-btn{display:inline-block;padding:2px 8px;border-radius:999px;font-size:.82em;font-weight:600;vertical-align:baseline}
.mini-good{background:var(--accent);color:var(--accent-ink)}
.mini-open{background:transparent;border:1px solid var(--accent-tint-line);color:var(--accent-tint-ink)}
.coach-explain{margin:2px 0 0;padding:9px 12px;background:var(--accent-tint);border:1px solid var(--accent-tint-line);
  border-radius:10px;color:var(--accent-tint-ink);font-size:.82rem;text-align:left;line-height:1.4}

/* ---- toast: colour variants (cyan / amber) ---- */
#toast.toast-cyan{border-color:var(--cyan-neon);box-shadow:0 0 18px rgba(63,211,220,.28)}
#toast.toast-cyan .toast-eyebrow{color:var(--cyan-neon)}
#toast.toast-amber{border-color:var(--amber);box-shadow:0 0 18px rgba(224,169,74,.28)}
#toast.toast-amber .toast-eyebrow{color:var(--amber)}

/* ---- memory screen: card-list redesign (sortbar, legend filters, rows, status
   buttons). The old .mem-table* system it replaced is retired (see above). ---- */
.warmup-mem-row::before{content:"";position:absolute;left:2px;top:.55em;width:6px;height:6px;border-radius:50%;background:var(--accent)}
.mem-sortbar{display:flex;align-items:center;gap:8px;margin:8px 0}
.mem-sortbar .mem-sort{width:auto;min-height:32px;margin:0;padding:5px 12px;font-size:.72rem;font-weight:600;
  font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;
  display:inline-flex;align-items:center;gap:5px;
  background:transparent;border:1px solid var(--line2);border-radius:999px;color:var(--dim)}
.mem-sortbar .mem-sort.on{background:var(--accent-tint);border-color:var(--accent);color:var(--accent-tint-ink);font-weight:600}
.mem-sortbar .mem-sort svg{width:11px;height:11px}
.mem-legend{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 10px}
.mem-legend-btn{width:auto;min-height:26px;margin:0;padding:4px 9px;font-size:.72rem;
  display:inline-flex;align-items:center;gap:4px;color:var(--dim);
  background:transparent;border:1px solid var(--line2);border-radius:999px}
.mem-legend-btn[aria-pressed="true"]{background:var(--accent-tint);border-color:var(--accent);color:var(--accent-tint-ink);font-weight:600}
.mem-legend-btn svg{width:13px;height:13px}
.mem-list{display:flex;flex-direction:column;gap:6px;margin:8px 0 16px}
.mem-row{display:flex;gap:10px;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:8px 10px;align-items:center}
.mem-row-left{flex:1;min-width:0}
.mem-row-title{margin:0 0 3px;font-weight:600;font-size:.88rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mem-row-sub{display:flex;align-items:center;gap:4px}
.mem-row-date{font-size:.72rem}
.mem-status-row{display:flex;gap:5px;flex:0 0 auto}
.mem-status{width:28px;height:28px;min-height:28px;flex:0 0 auto;margin:0;padding:0;
  border-radius:7px;background:transparent;border:1px solid var(--line2);color:var(--dim);
  display:flex;align-items:center;justify-content:center}
.mem-status svg{width:14px;height:14px}
.mem-status.on{background:var(--accent-tint);border-color:var(--accent);color:var(--accent-tint-ink)}
/* Series-layout wave: memory medium filter (All/TV/Film) + per-row medium
   marker, both shown only on a mixed film+series history. */
.medium-filter{display:flex;gap:8px;margin:0 0 10px}
.medium-filter-btn{width:auto;min-height:32px;margin:0;padding:5px 12px;font-size:.72rem;font-weight:600;
  font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;
  display:inline-flex;align-items:center;gap:5px;
  background:transparent;border:1px solid var(--line2);border-radius:999px;color:var(--dim)}
.medium-filter-btn.on{background:var(--accent-tint);border-color:var(--accent);color:var(--accent-tint-ink)}
.medium-filter-btn svg{width:13px;height:13px}
.mem-row-medium{display:inline-flex;align-items:center;gap:3px;color:var(--dim);
  font-size:.72rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em}
.mem-row-medium svg{width:12px;height:12px}
.mem-status.mem-never-on{background:rgba(255,80,80,.12);border-color:var(--danger);color:var(--danger)}
.mem-remove-icon{width:28px;height:28px;min-height:28px;flex:0 0 auto;margin:0 2px 0 0;padding:0;
  background:transparent;border:0;color:#F0A878;display:flex;align-items:center;justify-content:center}
.mem-remove-icon svg{width:14px;height:14px}
/* UI fidelity T8c: the approved memory screen draws this trash at 13px; the
   shared registry's default is 16px and nothing overrode it here. Same CSS
   technique the row-level trash above already uses. */
#delete-profile svg{width:13px;height:13px}

/* ---- warm-up: progress bar, search field with icon, bigger cards ---- */
.warmup-card-body button+button{margin-top:8px}
.warmup-progress{height:6px;border-radius:999px;background:var(--line);overflow:hidden;margin:6px 0 12px}
.warmup-progress-fill{height:100%;border-radius:999px;background:var(--cyan-neon);
  box-shadow:0 0 8px var(--cyan-neon),0 0 16px rgba(63,211,220,.6);animation:progress-pulse 1.8s ease-in-out infinite}
@keyframes progress-pulse{0%,100%{opacity:.75}50%{opacity:1}}
.search-wrap{position:relative}
.search-wrap input{padding-left:42px;border-color:var(--accent);border-width:2px;font-weight:500}
.search-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);color:var(--accent);pointer-events:none}

/* ---- .btn-ico utility (spec R-BYTES): a class for the repeated inline
   display:flex;align-items:center;justify-content:center;gap:8px on icon+label
   buttons. Visually identical; a deliberate deviation from the markup. ---- */
.btn-ico{display:flex;align-items:center;justify-content:center;gap:8px}

/* ---- reduced motion: the 11 remaining new gallery guards (the background
   guard sits with the bg system up top; six older app guards are unchanged in
   place). Every decorative loop stops; nothing structural moves. ---- */
@media (prefers-reduced-motion:reduce){.ticket-pink .ic svg,.ticket-cyan .ic svg rect,.ticket-amber .ic svg{animation:none}}
@media (prefers-reduced-motion:reduce){.ticket,#more{animation:none}}
@media (prefers-reduced-motion:reduce){.chip.on{animation:none}}
@media (prefers-reduced-motion:reduce){#more .count{animation:none}}
@media (prefers-reduced-motion:reduce){#coach-ok{animation:none}}
@media (prefers-reduced-motion:reduce){#seen-nope svg,#seen-liked svg,#seen-loved svg,.rate-grid button[data-r="not_seen_no"] svg,#never-again svg,.rate-grid button[data-r="not_seen_want"] svg,.rate-grid button[data-r="not_seen_maybe"] svg,#seen-it svg{animation:none}}
@media (prefers-reduced-motion:reduce){.pbar-p0 .pbar-fill{animation:none}}
@media (prefers-reduced-motion:reduce){.home-pulse{animation:none}}
@media (prefers-reduced-motion:reduce){#double-feature-title span{animation:none}}
@media (prefers-reduced-motion:reduce){.spotlight{animation:none;opacity:.5}}
@media (prefers-reduced-motion:reduce){.warmup-progress-fill{animation:none}}

/* ---- CL Task 9: the list picker (landing -> GET /api/lists) - a self-
   contained overlay (NOT #overlay, which app.js's render() hides whenever
   the stage isn't 'rating') and its tappable rows, plus the rating-stage
   position readout beside the match pill. ---- */
.list-picker{position:fixed;inset:0;background:rgba(6,8,16,.93);display:flex;
  align-items:center;justify-content:center;padding:20px;z-index:10}
.list-picker-panel{max-width:420px;width:100%;max-height:82vh;overflow-y:auto;text-align:left;
  background:var(--card);border-radius:16px;padding:18px 16px;box-shadow:0 12px 44px rgba(0,0,0,.55)}
.list-picker-panel h2{margin:0 0 6px;font-family:var(--font-head);text-align:center}
.list-row{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;
  text-align:left;background:rgba(255,255,255,.05);border:1px solid var(--line2);
  border-radius:12px;padding:10px 14px;margin:10px 0}
.list-row strong{font-family:var(--font-head)}
.list-pos{font-size:.8rem;color:var(--dim)}

